mktree.con commit Merge branch 'maint-1.6.0' into maint-1.6.1 (f29d669)
   1/*
   2 * GIT - the stupid content tracker
   3 *
   4 * Copyright (c) Junio C Hamano, 2006
   5 */
   6#include "cache.h"
   7#include "quote.h"
   8#include "tree.h"
   9
  10static struct treeent {
  11        unsigned mode;
  12        unsigned char sha1[20];
  13        int len;
  14        char name[FLEX_ARRAY];
  15} **entries;
  16static int alloc, used;
  17
  18static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
  19{
  20        struct treeent *ent;
  21        int len = strlen(path);
  22        if (strchr(path, '/'))
  23                die("path %s contains slash", path);
  24
  25        if (alloc <= used) {
  26                alloc = alloc_nr(used);
  27                entries = xrealloc(entries, sizeof(*entries) * alloc);
  28        }
  29        ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
  30        ent->mode = mode;
  31        ent->len = len;
  32        hashcpy(ent->sha1, sha1);
  33        memcpy(ent->name, path, len+1);
  34}
  35
  36static int ent_compare(const void *a_, const void *b_)
  37{
  38        struct treeent *a = *(struct treeent **)a_;
  39        struct treeent *b = *(struct treeent **)b_;
  40        return base_name_compare(a->name, a->len, a->mode,
  41                                 b->name, b->len, b->mode);
  42}
  43
  44static void write_tree(unsigned char *sha1)
  45{
  46        struct strbuf buf;
  47        size_t size;
  48        int i;
  49
  50        qsort(entries, used, sizeof(*entries), ent_compare);
  51        for (size = i = 0; i < used; i++)
  52                size += 32 + entries[i]->len;
  53
  54        strbuf_init(&buf, size);
  55        for (i = 0; i < used; i++) {
  56                struct treeent *ent = entries[i];
  57                strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
  58                strbuf_add(&buf, ent->sha1, 20);
  59        }
  60
  61        write_sha1_file(buf.buf, buf.len, tree_type, sha1);
  62}
  63
  64static const char mktree_usage[] = "git-mktree [-z]";
  65
  66int main(int ac, char **av)
  67{
  68        struct strbuf sb = STRBUF_INIT;
  69        struct strbuf p_uq = STRBUF_INIT;
  70        unsigned char sha1[20];
  71        int line_termination = '\n';
  72
  73        setup_git_directory();
  74
  75        while ((1 < ac) && av[1][0] == '-') {
  76                char *arg = av[1];
  77                if (!strcmp("-z", arg))
  78                        line_termination = 0;
  79                else
  80                        usage(mktree_usage);
  81                ac--;
  82                av++;
  83        }
  84
  85        while (strbuf_getline(&sb, stdin, line_termination) != EOF) {
  86                char *ptr, *ntr;
  87                unsigned mode;
  88                enum object_type type;
  89                char *path;
  90
  91                ptr = sb.buf;
  92                /* Input is non-recursive ls-tree output format
  93                 * mode SP type SP sha1 TAB name
  94                 */
  95                mode = strtoul(ptr, &ntr, 8);
  96                if (ptr == ntr || !ntr || *ntr != ' ')
  97                        die("input format error: %s", sb.buf);
  98                ptr = ntr + 1; /* type */
  99                ntr = strchr(ptr, ' ');
 100                if (!ntr || sb.buf + sb.len <= ntr + 40 ||
 101                    ntr[41] != '\t' ||
 102                    get_sha1_hex(ntr + 1, sha1))
 103                        die("input format error: %s", sb.buf);
 104                type = sha1_object_info(sha1, NULL);
 105                if (type < 0)
 106                        die("object %s unavailable", sha1_to_hex(sha1));
 107                *ntr++ = 0; /* now at the beginning of SHA1 */
 108                if (type != type_from_string(ptr))
 109                        die("object type %s mismatch (%s)", ptr, typename(type));
 110
 111                path = ntr + 41;  /* at the beginning of name */
 112                if (line_termination && path[0] == '"') {
 113                        strbuf_reset(&p_uq);
 114                        if (unquote_c_style(&p_uq, path, NULL)) {
 115                                die("invalid quoting");
 116                        }
 117                        path = p_uq.buf;
 118                }
 119
 120                append_to_tree(mode, sha1, path);
 121        }
 122        strbuf_release(&p_uq);
 123        strbuf_release(&sb);
 124
 125        write_tree(sha1);
 126        puts(sha1_to_hex(sha1));
 127        exit(0);
 128}