read-tree.con commit Make "update-cache" a bit friendlier to use (and harder to mis-use). (121481a)
   1/*
   2 * GIT - The information manager from hell
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 */
   6#include "cache.h"
   7
   8static int read_one_entry(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode)
   9{
  10        int len = strlen(pathname);
  11        unsigned int size = cache_entry_size(baselen + len);
  12        struct cache_entry *ce = malloc(size);
  13
  14        memset(ce, 0, size);
  15
  16        ce->st_mode = mode;
  17        ce->namelen = baselen + len;
  18        memcpy(ce->name, base, baselen);
  19        memcpy(ce->name + baselen, pathname, len+1);
  20        memcpy(ce->sha1, sha1, 20);
  21        return add_cache_entry(ce, 1);
  22}
  23
  24static int read_tree(unsigned char *sha1, const char *base, int baselen)
  25{
  26        void *buffer;
  27        unsigned long size;
  28        char type[20];
  29
  30        buffer = read_sha1_file(sha1, type, &size);
  31        if (!buffer)
  32                return -1;
  33        if (strcmp(type, "tree"))
  34                return -1;
  35        while (size) {
  36                int len = strlen(buffer)+1;
  37                unsigned char *sha1 = buffer + len;
  38                char *path = strchr(buffer, ' ')+1;
  39                unsigned int mode;
  40
  41                if (size < len + 20 || sscanf(buffer, "%o", &mode) != 1)
  42                        return -1;
  43
  44                buffer = sha1 + 20;
  45                size -= len + 20;
  46
  47                if (S_ISDIR(mode)) {
  48                        int retval;
  49                        int pathlen = strlen(path);
  50                        char *newbase = malloc(baselen + 1 + pathlen);
  51                        memcpy(newbase, base, baselen);
  52                        memcpy(newbase + baselen, path, pathlen);
  53                        newbase[baselen + pathlen] = '/';
  54                        retval = read_tree(sha1, newbase, baselen + pathlen + 1);
  55                        free(newbase);
  56                        if (retval)
  57                                return -1;
  58                        continue;
  59                }
  60                if (read_one_entry(sha1, base, baselen, path, mode) < 0)
  61                        return -1;
  62        }
  63        return 0;
  64}
  65
  66int main(int argc, char **argv)
  67{
  68        int i, newfd;
  69        unsigned char sha1[20];
  70
  71        newfd = open(".dircache/index.lock", O_RDWR | O_CREAT | O_EXCL, 0600);
  72        if (newfd < 0)
  73                usage("unable to create new cachefile");
  74
  75        for (i = 1; i < argc; i++) {
  76                const char *arg = argv[i];
  77
  78                /* "-m" stands for "merge" current directory cache */
  79                if (!strcmp(arg, "-m")) {
  80                        if (active_cache) {
  81                                fprintf(stderr, "read-tree: cannot merge old cache on top of new\n");
  82                                goto out;
  83                        }
  84                        if (read_cache() < 0) {
  85                                fprintf(stderr, "read-tree: corrupt directory cache\n");
  86                                goto out;
  87                        }
  88                        continue;
  89                }
  90                if (get_sha1_hex(arg, sha1) < 0) {
  91                        fprintf(stderr, "read-tree [-m] <sha1>\n");
  92                        goto out;
  93                }
  94                if (read_tree(sha1, "", 0) < 0) {
  95                        fprintf(stderr, "failed to unpack tree object %s\n", arg);
  96                        goto out;
  97                }
  98        }
  99        if (!write_cache(newfd, active_cache, active_nr) && !rename(".dircache/index.lock", ".dircache/index"))
 100                return 0;
 101
 102out:
 103        unlink(".dircache/index.lock");
 104        exit(1);
 105}