Git fork
at reftables-rust 160 lines 3.9 kB view raw
1/* 2 * GIT - The information manager from hell 3 * 4 * Copyright (C) Linus Torvalds, 2005 5 */ 6#define USE_THE_REPOSITORY_VARIABLE 7#include "builtin.h" 8#include "config.h" 9#include "environment.h" 10#include "gettext.h" 11#include "hex.h" 12#include "object-name.h" 13#include "odb.h" 14 15#include "commit.h" 16#include "parse-options.h" 17 18static const char * const commit_tree_usage[] = { 19 N_("git commit-tree <tree> [(-p <parent>)...]"), 20 N_("git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]\n" 21 " [(-F <file>)...] <tree>"), 22 NULL 23}; 24 25static const char *sign_commit; 26 27static void new_parent(struct commit *parent, struct commit_list **parents_p) 28{ 29 struct object_id *oid = &parent->object.oid; 30 struct commit_list *parents; 31 for (parents = *parents_p; parents; parents = parents->next) { 32 if (parents->item == parent) { 33 error(_("duplicate parent %s ignored"), oid_to_hex(oid)); 34 return; 35 } 36 parents_p = &parents->next; 37 } 38 commit_list_insert(parent, parents_p); 39} 40 41static int parse_parent_arg_callback(const struct option *opt, 42 const char *arg, int unset) 43{ 44 struct object_id oid; 45 struct commit_list **parents = opt->value; 46 47 BUG_ON_OPT_NEG_NOARG(unset, arg); 48 49 if (repo_get_oid_commit(the_repository, arg, &oid)) 50 die(_("not a valid object name %s"), arg); 51 52 odb_assert_oid_type(the_repository->objects, &oid, OBJ_COMMIT); 53 new_parent(lookup_commit(the_repository, &oid), parents); 54 return 0; 55} 56 57static int parse_message_arg_callback(const struct option *opt, 58 const char *arg, int unset) 59{ 60 struct strbuf *buf = opt->value; 61 62 BUG_ON_OPT_NEG_NOARG(unset, arg); 63 64 if (buf->len) 65 strbuf_addch(buf, '\n'); 66 strbuf_addstr(buf, arg); 67 strbuf_complete_line(buf); 68 69 return 0; 70} 71 72static int parse_file_arg_callback(const struct option *opt, 73 const char *arg, int unset) 74{ 75 int fd; 76 struct strbuf *buf = opt->value; 77 78 BUG_ON_OPT_NEG_NOARG(unset, arg); 79 80 if (buf->len) 81 strbuf_addch(buf, '\n'); 82 if (!strcmp(arg, "-")) 83 fd = 0; 84 else { 85 fd = xopen(arg, O_RDONLY); 86 } 87 if (strbuf_read(buf, fd, 0) < 0) 88 die_errno(_("git commit-tree: failed to read '%s'"), arg); 89 if (fd && close(fd)) 90 die_errno(_("git commit-tree: failed to close '%s'"), arg); 91 92 return 0; 93} 94 95int cmd_commit_tree(int argc, 96 const char **argv, 97 const char *prefix, 98 struct repository *repo UNUSED) 99{ 100 static struct strbuf buffer = STRBUF_INIT; 101 struct commit_list *parents = NULL; 102 struct object_id tree_oid; 103 struct object_id commit_oid; 104 105 struct option options[] = { 106 OPT_CALLBACK_F('p', NULL, &parents, N_("parent"), 107 N_("id of a parent commit object"), PARSE_OPT_NONEG, 108 parse_parent_arg_callback), 109 OPT_CALLBACK_F('m', NULL, &buffer, N_("message"), 110 N_("commit message"), PARSE_OPT_NONEG, 111 parse_message_arg_callback), 112 OPT_CALLBACK_F('F', NULL, &buffer, N_("file"), 113 N_("read commit log message from file"), PARSE_OPT_NONEG, 114 parse_file_arg_callback), 115 { 116 .type = OPTION_STRING, 117 .short_name = 'S', 118 .long_name = "gpg-sign", 119 .value = &sign_commit, 120 .argh = N_("key-id"), 121 .help = N_("GPG sign commit"), 122 .flags = PARSE_OPT_OPTARG, 123 .defval = (intptr_t) "", 124 }, 125 OPT_END() 126 }; 127 int ret; 128 129 repo_config(the_repository, git_default_config, NULL); 130 131 show_usage_with_options_if_asked(argc, argv, 132 commit_tree_usage, options); 133 134 argc = parse_options(argc, argv, prefix, options, commit_tree_usage, 0); 135 136 if (argc != 1) 137 die(_("must give exactly one tree")); 138 139 if (repo_get_oid_tree(the_repository, argv[0], &tree_oid)) 140 die(_("not a valid object name %s"), argv[0]); 141 142 if (!buffer.len) { 143 if (strbuf_read(&buffer, 0, 0) < 0) 144 die_errno(_("git commit-tree: failed to read")); 145 } 146 147 if (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid, 148 NULL, sign_commit)) { 149 ret = 1; 150 goto out; 151 } 152 153 printf("%s\n", oid_to_hex(&commit_oid)); 154 ret = 0; 155 156out: 157 free_commit_list(parents); 158 strbuf_release(&buffer); 159 return ret; 160}