read-tree.con commit Make read-tree actually unpack the whole tree. (e497ea2)
   1/*
   2 * GIT - The information manager from hell
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 */
   6#include "cache.h"
   7
   8static void create_directories(const char *path)
   9{
  10        int len = strlen(path);
  11        char *buf = malloc(len + 1);
  12        const char *slash = path;
  13
  14        while ((slash = strchr(slash+1, '/')) != NULL) {
  15                len = slash - path;
  16                memcpy(buf, path, len);
  17                buf[len] = 0;
  18                mkdir(buf, 0700);
  19        }
  20}
  21
  22static int create_file(const char *path)
  23{
  24        int fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0600);
  25        if (fd < 0) {
  26                if (errno == ENOENT) {
  27                        create_directories(path);
  28                        fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0600);
  29                }
  30        }
  31        return fd;
  32}
  33
  34static int unpack(unsigned char *sha1)
  35{
  36        void *buffer;
  37        unsigned long size;
  38        char type[20];
  39
  40        buffer = read_sha1_file(sha1, type, &size);
  41        if (!buffer)
  42                usage("unable to read sha1 file");
  43        if (strcmp(type, "tree"))
  44                usage("expected a 'tree' node");
  45        while (size) {
  46                int len = strlen(buffer)+1;
  47                unsigned char *sha1 = buffer + len;
  48                char *path = strchr(buffer, ' ')+1;
  49                char *data;
  50                unsigned long filesize;
  51                unsigned int mode;
  52                int fd;
  53
  54                if (size < len + 20 || sscanf(buffer, "%o", &mode) != 1)
  55                        usage("corrupt 'tree' file");
  56                buffer = sha1 + 20;
  57                size -= len + 20;
  58                data = read_sha1_file(sha1, type, &filesize);
  59                if (!data || strcmp(type, "blob"))
  60                        usage("tree file refers to bad file data");
  61                fd = create_file(path);
  62                if (fd < 0)
  63                        usage("unable to create file");
  64                if (write(fd, data, filesize) != filesize)
  65                        usage("unable to write file");
  66                fchmod(fd, mode);
  67                close(fd);
  68                free(data);
  69        }
  70        return 0;
  71}
  72
  73int main(int argc, char **argv)
  74{
  75        int fd;
  76        unsigned char sha1[20];
  77
  78        if (argc != 2)
  79                usage("read-tree <key>");
  80        if (get_sha1_hex(argv[1], sha1) < 0)
  81                usage("read-tree <key>");
  82        sha1_file_directory = getenv(DB_ENVIRONMENT);
  83        if (!sha1_file_directory)
  84                sha1_file_directory = DEFAULT_DB_ENVIRONMENT;
  85        if (unpack(sha1) < 0)
  86                usage("unpack failed");
  87        return 0;
  88}