diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-03-13 15:42:45 -0700 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2014-03-13 20:48:31 -0700 |
commit | 3fe0019bc2939aea4e89cbb8bc5aeb5edeb456d9 (patch) | |
tree | cbd3b2b6fa7f2b31977256f1e909920ebe916840 /save-git.c | |
parent | 0b114a198eb3a648c507bc801a0343bf04dc0191 (diff) | |
download | subsurface-3fe0019bc2939aea4e89cbb8bc5aeb5edeb456d9.tar.gz |
git object format: make sure parenthood isn't lost when saving
This makes subsurface remember the git source commit of the dive data.
If you save to an existing branch, subsurface will now complain and
refuse to save if you try to save if the existing branch is not related
to the original source. That would destroy the history of the dive
data, which in turn would make it impossible to do sane merging of the
data.
If you save to a new branch, it will see if the previous parent commit
is known in the repository you are saving to, and will save parenthood
information if so. Otherwise it will save it as a new parentless commit
("root commit" in git parlance).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
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); } /* |