From 633e3556ccbcc7e443f5e9194c4a830181696ef0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 10 May 2009 10:28:18 -0700 Subject: build-in git-mktree Signed-off-by: Junio C Hamano --- Makefile | 2 +- builtin-mktree.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++ builtin.h | 1 + git.c | 1 + mktree.c | 131 ------------------------------------------------------- 5 files changed, 130 insertions(+), 132 deletions(-) create mode 100644 builtin-mktree.c delete mode 100644 mktree.c diff --git a/Makefile b/Makefile index 6e216436c3..9d9f0dac27 100644 --- a/Makefile +++ b/Makefile @@ -332,7 +332,6 @@ PROGRAMS += git-index-pack$X PROGRAMS += git-merge-index$X PROGRAMS += git-merge-tree$X PROGRAMS += git-mktag$X -PROGRAMS += git-mktree$X PROGRAMS += git-pack-redundant$X PROGRAMS += git-patch-id$X PROGRAMS += git-shell$X @@ -586,6 +585,7 @@ BUILTIN_OBJS += builtin-merge-base.o BUILTIN_OBJS += builtin-merge-file.o BUILTIN_OBJS += builtin-merge-ours.o BUILTIN_OBJS += builtin-merge-recursive.o +BUILTIN_OBJS += builtin-mktree.o BUILTIN_OBJS += builtin-mv.o BUILTIN_OBJS += builtin-name-rev.o BUILTIN_OBJS += builtin-pack-objects.o diff --git a/builtin-mktree.c b/builtin-mktree.c new file mode 100644 index 0000000000..3d054272d5 --- /dev/null +++ b/builtin-mktree.c @@ -0,0 +1,127 @@ +/* + * GIT - the stupid content tracker + * + * Copyright (c) Junio C Hamano, 2006, 2009 + */ +#include "builtin.h" +#include "quote.h" +#include "tree.h" + +static struct treeent { + unsigned mode; + unsigned char sha1[20]; + int len; + char name[FLEX_ARRAY]; +} **entries; +static int alloc, used; + +static void append_to_tree(unsigned mode, unsigned char *sha1, char *path) +{ + struct treeent *ent; + int len = strlen(path); + if (strchr(path, '/')) + die("path %s contains slash", path); + + if (alloc <= used) { + alloc = alloc_nr(used); + entries = xrealloc(entries, sizeof(*entries) * alloc); + } + ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1); + ent->mode = mode; + ent->len = len; + hashcpy(ent->sha1, sha1); + memcpy(ent->name, path, len+1); +} + +static int ent_compare(const void *a_, const void *b_) +{ + struct treeent *a = *(struct treeent **)a_; + struct treeent *b = *(struct treeent **)b_; + return base_name_compare(a->name, a->len, a->mode, + b->name, b->len, b->mode); +} + +static void write_tree(unsigned char *sha1) +{ + struct strbuf buf; + size_t size; + int i; + + qsort(entries, used, sizeof(*entries), ent_compare); + for (size = i = 0; i < used; i++) + size += 32 + entries[i]->len; + + strbuf_init(&buf, size); + for (i = 0; i < used; i++) { + struct treeent *ent = entries[i]; + strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0'); + strbuf_add(&buf, ent->sha1, 20); + } + + write_sha1_file(buf.buf, buf.len, tree_type, sha1); +} + +static const char mktree_usage[] = "git mktree [-z]"; + +int cmd_mktree(int ac, const char **av, const char *prefix) +{ + struct strbuf sb = STRBUF_INIT; + struct strbuf p_uq = STRBUF_INIT; + unsigned char sha1[20]; + int line_termination = '\n'; + + while ((1 < ac) && av[1][0] == '-') { + const char *arg = av[1]; + if (!strcmp("-z", arg)) + line_termination = 0; + else + usage(mktree_usage); + ac--; + av++; + } + + while (strbuf_getline(&sb, stdin, line_termination) != EOF) { + char *ptr, *ntr; + unsigned mode; + enum object_type type; + char *path; + + ptr = sb.buf; + /* + * Read non-recursive ls-tree output format: + * mode SP type SP sha1 TAB name + */ + mode = strtoul(ptr, &ntr, 8); + if (ptr == ntr || !ntr || *ntr != ' ') + die("input format error: %s", sb.buf); + ptr = ntr + 1; /* type */ + ntr = strchr(ptr, ' '); + if (!ntr || sb.buf + sb.len <= ntr + 40 || + ntr[41] != '\t' || + get_sha1_hex(ntr + 1, sha1)) + die("input format error: %s", sb.buf); + type = sha1_object_info(sha1, NULL); + 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] == '"') { + strbuf_reset(&p_uq); + if (unquote_c_style(&p_uq, path, NULL)) { + die("invalid quoting"); + } + path = p_uq.buf; + } + + append_to_tree(mode, sha1, path); + } + strbuf_release(&p_uq); + strbuf_release(&sb); + + write_tree(sha1); + puts(sha1_to_hex(sha1)); + exit(0); +} diff --git a/builtin.h b/builtin.h index 425ff8e89b..20427d2963 100644 --- a/builtin.h +++ b/builtin.h @@ -72,6 +72,7 @@ extern int cmd_merge_base(int argc, const char **argv, const char *prefix); extern int cmd_merge_ours(int argc, const char **argv, const char *prefix); extern int cmd_merge_file(int argc, const char **argv, const char *prefix); extern int cmd_merge_recursive(int argc, const char **argv, const char *prefix); +extern int cmd_mktree(int argc, const char **argv, const char *prefix); extern int cmd_mv(int argc, const char **argv, const char *prefix); extern int cmd_name_rev(int argc, const char **argv, const char *prefix); extern int cmd_pack_objects(int argc, const char **argv, const char *prefix); diff --git a/git.c b/git.c index 5a00726d09..7d7f949f0d 100644 --- a/git.c +++ b/git.c @@ -327,6 +327,7 @@ static void handle_internal_command(int argc, const char **argv) { "merge-ours", cmd_merge_ours, RUN_SETUP }, { "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE }, { "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE }, + { "mktree", cmd_mktree, RUN_SETUP }, { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE }, { "name-rev", cmd_name_rev, RUN_SETUP }, { "pack-objects", cmd_pack_objects, RUN_SETUP }, diff --git a/mktree.c b/mktree.c deleted file mode 100644 index 137a0950f6..0000000000 --- a/mktree.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * GIT - the stupid content tracker - * - * Copyright (c) Junio C Hamano, 2006 - */ -#include "cache.h" -#include "quote.h" -#include "tree.h" -#include "exec_cmd.h" - -static struct treeent { - unsigned mode; - unsigned char sha1[20]; - int len; - char name[FLEX_ARRAY]; -} **entries; -static int alloc, used; - -static void append_to_tree(unsigned mode, unsigned char *sha1, char *path) -{ - struct treeent *ent; - int len = strlen(path); - if (strchr(path, '/')) - die("path %s contains slash", path); - - if (alloc <= used) { - alloc = alloc_nr(used); - entries = xrealloc(entries, sizeof(*entries) * alloc); - } - ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1); - ent->mode = mode; - ent->len = len; - hashcpy(ent->sha1, sha1); - memcpy(ent->name, path, len+1); -} - -static int ent_compare(const void *a_, const void *b_) -{ - struct treeent *a = *(struct treeent **)a_; - struct treeent *b = *(struct treeent **)b_; - return base_name_compare(a->name, a->len, a->mode, - b->name, b->len, b->mode); -} - -static void write_tree(unsigned char *sha1) -{ - struct strbuf buf; - size_t size; - int i; - - qsort(entries, used, sizeof(*entries), ent_compare); - for (size = i = 0; i < used; i++) - size += 32 + entries[i]->len; - - strbuf_init(&buf, size); - for (i = 0; i < used; i++) { - struct treeent *ent = entries[i]; - strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0'); - strbuf_add(&buf, ent->sha1, 20); - } - - write_sha1_file(buf.buf, buf.len, tree_type, sha1); -} - -static const char mktree_usage[] = "git mktree [-z]"; - -int main(int ac, char **av) -{ - struct strbuf sb = STRBUF_INIT; - struct strbuf p_uq = STRBUF_INIT; - unsigned char sha1[20]; - int line_termination = '\n'; - - git_extract_argv0_path(av[0]); - - setup_git_directory(); - - while ((1 < ac) && av[1][0] == '-') { - char *arg = av[1]; - if (!strcmp("-z", arg)) - line_termination = 0; - else - usage(mktree_usage); - ac--; - av++; - } - - while (strbuf_getline(&sb, stdin, line_termination) != EOF) { - char *ptr, *ntr; - unsigned mode; - enum object_type type; - char *path; - - ptr = sb.buf; - /* Input is non-recursive ls-tree output format - * mode SP type SP sha1 TAB name - */ - mode = strtoul(ptr, &ntr, 8); - if (ptr == ntr || !ntr || *ntr != ' ') - die("input format error: %s", sb.buf); - ptr = ntr + 1; /* type */ - ntr = strchr(ptr, ' '); - if (!ntr || sb.buf + sb.len <= ntr + 40 || - ntr[41] != '\t' || - get_sha1_hex(ntr + 1, sha1)) - die("input format error: %s", sb.buf); - type = sha1_object_info(sha1, NULL); - 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] == '"') { - strbuf_reset(&p_uq); - if (unquote_c_style(&p_uq, path, NULL)) { - die("invalid quoting"); - } - path = p_uq.buf; - } - - append_to_tree(mode, sha1, path); - } - strbuf_release(&p_uq); - strbuf_release(&sb); - - write_tree(sha1); - puts(sha1_to_hex(sha1)); - exit(0); -} -- cgit v1.2.3 From 1fdee85c8844a2cbfdf2f4c0a9c0964b78beb37e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 10 May 2009 10:31:56 -0700 Subject: mktree: use parse-options Signed-off-by: Junio C Hamano --- builtin-mktree.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/builtin-mktree.c b/builtin-mktree.c index 3d054272d5..2b3145bc72 100644 --- a/builtin-mktree.c +++ b/builtin-mktree.c @@ -6,6 +6,7 @@ #include "builtin.h" #include "quote.h" #include "tree.h" +#include "parse-options.h" static struct treeent { unsigned mode; @@ -61,7 +62,10 @@ static void write_tree(unsigned char *sha1) write_sha1_file(buf.buf, buf.len, tree_type, sha1); } -static const char mktree_usage[] = "git mktree [-z]"; +static const char *mktree_usage[] = { + "git mktree [-z]", + NULL +}; int cmd_mktree(int ac, const char **av, const char *prefix) { @@ -69,16 +73,12 @@ int cmd_mktree(int ac, const char **av, const char *prefix) struct strbuf p_uq = STRBUF_INIT; unsigned char sha1[20]; int line_termination = '\n'; + const struct option option[] = { + OPT_SET_INT('z', NULL, &line_termination, "input is NUL terminated", '\0'), + OPT_END() + }; - while ((1 < ac) && av[1][0] == '-') { - const char *arg = av[1]; - if (!strcmp("-z", arg)) - line_termination = 0; - else - usage(mktree_usage); - ac--; - av++; - } + ac = parse_options(ac, av, option, mktree_usage, 0); while (strbuf_getline(&sb, stdin, line_termination) != EOF) { char *ptr, *ntr; -- cgit v1.2.3 From fe0bb5f7bce3dbcc32325c74e693a726d0c2808b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 10 May 2009 10:41:22 -0700 Subject: builtin-mktree.c: use a helper function to handle one line of input The main() function used to do the whole thing; this moves the handling of a single input line to a separate function to make it easier to read. Signed-off-by: Junio C Hamano --- builtin-mktree.c | 82 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/builtin-mktree.c b/builtin-mktree.c index 2b3145bc72..133ab4b0f8 100644 --- a/builtin-mktree.c +++ b/builtin-mktree.c @@ -67,10 +67,48 @@ static const char *mktree_usage[] = { NULL }; +static void mktree_line(char *buf, size_t len, int line_termination) +{ + char *ptr, *ntr; + unsigned mode; + enum object_type type; + char *path; + unsigned char sha1[20]; + + ptr = buf; + /* + * Read non-recursive ls-tree output format: + * mode SP type SP sha1 TAB name + */ + mode = strtoul(ptr, &ntr, 8); + if (ptr == ntr || !ntr || *ntr != ' ') + die("input format error: %s", buf); + ptr = ntr + 1; /* type */ + ntr = strchr(ptr, ' '); + if (!ntr || buf + len <= ntr + 40 || + ntr[41] != '\t' || + get_sha1_hex(ntr + 1, sha1)) + die("input format error: %s", buf); + type = sha1_object_info(sha1, NULL); + 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] == '"') { + struct strbuf p_uq = STRBUF_INIT; + if (unquote_c_style(&p_uq, path, NULL)) + die("invalid quoting"); + path = strbuf_detach(&p_uq, NULL); + } + append_to_tree(mode, sha1, path); +} + int cmd_mktree(int ac, const char **av, const char *prefix) { struct strbuf sb = STRBUF_INIT; - struct strbuf p_uq = STRBUF_INIT; unsigned char sha1[20]; int line_termination = '\n'; const struct option option[] = { @@ -80,45 +118,9 @@ int cmd_mktree(int ac, const char **av, const char *prefix) ac = parse_options(ac, av, option, mktree_usage, 0); - while (strbuf_getline(&sb, stdin, line_termination) != EOF) { - char *ptr, *ntr; - unsigned mode; - enum object_type type; - char *path; - - ptr = sb.buf; - /* - * Read non-recursive ls-tree output format: - * mode SP type SP sha1 TAB name - */ - mode = strtoul(ptr, &ntr, 8); - if (ptr == ntr || !ntr || *ntr != ' ') - die("input format error: %s", sb.buf); - ptr = ntr + 1; /* type */ - ntr = strchr(ptr, ' '); - if (!ntr || sb.buf + sb.len <= ntr + 40 || - ntr[41] != '\t' || - get_sha1_hex(ntr + 1, sha1)) - die("input format error: %s", sb.buf); - type = sha1_object_info(sha1, NULL); - 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] == '"') { - strbuf_reset(&p_uq); - if (unquote_c_style(&p_uq, path, NULL)) { - die("invalid quoting"); - } - path = p_uq.buf; - } - - append_to_tree(mode, sha1, path); - } - strbuf_release(&p_uq); + while (strbuf_getline(&sb, stdin, line_termination) != EOF) + mktree_line(sb.buf, sb.len, line_termination); + strbuf_release(&sb); write_tree(sha1); -- cgit v1.2.3 From ad87b5dd93f61a046236febf1becc78d0ad6452a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 10 May 2009 10:45:52 -0700 Subject: mktree: do not barf on a submodule commit It is perfectly normal if a tree entry points at a missing commit as long as the mode of the entry says it is a submodule. Signed-off-by: Junio C Hamano --- builtin-mktree.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/builtin-mktree.c b/builtin-mktree.c index 133ab4b0f8..17cdb3d63a 100644 --- a/builtin-mktree.c +++ b/builtin-mktree.c @@ -89,9 +89,16 @@ static void mktree_line(char *buf, size_t len, int line_termination) ntr[41] != '\t' || get_sha1_hex(ntr + 1, sha1)) die("input format error: %s", buf); - type = sha1_object_info(sha1, NULL); + + /* 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 (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)); -- cgit v1.2.3 From 801cfae8fd683761ae268cab8cec08e4b0f5a35b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 10 May 2009 11:18:59 -0700 Subject: t1010: add mktree test So far mktree (which has always been a quick hack) had no test. At least give it a bit of test coverage. Signed-off-by: Junio C Hamano --- t/t1010-mktree.sh | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100755 t/t1010-mktree.sh diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh new file mode 100755 index 0000000000..4d9b1383c6 --- /dev/null +++ b/t/t1010-mktree.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +test_description='git mktree' + +. ./test-lib.sh + +test_expect_success setup ' + for d in a a. a0 + do + mkdir "$d" && echo "$d/one" >"$d/one" && + git add "$d" + done && + echo one >one && + git add one && + git write-tree >tree && + git ls-tree $(cat tree) >top && + git ls-tree -r $(cat tree) >all && + test_tick && + git commit -q -m one && + H=$(git rev-parse HEAD) && + git update-index --add --cacheinfo 160000 $H sub && + test_tick && + git commit -q -m two && + git rev-parse HEAD^{tree} >tree.withsub && + git ls-tree HEAD >top.withsub && + git ls-tree -r HEAD >all.withsub +' + +test_expect_success 'ls-tree piped to mktree (1)' ' + git mktree actual && + test_cmp tree actual +' + +test_expect_success 'ls-tree piped to mktree (2)' ' + git mktree actual && + test_cmp tree.withsub actual +' + +test_expect_success 'ls-tree output in wrong order given to mktree (1)' ' + perl -e "print reverse <>" actual && + test_cmp tree actual +' + +test_expect_success 'ls-tree output in wrong order given to mktree (2)' ' + perl -e "print reverse <>" actual && + test_cmp tree.withsub actual +' + +test_expect_failure 'mktree reads ls-tree -r output (1)' ' + git mktree actual && + test_cmp tree actual +' + +test_expect_failure 'mktree reads ls-tree -r output (2)' ' + git mktree actual && + test_cmp tree.withsub actual +' + +test_done -- cgit v1.2.3 From 1c64e79a622b43cff2d919632393c51f3fcc4f43 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 10 May 2009 11:30:03 -0700 Subject: mktree --missing: allow missing objects We need to allow input lines that point at objects that we do not have when dealing with submodule entries anyway. This adds an explicit option to allow missing objects of other types, to be consistent with the use of --info-only option to the update-index command and --missing-ok option to the write-tree command. Signed-off-by: Junio C Hamano --- builtin-mktree.c | 13 +++++++++---- t/t1010-mktree.sh | 10 ++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/builtin-mktree.c b/builtin-mktree.c index 17cdb3d63a..e1c9a2701a 100644 --- a/builtin-mktree.c +++ b/builtin-mktree.c @@ -67,7 +67,7 @@ static const char *mktree_usage[] = { 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; @@ -91,10 +91,13 @@ 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)) + if (S_ISGITLINK(mode)) + allow_missing = 1; + + if (!allow_missing) type = sha1_object_info(sha1, NULL); else - type = OBJ_COMMIT; + type = object_type(mode); if (type < 0) die("object %s unavailable", sha1_to_hex(sha1)); @@ -118,15 +121,17 @@ 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; 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_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); + mktree_line(sb.buf, sb.len, line_termination, allow_missing); strbuf_release(&sb); diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh index 4d9b1383c6..9956e3ad62 100755 --- a/t/t1010-mktree.sh +++ b/t/t1010-mktree.sh @@ -10,6 +10,11 @@ test_expect_success setup ' mkdir "$d" && echo "$d/one" >"$d/one" && git add "$d" done && + echo zero >one && + git update-index --add --info-only one && + git write-tree --missing-ok >tree.missing && + git ls-tree $(cat tree.missing) >top.missing && + git ls-tree -r $(cat tree.missing) >all.missing && echo one >one && git add one && git write-tree >tree && @@ -48,6 +53,11 @@ test_expect_success 'ls-tree output in wrong order given to mktree (2)' ' test_cmp tree.withsub actual ' +test_expect_success 'allow missing object with --missing' ' + git mktree --missing actual && + test_cmp tree.missing actual +' + test_expect_failure 'mktree reads ls-tree -r output (1)' ' git mktree actual && test_cmp tree actual -- cgit v1.2.3 From e01662bb5da721d65226f4b173858ea3bf0bde30 Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Thu, 14 May 2009 12:46:03 -0700 Subject: mktree --missing: updated usage message and man page Update usage message in builtin-mktree.c to include '--missing'. Do the same to man page and clarify that the input does not have to be sorted. Signed-off-by: Josh Micich Signed-off-by: Junio C Hamano --- Documentation/git-mktree.txt | 13 ++++++++++--- builtin-mktree.c | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Documentation/git-mktree.txt b/Documentation/git-mktree.txt index af19f06ed7..7336f48bd1 100644 --- a/Documentation/git-mktree.txt +++ b/Documentation/git-mktree.txt @@ -8,12 +8,13 @@ git-mktree - Build a tree-object from ls-tree formatted text SYNOPSIS -------- -'git mktree' [-z] +'git mktree' [-z] [--missing] DESCRIPTION ----------- -Reads standard input in non-recursive `ls-tree` output format, -and creates a tree object. The object name of the tree object +Reads standard input in non-recursive `ls-tree` output format, and creates +a tree object. The order of the tree entries is normalised by mktree so +pre-sorting the input is not required. The object name of the tree object built is written to the standard output. OPTIONS @@ -21,6 +22,12 @@ OPTIONS -z:: Read the NUL-terminated `ls-tree -z` output instead. +--missing:: + Allow missing objects. The default behaviour (without this option) + is to verify that each tree entry's sha1 identifies an existing + object. This option has no effect on the treatment of gitlink entries + (aka "submodules") which are always allowed to be missing. + Author ------ Written by Junio C Hamano diff --git a/builtin-mktree.c b/builtin-mktree.c index e1c9a2701a..5ff04753b7 100644 --- a/builtin-mktree.c +++ b/builtin-mktree.c @@ -63,7 +63,7 @@ static void write_tree(unsigned char *sha1) } static const char *mktree_usage[] = { - "git mktree [-z]", + "git mktree [-z] [--missing]", NULL }; -- cgit v1.2.3 From f1cf2d8b1467b5973f249703b31e709eaede97ad Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Thu, 14 May 2009 12:51:15 -0700 Subject: mktree --batch: build more than one tree object This option works in a similar way to the '--batch' option of 'git cat-file'. It enables creation of many tree objects with a single process. The change was motivated by performance considerations in applications that need to create many tree objects. A non-rigorous test showed tree creation times improved from (roughly) 200ms to 50ms. Signed-off-by: Josh Micich Signed-off-by: Junio C Hamano --- Documentation/git-mktree.txt | 8 +++++++- builtin-mktree.c | 40 +++++++++++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/Documentation/git-mktree.txt b/Documentation/git-mktree.txt index 7336f48bd1..81e3326772 100644 --- a/Documentation/git-mktree.txt +++ b/Documentation/git-mktree.txt @@ -8,7 +8,7 @@ git-mktree - Build a tree-object from ls-tree formatted text SYNOPSIS -------- -'git mktree' [-z] [--missing] +'git mktree' [-z] [--missing] [--batch] DESCRIPTION ----------- @@ -28,6 +28,12 @@ OPTIONS object. This option has no effect on the treatment of gitlink entries (aka "submodules") which are always allowed to be missing. +--batch:: + Allow building of more than one tree object before exiting. Each + tree is separated by as single blank line. The final new-line is + optional. Note - if the '-z' option is used, lines are terminated + with NUL. + Author ------ Written by Junio C Hamano diff --git a/builtin-mktree.c b/builtin-mktree.c index 5ff04753b7..73b0abbd8d 100644 --- a/builtin-mktree.c +++ b/builtin-mktree.c @@ -63,7 +63,7 @@ static void write_tree(unsigned char *sha1) } static const char *mktree_usage[] = { - "git mktree [-z] [--missing]", + "git mktree [-z] [--missing] [--batch]", NULL }; @@ -122,20 +122,46 @@ int cmd_mktree(int ac, const char **av, const char *prefix) 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, allow_missing); - + 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); } -- cgit v1.2.3 From 31c8221acb7c7acaea6ce2c680c2985581ce0066 Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Thu, 14 May 2009 15:49:10 -0700 Subject: mktree: validate entry type in input Previously mktree would accept tree entries which had a mismatch between the declared type and the actual type of object. Check the actual type of the object when it is available locally. Signed-off-by: Josh Micich Signed-off-by: Junio C Hamano --- builtin-mktree.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/builtin-mktree.c b/builtin-mktree.c index 73b0abbd8d..dc4f1a711d 100644 --- a/builtin-mktree.c +++ b/builtin-mktree.c @@ -71,7 +71,8 @@ static void mktree_line(char *buf, size_t len, int line_termination, int allow_m { 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]; @@ -94,17 +95,8 @@ static void mktree_line(char *buf, size_t len, int line_termination, int allow_m if (S_ISGITLINK(mode)) allow_missing = 1; - if (!allow_missing) - type = sha1_object_info(sha1, NULL); - else - type = object_type(mode); - - 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] == '"') { @@ -113,6 +105,37 @@ static void mktree_line(char *buf, size_t len, int line_termination, int allow_m 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); } -- cgit v1.2.3