mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Cloud storage: try to brute force your way around merge issues
This seems to do the right thing in several cases that I tested, but I'm worried if it might end up causing us data loss in other cases. This needs a TON of testing. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
70c38de3a1
commit
f177b2ec53
1 changed files with 43 additions and 27 deletions
70
git-access.c
70
git-access.c
|
@ -203,35 +203,51 @@ static int try_to_git_merge(git_repository *repo, git_reference *local, git_refe
|
||||||
if (git_merge_trees(&merged_index, repo, base_tree, local_tree, remote_tree, &merge_options))
|
if (git_merge_trees(&merged_index, repo, base_tree, local_tree, remote_tree, &merge_options))
|
||||||
return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: merge failed (%s)"), giterr_last()->message);
|
return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: merge failed (%s)"), giterr_last()->message);
|
||||||
if (git_index_has_conflicts(merged_index)) {
|
if (git_index_has_conflicts(merged_index)) {
|
||||||
return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: merge conflict - manual intervention needed"));
|
int error;
|
||||||
} else {
|
const git_index_entry *ancestor = NULL,
|
||||||
git_oid merge_oid, commit_oid;
|
*ours = NULL,
|
||||||
git_tree *merged_tree;
|
*theirs = NULL;
|
||||||
git_signature *author;
|
git_index_conflict_iterator *iter = NULL;
|
||||||
git_commit *commit;
|
error = git_index_conflict_iterator_new(&iter, merged_index);
|
||||||
|
while (git_index_conflict_next(&ancestor, &ours, &theirs, iter)
|
||||||
if (git_index_write_tree_to(&merge_oid, merged_index, repo))
|
!= GIT_ITEROVER) {
|
||||||
return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: writing the tree failed (%s)"), giterr_last()->message);
|
/* Mark this conflict as resolved */
|
||||||
if (git_tree_lookup(&merged_tree, repo, &merge_oid))
|
fprintf(stderr, "conflict in %s / %s / %s\n",
|
||||||
return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: tree lookup failed (%s)"), giterr_last()->message);
|
ours ? ours->path : "-",
|
||||||
if (git_signature_default(&author, repo) < 0)
|
theirs ? theirs->path : "-",
|
||||||
return report_error(translate("gettextFromC", "Failed to get author: (%s)"), giterr_last()->message);
|
ancestor ? ancestor->path : "-");
|
||||||
if (git_commit_create_v(&commit_oid, repo, "HEAD", author, author, NULL, "automatic merge", merged_tree, 2, local_commit, remote_commit))
|
error = git_index_conflict_remove(merged_index, ours->path);
|
||||||
return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: git commit create failed (%s)"), giterr_last()->message);
|
|
||||||
if (git_commit_lookup(&commit, repo, &commit_oid))
|
|
||||||
return report_error(translate("gettextFromC", "Error: could not lookup the merge commit I just created (%s)"), giterr_last()->message);
|
|
||||||
if (git_branch_is_head(local) && !git_repository_is_bare(repo)) {
|
|
||||||
git_object *parent;
|
|
||||||
git_reference_peel(&parent, local, GIT_OBJ_COMMIT);
|
|
||||||
if (update_git_checkout(repo, parent, merged_tree)) {
|
|
||||||
report_error("Warning: checked out branch is inconsistent with git data");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (git_reference_set_target(&local, local, &commit_oid, "Subsurface merge event"))
|
git_index_conflict_iterator_free(iter);
|
||||||
return report_error("Error: failed to update branch (%s)", giterr_last()->message);
|
report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: merge conflict - manual intervention needed"));
|
||||||
set_git_id(&commit_oid);
|
|
||||||
git_signature_free(author);
|
|
||||||
}
|
}
|
||||||
|
git_oid merge_oid, commit_oid;
|
||||||
|
git_tree *merged_tree;
|
||||||
|
git_signature *author;
|
||||||
|
git_commit *commit;
|
||||||
|
|
||||||
|
if (git_index_write_tree_to(&merge_oid, merged_index, repo))
|
||||||
|
return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: writing the tree failed (%s)"), giterr_last()->message);
|
||||||
|
if (git_tree_lookup(&merged_tree, repo, &merge_oid))
|
||||||
|
return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: tree lookup failed (%s)"), giterr_last()->message);
|
||||||
|
if (git_signature_default(&author, repo) < 0)
|
||||||
|
return report_error(translate("gettextFromC", "Failed to get author: (%s)"), giterr_last()->message);
|
||||||
|
if (git_commit_create_v(&commit_oid, repo, NULL, author, author, NULL, "automatic merge", merged_tree, 2, local_commit, remote_commit))
|
||||||
|
return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: git commit create failed (%s)"), giterr_last()->message);
|
||||||
|
if (git_commit_lookup(&commit, repo, &commit_oid))
|
||||||
|
return report_error(translate("gettextFromC", "Error: could not lookup the merge commit I just created (%s)"), giterr_last()->message);
|
||||||
|
if (git_branch_is_head(local) && !git_repository_is_bare(repo)) {
|
||||||
|
git_object *parent;
|
||||||
|
git_reference_peel(&parent, local, GIT_OBJ_COMMIT);
|
||||||
|
if (update_git_checkout(repo, parent, merged_tree)) {
|
||||||
|
report_error("Warning: checked out branch is inconsistent with git data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (git_reference_set_target(&local, local, &commit_oid, "Subsurface merge event"))
|
||||||
|
return report_error("Error: failed to update branch (%s)", giterr_last()->message);
|
||||||
|
set_git_id(&commit_oid);
|
||||||
|
git_signature_free(author);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue