X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=write-tree.c;h=bd07da6183b25470b00b9a2eedef29b7275760ec;hb=HEAD;hp=e2bbbd261e76800df8882c2bb9f15dda953804d2;hpb=ccc4feb579265266d0a4a73c0c9443ecc0c26ce3;p=git.git diff --git a/write-tree.c b/write-tree.c index e2bbbd26..bd07da61 100644 --- a/write-tree.c +++ b/write-tree.c @@ -4,111 +4,69 @@ * Copyright (C) Linus Torvalds, 2005 */ #include "cache.h" +#include "tree.h" +#include "cache-tree.h" -static int check_valid_sha1(unsigned char *sha1) -{ - char *filename = sha1_file_name(sha1); - int ret; - - /* If we were anal, we'd check that the sha1 of the contents actually matches */ - ret = access(filename, R_OK); - if (ret) - perror(filename); - return ret; -} - -static int prepend_integer(char *buffer, unsigned val, int i) -{ - buffer[--i] = '\0'; - do { - buffer[--i] = '0' + (val % 10); - val /= 10; - } while (val); - return i; -} - -#define ORIG_OFFSET (40) /* Enough space to add the header of "tree \0" */ - -static int write_tree(struct cache_entry **cachep, int maxentries, const char *base, int baselen, unsigned char *returnsha1) -{ - unsigned char subdir_sha1[20]; - unsigned long size, offset; - char *buffer; - int i, nr; - - /* Guess at some random initial size */ - size = 8192; - buffer = malloc(size); - offset = ORIG_OFFSET; - - nr = 0; - do { - struct cache_entry *ce = cachep[nr]; - const char *pathname = ce->name, *filename, *dirname; - int pathlen = ce_namelen(ce), entrylen; - unsigned char *sha1; - unsigned int mode; - - /* Did we hit the end of the directory? Return how many we wrote */ - if (baselen >= pathlen || memcmp(base, pathname, baselen)) - break; - - sha1 = ce->sha1; - mode = ntohl(ce->ce_mode); +static int missing_ok = 0; +static char *prefix = NULL; - /* Do we have _further_ subdirectories? */ - filename = pathname + baselen; - dirname = strchr(filename, '/'); - if (dirname) { - int subdir_written; +static const char write_tree_usage[] = +"git-write-tree [--missing-ok] [--prefix=/]"; - subdir_written = write_tree(cachep + nr, maxentries - nr, pathname, dirname-pathname+1, subdir_sha1); - nr += subdir_written; - - /* Now we need to write out the directory entry into this tree.. */ - mode = S_IFDIR; - pathlen = dirname - pathname; - - /* ..but the directory entry doesn't count towards the total count */ - nr--; - sha1 = subdir_sha1; - } - - if (check_valid_sha1(sha1) < 0) - exit(1); - - entrylen = pathlen - baselen; - if (offset + entrylen + 100 > size) { - size = alloc_nr(offset + entrylen + 100); - buffer = realloc(buffer, size); - } - offset += sprintf(buffer + offset, "%o %.*s", mode, entrylen, filename); - buffer[offset++] = 0; - memcpy(buffer + offset, sha1, 20); - offset += 20; - nr++; - } while (nr < maxentries); - - i = prepend_integer(buffer, offset - ORIG_OFFSET, ORIG_OFFSET); - i -= 5; - memcpy(buffer+i, "tree ", 5); - - buffer += i; - offset -= i; - - write_sha1_file(buffer, offset, returnsha1); - return nr; -} +static struct lock_file lock_file; int main(int argc, char **argv) { - int entries = read_cache(); - unsigned char sha1[20]; - - if (entries <= 0) - die("write-tree: no cache contents to write"); - if (write_tree(active_cache, entries, "", 0, sha1) != entries) - die("write-tree: internal error"); - printf("%s\n", sha1_to_hex(sha1)); + int entries, was_valid, newfd; + + setup_git_directory(); + + newfd = hold_lock_file_for_update(&lock_file, get_index_file()); + entries = read_cache(); + + 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"); + + if (entries < 0) + die("git-write-tree: error reading cache"); + + if (!active_cache_tree) + active_cache_tree = cache_tree(); + + was_valid = cache_tree_fully_valid(active_cache_tree); + if (!was_valid) { + if (cache_tree_update(active_cache_tree, + active_cache, active_nr, + missing_ok, 0) < 0) + die("git-write-tree: error building trees"); + if (0 <= newfd) { + if (!write_cache(newfd, active_cache, active_nr)) + commit_lock_file(&lock_file); + } + /* Not being able to write is fine -- we are only interested + * in updating the cache-tree part, and if the next caller + * ends up using the old index with unupdated cache-tree part + * it misses the work we did here, but that is just a + * performance penalty and not a big deal. + */ + } + 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; }