These versions assume that the given trees for diff are toplevel trees. They simply go down to find $GIT_DIR/narrow subtree and do diff on those trees instead. diff_tree_sha1 callers must be adapted to use this version to support narrow repos. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- diff.h | 5 ++++ tree-diff.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 0 deletions(-) diff --git a/diff.h b/diff.h index d43da9d..13b4f10 100644 --- a/diff.h +++ b/diff.h @@ -171,6 +171,11 @@ extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new, extern int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_options *opt); +extern int narrow_diff_tree_sha1(const unsigned char *old, const unsigned char *new, + const char *base, struct diff_options *opt); +extern int narrow_diff_root_tree_sha1(const unsigned char *new, const char *base, + struct diff_options *opt); + struct combine_diff_path { struct combine_diff_path *next; int len; diff --git a/tree-diff.c b/tree-diff.c index cd659c6..31b0842 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -433,6 +433,45 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha return retval; } +int narrow_diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base, struct diff_options *opt) +{ + unsigned char old2[20], new2[20]; + char *new_base = NULL; + int retval; + + if (get_narrow_prefix()) { + int len1 = strlen(get_narrow_prefix()); + int len2 = base ? strlen(base) : 0; + unsigned long size; + unsigned char deref_sha1[20]; + + if (len2 && !strncmp(base, get_narrow_prefix(), len1) && + (base[len1] == '/' || base[len1] == '\0')) + ; /* good */ + else { + new_base = xmalloc(len1 + 1 + len2 + 1); + memcpy(new_base, get_narrow_prefix, len1+1); + if (len2) { + new_base[len1] = '/'; + memcpy(new_base+len1+1, base, len2+1); + } + base = new_base; + } + + free(read_object_with_reference(old, tree_type, &size, deref_sha1)); + if (!find_tree(deref_sha1, old2, get_narrow_prefix())) + hashcpy(old2, (const unsigned char *)EMPTY_TREE_SHA1_BIN); + old = old2; + free(read_object_with_reference(new, tree_type, &size, deref_sha1)); + if (!find_tree(deref_sha1, new2, get_narrow_prefix())) + hashcpy(new2, (const unsigned char *)EMPTY_TREE_SHA1_BIN); + new = new2; + } + retval = diff_tree_sha1(old, new, base, opt); + free(new_base); + return retval; +} + int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_options *opt) { int retval; @@ -451,6 +490,41 @@ int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_ return retval; } +int narrow_diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_options *opt) +{ + unsigned char new2[20]; + char *new_base = NULL; + int retval; + + if (get_narrow_prefix()) { + int len1 = strlen(get_narrow_prefix()); + int len2 = base ? strlen(base) : 0; + unsigned long size; + unsigned char deref_sha1[20]; + + if (len2 && !strncmp(base, get_narrow_prefix(), len1) && + (base[len1] == '/' || base[len1] == '\0')) + ; /* good */ + else { + new_base = xmalloc(len1 + 1 + len2 + 1); + memcpy(new_base, get_narrow_prefix, len1+1); + if (len2) { + new_base[len1] = '/'; + memcpy(new_base+len1+1, base, len2+1); + } + base = new_base; + } + + free(read_object_with_reference(new, tree_type, &size, deref_sha1)); + if (!find_tree(deref_sha1, new2, get_narrow_prefix())) + hashcpy(new2, (const unsigned char *)EMPTY_TREE_SHA1_BIN); + new = new2; + } + retval = diff_root_tree_sha1(new, base, opt); + free(new_base); + return retval; +} + static int count_paths(const char **paths) { int i = 0; -- 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