current, err := products.Find(ctx, product.ID)
if err != nil {
return EditResult{}, err
}
candidateFiles, err := productFiles.BuildCandidate(ctx, current, submittedEdit)
if err != nil {
return EditResult{}, err
}
change, err := repo.CreateCommit(storage.CommitOptions{
TargetBranch: "main",
ExpectedHeadSHA: current.HeadRevision,
CommitMessage: fmt.Sprintf("Update %s", current.Name),
Author: storage.CommitSignature{Name: editor.Name, Email: editor.Email},
})
if err != nil {
return EditResult{}, err
}
for path, contents := range candidateFiles {
change = change.AddFileFromString(path, contents, nil)
}
for _, path := range productFiles.DeletedPaths(current.Files, candidateFiles) {
change = change.DeletePath(path)
}
committed, err := change.Send(ctx)
if err != nil {
var refErr *storage.RefUpdateError
if errors.As(err, &refErr) {
switch refErr.Reason {
case storage.RefUpdateReasonConflict:
return EditResult{OK: false, Reason: "conflict"}, nil
case storage.RefUpdateReasonPreconditionFailed:
return EditResult{OK: true, Reason: "no_changes"}, nil
}
}
return EditResult{}, err
}