diff --no-index: fix -R with stdin
[git/debian.git] / builtin / commit-tree.c
blobd1d251c3ded2798ecb6667034bb7e21477be847d
1 /*
2 * GIT - The information manager from hell
4 * Copyright (C) Linus Torvalds, 2005
5 */
6 #include "cache.h"
7 #include "config.h"
8 #include "gettext.h"
9 #include "hex.h"
10 #include "object-name.h"
11 #include "object-store.h"
12 #include "repository.h"
13 #include "commit.h"
14 #include "tree.h"
15 #include "builtin.h"
16 #include "utf8.h"
17 #include "gpg-interface.h"
18 #include "parse-options.h"
20 static const char * const commit_tree_usage[] = {
21 N_("git commit-tree <tree> [(-p <parent>)...]"),
22 N_("git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]\n"
23 " [(-F <file>)...] <tree>"),
24 NULL
27 static const char *sign_commit;
29 static void new_parent(struct commit *parent, struct commit_list **parents_p)
31 struct object_id *oid = &parent->object.oid;
32 struct commit_list *parents;
33 for (parents = *parents_p; parents; parents = parents->next) {
34 if (parents->item == parent) {
35 error(_("duplicate parent %s ignored"), oid_to_hex(oid));
36 return;
38 parents_p = &parents->next;
40 commit_list_insert(parent, parents_p);
43 static int parse_parent_arg_callback(const struct option *opt,
44 const char *arg, int unset)
46 struct object_id oid;
47 struct commit_list **parents = opt->value;
49 BUG_ON_OPT_NEG_NOARG(unset, arg);
51 if (repo_get_oid_commit(the_repository, arg, &oid))
52 die(_("not a valid object name %s"), arg);
54 assert_oid_type(&oid, OBJ_COMMIT);
55 new_parent(lookup_commit(the_repository, &oid), parents);
56 return 0;
59 static int parse_message_arg_callback(const struct option *opt,
60 const char *arg, int unset)
62 struct strbuf *buf = opt->value;
64 BUG_ON_OPT_NEG_NOARG(unset, arg);
66 if (buf->len)
67 strbuf_addch(buf, '\n');
68 strbuf_addstr(buf, arg);
69 strbuf_complete_line(buf);
71 return 0;
74 static int parse_file_arg_callback(const struct option *opt,
75 const char *arg, int unset)
77 int fd;
78 struct strbuf *buf = opt->value;
80 BUG_ON_OPT_NEG_NOARG(unset, arg);
82 if (buf->len)
83 strbuf_addch(buf, '\n');
84 if (!strcmp(arg, "-"))
85 fd = 0;
86 else {
87 fd = xopen(arg, O_RDONLY);
89 if (strbuf_read(buf, fd, 0) < 0)
90 die_errno(_("git commit-tree: failed to read '%s'"), arg);
91 if (fd && close(fd))
92 die_errno(_("git commit-tree: failed to close '%s'"), arg);
94 return 0;
97 int cmd_commit_tree(int argc, const char **argv, const char *prefix)
99 static struct strbuf buffer = STRBUF_INIT;
100 struct commit_list *parents = NULL;
101 struct object_id tree_oid;
102 struct object_id commit_oid;
104 struct option options[] = {
105 OPT_CALLBACK_F('p', NULL, &parents, N_("parent"),
106 N_("id of a parent commit object"), PARSE_OPT_NONEG,
107 parse_parent_arg_callback),
108 OPT_CALLBACK_F('m', NULL, &buffer, N_("message"),
109 N_("commit message"), PARSE_OPT_NONEG,
110 parse_message_arg_callback),
111 OPT_CALLBACK_F('F', NULL, &buffer, N_("file"),
112 N_("read commit log message from file"), PARSE_OPT_NONEG,
113 parse_file_arg_callback),
114 { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
115 N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
116 OPT_END()
119 git_config(git_default_config, NULL);
121 if (argc < 2 || !strcmp(argv[1], "-h"))
122 usage_with_options(commit_tree_usage, options);
124 argc = parse_options(argc, argv, prefix, options, commit_tree_usage, 0);
126 if (argc != 1)
127 die(_("must give exactly one tree"));
129 if (repo_get_oid_tree(the_repository, argv[0], &tree_oid))
130 die(_("not a valid object name %s"), argv[0]);
132 if (!buffer.len) {
133 if (strbuf_read(&buffer, 0, 0) < 0)
134 die_errno(_("git commit-tree: failed to read"));
137 if (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,
138 NULL, sign_commit)) {
139 strbuf_release(&buffer);
140 return 1;
143 printf("%s\n", oid_to_hex(&commit_oid));
144 strbuf_release(&buffer);
145 return 0;