X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=builtin-mktree.c;h=098395fda1932674e29f8d2cb332c722a6cb275f;hb=8918f5cf962866c2bb36bdf6b417bfcdb523280a;hp=17cdb3d63a79cbf113151d53b6d2bf280a1045a3;hpb=ad87b5dd93f61a046236febf1becc78d0ad6452a;p=git.git diff --git a/builtin-mktree.c b/builtin-mktree.c index 17cdb3d63..098395fda 100644 --- a/builtin-mktree.c +++ b/builtin-mktree.c @@ -63,15 +63,16 @@ static void write_tree(unsigned char *sha1) } static const char *mktree_usage[] = { - "git mktree [-z]", + "git mktree [-z] [--missing] [--batch]", NULL }; -static void mktree_line(char *buf, size_t len, int line_termination) +static void mktree_line(char *buf, size_t len, int line_termination, int allow_missing) { char *ptr, *ntr; unsigned mode; - enum object_type type; + enum object_type mode_type; /* object type derived from mode */ + enum object_type obj_type; /* object type derived from sha */ char *path; unsigned char sha1[20]; @@ -91,17 +92,11 @@ static void mktree_line(char *buf, size_t len, int line_termination) die("input format error: %s", buf); /* It is perfectly normal if we do not have a commit from a submodule */ - if (!S_ISGITLINK(mode)) - type = sha1_object_info(sha1, NULL); - else - type = OBJ_COMMIT; + if (S_ISGITLINK(mode)) + allow_missing = 1; - if (type < 0) - die("object %s unavailable", sha1_to_hex(sha1)); *ntr++ = 0; /* now at the beginning of SHA1 */ - if (type != type_from_string(ptr)) - die("object type %s mismatch (%s)", ptr, typename(type)); path = ntr + 41; /* at the beginning of name */ if (line_termination && path[0] == '"') { @@ -110,6 +105,37 @@ static void mktree_line(char *buf, size_t len, int line_termination) die("invalid quoting"); path = strbuf_detach(&p_uq, NULL); } + + /* + * Object type is redundantly derivable three ways. + * These should all agree. + */ + mode_type = object_type(mode); + if (mode_type != type_from_string(ptr)) { + die("entry '%s' object type (%s) doesn't match mode type (%s)", + path, ptr, typename(mode_type)); + } + + /* Check the type of object identified by sha1 */ + obj_type = sha1_object_info(sha1, NULL); + if (obj_type < 0) { + if (allow_missing) { + ; /* no problem - missing objects are presumed to be of the right type */ + } else { + die("entry '%s' object %s is unavailable", path, sha1_to_hex(sha1)); + } + } else { + if (obj_type != mode_type) { + /* + * The object exists but is of the wrong type. + * This is a problem regardless of allow_missing + * because the new tree entry will never be correct. + */ + die("entry '%s' object %s is a %s but specified type was (%s)", + path, sha1_to_hex(sha1), typename(obj_type), typename(mode_type)); + } + } + append_to_tree(mode, sha1, path); } @@ -118,19 +144,47 @@ int cmd_mktree(int ac, const char **av, const char *prefix) struct strbuf sb = STRBUF_INIT; unsigned char sha1[20]; int line_termination = '\n'; + int allow_missing = 0; + int is_batch_mode = 0; + int got_eof = 0; + const struct option option[] = { OPT_SET_INT('z', NULL, &line_termination, "input is NUL terminated", '\0'), + OPT_SET_INT( 0 , "missing", &allow_missing, "allow missing objects", 1), + OPT_SET_INT( 0 , "batch", &is_batch_mode, "allow creation of more than one tree", 1), OPT_END() }; - ac = parse_options(ac, av, option, mktree_usage, 0); - - while (strbuf_getline(&sb, stdin, line_termination) != EOF) - mktree_line(sb.buf, sb.len, line_termination); - + ac = parse_options(ac, av, prefix, option, mktree_usage, 0); + + while (!got_eof) { + while (1) { + if (strbuf_getline(&sb, stdin, line_termination) == EOF) { + got_eof = 1; + break; + } + if (sb.buf[0] == '\0') { + /* empty lines denote tree boundaries in batch mode */ + if (is_batch_mode) + break; + die("input format error: (blank line only valid in batch mode)"); + } + mktree_line(sb.buf, sb.len, line_termination, allow_missing); + } + if (is_batch_mode && got_eof && used < 1) { + /* + * Execution gets here if the last tree entry is terminated with a + * new-line. The final new-line has been made optional to be + * consistent with the original non-batch behaviour of mktree. + */ + ; /* skip creating an empty tree */ + } else { + write_tree(sha1); + puts(sha1_to_hex(sha1)); + fflush(stdout); + } + used=0; /* reset tree entry buffer for re-use in batch mode */ + } strbuf_release(&sb); - - write_tree(sha1); - puts(sha1_to_hex(sha1)); exit(0); }