commit - 46f68b205b4ab514846c5352c6d952720b9da365
commit + f69721c3fc6f5a7b7a11a49a1fd7a99182ef01f0
blob - d8e2403ac8b60843492a2228a507dad1ac532791
blob + 4e9889d1ca69a14aedc6dcae7c29125180dae6cc
--- lib/diff3.c
+++ lib/diff3.c
* is stored in last[1-3];
*/
int last[4];
- char f1mark[PATH_MAX], f3mark[PATH_MAX]; /* markers for -E and -X */
+ char f1mark[PATH_MAX];
+ char f2mark[PATH_MAX];
+ char f3mark[PATH_MAX];
char *buf;
static const struct got_error *increase(struct diff3_state *);
static const struct got_error *diff3_internal(char *, char *, char *,
char *, char *, const char *, const char *, struct diff3_state *,
- const char *, const char *);
+ const char *, const char *, const char *);
static const struct got_error *
diff_output(BUF *diffbuf, const char *fmt, ...)
*/
const struct got_error *
got_merge_diff3(int *overlapcnt, int outfd, const char *p1, const char *p2,
- const char *p3, const char *label1, const char *label3)
+ const char *p3, const char *label1, const char *label2, const char *label3)
{
const struct got_error *err = NULL;
char *dp13, *dp23, *path1, *path2, *path3;
d3s->diffbuf = diffb;
err = diff3_internal(dp13, dp23, path1, path2, path3,
- label1, label3, d3s, label1, label3);
+ label1, label3, d3s, label1, label2, label3);
if (err) {
buf_free(diffb);
diffb = NULL;
static const struct got_error *
diff3_internal(char *dp13, char *dp23, char *path1, char *path2, char *path3,
const char *fmark, const char *rmark, struct diff3_state *d3s,
- const char *label1, const char *label3)
+ const char *label1, const char *label2, const char *label3)
{
const struct got_error *err = NULL;
ssize_t m, n;
int i;
i = snprintf(d3s->f1mark, sizeof(d3s->f1mark),
- "%s %s", GOT_DIFF_CONFLICT_MARKER_BEGIN, label1);
+ "%s%s%s", GOT_DIFF_CONFLICT_MARKER_BEGIN,
+ label1 ? " " : "", label1 ? label1 : "");
if (i < 0 || i >= (int)sizeof(d3s->f1mark))
return got_error(GOT_ERR_NO_SPACE);
+ i = snprintf(d3s->f2mark, sizeof(d3s->f2mark),
+ "%s%s%s", GOT_DIFF_CONFLICT_MARKER_ORIG,
+ label2 ? " " : "", label2 ? label2 : "");
+ if (i < 0 || i >= (int)sizeof(d3s->f2mark))
+ return got_error(GOT_ERR_NO_SPACE);
+
i = snprintf(d3s->f3mark, sizeof(d3s->f3mark),
- "%s %s", GOT_DIFF_CONFLICT_MARKER_END, label3);
+ "%s%s%s", GOT_DIFF_CONFLICT_MARKER_END,
+ label3 ? " " : "", label3 ? label3 : "");
if (i < 0 || i >= (int)sizeof(d3s->f3mark))
return got_error(GOT_ERR_NO_SPACE);
} else if (d3s->de[n].oldo.from < d3s->de[n].oldo.to) {
/* Output a block of 3-way diff base file content. */
err = diff_output(d3s->diffbuf, "%da\n%s\n",
- d3s->de[n].old.to -1,
- GOT_DIFF_CONFLICT_MARKER_ORIG);
+ d3s->de[n].old.to - 1, d3s->f2mark);
if (err)
return err;
if (fseeko(d3s->fp[1], d3s->de[n].oldo.from, SEEK_SET)
blob - 0d74b1bbdb78b195fcfd6b16c5042af2a781aa5f
blob + ace2137e04157dfffb2d383748e8d9561c074ac1
--- lib/got_lib_diff.h
+++ lib/got_lib_diff.h
void got_diff_free_changes(struct got_diff_changes *);
const struct got_error *got_merge_diff3(int *, int, const char *, const char *,
- const char *, const char *, const char *);
+ const char *, const char *, const char *, const char *);
const struct got_error *got_diff_files(struct got_diff_changes **,
struct got_diff_state **, struct got_diff_args **, int *, FILE *, size_t,
blob - e289542324a5a24dba52bcccb0d657378875d631
blob + c4df32a19603acd84d6a098d33892f92581f2f71
--- lib/worktree.c
+++ lib/worktree.c
#ifndef MIN
#define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
#endif
+
+#define GOT_MERGE_LABEL_MERGED "merged change"
+#define GOT_MERGE_LABEL_BASE "3-way merge base"
static const struct got_error *
create_meta_file(const char *path_got, const char *name, const char *content)
merge_file(int *local_changes_subsumed, struct got_worktree *worktree,
struct got_blob_object *blob_orig, const char *ondisk_path,
const char *path, uint16_t st_mode, const char *deriv_path,
- const char *label_deriv, struct got_repository *repo,
+ const char *label_orig, const char *label_deriv,
+ struct got_repository *repo,
got_worktree_checkout_cb progress_cb, void *progress_arg)
{
const struct got_error *err = NULL;
}
err = got_merge_diff3(&overlapcnt, merged_fd, deriv_path,
- blob_orig_path, ondisk_path, label_deriv, path);
+ blob_orig_path, ondisk_path, label_deriv, label_orig, NULL);
if (err)
goto done;
static const struct got_error *
merge_blob(int *local_changes_subsumed, struct got_worktree *worktree,
struct got_blob_object *blob_orig, const char *ondisk_path,
- const char *path, uint16_t st_mode, struct got_blob_object *blob_deriv,
- struct got_object_id *deriv_base_commit_id,
- struct got_repository *repo, got_worktree_checkout_cb progress_cb,
- void *progress_arg)
+ const char *path, uint16_t st_mode, const char *label_orig,
+ struct got_blob_object *blob_deriv,
+ struct got_object_id *deriv_base_commit_id, struct got_repository *repo,
+ got_worktree_checkout_cb progress_cb, void *progress_arg)
{
const struct got_error *err = NULL;
FILE *f_deriv = NULL;
err = got_object_id_str(&id_str, deriv_base_commit_id);
if (err)
goto done;
- if (asprintf(&label_deriv, "commit %s", id_str) == -1) {
+ if (asprintf(&label_deriv, "%s: commit %s",
+ GOT_MERGE_LABEL_MERGED, id_str) == -1) {
err = got_error_from_errno("asprintf");
goto done;
}
err = merge_file(local_changes_subsumed, worktree, blob_orig,
- ondisk_path, path, st_mode, blob_deriv_path, label_deriv,
- repo, progress_cb, progress_arg);
+ ondisk_path, path, st_mode, blob_deriv_path, label_orig,
+ label_deriv, repo, progress_cb, progress_arg);
done:
if (f_deriv && fclose(f_deriv) != 0 && err == NULL)
err = got_error_from_errno("fclose");
if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_ADD) {
int update_timestamps;
struct got_blob_object *blob2 = NULL;
+ char *label_orig = NULL;
if (got_fileindex_entry_has_blob(ie)) {
struct got_object_id id2;
memcpy(id2.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
err = got_object_open_as_blob(&blob2, repo, &id2, 8192);
if (err)
+ goto done;
+ }
+ if (got_fileindex_entry_has_commit(ie)) {
+ char id_str[SHA1_DIGEST_STRING_LENGTH];
+ if (got_sha1_digest_to_str(ie->commit_sha1, id_str,
+ sizeof(id_str)) == NULL) {
+ err = got_error(GOT_ERR_BAD_OBJ_ID_STR);
+ goto done;
+ }
+ if (asprintf(&label_orig, "%s: commit %s",
+ GOT_MERGE_LABEL_BASE, id_str) == -1) {
+ err = got_error_from_errno("asprintf");
goto done;
+ }
}
err = merge_blob(&update_timestamps, worktree, blob2,
- ondisk_path, path, sb.st_mode, blob,
+ ondisk_path, path, sb.st_mode, label_orig, blob,
worktree->base_commit_id, repo,
progress_cb, progress_arg);
+ free(label_orig);
if (blob2)
got_object_blob_close(blob2);
if (err)
void *progress_arg;
got_cancel_cb cancel_cb;
void *cancel_arg;
+ const char *label_orig;
struct got_object_id *commit_id2;
};
}
err = merge_blob(&local_changes_subsumed, a->worktree, blob1,
- ondisk_path, path2, sb.st_mode, blob2, a->commit_id2, repo,
- a->progress_cb, a->progress_arg);
+ ondisk_path, path2, sb.st_mode, a->label_orig, blob2,
+ a->commit_id2, repo, a->progress_cb, a->progress_arg);
} else if (blob1) {
ie = got_fileindex_entry_get(a->fileindex, path1,
strlen(path1));
goto done;
}
err = merge_blob(&local_changes_subsumed, a->worktree,
- NULL, ondisk_path, path2, sb.st_mode, blob2,
- a->commit_id2, repo,
- a->progress_cb, a->progress_arg);
+ NULL, ondisk_path, path2, sb.st_mode,
+ a->label_orig, blob2, a->commit_id2, repo,
+ a->progress_cb,
+ a->progress_arg);
if (status == GOT_STATUS_DELETE) {
err = update_blob_fileindex_entry(a->worktree,
a->fileindex, ie, ondisk_path, ie->path,
struct got_object_id *tree_id1 = NULL, *tree_id2 = NULL;
struct got_tree_object *tree1 = NULL, *tree2 = NULL;
struct merge_file_cb_arg arg;
+ char *label_orig = NULL;
if (commit_id1) {
+ char *id_str;
+
err = got_object_id_by_path(&tree_id1, repo, commit_id1,
worktree->path_prefix);
if (err)
err = got_object_open_as_tree(&tree1, repo, tree_id1);
if (err)
goto done;
+
+ err = got_object_id_str(&id_str, commit_id1);
+ if (err)
+ goto done;
+
+ if (asprintf(&label_orig, "%s: commit %s",
+ GOT_MERGE_LABEL_BASE, id_str) == -1) {
+ err = got_error_from_errno("asprintf");
+ free(id_str);
+ goto done;
+ }
+ free(id_str);
}
err = got_object_id_by_path(&tree_id2, repo, commit_id2,
arg.progress_arg = progress_arg;
arg.cancel_cb = cancel_cb;
arg.cancel_arg = cancel_arg;
+ arg.label_orig = label_orig;
arg.commit_id2 = commit_id2;
err = got_diff_tree(tree1, tree2, "", "", repo, merge_file_cb, &arg, 1);
sync_err = sync_fileindex(fileindex, fileindex_path);
got_object_tree_close(tree1);
if (tree2)
got_object_tree_close(tree2);
+ free(label_orig);
return err;
}
struct got_blob_object *blob_base = NULL, *blob_staged = NULL;
char *ondisk_path = NULL, *path_unstaged_content = NULL;
char *path_new_staged_content = NULL;
+ char *id_str = NULL, *label_orig = NULL;
int local_changes_subsumed;
struct stat sb;
== -1)
return got_error_from_errno("asprintf");
+ err = got_object_id_str(&id_str,
+ commit_id ? commit_id : a->worktree->base_commit_id);
+ if (err)
+ goto done;
+ if (asprintf(&label_orig, "%s: commit %s", GOT_MERGE_LABEL_BASE,
+ id_str) == -1) {
+ err = got_error_from_errno("asprintf");
+ goto done;
+ }
+
switch (staged_status) {
case GOT_STATUS_MODIFY:
err = got_object_open_as_blob(&blob_base, a->repo,
err = merge_file(&local_changes_subsumed,
a->worktree, blob_base, ondisk_path,
relpath, got_fileindex_perms_to_st(ie),
- path_unstaged_content, "unstaged",
- a->repo, a->progress_cb, a->progress_arg);
+ path_unstaged_content, label_orig,
+ "unstaged", a->repo, a->progress_cb,
+ a->progress_arg);
if (err == NULL &&
path_new_staged_content == NULL)
got_fileindex_entry_stage_set(ie,
break;
err = merge_blob(&local_changes_subsumed, a->worktree,
blob_base, ondisk_path, relpath,
- got_fileindex_perms_to_st(ie), blob_staged,
+ got_fileindex_perms_to_st(ie), label_orig, blob_staged,
commit_id ? commit_id : a->worktree->base_commit_id,
a->repo, a->progress_cb, a->progress_arg);
if (err == NULL)
err = (*a->progress_cb)(a->progress_arg, status, relpath);
break;
}
-
+done:
free(ondisk_path);
if (path_unstaged_content &&
unlink(path_unstaged_content) == -1 && err == NULL)
got_object_blob_close(blob_base);
if (blob_staged)
got_object_blob_close(blob_staged);
+ free(id_str);
+ free(label_orig);
return err;
}
blob - 31587c10a62466ca183a27d0985a8816a43d7053
blob + 43a0f3a840e30d3749f4690d900e34f9cc447465
--- regress/cmdline/diff.sh
+++ regress/cmdline/diff.sh
echo "8" >> $testroot/repo/numbers
(cd $testroot/repo && git add numbers)
git_commit $testroot/repo -m "added numbers file"
+ local base_commit=`git_show_head $testroot/repo`
got checkout $testroot/repo $testroot/wt > /dev/null
ret="$?"
echo '+++ numbers' >> $testroot/stdout.expected
echo '@@ -1,8 +1,20 @@' >> $testroot/stdout.expected
echo ' 1' >> $testroot/stdout.expected
- echo "+<<<<<<< commit $head_rev" >> $testroot/stdout.expected
+ echo "+<<<<<<< merged change: commit $head_rev" \
+ >> $testroot/stdout.expected
echo ' 22' >> $testroot/stdout.expected
- echo '+|||||||' >> $testroot/stdout.expected
+ echo "+||||||| 3-way merge base: commit $base_commit" \
+ >> $testroot/stdout.expected
echo '+2' >> $testroot/stdout.expected
echo '+=======' >> $testroot/stdout.expected
echo '+77' >> $testroot/stdout.expected
- echo '+>>>>>>> numbers' >> $testroot/stdout.expected
+ echo '+>>>>>>>' >> $testroot/stdout.expected
echo ' 3' >> $testroot/stdout.expected
echo ' 4' >> $testroot/stdout.expected
echo ' 5' >> $testroot/stdout.expected
echo ' 6' >> $testroot/stdout.expected
echo ' 7' >> $testroot/stdout.expected
- echo "+<<<<<<< commit $head_rev" >> $testroot/stdout.expected
+ echo "+<<<<<<< merged change: commit $head_rev" \
+ >> $testroot/stdout.expected
echo ' 33' >> $testroot/stdout.expected
- echo '+|||||||' >> $testroot/stdout.expected
+ echo "+||||||| 3-way merge base: commit $base_commit" \
+ >> $testroot/stdout.expected
echo '+8' >> $testroot/stdout.expected
echo '+=======' >> $testroot/stdout.expected
echo '+88' >> $testroot/stdout.expected
- echo '+>>>>>>> numbers' >> $testroot/stdout.expected
+ echo '+>>>>>>>' >> $testroot/stdout.expected
(cd $testroot/wt && got diff > $testroot/stdout)
blob - c94727a0b05067fb3a4deadd1017588265245e68 (mode 744)
blob + 62a0455a66d4559f543efeddcfbe821bfa742d26 (mode 755)
--- regress/cmdline/rebase.sh
+++ regress/cmdline/rebase.sh
function test_rebase_continue {
local testroot=`test_init rebase_continue`
+ local init_commit=`git_show_head $testroot/repo`
(cd $testroot/repo && git checkout -q -b newbranch)
echo "modified alpha on branch" > $testroot/repo/alpha
return 1
fi
- echo "<<<<<<< commit $orig_commit1" > $testroot/content.expected
+ echo "<<<<<<< merged change: commit $orig_commit1" \
+ > $testroot/content.expected
echo "modified alpha on branch" >> $testroot/content.expected
- echo "|||||||" >> $testroot/content.expected
+ echo "||||||| 3-way merge base: commit $init_commit" \
+ >> $testroot/content.expected
echo "alpha" >> $testroot/content.expected
echo "=======" >> $testroot/content.expected
echo "modified alpha on master" >> $testroot/content.expected
- echo '>>>>>>> alpha' >> $testroot/content.expected
+ echo '>>>>>>>' >> $testroot/content.expected
cat $testroot/wt/alpha > $testroot/content
cmp -s $testroot/content.expected $testroot/content
ret="$?"
return 1
fi
- echo "<<<<<<< commit $orig_commit1" > $testroot/content.expected
+ echo "<<<<<<< merged change: commit $orig_commit1" \
+ > $testroot/content.expected
echo "modified alpha on branch" >> $testroot/content.expected
- echo "|||||||" >> $testroot/content.expected
+ echo "||||||| 3-way merge base: commit $init_commit" \
+ >> $testroot/content.expected
echo "alpha" >> $testroot/content.expected
echo "=======" >> $testroot/content.expected
echo "modified alpha on master" >> $testroot/content.expected
- echo '>>>>>>> alpha' >> $testroot/content.expected
+ echo '>>>>>>>' >> $testroot/content.expected
cat $testroot/wt/alpha > $testroot/content
cmp -s $testroot/content.expected $testroot/content
ret="$?"
return 1
fi
- echo "<<<<<<< commit $orig_commit1" > $testroot/content.expected
+ echo "<<<<<<< merged change: commit $orig_commit1" \
+ > $testroot/content.expected
echo "modified alpha on branch" >> $testroot/content.expected
- echo "|||||||" >> $testroot/content.expected
+ echo "||||||| 3-way merge base: commit $init_commit" \
+ >> $testroot/content.expected
echo "alpha" >> $testroot/content.expected
echo "=======" >> $testroot/content.expected
echo "modified alpha on master" >> $testroot/content.expected
- echo '>>>>>>> alpha' >> $testroot/content.expected
+ echo '>>>>>>>' >> $testroot/content.expected
cat $testroot/wt/alpha > $testroot/content
cmp -s $testroot/content.expected $testroot/content
ret="$?"
return 1
fi
- echo "<<<<<<< commit $orig_commit1" > $testroot/content.expected
+ echo "<<<<<<< merged change: commit $orig_commit1" \
+ > $testroot/content.expected
echo "modified alpha on branch" >> $testroot/content.expected
- echo "|||||||" >> $testroot/content.expected
+ echo "||||||| 3-way merge base: commit $init_commit" \
+ >> $testroot/content.expected
echo "alpha" >> $testroot/content.expected
echo "=======" >> $testroot/content.expected
echo "modified alpha on master" >> $testroot/content.expected
- echo '>>>>>>> alpha' >> $testroot/content.expected
+ echo '>>>>>>>' >> $testroot/content.expected
cat $testroot/wt/alpha > $testroot/content
cmp -s $testroot/content.expected $testroot/content
ret="$?"
blob - 4aa56793bd1b5831b7a8e3680b244722e712a0dd
blob + 2225b5ae82ab9273a4760df29891aa221c5898b3
--- regress/cmdline/update.sh
+++ regress/cmdline/update.sh
echo "8" >> $testroot/repo/numbers
(cd $testroot/repo && git add numbers)
git_commit $testroot/repo -m "added numbers file"
+ local base_commit=`git_show_head $testroot/repo`
got checkout $testroot/repo $testroot/wt > /dev/null
ret="$?"
return 1
fi
- echo -n "<<<<<<< commit " > $testroot/content.expected
+ echo -n "<<<<<<< merged change: commit " > $testroot/content.expected
git_show_head $testroot/repo >> $testroot/content.expected
echo >> $testroot/content.expected
echo "modified alpha" >> $testroot/content.expected
- echo "|||||||" >> $testroot/content.expected
+ echo "||||||| 3-way merge base: commit $base_commit" \
+ >> $testroot/content.expected
echo "alpha" >> $testroot/content.expected
echo "=======" >> $testroot/content.expected
echo "modified alpha, too" >> $testroot/content.expected
- echo '>>>>>>> alpha' >> $testroot/content.expected
+ echo '>>>>>>>' >> $testroot/content.expected
echo "modified beta" >> $testroot/content.expected
echo "1" >> $testroot/content.expected
echo "22" >> $testroot/content.expected
return 1
fi
- echo -n "<<<<<<< commit " > $testroot/content.expected
+ echo -n "<<<<<<< merged change: commit " > $testroot/content.expected
git_show_head $testroot/repo >> $testroot/content.expected
echo >> $testroot/content.expected
echo "new" >> $testroot/content.expected
echo "=======" >> $testroot/content.expected
echo "also new" >> $testroot/content.expected
- echo '>>>>>>> gamma/new' >> $testroot/content.expected
+ echo '>>>>>>>' >> $testroot/content.expected
cat $testroot/wt/gamma/new > $testroot/content
function test_update_to_another_branch {
local testroot=`test_init update_to_another_branch`
+ local base_commit=`git_show_head $testroot/repo`
got checkout $testroot/repo $testroot/wt > /dev/null
ret="$?"
return 1
fi
- echo -n "<<<<<<< commit " > $testroot/content.expected
+ echo -n "<<<<<<< merged change: commit " > $testroot/content.expected
git_show_head $testroot/repo >> $testroot/content.expected
echo >> $testroot/content.expected
echo "modified alpha on new branch" >> $testroot/content.expected
- echo "|||||||" >> $testroot/content.expected
+ echo "||||||| 3-way merge base: commit $base_commit" \
+ >> $testroot/content.expected
echo "alpha" >> $testroot/content.expected
echo "=======" >> $testroot/content.expected
echo "modified alpha in work tree" >> $testroot/content.expected
- echo '>>>>>>> alpha' >> $testroot/content.expected
+ echo '>>>>>>>' >> $testroot/content.expected
cat $testroot/wt/alpha > $testroot/content