builtin / commit-tree.con commit rev-list: let traversal die when --missing is not in use (ee4dfee)
   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 (!strcmp(arg, "--gpg-sign")) {
  70                    sign_commit = "";
  71                    continue;
  72                }
  73
  74                if (skip_prefix(arg, "-S", &sign_commit) ||
  75                        skip_prefix(arg, "--gpg-sign=", &sign_commit))
  76                        continue;
  77
  78                if (!strcmp(arg, "--no-gpg-sign")) {
  79                        sign_commit = NULL;
  80                        continue;
  81                }
  82
  83                if (!strcmp(arg, "-m")) {
  84                        if (argc <= ++i)
  85                                usage(commit_tree_usage);
  86                        if (buffer.len)
  87                                strbuf_addch(&buffer, '\n');
  88                        strbuf_addstr(&buffer, argv[i]);
  89                        strbuf_complete_line(&buffer);
  90                        continue;
  91                }
  92
  93                if (!strcmp(arg, "-F")) {
  94                        int fd;
  95
  96                        if (argc <= ++i)
  97                                usage(commit_tree_usage);
  98                        if (buffer.len)
  99                                strbuf_addch(&buffer, '\n');
 100                        if (!strcmp(argv[i], "-"))
 101                                fd = 0;
 102                        else {
 103                                fd = open(argv[i], O_RDONLY);
 104                                if (fd < 0)
 105                                        die_errno("git commit-tree: failed to open '%s'",
 106                                                  argv[i]);
 107                        }
 108                        if (strbuf_read(&buffer, fd, 0) < 0)
 109                                die_errno("git commit-tree: failed to read '%s'",
 110                                          argv[i]);
 111                        if (fd && close(fd))
 112                                die_errno("git commit-tree: failed to close '%s'",
 113                                          argv[i]);
 114                        continue;
 115                }
 116
 117                if (get_oid_tree(arg, &tree_oid))
 118                        die("Not a valid object name %s", arg);
 119                if (got_tree)
 120                        die("Cannot give more than one trees");
 121                got_tree = 1;
 122        }
 123
 124        if (!buffer.len) {
 125                if (strbuf_read(&buffer, 0, 0) < 0)
 126                        die_errno("git commit-tree: failed to read");
 127        }
 128
 129        if (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,
 130                        NULL, sign_commit)) {
 131                strbuf_release(&buffer);
 132                return 1;
 133        }
 134
 135        printf("%s\n", oid_to_hex(&commit_oid));
 136        strbuf_release(&buffer);
 137        return 0;
 138}