0

I have a file called w.txt that holds 4 random numbers I am trying to push it to a git repo and I have the following code:

    aa=open(fileName,'r').read()
    print(aa)
    text= base64.b64encode(aa.encode("utf-8"))
    api="https://api.github.com/repos/Ixonblitz-MatOS/Worm/contents/w.txt"
    headers = {
        "Authorization": f'''Bearer {token}''',
        "Content-type": "application/vnd.github+json"
    }
    data = {
        "message": msg, # Put your commit message here.
        "content": text.decode("utf-8")
    }

    r = requests.put(api, headers=headers, json=data)
    print(r.text)

In this case fileName is "w.txt" and the api is the api for my repo and the correct token is being used. What am I missing? It is leaving the file on my repo empty instead of putting the numbers there.

  • What is coming back from `print(r.text)`? What is `r.status_code`. I believe a successful status_code is `201`. If it isn't `201`, what is the contents of `response.json()['message']`? – JNevill Feb 13 '23 at 15:24
  • `r.text` returns `'{"message":"Invalid request.\\n\\n\\"sha\\" wasn\'t supplied.","documentation_url":"https://docs.github.com/rest/reference/repos#create-or-update-file-contents"}'` – user19926715 Feb 13 '23 at 15:27
  • `status_code` is `422` – user19926715 Feb 13 '23 at 15:28
  • 1
    Also, I may be off base here since I haven't attempted myself, but the examples I find online suggest that the token in the header is formatted like `'token {token}'`, not`'bearer {token}'`. But... perhaps this is another form of auth that the examples don't include. – JNevill Feb 13 '23 at 15:29
  • let me try this – user19926715 Feb 13 '23 at 15:30
  • Still recieve `{"message":"Invalid request.\n\n\"sha\" wasn't supplied.","documentation_url":"https://docs.github.com/rest/reference/repos#create-or-update-file-contents"}` in `r.text` – user19926715 Feb 13 '23 at 15:32
  • [Related](https://community.n8n.io/t/error-github-error-response-422-invalid-request-sha-wasnt-supplied/5298)? – Wakeme UpNow Feb 13 '23 at 15:33
  • @WakemeUpNow That was where I was headed, digging into this, I've seen a few folks suggest that if trying to create a file that already exists on base branch, then you will get this message. – JNevill Feb 13 '23 at 15:38
  • This actually worked it was because instead of actively updating an existing file it tries to create one causing the issue – user19926715 Feb 13 '23 at 15:39
  • Then that lwaves me the question how you actively update or delete a file in python with it – user19926715 Feb 13 '23 at 15:39
  • [this gist](https://gist.github.com/avullo/b8153522f015a8b908072833b95c3408) suggests it's kind of ugly. You pull down the tree, find the file, get the sha, package your change, include the sha, and shoot it back at the API. :/ – JNevill Feb 13 '23 at 15:43
  • Oh how do you pull down the tree I haven't used this API very much – user19926715 Feb 13 '23 at 15:45

2 Answers2

2

You need to provide the SHA of the file as the error message says.

To get the SHA, you can get the file like this:

import requests

url = "https://api.github.com/repos/Ixonblitz-MatOS/Worm/contents/w.txt"

headers = {
  'Accept': 'application/vnd.github+json',
  'Authorization': 'Bearer <token>',
}

response = requests.request("GET", url, headers=headers)

data = response.json()

The SHA will be at data['sha'].

Then you need to modify your request to include the SHA:

    data = {
        "message": msg, # Put your commit message here.
        "content": text.decode("utf-8"),
        "sha": data['sha']
    }

The /repos/{owner}/{repo}/contents/{path} API route to fetch files has some size limits. See below:

If the requested file's size is:

  • 1 MB or smaller: All features of this endpoint are supported.
  • Between 1-100 MB: Only the raw or object custom media types are supported. Both will work as normal, except that when using the object media type, the content field will be an empty string and the encoding field will be "none". To get the contents of these larger files, use the raw media type.
  • Greater than 100 MB: This endpoint is not supported.

For larger files, you will have to clone the repository and then calculate the SHA locally.

D Malan
  • 10,272
  • 3
  • 25
  • 50
0

Why don't you do it this way.

from git import Repo

PATH_OF_GIT_REPO = r'path\to\your\project\folder\.git'  # make sure .git folder is properly configured
COMMIT_MESSAGE = 'comment from python script'

def git_push():
    try:
        repo = Repo(PATH_OF_GIT_REPO)
        repo.git.add(update=True)
        repo.index.commit(COMMIT_MESSAGE)
        origin = repo.remote(name='origin')
        origin.push()
    except:
        print('Some error occured while pushing the code')    

git_push()