- int baselen = strlen(base);
- char *newbase = xmalloc(baselen + pathlen + 2);
- memcpy(newbase, base, baselen);
- memcpy(newbase + baselen, path, pathlen);
- memcpy(newbase + baselen + pathlen, "/", 2);
- return newbase;
-}
-
-static void show_file(const char *prefix, void *tree, unsigned long size, const char *base);
-
-/* A whole sub-tree went away or appeared */
-static void show_tree(const char *prefix, void *tree, unsigned long size, const char *base)
-{
- while (size) {
- show_file(prefix, tree, size, base);
- update_tree_entry(&tree, &size);
- }
-}
-
-/* A file entry went away or appeared */
-static void show_file(const char *prefix, void *tree, unsigned long size, const char *base)
-{
- unsigned mode;
- const char *path;
- const unsigned char *sha1 = extract(tree, size, &path, &mode);
-
- if (header) {
- printf("%s", header);
- header = NULL;
- }
-
- if (silent)
- return;
-
- if (recursive && S_ISDIR(mode)) {
- char type[20];
- unsigned long size;
- char *newbase = malloc_base(base, path, strlen(path));
- void *tree;
-
- tree = read_sha1_file(sha1, type, &size);
- if (!tree || strcmp(type, "tree"))
- die("corrupt tree sha %s", sha1_to_hex(sha1));
-
- show_tree(prefix, tree, size, newbase);
-
- free(tree);
- free(newbase);
- return;
- }
-
- if (generate_patch) {
- if (!S_ISDIR(mode))
- diff_addremove(prefix[0], mode, sha1, base, path);
- }
- else
- printf("%s%06o\t%s\t%s\t%s%s%c", prefix, mode,
- S_ISDIR(mode) ? "tree" : "blob",
- sha1_to_hex(sha1), base, path,
- line_termination);
-}
-
-static int compare_tree_entry(void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base)
-{
- unsigned mode1, mode2;
- const char *path1, *path2;
- const unsigned char *sha1, *sha2;
- int cmp, pathlen1, pathlen2;
- char old_sha1_hex[50];
-
- sha1 = extract(tree1, size1, &path1, &mode1);
- sha2 = extract(tree2, size2, &path2, &mode2);
-
- pathlen1 = strlen(path1);
- pathlen2 = strlen(path2);
- cmp = cache_name_compare(path1, pathlen1, path2, pathlen2);
- if (cmp < 0) {
- show_file("-", tree1, size1, base);
- return -1;
- }
- if (cmp > 0) {
- show_file("+", tree2, size2, base);
- return 1;
- }
- if (!memcmp(sha1, sha2, 20) && mode1 == mode2)
- return 0;
-
- /*
- * If the filemode has changed to/from a directory from/to a regular
- * file, we need to consider it a remove and an add.
- */
- if (S_ISDIR(mode1) != S_ISDIR(mode2)) {
- show_file("-", tree1, size1, base);
- show_file("+", tree2, size2, base);