#include "notes.h"
#include "notes-merge.h"
#include "strbuf.h"
+#include "notes-utils.h"
struct notes_merge_pair {
unsigned char obj[20], base[20], local[20], remote[20];
switch (p->status) {
case DIFF_STATUS_MODIFIED:
assert(p->one->mode == p->two->mode);
- assert(!is_null_sha1(p->one->sha1));
- assert(!is_null_sha1(p->two->sha1));
+ assert(!is_null_oid(&p->one->oid));
+ assert(!is_null_oid(&p->two->oid));
break;
case DIFF_STATUS_ADDED:
- assert(is_null_sha1(p->one->sha1));
+ assert(is_null_oid(&p->one->oid));
break;
case DIFF_STATUS_DELETED:
- assert(is_null_sha1(p->two->sha1));
+ assert(is_null_oid(&p->two->oid));
break;
default:
return -1;
if (verify_notes_filepair(p, obj)) {
trace_printf("\t\tCannot merge entry '%s' (%c): "
"%.7s -> %.7s. Skipping!\n", p->one->path,
- p->status, sha1_to_hex(p->one->sha1),
- sha1_to_hex(p->two->sha1));
+ p->status, oid_to_hex(&p->one->oid),
+ oid_to_hex(&p->two->oid));
continue;
}
mp = find_notes_merge_pair_pos(changes, len, obj, 1, &occupied);
if (occupied) {
/* We've found an addition/deletion pair */
assert(!hashcmp(mp->obj, obj));
- if (is_null_sha1(p->one->sha1)) { /* addition */
+ if (is_null_oid(&p->one->oid)) { /* addition */
assert(is_null_sha1(mp->remote));
- hashcpy(mp->remote, p->two->sha1);
- } else if (is_null_sha1(p->two->sha1)) { /* deletion */
+ hashcpy(mp->remote, p->two->oid.hash);
+ } else if (is_null_oid(&p->two->oid)) { /* deletion */
assert(is_null_sha1(mp->base));
- hashcpy(mp->base, p->one->sha1);
+ hashcpy(mp->base, p->one->oid.hash);
} else
assert(!"Invalid existing change recorded");
} else {
hashcpy(mp->obj, obj);
- hashcpy(mp->base, p->one->sha1);
+ hashcpy(mp->base, p->one->oid.hash);
hashcpy(mp->local, uninitialized);
- hashcpy(mp->remote, p->two->sha1);
+ hashcpy(mp->remote, p->two->oid.hash);
len++;
}
trace_printf("\t\tStored remote change for %s: %.7s -> %.7s\n",
sha1_to_hex(mp->remote));
}
diff_flush(&opt);
- diff_tree_release_paths(&opt);
+ clear_pathspec(&opt.pathspec);
*num_changes = len;
return changes;
if (verify_notes_filepair(p, obj)) {
trace_printf("\t\tCannot merge entry '%s' (%c): "
"%.7s -> %.7s. Skipping!\n", p->one->path,
- p->status, sha1_to_hex(p->one->sha1),
- sha1_to_hex(p->two->sha1));
+ p->status, oid_to_hex(&p->one->oid),
+ oid_to_hex(&p->two->oid));
continue;
}
mp = find_notes_merge_pair_pos(changes, len, obj, 0, &match);
if (!match) {
trace_printf("\t\tIgnoring local-only change for %s: "
"%.7s -> %.7s\n", sha1_to_hex(obj),
- sha1_to_hex(p->one->sha1),
- sha1_to_hex(p->two->sha1));
+ oid_to_hex(&p->one->oid),
+ oid_to_hex(&p->two->oid));
continue;
}
assert(!hashcmp(mp->obj, obj));
- if (is_null_sha1(p->two->sha1)) { /* deletion */
+ if (is_null_oid(&p->two->oid)) { /* deletion */
/*
* Either this is a true deletion (1), or it is part
* of an A/D pair (2), or D/A pair (3):
*/
if (!hashcmp(mp->local, uninitialized))
hashclr(mp->local);
- } else if (is_null_sha1(p->one->sha1)) { /* addition */
+ } else if (is_null_oid(&p->one->oid)) { /* addition */
/*
* Either this is a true addition (1), or it is part
* of an A/D pair (2), or D/A pair (3):
*/
assert(is_null_sha1(mp->local) ||
!hashcmp(mp->local, uninitialized));
- hashcpy(mp->local, p->two->sha1);
+ hashcpy(mp->local, p->two->oid.hash);
} else { /* modification */
/*
* This is a true modification. p->one->sha1 shall
* match mp->base, and mp->local shall be uninitialized.
* Set mp->local to p->two->sha1.
*/
- assert(!hashcmp(p->one->sha1, mp->base));
+ assert(!hashcmp(p->one->oid.hash, mp->base));
assert(!hashcmp(mp->local, uninitialized));
- hashcpy(mp->local, p->two->sha1);
+ hashcpy(mp->local, p->two->oid.hash);
}
trace_printf("\t\tStored local change for %s: %.7s -> %.7s\n",
sha1_to_hex(mp->obj), sha1_to_hex(mp->base),
sha1_to_hex(mp->local));
}
diff_flush(&opt);
- diff_tree_release_paths(&opt);
+ clear_pathspec(&opt.pathspec);
}
static void check_notes_merge_worktree(struct notes_merge_options *o)
"(%s exists).", git_path("NOTES_MERGE_*"));
}
- if (safe_create_leading_directories(git_path(
+ if (safe_create_leading_directories_const(git_path(
NOTES_MERGE_WORKTREE "/.test")))
die_errno("unable to create directory %s",
git_path(NOTES_MERGE_WORKTREE));
const char *buf, unsigned long size)
{
int fd;
- char *path = git_path(NOTES_MERGE_WORKTREE "/%s", sha1_to_hex(obj));
- if (safe_create_leading_directories(path))
+ char *path = git_pathdup(NOTES_MERGE_WORKTREE "/%s", sha1_to_hex(obj));
+ if (safe_create_leading_directories_const(path))
die_errno("unable to create directory for '%s'", path);
- if (file_exists(path))
- die("found existing file at '%s'", path);
- fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0666);
- if (fd < 0)
- die_errno("failed to open '%s'", path);
+ fd = xopen(path, O_WRONLY | O_EXCL | O_CREAT, 0666);
while (size > 0) {
long ret = write_in_full(fd, buf, size);
}
close(fd);
+ free(path);
}
static void write_note_to_worktree(const unsigned char *obj,
return conflicts ? -1 : 1;
}
-void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
- const struct strbuf *msg, unsigned char *result_sha1)
-{
- unsigned char tree_sha1[20];
-
- assert(t->initialized);
-
- if (write_notes_tree(t, tree_sha1))
- die("Failed to write notes tree to database");
-
- if (!parents) {
- /* Deduce parent commit from t->ref */
- unsigned char parent_sha1[20];
- if (!read_ref(t->ref, parent_sha1)) {
- struct commit *parent = lookup_commit(parent_sha1);
- if (!parent || parse_commit(parent))
- die("Failed to find/parse commit %s", t->ref);
- commit_list_insert(parent, &parents);
- }
- /* else: t->ref points to nothing, assume root/orphan commit */
- }
-
- if (commit_tree(msg, tree_sha1, parents, result_sha1, NULL, NULL))
- die("Failed to commit notes tree to database");
-}
-
int notes_merge(struct notes_merge_options *o,
struct notes_tree *local_tree,
unsigned char *result_sha1)
o->local_ref, o->remote_ref);
/* Dereference o->local_ref into local_sha1 */
- if (read_ref_full(o->local_ref, local_sha1, 0, NULL))
+ if (read_ref_full(o->local_ref, 0, local_sha1, NULL))
die("Failed to resolve local notes ref '%s'", o->local_ref);
else if (!check_refname_format(o->local_ref, 0) &&
is_null_sha1(local_sha1))
assert(local && remote);
/* Find merge bases */
- bases = get_merge_bases(local, remote, 1);
+ bases = get_merge_bases(local, remote);
if (!bases) {
base_sha1 = null_sha1;
base_tree_sha1 = EMPTY_TREE_SHA1_BIN;
if (o->verbosity >= 4)
printf("No merge base found; doing history-less merge\n");
} else if (!bases->next) {
- base_sha1 = bases->item->object.sha1;
- base_tree_sha1 = bases->item->tree->object.sha1;
+ base_sha1 = bases->item->object.oid.hash;
+ base_tree_sha1 = bases->item->tree->object.oid.hash;
if (o->verbosity >= 4)
printf("One merge base found (%.7s)\n",
sha1_to_hex(base_sha1));
} else {
/* TODO: How to handle multiple merge-bases? */
- base_sha1 = bases->item->object.sha1;
- base_tree_sha1 = bases->item->tree->object.sha1;
+ base_sha1 = bases->item->object.oid.hash;
+ base_tree_sha1 = bases->item->tree->object.oid.hash;
if (o->verbosity >= 3)
printf("Multiple merge bases found. Using the first "
"(%.7s)\n", sha1_to_hex(base_sha1));
if (o->verbosity >= 4)
printf("Merging remote commit %.7s into local commit %.7s with "
- "merge-base %.7s\n", sha1_to_hex(remote->object.sha1),
- sha1_to_hex(local->object.sha1),
+ "merge-base %.7s\n", oid_to_hex(&remote->object.oid),
+ oid_to_hex(&local->object.oid),
sha1_to_hex(base_sha1));
- if (!hashcmp(remote->object.sha1, base_sha1)) {
+ if (!hashcmp(remote->object.oid.hash, base_sha1)) {
/* Already merged; result == local commit */
if (o->verbosity >= 2)
printf("Already up-to-date!\n");
- hashcpy(result_sha1, local->object.sha1);
+ hashcpy(result_sha1, local->object.oid.hash);
goto found_result;
}
- if (!hashcmp(local->object.sha1, base_sha1)) {
+ if (!hashcmp(local->object.oid.hash, base_sha1)) {
/* Fast-forward; result == remote commit */
if (o->verbosity >= 2)
printf("Fast-forward\n");
- hashcpy(result_sha1, remote->object.sha1);
+ hashcpy(result_sha1, remote->object.oid.hash);
goto found_result;
}
- result = merge_from_diffs(o, base_tree_sha1, local->tree->object.sha1,
- remote->tree->object.sha1, local_tree);
+ result = merge_from_diffs(o, base_tree_sha1, local->tree->object.oid.hash,
+ remote->tree->object.oid.hash, local_tree);
if (result != 0) { /* non-trivial merge (with or without conflicts) */
/* Commit (partial) result */
struct commit_list *parents = NULL;
commit_list_insert(remote, &parents); /* LIFO order */
commit_list_insert(local, &parents);
- create_notes_commit(local_tree, parents, &o->commit_msg,
+ create_notes_commit(local_tree, parents,
+ o->commit_msg.buf, o->commit_msg.len,
result_sha1);
}
DIR *dir;
struct dirent *e;
struct strbuf path = STRBUF_INIT;
- char *msg = strstr(partial_commit->buffer, "\n\n");
- struct strbuf sb_msg = STRBUF_INIT;
+ const char *buffer = get_commit_buffer(partial_commit, NULL);
+ const char *msg = strstr(buffer, "\n\n");
int baselen;
strbuf_addstr(&path, git_path(NOTES_MERGE_WORKTREE));
strbuf_setlen(&path, baselen);
}
- strbuf_attach(&sb_msg, msg, strlen(msg), strlen(msg) + 1);
- create_notes_commit(partial_tree, partial_commit->parents, &sb_msg,
- result_sha1);
+ create_notes_commit(partial_tree, partial_commit->parents,
+ msg, strlen(msg), result_sha1);
+ unuse_commit_buffer(partial_commit, buffer);
if (o->verbosity >= 4)
printf("Finalized notes merge commit: %s\n",
sha1_to_hex(result_sha1));