summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Shawn O. Pearce <spearce@spearce.org>2007-01-11 22:21:38 -0500
committerLibravatar Shawn O. Pearce <spearce@spearce.org>2007-01-14 02:15:12 -0500
commit62b6f48388faf0ac2432a07cfc53aa904c591f8f (patch)
tree2dfad5f3e00bb1d67a33556104f93f60451aafa9
parentFix repository corruption when using marks for modified blobs. (diff)
downloadtgif-62b6f48388faf0ac2432a07cfc53aa904c591f8f.tar.xz
Support creation of merge commits in fast-import.
Some importers are able to determine when branch merges occurred within their source data. In these cases they will want to supply the correct commits to fast-import so that a proper merge commit will exist in Git. This is now supported by supplying a 'merge ' command after the commit message and optional from command. A merge is not actually performed by fast-import, its assumed that the frontend performed any sort of merging activity already and that fast-import should simply be storing its result. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
-rw-r--r--fast-import.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/fast-import.c b/fast-import.c
index e9a46c6c3a..15db4b39d1 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -20,6 +20,7 @@ Format of STDIN stream:
'committer' sp name '<' email '>' ts tz lf
commit_msg
('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
+ ('merge' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)*
file_change*
lf;
commit_msg ::= data;
@@ -202,6 +203,11 @@ struct dbuf
size_t capacity;
};
+struct hash_list
+{
+ struct hash_list *next;
+ unsigned char sha1[20];
+};
/* Stats and misc. counters */
static unsigned long max_depth = 10;
@@ -1502,6 +1508,48 @@ static void cmd_from(struct branch *b)
read_next_command();
}
+static struct hash_list* cmd_merge(unsigned int *count)
+{
+ struct hash_list *list = NULL, *n, *e;
+ const char *from, *endp;
+ char *str_uq;
+ struct branch *s;
+
+ *count = 0;
+ while (!strncmp("merge ", command_buf.buf, 6)) {
+ from = strchr(command_buf.buf, ' ') + 1;
+ str_uq = unquote_c_style(from, &endp);
+ if (str_uq) {
+ if (*endp)
+ die("Garbage after string in: %s", command_buf.buf);
+ from = str_uq;
+ }
+
+ n = xmalloc(sizeof(*n));
+ s = lookup_branch(from);
+ if (s)
+ hashcpy(n->sha1, s->sha1);
+ else if (*from == ':') {
+ unsigned long idnum = strtoul(from + 1, NULL, 10);
+ struct object_entry *oe = find_mark(idnum);
+ if (oe->type != OBJ_COMMIT)
+ die("Mark :%lu not a commit", idnum);
+ hashcpy(n->sha1, oe->sha1);
+ } else if (get_sha1(from, n->sha1))
+ die("Invalid ref name or SHA1 expression: %s", from);
+
+ n->next = NULL;
+ if (list)
+ e->next = n;
+ else
+ list = n;
+ e = n;
+ *count++;
+ read_next_command();
+ }
+ return list;
+}
+
static void cmd_new_commit()
{
struct branch *b;
@@ -1512,6 +1560,8 @@ static void cmd_new_commit()
char *sp;
char *author = NULL;
char *committer = NULL;
+ struct hash_list *merge_list = NULL;
+ unsigned int merge_count;
/* Obtain the branch name from the rest of our command */
sp = strchr(command_buf.buf, ' ') + 1;
@@ -1542,6 +1592,7 @@ static void cmd_new_commit()
msg = cmd_data(&msglen);
read_next_command();
cmd_from(b);
+ merge_list = cmd_merge(&merge_count);
/* ensure the branch is active/loaded */
if (!b->branch_tree.tree || !max_active_branches) {
@@ -1567,6 +1618,7 @@ static void cmd_new_commit()
hashcpy(b->branch_tree.versions[0].sha1,
b->branch_tree.versions[1].sha1);
size_dbuf(&new_data, 97 + msglen
+ + merge_count * 49
+ (author
? strlen(author) + strlen(committer)
: 2 * strlen(committer)));
@@ -1575,6 +1627,12 @@ static void cmd_new_commit()
sha1_to_hex(b->branch_tree.versions[1].sha1));
if (!is_null_sha1(b->sha1))
sp += sprintf(sp, "parent %s\n", sha1_to_hex(b->sha1));
+ while (merge_list) {
+ struct hash_list *next = merge_list->next;
+ sp += sprintf(sp, "parent %s\n", sha1_to_hex(merge_list->sha1));
+ free(merge_list);
+ merge_list = next;
+ }
if (author)
sp += sprintf(sp, "%s\n", author);
else