stream ::= cmd*;
cmd ::= new_blob
- | new_branch
| new_commit
| new_tag
;
file_content;
file_content ::= data;
- new_branch ::= 'branch' sp ref_str lf
- ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
- lf;
-
new_commit ::= 'commit' sp ref_str lf
- mark?
- ('author' sp name '<' email '>' ts tz lf)?
- 'committer' sp name '<' email '>' ts tz lf
- commit_msg
+ ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
+ mark?
+ ('author' sp name '<' email '>' ts tz lf)?
+ 'committer' sp name '<' email '>' ts tz lf
+ commit_msg
file_change*
lf;
commit_msg ::= data;
} else {
char type[20];
buf = read_sha1_file(root->sha1, type, &size);
- if (!buf || !strcmp(type, tree_type))
+ if (!buf || strcmp(type, tree_type))
die("Can't load tree %s", sha1_to_hex(root->sha1));
}
free(p_uq);
}
+static void cmd_from(struct branch *b)
+{
+ const char *from, *endp;
+ char *str_uq;
+ struct branch *s;
+
+ if (strncmp("from ", command_buf.buf, 5))
+ return;
+
+ if (b->last_commit)
+ die("Can't reinitailize branch %s", b->name);
+
+ 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;
+ }
+
+ s = lookup_branch(from);
+ if (b == s)
+ die("Can't create a branch from itself: %s", b->name);
+ else if (s) {
+ memcpy(b->sha1, s->sha1, 20);
+ memcpy(b->branch_tree.sha1, s->branch_tree.sha1, 20);
+ } else if (*from == ':') {
+ unsigned long idnum = strtoul(from + 1, NULL, 10);
+ struct object_entry *oe = find_mark(idnum);
+ unsigned long size;
+ char *buf;
+ if (oe->type != OBJ_COMMIT)
+ die("Mark :%lu not a commit", idnum);
+ memcpy(b->sha1, oe->sha1, 20);
+ buf = unpack_entry(oe->offset, &size);
+ if (!buf || size < 46)
+ die("Not a valid commit: %s", from);
+ if (memcmp("tree ", buf, 5)
+ || get_sha1_hex(buf + 5, b->branch_tree.sha1))
+ die("The commit %s is corrupt", sha1_to_hex(b->sha1));
+ free(buf);
+ } else if (!get_sha1(from, b->sha1)) {
+ if (!memcmp(b->sha1, null_sha1, 20))
+ memcpy(b->branch_tree.sha1, null_sha1, 20);
+ else {
+ unsigned long size;
+ char *buf;
+
+ buf = read_object_with_reference(b->sha1,
+ type_names[OBJ_COMMIT], &size, b->sha1);
+ if (!buf || size < 46)
+ die("Not a valid commit: %s", from);
+ if (memcmp("tree ", buf, 5)
+ || get_sha1_hex(buf + 5, b->branch_tree.sha1))
+ die("The commit %s is corrupt", sha1_to_hex(b->sha1));
+ free(buf);
+ }
+ } else
+ die("Invalid ref name or SHA1 expression: %s", from);
+
+ read_next_command();
+}
+
static void cmd_new_commit()
{
struct branch *b;
}
b = lookup_branch(sp);
if (!b)
- die("Branch not declared: %s", sp);
+ b = new_branch(sp);
if (str_uq)
free(str_uq);
read_next_command();
+ cmd_from(b);
cmd_mark();
if (!strncmp("author ", command_buf.buf, 7)) {
author = strdup(command_buf.buf);
b->last_commit = object_count_by_type[OBJ_COMMIT];
}
-static void cmd_new_branch()
-{
- struct branch *b;
- char *str_uq;
- const char *endp;
- char *sp;
-
- /* Obtain the new branch name from the rest of our command */
- sp = strchr(command_buf.buf, ' ') + 1;
- str_uq = unquote_c_style(sp, &endp);
- if (str_uq) {
- if (*endp)
- die("Garbage after ref in: %s", command_buf.buf);
- sp = str_uq;
- }
- b = new_branch(sp);
- if (str_uq)
- free(str_uq);
- read_next_command();
-
- /* from ... */
- if (!strncmp("from ", command_buf.buf, 5)) {
- const char *from;
- struct branch *s;
-
- 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;
- }
-
- s = lookup_branch(from);
- if (b == s)
- die("Can't create a branch from itself: %s", b->name);
- else if (s) {
- memcpy(b->sha1, s->sha1, 20);
- memcpy(b->branch_tree.sha1, s->branch_tree.sha1, 20);
- } else if (*from == ':') {
- unsigned long idnum = strtoul(from + 1, NULL, 10);
- struct object_entry *oe = find_mark(idnum);
- unsigned long size;
- char *buf;
- if (oe->type != OBJ_COMMIT)
- die("Mark :%lu not a commit", idnum);
- memcpy(b->sha1, oe->sha1, 20);
- buf = unpack_entry(oe->offset, &size);
- if (!buf || size < 46)
- die("Not a valid commit: %s", from);
- if (memcmp("tree ", buf, 5)
- || get_sha1_hex(buf + 5, b->branch_tree.sha1))
- die("The commit %s is corrupt", sha1_to_hex(b->sha1));
- free(buf);
- } else if (!get_sha1(from, b->sha1)) {
- if (!memcmp(b->sha1, null_sha1, 20))
- memcpy(b->branch_tree.sha1, null_sha1, 20);
- else {
- unsigned long size;
- char *buf;
-
- buf = read_object_with_reference(b->sha1,
- type_names[OBJ_COMMIT], &size, b->sha1);
- if (!buf || size < 46)
- die("Not a valid commit: %s", from);
- if (memcmp("tree ", buf, 5)
- || get_sha1_hex(buf + 5, b->branch_tree.sha1))
- die("The commit %s is corrupt", sha1_to_hex(b->sha1));
- free(buf);
- }
- } else
- die("Invalid ref name or SHA1 expression: %s", from);
-
- if (str_uq)
- free(str_uq);
- read_next_command();
- } else {
- memcpy(b->sha1, null_sha1, 20);
- memcpy(b->branch_tree.sha1, null_sha1, 20);
- }
-
- if (command_buf.eof || command_buf.len > 1)
- die("An lf did not terminate the branch command as expected.");
-}
-
static void cmd_new_tag()
{
char *str_uq;
break;
else if (!strcmp("blob", command_buf.buf))
cmd_new_blob();
- else if (!strncmp("branch ", command_buf.buf, 7))
- cmd_new_branch();
else if (!strncmp("commit ", command_buf.buf, 7))
cmd_new_commit();
else if (!strncmp("tag ", command_buf.buf, 4))