blob: 1bb78198392e9e13db117e87a4d421e17d10b26a [file] [log] [blame]
Linus Torvalds8bc9a0c2005-04-07 15:16:10 -07001/*
2 * GIT - The information manager from hell
3 *
4 * Copyright (C) Linus Torvalds, 2005
5 */
Elijah Newrenbc5c5ec2023-05-16 06:33:57 +00006#include "builtin.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07007#include "config.h"
Elijah Newrenf394e092023-03-21 06:25:54 +00008#include "gettext.h"
Elijah Newren41771fa2023-02-24 00:09:27 +00009#include "hex.h"
Elijah Newrendabab1d2023-04-11 00:41:49 -070010#include "object-name.h"
Elijah Newrena034e912023-05-16 06:34:06 +000011#include "object-store-ll.h"
Stefan Bellerc1f5eb42018-06-28 18:21:59 -070012#include "repository.h"
Peter Eriksen8e440252006-04-02 14:44:09 +020013#include "commit.h"
Brandon Richardsoncbdeab92019-03-07 11:44:09 -040014#include "parse-options.h"
Linus Torvaldse83c5162005-04-07 15:13:13 -070015
Brandon Richardsoncbdeab92019-03-07 11:44:09 -040016static const char * const commit_tree_usage[] = {
Ævar Arnfjörð Bjarmasond9054a12022-10-13 17:39:18 +020017 N_("git commit-tree <tree> [(-p <parent>)...]"),
Ævar Arnfjörð Bjarmason5af8b612022-10-13 17:39:02 +020018 N_("git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]\n"
19 " [(-F <file>)...] <tree>"),
Brandon Richardsoncbdeab92019-03-07 11:44:09 -040020 NULL
21};
Junio C Hamanoc5bac172005-04-20 19:49:16 -070022
Nicolas Vigierd95bfb12013-11-05 00:14:41 +010023static const char *sign_commit;
24
Johannes Schindelinef98c5c2008-06-27 13:24:47 +010025static void new_parent(struct commit *parent, struct commit_list **parents_p)
Linus Torvaldsb3892372005-06-19 10:40:10 -070026{
brian m. carlsonf2fd0762015-11-10 02:22:28 +000027 struct object_id *oid = &parent->object.oid;
Johannes Schindelinef98c5c2008-06-27 13:24:47 +010028 struct commit_list *parents;
29 for (parents = *parents_p; parents; parents = parents->next) {
30 if (parents->item == parent) {
Brandon Richardsoncbdeab92019-03-07 11:44:09 -040031 error(_("duplicate parent %s ignored"), oid_to_hex(oid));
Johannes Schindelinef98c5c2008-06-27 13:24:47 +010032 return;
Linus Torvaldsb3892372005-06-19 10:40:10 -070033 }
Johannes Schindelinef98c5c2008-06-27 13:24:47 +010034 parents_p = &parents->next;
Linus Torvaldsb3892372005-06-19 10:40:10 -070035 }
Johannes Schindelinef98c5c2008-06-27 13:24:47 +010036 commit_list_insert(parent, parents_p);
Linus Torvaldsb3892372005-06-19 10:40:10 -070037}
38
Brandon Richardsoncbdeab92019-03-07 11:44:09 -040039static int parse_parent_arg_callback(const struct option *opt,
40 const char *arg, int unset)
41{
42 struct object_id oid;
43 struct commit_list **parents = opt->value;
44
45 BUG_ON_OPT_NEG_NOARG(unset, arg);
46
Ævar Arnfjörð Bjarmasond850b7a2023-03-28 15:58:46 +020047 if (repo_get_oid_commit(the_repository, arg, &oid))
Brandon Richardsoncbdeab92019-03-07 11:44:09 -040048 die(_("not a valid object name %s"), arg);
49
50 assert_oid_type(&oid, OBJ_COMMIT);
51 new_parent(lookup_commit(the_repository, &oid), parents);
52 return 0;
53}
54
55static int parse_message_arg_callback(const struct option *opt,
56 const char *arg, int unset)
57{
58 struct strbuf *buf = opt->value;
59
60 BUG_ON_OPT_NEG_NOARG(unset, arg);
61
62 if (buf->len)
63 strbuf_addch(buf, '\n');
64 strbuf_addstr(buf, arg);
65 strbuf_complete_line(buf);
66
67 return 0;
68}
69
70static int parse_file_arg_callback(const struct option *opt,
71 const char *arg, int unset)
72{
73 int fd;
74 struct strbuf *buf = opt->value;
75
76 BUG_ON_OPT_NEG_NOARG(unset, arg);
77
78 if (buf->len)
79 strbuf_addch(buf, '\n');
80 if (!strcmp(arg, "-"))
81 fd = 0;
82 else {
René Scharfe66e905b2021-08-25 22:16:46 +020083 fd = xopen(arg, O_RDONLY);
Brandon Richardsoncbdeab92019-03-07 11:44:09 -040084 }
85 if (strbuf_read(buf, fd, 0) < 0)
86 die_errno(_("git commit-tree: failed to read '%s'"), arg);
87 if (fd && close(fd))
88 die_errno(_("git commit-tree: failed to close '%s'"), arg);
89
90 return 0;
91}
92
Miklos Vajna7b9c0a62008-07-01 04:37:49 +020093int cmd_commit_tree(int argc, const char **argv, const char *prefix)
94{
Brandon Richardsoncbdeab92019-03-07 11:44:09 -040095 static struct strbuf buffer = STRBUF_INIT;
Miklos Vajna7b9c0a62008-07-01 04:37:49 +020096 struct commit_list *parents = NULL;
brian m. carlson031cee52016-09-05 20:08:10 +000097 struct object_id tree_oid;
98 struct object_id commit_oid;
Brandon Richardsoncbdeab92019-03-07 11:44:09 -040099
100 struct option options[] = {
Denton Liu203c8532020-04-28 04:36:28 -0400101 OPT_CALLBACK_F('p', NULL, &parents, N_("parent"),
Brandon Richardsoncbdeab92019-03-07 11:44:09 -0400102 N_("id of a parent commit object"), PARSE_OPT_NONEG,
Denton Liu203c8532020-04-28 04:36:28 -0400103 parse_parent_arg_callback),
104 OPT_CALLBACK_F('m', NULL, &buffer, N_("message"),
Brandon Richardsoncbdeab92019-03-07 11:44:09 -0400105 N_("commit message"), PARSE_OPT_NONEG,
Denton Liu203c8532020-04-28 04:36:28 -0400106 parse_message_arg_callback),
107 OPT_CALLBACK_F('F', NULL, &buffer, N_("file"),
Brandon Richardsoncbdeab92019-03-07 11:44:09 -0400108 N_("read commit log message from file"), PARSE_OPT_NONEG,
Denton Liu203c8532020-04-28 04:36:28 -0400109 parse_file_arg_callback),
Brandon Richardsoncbdeab92019-03-07 11:44:09 -0400110 { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
111 N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
112 OPT_END()
113 };
Miklos Vajna7b9c0a62008-07-01 04:37:49 +0200114
Jeff Kingcc5d1d32023-02-26 17:40:46 -0500115 git_config(git_default_config, NULL);
Miklos Vajna7b9c0a62008-07-01 04:37:49 +0200116
Jonathan Nieder6e9daef2009-11-09 09:04:44 -0600117 if (argc < 2 || !strcmp(argv[1], "-h"))
Brandon Richardsoncbdeab92019-03-07 11:44:09 -0400118 usage_with_options(commit_tree_usage, options);
Miklos Vajna7b9c0a62008-07-01 04:37:49 +0200119
Brandon Richardsoncbdeab92019-03-07 11:44:09 -0400120 argc = parse_options(argc, argv, prefix, options, commit_tree_usage, 0);
Miklos Vajna7b9c0a62008-07-01 04:37:49 +0200121
Brandon Richardsoncbdeab92019-03-07 11:44:09 -0400122 if (argc != 1)
123 die(_("must give exactly one tree"));
Brandon Richardson70ddbd72019-01-19 19:23:34 -0400124
Ævar Arnfjörð Bjarmasond850b7a2023-03-28 15:58:46 +0200125 if (repo_get_oid_tree(the_repository, argv[0], &tree_oid))
Brandon Richardsoncbdeab92019-03-07 11:44:09 -0400126 die(_("not a valid object name %s"), argv[0]);
Miklos Vajna7b9c0a62008-07-01 04:37:49 +0200127
Junio C Hamano96b8d932011-11-09 11:54:04 -0800128 if (!buffer.len) {
129 if (strbuf_read(&buffer, 0, 0) < 0)
Brandon Richardsoncbdeab92019-03-07 11:44:09 -0400130 die_errno(_("git commit-tree: failed to read"));
Junio C Hamano96b8d932011-11-09 11:54:04 -0800131 }
Miklos Vajna7b9c0a62008-07-01 04:37:49 +0200132
Patryk Obara5078f342018-01-28 01:13:16 +0100133 if (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,
134 NULL, sign_commit)) {
Jonathan Nieder79bc2af2010-10-02 03:41:00 -0500135 strbuf_release(&buffer);
Junio C Hamano7561d9f2006-03-24 22:23:25 -0800136 return 1;
Jonathan Nieder79bc2af2010-10-02 03:41:00 -0500137 }
138
brian m. carlson031cee52016-09-05 20:08:10 +0000139 printf("%s\n", oid_to_hex(&commit_oid));
Jonathan Nieder79bc2af2010-10-02 03:41:00 -0500140 strbuf_release(&buffer);
141 return 0;
Linus Torvaldse83c5162005-04-07 15:13:13 -0700142}