As stated somewhere, the index in narrow repo is also narrowed. When a users are done with his changes and about to commit, the new narrow tree created from index will be grafted back to a base toplevel tree (usually from parent commit). The result is a new toplevel tree with user's changes and suitable for commits. This function does exactly that. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- narrow-tree.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ narrow-tree.h | 2 + 2 files changed, 68 insertions(+), 0 deletions(-) diff --git a/narrow-tree.c b/narrow-tree.c index 46e913d..73d4f22 100644 --- a/narrow-tree.c +++ b/narrow-tree.c @@ -1,4 +1,14 @@ #include "cache.h" +#include "commit.h" +#include "tree.h" +#include "diff.h" +#include "revision.h" +#include "refs.h" +#include "tag.h" +#include "progress.h" +#include "pack.h" +#include "sha1-lookup.h" +#include "csum-file.h" #include "narrow-tree.h" static const char *narrow_prefix; @@ -29,3 +39,59 @@ const char *get_narrow_prefix() { return narrow_prefix; } + +/* + * The opposite of narrow_tree(). Put the subtree back to the original tree. + */ +int join_narrow_tree(const unsigned char *base, + unsigned char *newsha1, + const unsigned char *subtree_sha1, + const char *prefix) +{ + struct tree_desc desc; + struct name_entry entry; + struct strbuf buffer; + enum object_type type; + const char *slash; + char *buf; + int subtree_len; + unsigned long size; + + slash = strchr(prefix, '/'); + subtree_len = slash ? slash - prefix : strlen(prefix); + + buf = read_sha1_file(base, &type, &size); + if (!buf || type != OBJ_TREE) + die("Bad tree %s", sha1_to_hex(base)); + + init_tree_desc(&desc, buf, size); + strbuf_init(&buffer, 8192); + while (tree_entry(&desc, &entry)) { + strbuf_addf(&buffer, "%o %.*s%c", entry.mode, strlen(entry.path), entry.path, '\0'); + + if (S_ISDIR(entry.mode) && + subtree_len == strlen(entry.path) && + !strncmp(entry.path, prefix, subtree_len)) { + if (slash && slash[1]) /* trailing slash does not count */ + join_narrow_tree(entry.sha1, newsha1, + subtree_sha1, slash+1); + else + memcpy(newsha1, subtree_sha1, 20); /* replace the tree */ + + /* FIXME, what if placeholder tree does not exist? */ + + strbuf_add(&buffer, newsha1, 20); + } + else + strbuf_add(&buffer, entry.sha1, 20); + } + + free(buf); + if (write_sha1_file(buffer.buf, buffer.len, tree_type, newsha1)) { + error("Could not write replaced tree for %s", sha1_to_hex(subtree_sha1)); + strbuf_release(&buffer); + return 1; + } + strbuf_release(&buffer); + return 0; +} diff --git a/narrow-tree.h b/narrow-tree.h index aa8c94f..ecb3ded 100644 --- a/narrow-tree.h +++ b/narrow-tree.h @@ -1 +1,3 @@ extern int check_narrow_prefix(); +extern int join_narrow_tree(const unsigned char *base, unsigned char *newsha1, + const unsigned char *subtree_sha1, const char *prefix); -- 1.7.1.rc1.69.g24c2f7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html