diff options
Diffstat (limited to 'save-git.c')
-rw-r--r-- | save-git.c | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/save-git.c b/save-git.c index 4760fe32a..ab00ba951 100644 --- a/save-git.c +++ b/save-git.c @@ -741,6 +741,23 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o } /* + * See if we can find the parent ID that the git data came from + */ +static git_object *try_to_find_parent(const char *hex_id, git_repository *repo) +{ + git_oid object_id; + git_commit *commit; + + if (!hex_id) + return NULL; + if (git_oid_fromstr(&object_id, hex_id)) + return NULL; + if (git_commit_lookup(&commit, repo, &object_id)) + return NULL; + return (git_object *)commit; +} + +/* * libgit2 revision 0.20 and earlier do not have the signature and * message log arguments. */ @@ -769,15 +786,18 @@ static int create_new_commit(git_repository *repo, const char *branch, git_oid * case GIT_EINVALIDSPEC: return report_error("Invalid branch name '%s'", branch); case GIT_ENOTFOUND: /* We'll happily create it */ - ref = NULL; parent = NULL; + ref = NULL; + parent = try_to_find_parent(saved_git_id, repo); break; case 0: if (git_reference_peel(&parent, ref, GIT_OBJ_COMMIT)) return report_error("Unable to look up parent in branch '%s'", branch); - /* If the parent commit has the same tree ID, do nothing */ - if (git_oid_equal(tree_id, git_commit_tree_id((const git_commit *) parent))) - return 0; + if (saved_git_id) { + const git_oid *id = git_commit_id((const git_commit *) parent); + if (git_oid_strcmp(id, saved_git_id)) + return report_error("The git branch does not match the git parent of the source"); + } /* all good */ break; @@ -790,12 +810,21 @@ static int create_new_commit(git_repository *repo, const char *branch, git_oid * if (git_signature_now(&author, "Subsurface", "subsurface@hohndel.org")) return report_error("No user name configuration in git repo"); - put_format(&commit_msg, "Created by subsurface %s\n", VERSION_STRING); - if (git_commit_create_v(&commit_id, repo, NULL, author, author, NULL, mb_cstring(&commit_msg), tree, parent != NULL, parent)) - return report_error("Git commit create failed (%s)", strerror(errno)); - - if (git_commit_lookup(&commit, repo, &commit_id)) - return report_error("Could not look up newly created commit"); + /* If the parent commit has the same tree ID, do not create a new commit */ + if (parent && git_oid_equal(tree_id, git_commit_tree_id((const git_commit *) parent))) { + /* If the parent already came from the ref, the commit is already there */ + if (ref) + return 0; + /* Else we do want to create the new branch, but with the old commit */ + commit = (git_commit *) parent; + } else { + put_format(&commit_msg, "Created by subsurface %s\n", VERSION_STRING); + if (git_commit_create_v(&commit_id, repo, NULL, author, author, NULL, mb_cstring(&commit_msg), tree, parent != NULL, parent)) + return report_error("Git commit create failed (%s)", strerror(errno)); + + if (git_commit_lookup(&commit, repo, &commit_id)) + return report_error("Could not look up newly created commit"); + } if (!ref) { if (git_branch_create(&ref, repo, branch, commit, 0, author, "Create branch")) @@ -803,6 +832,7 @@ static int create_new_commit(git_repository *repo, const char *branch, git_oid * } if (git_reference_set_target(&ref, ref, &commit_id, author, "Subsurface save event")) return report_error("Failed to update branch '%s'", branch); + set_git_id(&commit_id); return 0; } @@ -850,8 +880,7 @@ static int do_git_save(git_repository *repo, const char *branch, bool select_onl return report_error("git tree write failed"); /* And save the tree! */ - create_new_commit(repo, branch, &id); - return 0; + return create_new_commit(repo, branch, &id); } /* |