builtin / commit-tree.con commit Merge branch 'tb/void-check-attr' (10de0f8)
   1/*
   2 * GIT - The information manager from hell
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 */
   6#include "cache.h"
   7#include "config.h"
   8#include "object-store.h"
   9#include "repository.h"
  10#include "commit.h"
  11#include "tree.h"
  12#include "builtin.h"
  13#include "utf8.h"
  14#include "gpg-interface.h"
  15
  16static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-S[<keyid>]] [-m <message>] [-F <file>] <sha1>";
  17
  18static const char *sign_commit;
  19
  20static void new_parent(struct commit *parent, struct commit_list **parents_p)
  21{
  22        struct object_id *oid = &parent->object.oid;
  23        struct commit_list *parents;
  24        for (parents = *parents_p; parents; parents = parents->next) {
  25                if (parents->item == parent) {
  26                        error("duplicate parent %s ignored", oid_to_hex(oid));
  27                        return;
  28                }
  29                parents_p = &parents->next;
  30        }
  31        commit_list_insert(parent, parents_p);
  32}
  33
  34static int commit_tree_config(const char *var, const char *value, void *cb)
  35{
  36        int status = git_gpg_config(var, value, NULL);
  37        if (status)
  38                return status;
  39        return git_default_config(var, value, cb);
  40}
  41
  42int cmd_commit_tree(int argc, const char **argv, const char *prefix)
  43{
  44        int i, got_tree = 0;
  45        struct commit_list *parents = NULL;
  46        struct object_id tree_oid;
  47        struct object_id commit_oid;
  48        struct strbuf buffer = STRBUF_INIT;
  49
  50        git_config(commit_tree_config, NULL);
  51
  52        if (argc < 2 || !strcmp(argv[1], "-h"))
  53                usage(commit_tree_usage);
  54
  55        for (i = 1; i < argc; i++) {
  56                const char *arg = argv[i];
  57                if (!strcmp(arg, "-p")) {
  58                        struct object_id oid;
  59                        if (argc <= ++i)
  60                                usage(commit_tree_usage);
  61                        if (get_oid_commit(argv[i], &oid))
  62                                die("Not a valid object name %s", argv[i]);
  63                        assert_oid_type(&oid, OBJ_COMMIT);
  64                        new_parent(lookup_commit(the_repository, &oid),
  65                                                 &parents);
  66                        continue;
  67                }
  68
  69                if (skip_prefix(arg, "-S", &sign_commit))
  70                        continue;
  71
  72                if (!strcmp(arg, "--no-gpg-sign")) {
  73                        sign_commit = NULL;
  74                        continue;
  75                }
  76
  77                if (!strcmp(arg, "-m")) {
  78                        if (argc <= ++i)
  79                                usage(commit_tree_usage);
  80                        if (buffer.len)
  81                                strbuf_addch(&buffer, '\n');
  82                        strbuf_addstr(&buffer, argv[i]);
  83                        strbuf_complete_line(&buffer);
  84                        continue;
  85                }
  86
  87                if (!strcmp(arg, "-F")) {
  88                        int fd;
  89
  90                        if (argc <= ++i)
  91                                usage(commit_tree_usage);
  92                        if (buffer.len)
  93                                strbuf_addch(&buffer, '\n');
  94                        if (!strcmp(argv[i], "-"))
  95                                fd = 0;
  96                        else {
  97                                fd = open(argv[i], O_RDONLY);
  98                                if (fd < 0)
  99                                        die_errno("git commit-tree: failed to open '%s'",
 100                                                  argv[i]);
 101                        }
 102                        if (strbuf_read(&buffer, fd, 0) < 0)
 103                                die_errno("git commit-tree: failed to read '%s'",
 104                                          argv[i]);
 105                        if (fd && close(fd))
 106                                die_errno("git commit-tree: failed to close '%s'",
 107                                          argv[i]);
 108                        continue;
 109                }
 110
 111                if (get_oid_tree(arg, &tree_oid))
 112                        die("Not a valid object name %s", arg);
 113                if (got_tree)
 114                        die("Cannot give more than one trees");
 115                got_tree = 1;
 116        }
 117
 118        if (!buffer.len) {
 119                if (strbuf_read(&buffer, 0, 0) < 0)
 120                        die_errno("git commit-tree: failed to read");
 121        }
 122
 123        if (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,
 124                        NULL, sign_commit)) {
 125                strbuf_release(&buffer);
 126                return 1;
 127        }
 128
 129        printf("%s\n", oid_to_hex(&commit_oid));
 130        strbuf_release(&buffer);
 131        return 0;
 132}