diff --git a/Documentation/git-write-tree.txt b/Documentation/git-write-tree.txt index 77e12cb949..c85fa89c30 100644 --- a/Documentation/git-write-tree.txt +++ b/Documentation/git-write-tree.txt @@ -8,7 +8,7 @@ git-write-tree - Creates a tree object from the current index SYNOPSIS -------- -'git-write-tree' [--missing-ok] +'git-write-tree' [--missing-ok] [--prefix=/] DESCRIPTION ----------- @@ -30,6 +30,12 @@ OPTIONS directory exist in the object database. This option disables this check. +--prefix=/:: + Writes a tree object that represents a subdirectory + ``. This can be used to write the tree object + for a subproject that is in the named subdirectory. + + Author ------ Written by Linus Torvalds diff --git a/cache-tree.c b/cache-tree.c index e452238ba7..dae4399c1e 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -525,3 +525,29 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size) return NULL; /* not the whole tree */ return read_one(&buffer, &size); } + +struct cache_tree *cache_tree_find(struct cache_tree *it, const char *path) +{ + while (*path) { + const char *slash; + struct cache_tree_sub *sub; + + slash = strchr(path, '/'); + if (!slash) + slash = path + strlen(path); + /* between path and slash is the name of the + * subtree to look for. + */ + sub = find_subtree(it, path, slash - path, 0); + if (!sub) + return NULL; + it = sub->cache_tree; + if (slash) + while (*slash && *slash == '/') + slash++; + if (!slash || !*slash) + return it; /* prefix ended with slashes */ + path = slash; + } + return it; +} diff --git a/cache-tree.h b/cache-tree.h index 72c64801f5..119407e3a1 100644 --- a/cache-tree.h +++ b/cache-tree.h @@ -28,4 +28,6 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size); int cache_tree_fully_valid(struct cache_tree *); int cache_tree_update(struct cache_tree *, struct cache_entry **, int, int, int); +struct cache_tree *cache_tree_find(struct cache_tree *, const char *); + #endif diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index cf33989b56..2c9bbb59b0 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -195,6 +195,20 @@ test_expect_success \ 'git-ls-tree -r output for a known tree.' \ 'diff current expected' +test_expect_success \ + 'writing partial tree out with git-write-tree --prefix.' \ + 'ptree=$(git-write-tree --prefix=path3)' +test_expect_success \ + 'validate object ID for a known tree.' \ + 'test "$ptree" = 21ae8269cacbe57ae09138dcc3a2887f904d02b3' + +test_expect_success \ + 'writing partial tree out with git-write-tree --prefix.' \ + 'ptree=$(git-write-tree --prefix=path3/subp3)' +test_expect_success \ + 'validate object ID for a known tree.' \ + 'test "$ptree" = 3c5e5399f3a333eddecce7a9b9465b63f65f51e2' + ################################################################ rm .git/index test_expect_success \ diff --git a/write-tree.c b/write-tree.c index 7a4f691d8a..895e7a359d 100644 --- a/write-tree.c +++ b/write-tree.c @@ -8,8 +8,10 @@ #include "cache-tree.h" static int missing_ok = 0; +static char *prefix = NULL; -static const char write_tree_usage[] = "git-write-tree [--missing-ok]"; +static const char write_tree_usage[] = +"git-write-tree [--missing-ok] [--prefix=/]"; static struct cache_file cache_file; @@ -21,13 +23,18 @@ int main(int argc, char **argv) newfd = hold_index_file_for_update(&cache_file, get_index_file()); entries = read_cache(); - if (argc == 2) { - if (!strcmp(argv[1], "--missing-ok")) + + while (1 < argc) { + char *arg = argv[1]; + if (!strcmp(arg, "--missing-ok")) missing_ok = 1; + else if (!strncmp(arg, "--prefix=", 9)) + prefix = arg + 9; else die(write_tree_usage); + argc--; argv++; } - + if (argc > 2) die("too many options"); @@ -54,6 +61,12 @@ int main(int argc, char **argv) * performance penalty and not a big deal. */ } - printf("%s\n", sha1_to_hex(active_cache_tree->sha1)); + if (prefix) { + struct cache_tree *subtree = + cache_tree_find(active_cache_tree, prefix); + printf("%s\n", sha1_to_hex(subtree->sha1)); + } + else + printf("%s\n", sha1_to_hex(active_cache_tree->sha1)); return 0; }