mktree.con commit git-send-email: handle email address with quoted comma (0e73b3e)
   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;
  69        struct strbuf p_uq;
  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        strbuf_init(&sb, 0);
  86        strbuf_init(&p_uq, 0);
  87        while (strbuf_getline(&sb, stdin, line_termination) != EOF) {
  88                char *ptr, *ntr;
  89                unsigned mode;
  90                enum object_type type;
  91                char *path;
  92
  93                ptr = sb.buf;
  94                /* Input is non-recursive ls-tree output format
  95                 * mode SP type SP sha1 TAB name
  96                 */
  97                mode = strtoul(ptr, &ntr, 8);
  98                if (ptr == ntr || !ntr || *ntr != ' ')
  99                        die("input format error: %s", sb.buf);
 100                ptr = ntr + 1; /* type */
 101                ntr = strchr(ptr, ' ');
 102                if (!ntr || sb.buf + sb.len <= ntr + 40 ||
 103                    ntr[41] != '\t' ||
 104                    get_sha1_hex(ntr + 1, sha1))
 105                        die("input format error: %s", sb.buf);
 106                type = sha1_object_info(sha1, NULL);
 107                if (type < 0)
 108                        die("object %s unavailable", sha1_to_hex(sha1));
 109                *ntr++ = 0; /* now at the beginning of SHA1 */
 110                if (type != type_from_string(ptr))
 111                        die("object type %s mismatch (%s)", ptr, typename(type));
 112
 113                path = ntr + 41;  /* at the beginning of name */
 114                if (line_termination && path[0] == '"') {
 115                        strbuf_reset(&p_uq);
 116                        if (unquote_c_style(&p_uq, path, NULL)) {
 117                                die("invalid quoting");
 118                        }
 119                        path = p_uq.buf;
 120                }
 121
 122                append_to_tree(mode, sha1, path);
 123        }
 124        strbuf_release(&p_uq);
 125        strbuf_release(&sb);
 126
 127        write_tree(sha1);
 128        puts(sha1_to_hex(sha1));
 129        exit(0);
 130}