Unable to update existing file in repository - Error 409
Hi, I have a problem to updating existing file in repository.
I've created a function to obtain the last SHA from the file that I want to update:
func getSHAFile(ctx context.Context, accessToken string) string {
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: accessToken},
)
tc := oauth2.NewClient(ctx, ts)
client := github.NewClient(tc)
opt := &github.CommitsListOptions{
Path: *github.String("update/ciao.txt"),
}
commits, _, _ := client.Repositories.ListCommits(ctx, "duckt14", "Pippo", opt)
sha := commits[len(commits)-1].GetSHA()
return sha
}
Then, I have this function to update the file:
func updateFile(ctx context.Context, accessToken string, file []byte, author string, time time.Time, email string, path string, sha string) error {
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: accessToken},
)
tc := oauth2.NewClient(ctx, ts)
client := github.NewClient(tc)
opt := &github.RepositoryContentFileOptions{
Author: &github.CommitAuthor{
Name: &author,
Date: &time,
Email: &email,
},
Message: github.String("Updating test"),
Content: file,
SHA: &sha,
}
filepath := "update/ciao.txt"
_, _, err := client.Repositories.UpdateFile(ctx, "duckt14", "Pippo", filepath, opt)
return err
}
What succeed when I play the code is this error (409):
2023/03/14 17:25:25 PUT https://api.github.com/repos/duckt14/Pippo/contents/update/ciao.txt: 409 update/ciao.txt does not match c902b7ebed9a5f513fb5a796327ddcd7c7482337 []
I found this about the Error 409: https://github.com/PyGithub/PyGithub/issues/1815#issuecomment-805473881
Are there a solution for resolve with this error or any alternative solutions for updating a file into repository? 😕
Enrico
Are you trying to update it immediately after creating it? I've seen problems before where GitHub's internal servers have not yet fully updated (made consistent) and so one server has an empty SHA because it hasn't sync'd yet.
The only thing I can think of off-hand is to try to update it in a limited retry-loop with exponential backoff. (e.g. 1 second, 2, 4, 8, 16, 32, then fatal error)
@duckt14 You are using the commit hash but instead should be using the file hash. You are also using the earliest commit when you most likely want the latest.
opt := &github.CommitsListOptions{
Path: path,
}
org := *repo.Owner.Login
name := *repo.Name
commits, _, _ := client.Repositories.ListCommits(context.Background(), org, name, opt)
commit := commits[0]
t, _, _ := client.Git.GetTree(context.Background(), org, name, commit.GetSHA(), true)
for _, entry := range t.Entries {
if *entry.Path == path {
return *entry.SHA
}
}
for anyone coming across this with the problem that creating a new file works but updating an existing file doesn't work: when creating a new file, you can set the file's old blob sha to the empty string but for updating a file, the correct old file's blob sha must be given (hex-encoded)
Thank you, @m1cm1c ! Do you want to make a PR to update our documentation for the endpoint so that this is clearer to other users?
Do you want to make a PR to update our documentation for the endpoint so that this is clearer to other users?
the documentation already states it:
i just didn't read it at first ;) i only saw that the implementations of CreateFile() and UpdateFile() were identical, so i didn't read the documentation of UpdateFile() because i had already read the documentation of CreateFile()
Oh! Cool! 😁
Thank you, @m1cm1c !