git_config_colorbool: refactor stdout_is_tty handling
[git/git.git] / builtin / commit.c
CommitLineData
f5bbc322
KH
1/*
2 * Builtin "git commit"
3 *
4 * Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com>
5 * Based on git-commit.sh by Junio C Hamano and Linus Torvalds
6 */
7
8#include "cache.h"
9#include "cache-tree.h"
6b2f2d98 10#include "color.h"
2888605c 11#include "dir.h"
f5bbc322
KH
12#include "builtin.h"
13#include "diff.h"
14#include "diffcore.h"
15#include "commit.h"
16#include "revision.h"
17#include "wt-status.h"
18#include "run-command.h"
19#include "refs.h"
20#include "log-tree.h"
21#include "strbuf.h"
22#include "utf8.h"
23#include "parse-options.h"
c455c87c 24#include "string-list.h"
5b2fd956 25#include "rerere.h"
fa9dcf80 26#include "unpack-trees.h"
76e2f7ce 27#include "quote.h"
302ad7a9 28#include "submodule.h"
f5bbc322
KH
29
30static const char * const builtin_commit_usage[] = {
1b1dd23f 31 "git commit [options] [--] <filepattern>...",
f5bbc322
KH
32 NULL
33};
34
2f02b25f 35static const char * const builtin_status_usage[] = {
1b1dd23f 36 "git status [options] [--] <filepattern>...",
2f02b25f
SB
37 NULL
38};
39
49ff9a7a 40static const char implicit_ident_advice[] =
fc88e316 41N_("Your name and email address were configured automatically based\n"
49ff9a7a
JK
42"on your username and hostname. Please check that they are accurate.\n"
43"You can suppress this message by setting them explicitly:\n"
44"\n"
8bb45b25 45" git config --global user.name \"Your Name\"\n"
49ff9a7a
JK
46" git config --global user.email you@example.com\n"
47"\n"
3f142468 48"After doing this, you may fix the identity used for this commit with:\n"
49ff9a7a 49"\n"
fc88e316 50" git commit --amend --reset-author\n");
49ff9a7a 51
f197ed2f 52static const char empty_amend_advice[] =
fc88e316 53N_("You asked to amend the most recent commit, but doing so would make\n"
f197ed2f 54"it empty. You can repeat your command with --allow-empty, or you can\n"
fc88e316 55"remove the commit entirely with \"git reset HEAD^\".\n");
f197ed2f 56
37f7a857 57static const char empty_cherry_pick_advice[] =
6c80cd29 58N_("The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
37f7a857
JS
59"If you wish to commit it anyway, use:\n"
60"\n"
61" git commit --allow-empty\n"
62"\n"
6c80cd29 63"Otherwise, please use 'git reset'\n");
37f7a857 64
30988301 65static unsigned char head_sha1[20];
49ff9a7a 66
37f7a857 67static const char *use_message_buffer;
f5bbc322 68static const char commit_editmsg[] = "COMMIT_EDITMSG";
2888605c
JH
69static struct lock_file index_lock; /* real index */
70static struct lock_file false_lock; /* used only for partial commits */
71static enum {
72 COMMIT_AS_IS = 1,
73 COMMIT_NORMAL,
4b05548f 74 COMMIT_PARTIAL
2888605c 75} commit_style;
f5bbc322 76
dbd0f5c7 77static const char *logfile, *force_author;
984c6e7e 78static const char *template_file;
37f7a857
JS
79/*
80 * The _message variables are commit names from which to take
81 * the commit message and/or authorship.
82 */
83static const char *author_message, *author_message_buffer;
f5bbc322 84static char *edit_message, *use_message;
89ac1223 85static char *fixup_message, *squash_message;
b4bd4668 86static int all, edit_flag, also, interactive, patch_interactive, only, amend, signoff;
c51f6cee 87static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
c9b5fde7 88static int no_post_rewrite, allow_empty_message;
46a958b3 89static char *untracked_files_arg, *force_date, *ignore_submodule_arg;
5f065737
AR
90/*
91 * The default commit message cleanup mode will remove the lines
92 * beginning with # (shell comments) and leading and trailing
93 * whitespaces (empty lines or containing only whitespaces)
94 * if editor is used, and only the whitespaces if the message
95 * is specified explicitly.
96 */
97static enum {
98 CLEANUP_SPACE,
99 CLEANUP_NONE,
4b05548f 100 CLEANUP_ALL
5f065737
AR
101} cleanup_mode;
102static char *cleanup_arg;
f5bbc322 103
37f7a857
JS
104static enum commit_whence whence;
105static int use_editor = 1, initial_commit, include_status = 1;
2381e39e 106static int show_ignored_in_status;
3b6aeb3c
JS
107static const char *only_include_assumed;
108static struct strbuf message;
f9568530 109
7c9f7038
JK
110static int null_termination;
111static enum {
112 STATUS_FORMAT_LONG,
113 STATUS_FORMAT_SHORT,
4b05548f 114 STATUS_FORMAT_PORCELAIN
7c9f7038 115} status_format = STATUS_FORMAT_LONG;
05a59a08 116static int status_show_branch;
7c9f7038 117
f9568530
JS
118static int opt_parse_m(const struct option *opt, const char *arg, int unset)
119{
120 struct strbuf *buf = opt->value;
121 if (unset)
122 strbuf_setlen(buf, 0);
123 else {
124 strbuf_addstr(buf, arg);
3b6aeb3c 125 strbuf_addstr(buf, "\n\n");
f9568530
JS
126 }
127 return 0;
128}
f5bbc322
KH
129
130static struct option builtin_commit_options[] = {
8c839683
JN
131 OPT__QUIET(&quiet, "suppress summary after successful commit"),
132 OPT__VERBOSE(&verbose, "show diff in commit message template"),
f5bbc322 133
e97ca7f4 134 OPT_GROUP("Commit message options"),
726c4e3d 135 OPT_FILENAME('F', "file", &logfile, "read message from file"),
23c6a803
MG
136 OPT_STRING(0, "author", &force_author, "author", "override author for commit"),
137 OPT_STRING(0, "date", &force_date, "date", "override date for commit"),
138 OPT_CALLBACK('m', "message", &message, "message", "commit message", opt_parse_m),
139 OPT_STRING('c', "reedit-message", &edit_message, "commit", "reuse and edit message from specified commit"),
140 OPT_STRING('C', "reuse-message", &use_message, "commit", "reuse message from specified commit"),
141 OPT_STRING(0, "fixup", &fixup_message, "commit", "use autosquash formatted message to fixup specified commit"),
142 OPT_STRING(0, "squash", &squash_message, "commit", "use autosquash formatted message to squash specified commit"),
c51f6cee 143 OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"),
362b0dd5 144 OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
df217ed6 145 OPT_FILENAME('t', "template", &template_file, "use specified template file"),
f5bbc322 146 OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
e97ca7f4 147 OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
bed575e4 148 OPT_BOOLEAN(0, "status", &include_status, "include status in commit message template"),
e97ca7f4 149 /* end commit message options */
f5bbc322
KH
150
151 OPT_GROUP("Commit contents options"),
152 OPT_BOOLEAN('a', "all", &all, "commit all changed files"),
153 OPT_BOOLEAN('i', "include", &also, "add specified files to index for commit"),
154 OPT_BOOLEAN(0, "interactive", &interactive, "interactively add files"),
b4bd4668 155 OPT_BOOLEAN('p', "patch", &patch_interactive, "interactively add changes"),
d4ba07ca 156 OPT_BOOLEAN('o', "only", &only, "commit only specified files"),
f5bbc322 157 OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
3a5d13a3 158 OPT_BOOLEAN(0, "dry-run", &dry_run, "show what would be committed"),
7c9f7038
JK
159 OPT_SET_INT(0, "short", &status_format, "show status concisely",
160 STATUS_FORMAT_SHORT),
05a59a08 161 OPT_BOOLEAN(0, "branch", &status_show_branch, "show branch information"),
7c9f7038 162 OPT_SET_INT(0, "porcelain", &status_format,
ba9d7fe1 163 "machine-readable output", STATUS_FORMAT_PORCELAIN),
7c9f7038
JK
164 OPT_BOOLEAN('z', "null", &null_termination,
165 "terminate entries with NUL"),
f5bbc322 166 OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
6f6bee3b 167 OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, "bypass post-rewrite hook"),
8547090c 168 { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
e97ca7f4 169 /* end commit contents options */
f5bbc322 170
c9b5fde7
ÆAB
171 { OPTION_BOOLEAN, 0, "allow-empty", &allow_empty, NULL,
172 "ok to record an empty change",
173 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
174 { OPTION_BOOLEAN, 0, "allow-empty-message", &allow_empty_message, NULL,
175 "ok to record a change with an empty message",
176 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
177
f5bbc322
KH
178 OPT_END()
179};
180
37f7a857
JS
181static void determine_whence(struct wt_status *s)
182{
183 if (file_exists(git_path("MERGE_HEAD")))
184 whence = FROM_MERGE;
185 else if (file_exists(git_path("CHERRY_PICK_HEAD")))
186 whence = FROM_CHERRY_PICK;
187 else
188 whence = FROM_COMMIT;
189 if (s)
190 s->whence = whence;
191}
192
193static const char *whence_s(void)
194{
195 char *s = "";
196
197 switch (whence) {
198 case FROM_COMMIT:
199 break;
200 case FROM_MERGE:
201 s = "merge";
202 break;
203 case FROM_CHERRY_PICK:
204 s = "cherry-pick";
205 break;
206 }
207
208 return s;
209}
210
2888605c
JH
211static void rollback_index_files(void)
212{
213 switch (commit_style) {
214 case COMMIT_AS_IS:
215 break; /* nothing to do */
216 case COMMIT_NORMAL:
217 rollback_lock_file(&index_lock);
218 break;
219 case COMMIT_PARTIAL:
220 rollback_lock_file(&index_lock);
221 rollback_lock_file(&false_lock);
222 break;
223 }
224}
225
5a9dd399 226static int commit_index_files(void)
2888605c 227{
5a9dd399
BC
228 int err = 0;
229
2888605c
JH
230 switch (commit_style) {
231 case COMMIT_AS_IS:
232 break; /* nothing to do */
233 case COMMIT_NORMAL:
5a9dd399 234 err = commit_lock_file(&index_lock);
2888605c
JH
235 break;
236 case COMMIT_PARTIAL:
5a9dd399 237 err = commit_lock_file(&index_lock);
2888605c
JH
238 rollback_lock_file(&false_lock);
239 break;
240 }
5a9dd399
BC
241
242 return err;
2888605c
JH
243}
244
245/*
246 * Take a union of paths in the index and the named tree (typically, "HEAD"),
247 * and return the paths that match the given pattern in list.
248 */
c455c87c 249static int list_paths(struct string_list *list, const char *with_tree,
2888605c
JH
250 const char *prefix, const char **pattern)
251{
252 int i;
253 char *m;
254
255 for (i = 0; pattern[i]; i++)
256 ;
257 m = xcalloc(1, i);
258
259 if (with_tree)
260 overlay_tree_on_cache(with_tree, prefix);
261
262 for (i = 0; i < active_nr; i++) {
263 struct cache_entry *ce = active_cache[i];
7fce6e3c
NTND
264 struct string_list_item *item;
265
7a51ed66 266 if (ce->ce_flags & CE_UPDATE)
e87e22d0 267 continue;
0b50922a 268 if (!match_pathspec(pattern, ce->name, ce_namelen(ce), 0, m))
2888605c 269 continue;
78a395d3 270 item = string_list_insert(list, ce->name);
7fce6e3c
NTND
271 if (ce_skip_worktree(ce))
272 item->util = item; /* better a valid pointer than a fake one */
2888605c
JH
273 }
274
275 return report_path_error(m, pattern, prefix ? strlen(prefix) : 0);
276}
277
c455c87c 278static void add_remove_files(struct string_list *list)
2888605c
JH
279{
280 int i;
281 for (i = 0; i < list->nr; i++) {
d177cab0 282 struct stat st;
c455c87c 283 struct string_list_item *p = &(list->items[i]);
d177cab0 284
7fce6e3c
NTND
285 /* p->util is skip-worktree */
286 if (p->util)
b4d1690d 287 continue;
d177cab0 288
c455c87c
JS
289 if (!lstat(p->string, &st)) {
290 if (add_to_cache(p->string, &st, 0))
8a6179bc 291 die(_("updating files failed"));
960b8ad1 292 } else
c455c87c 293 remove_file_from_cache(p->string);
2888605c
JH
294 }
295}
296
fa9dcf80
LT
297static void create_base_index(void)
298{
299 struct tree *tree;
300 struct unpack_trees_options opts;
301 struct tree_desc t;
302
303 if (initial_commit) {
304 discard_cache();
305 return;
306 }
307
308 memset(&opts, 0, sizeof(opts));
309 opts.head_idx = 1;
310 opts.index_only = 1;
311 opts.merge = 1;
34110cd4
LT
312 opts.src_index = &the_index;
313 opts.dst_index = &the_index;
fa9dcf80
LT
314
315 opts.fn = oneway_merge;
316 tree = parse_tree_indirect(head_sha1);
317 if (!tree)
8a6179bc 318 die(_("failed to unpack HEAD tree object"));
fa9dcf80
LT
319 parse_tree(tree);
320 init_tree_desc(&t, tree->buffer, tree->size);
203a2fe1
DB
321 if (unpack_trees(1, &t, &opts))
322 exit(128); /* We've already reported the error, finish dying */
fa9dcf80
LT
323}
324
d38a30df
MM
325static void refresh_cache_or_die(int refresh_flags)
326{
327 /*
328 * refresh_flags contains REFRESH_QUIET, so the only errors
329 * are for unmerged entries.
330 */
331 if (refresh_cache(refresh_flags | REFRESH_IN_PORCELAIN))
332 die_resolve_conflict("commit");
333}
334
50b7e70f 335static char *prepare_index(int argc, const char **argv, const char *prefix, int is_status)
f5bbc322
KH
336{
337 int fd;
c455c87c 338 struct string_list partial;
2888605c 339 const char **pathspec = NULL;
1020d087 340 char *old_index_env = NULL;
50b7e70f 341 int refresh_flags = REFRESH_QUIET;
f5bbc322 342
50b7e70f
JH
343 if (is_status)
344 refresh_flags |= REFRESH_UNMERGED;
f5bbc322 345
f64fe7b4
JH
346 if (*argv)
347 pathspec = get_pathspec(prefix, argv);
2888605c 348
671c9b7e 349 if (read_cache_preload(pathspec) < 0)
8a6179bc 350 die(_("index file corrupt"));
671c9b7e 351
1020d087
CI
352 if (interactive) {
353 fd = hold_locked_index(&index_lock, 1);
354
355 refresh_cache_or_die(refresh_flags);
356
357 if (write_cache(fd, active_cache, active_nr) ||
358 close_lock_file(&index_lock))
359 die(_("unable to create temporary index"));
360
361 old_index_env = getenv(INDEX_ENVIRONMENT);
362 setenv(INDEX_ENVIRONMENT, index_lock.filename, 1);
363
b4bd4668 364 if (interactive_add(argc, argv, prefix, patch_interactive) != 0)
1020d087
CI
365 die(_("interactive add failed"));
366
367 if (old_index_env && *old_index_env)
368 setenv(INDEX_ENVIRONMENT, old_index_env, 1);
369 else
370 unsetenv(INDEX_ENVIRONMENT);
371
372 discard_cache();
373 read_cache_from(index_lock.filename);
374
375 commit_style = COMMIT_NORMAL;
376 return index_lock.filename;
377 }
378
2888605c
JH
379 /*
380 * Non partial, non as-is commit.
381 *
382 * (1) get the real index;
383 * (2) update the_index as necessary;
384 * (3) write the_index out to the real index (still locked);
385 * (4) return the name of the locked index file.
386 *
387 * The caller should run hooks on the locked real index, and
388 * (A) if all goes well, commit the real index;
389 * (B) on failure, rollback the real index.
390 */
391 if (all || (also && pathspec && *pathspec)) {
1f2362a9 392 fd = hold_locked_index(&index_lock, 1);
7ae02a30 393 add_files_to_cache(also ? prefix : NULL, pathspec, 0);
d38a30df 394 refresh_cache_or_die(refresh_flags);
4ed7cd3a
BC
395 if (write_cache(fd, active_cache, active_nr) ||
396 close_lock_file(&index_lock))
8a6179bc 397 die(_("unable to write new_index file"));
2888605c
JH
398 commit_style = COMMIT_NORMAL;
399 return index_lock.filename;
f5bbc322
KH
400 }
401
2888605c
JH
402 /*
403 * As-is commit.
404 *
405 * (1) return the name of the real index file.
406 *
73276235
MH
407 * The caller should run hooks on the real index,
408 * and create commit from the_index.
2888605c
JH
409 * We still need to refresh the index here.
410 */
411 if (!pathspec || !*pathspec) {
412 fd = hold_locked_index(&index_lock, 1);
d38a30df 413 refresh_cache_or_die(refresh_flags);
d5f5d0a9
JH
414 if (active_cache_changed) {
415 if (write_cache(fd, active_cache, active_nr) ||
416 commit_locked_index(&index_lock))
8a6179bc 417 die(_("unable to write new_index file"));
d5f5d0a9
JH
418 } else {
419 rollback_lock_file(&index_lock);
420 }
2888605c 421 commit_style = COMMIT_AS_IS;
f5bbc322
KH
422 return get_index_file();
423 }
424
2888605c
JH
425 /*
426 * A partial commit.
427 *
428 * (0) find the set of affected paths;
429 * (1) get lock on the real index file;
430 * (2) update the_index with the given paths;
431 * (3) write the_index out to the real index (still locked);
432 * (4) get lock on the false index file;
433 * (5) reset the_index from HEAD;
434 * (6) update the_index the same way as (2);
435 * (7) write the_index out to the false index file;
436 * (8) return the name of the false index file (still locked);
437 *
438 * The caller should run hooks on the locked false index, and
439 * create commit from it. Then
440 * (A) if all goes well, commit the real index;
441 * (B) on failure, rollback the real index;
442 * In either case, rollback the false index.
443 */
444 commit_style = COMMIT_PARTIAL;
445
37f7a857 446 if (whence != FROM_COMMIT)
6c80cd29 447 die(_("cannot do a partial commit during a %s."), whence_s());
2888605c
JH
448
449 memset(&partial, 0, sizeof(partial));
c455c87c 450 partial.strdup_strings = 1;
2888605c
JH
451 if (list_paths(&partial, initial_commit ? NULL : "HEAD", prefix, pathspec))
452 exit(1);
453
454 discard_cache();
455 if (read_cache() < 0)
8a6179bc 456 die(_("cannot read the index"));
2888605c
JH
457
458 fd = hold_locked_index(&index_lock, 1);
459 add_remove_files(&partial);
ef12b50d 460 refresh_cache(REFRESH_QUIET);
4ed7cd3a
BC
461 if (write_cache(fd, active_cache, active_nr) ||
462 close_lock_file(&index_lock))
8a6179bc 463 die(_("unable to write new_index file"));
f5bbc322 464
2888605c 465 fd = hold_lock_file_for_update(&false_lock,
a157400c
JH
466 git_path("next-index-%"PRIuMAX,
467 (uintmax_t) getpid()),
acd3b9ec 468 LOCK_DIE_ON_ERROR);
fa9dcf80
LT
469
470 create_base_index();
2888605c 471 add_remove_files(&partial);
d37d3203 472 refresh_cache(REFRESH_QUIET);
f5bbc322 473
4ed7cd3a
BC
474 if (write_cache(fd, active_cache, active_nr) ||
475 close_lock_file(&false_lock))
8a6179bc 476 die(_("unable to write temporary index file"));
959ba670
JK
477
478 discard_cache();
479 read_cache_from(false_lock.filename);
480
2888605c 481 return false_lock.filename;
f5bbc322
KH
482}
483
d249b098
JH
484static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn,
485 struct wt_status *s)
f5bbc322 486{
76e2f7ce
JH
487 unsigned char sha1[20];
488
d249b098
JH
489 if (s->relative_paths)
490 s->prefix = prefix;
f5bbc322
KH
491
492 if (amend) {
d249b098
JH
493 s->amend = 1;
494 s->reference = "HEAD^1";
f5bbc322 495 }
d249b098
JH
496 s->verbose = verbose;
497 s->index_file = index_file;
498 s->fp = fp;
499 s->nowarn = nowarn;
76e2f7ce 500 s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0;
f5bbc322 501
76e2f7ce 502 wt_status_collect(s);
7c9f7038
JK
503
504 switch (status_format) {
505 case STATUS_FORMAT_SHORT:
05a59a08 506 wt_shortstatus_print(s, null_termination, status_show_branch);
7c9f7038
JK
507 break;
508 case STATUS_FORMAT_PORCELAIN:
4a7cc2fd 509 wt_porcelain_print(s, null_termination);
7c9f7038
JK
510 break;
511 case STATUS_FORMAT_LONG:
512 wt_status_print(s);
513 break;
514 }
f5bbc322 515
d249b098 516 return s->commitable;
f5bbc322
KH
517}
518
ec84bd00
PB
519static int is_a_merge(const unsigned char *sha1)
520{
521 struct commit *commit = lookup_commit(sha1);
522 if (!commit || parse_commit(commit))
8a6179bc 523 die(_("could not parse HEAD commit"));
ec84bd00
PB
524 return !!(commit->parents && commit->parents->next);
525}
526
f5bbc322
KH
527static const char sign_off_header[] = "Signed-off-by: ";
528
4c28e4ad 529static void determine_author_info(struct strbuf *author_ident)
a45d46ba
SB
530{
531 char *name, *email, *date;
532
533 name = getenv("GIT_AUTHOR_NAME");
534 email = getenv("GIT_AUTHOR_EMAIL");
535 date = getenv("GIT_AUTHOR_DATE");
536
37f7a857 537 if (author_message) {
a45d46ba
SB
538 const char *a, *lb, *rb, *eol;
539
37f7a857 540 a = strstr(author_message_buffer, "\nauthor ");
a45d46ba 541 if (!a)
6c80cd29 542 die(_("invalid commit: %s"), author_message);
a45d46ba 543
fb7749e4
JN
544 lb = strchrnul(a + strlen("\nauthor "), '<');
545 rb = strchrnul(lb, '>');
546 eol = strchrnul(rb, '\n');
547 if (!*lb || !*rb || !*eol)
6c80cd29 548 die(_("invalid commit: %s"), author_message);
a45d46ba 549
fb7749e4
JN
550 if (lb == a + strlen("\nauthor "))
551 /* \nauthor <foo@example.com> */
552 name = xcalloc(1, 1);
553 else
554 name = xmemdupz(a + strlen("\nauthor "),
555 (lb - strlen(" ") -
556 (a + strlen("\nauthor "))));
557 email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
558 date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> ")));
a45d46ba
SB
559 }
560
561 if (force_author) {
562 const char *lb = strstr(force_author, " <");
563 const char *rb = strchr(force_author, '>');
564
565 if (!lb || !rb)
8a6179bc 566 die(_("malformed --author parameter"));
a45d46ba
SB
567 name = xstrndup(force_author, lb - force_author);
568 email = xstrndup(lb + 2, rb - (lb + 2));
569 }
570
02b47cd7
MV
571 if (force_date)
572 date = force_date;
4c28e4ad
JH
573 strbuf_addstr(author_ident, fmt_ident(name, email, date,
574 IDENT_ERROR_ON_NO_NAME));
a45d46ba
SB
575}
576
c1e01b0c
DB
577static int ends_rfc2822_footer(struct strbuf *sb)
578{
579 int ch;
580 int hit = 0;
581 int i, j, k;
582 int len = sb->len;
583 int first = 1;
584 const char *buf = sb->buf;
585
586 for (i = len - 1; i > 0; i--) {
587 if (hit && buf[i] == '\n')
588 break;
589 hit = (buf[i] == '\n');
590 }
591
592 while (i < len - 1 && buf[i] == '\n')
593 i++;
594
595 for (; i < len; i = k) {
596 for (k = i; k < len && buf[k] != '\n'; k++)
597 ; /* do nothing */
598 k++;
599
600 if ((buf[k] == ' ' || buf[k] == '\t') && !first)
601 continue;
602
603 first = 0;
604
605 for (j = 0; i + j < len; j++) {
606 ch = buf[i + j];
607 if (ch == ':')
608 break;
609 if (isalnum(ch) ||
610 (ch == '-'))
611 continue;
612 return 0;
613 }
614 }
615 return 1;
616}
617
4c28e4ad
JH
618static char *cut_ident_timestamp_part(char *string)
619{
620 char *ket = strrchr(string, '>');
621 if (!ket || ket[1] != ' ')
8a6179bc 622 die(_("Malformed ident string: '%s'"), string);
4c28e4ad
JH
623 *++ket = '\0';
624 return ket;
625}
626
d249b098 627static int prepare_to_commit(const char *index_file, const char *prefix,
4c28e4ad
JH
628 struct wt_status *s,
629 struct strbuf *author_ident)
f5bbc322
KH
630{
631 struct stat statbuf;
4c28e4ad 632 struct strbuf committer_ident = STRBUF_INIT;
bc5d248a 633 int commitable, saved_color_setting;
f285a2d7 634 struct strbuf sb = STRBUF_INIT;
f5bbc322 635 char *buffer;
8089c85b
PB
636 const char *hook_arg1 = NULL;
637 const char *hook_arg2 = NULL;
bb1ae3f6 638 int ident_shown = 0;
8b1ae678 639 int clean_message_contents = (cleanup_mode != CLEANUP_NONE);
f5bbc322 640
ec84bd00
PB
641 if (!no_verify && run_hook(index_file, "pre-commit", NULL))
642 return 0;
f5bbc322 643
89ac1223
PN
644 if (squash_message) {
645 /*
646 * Insert the proper subject line before other commit
647 * message options add their content.
648 */
649 if (use_message && !strcmp(use_message, squash_message))
650 strbuf_addstr(&sb, "squash! ");
651 else {
652 struct pretty_print_context ctx = {0};
653 struct commit *c;
654 c = lookup_commit_reference_by_name(squash_message);
655 if (!c)
8a6179bc 656 die(_("could not lookup commit %s"), squash_message);
89ac1223
PN
657 ctx.output_encoding = get_commit_output_encoding();
658 format_commit_message(c, "squash! %s\n\n", &sb,
659 &ctx);
660 }
661 }
662
f9568530
JS
663 if (message.len) {
664 strbuf_addbuf(&sb, &message);
8089c85b 665 hook_arg1 = "message";
f5bbc322
KH
666 } else if (logfile && !strcmp(logfile, "-")) {
667 if (isatty(0))
8a6179bc 668 fprintf(stderr, _("(reading log message from standard input)\n"));
f5bbc322 669 if (strbuf_read(&sb, 0, 0) < 0)
8a6179bc 670 die_errno(_("could not read log from standard input"));
8089c85b 671 hook_arg1 = "message";
f5bbc322
KH
672 } else if (logfile) {
673 if (strbuf_read_file(&sb, logfile, 0) < 0)
8a6179bc 674 die_errno(_("could not read log file '%s'"),
d824cbba 675 logfile);
8089c85b 676 hook_arg1 = "message";
f5bbc322
KH
677 } else if (use_message) {
678 buffer = strstr(use_message_buffer, "\n\n");
679 if (!buffer || buffer[2] == '\0')
8a6179bc 680 die(_("commit has empty message"));
f5bbc322 681 strbuf_add(&sb, buffer + 2, strlen(buffer + 2));
8089c85b
PB
682 hook_arg1 = "commit";
683 hook_arg2 = use_message;
d71b8ba7
PN
684 } else if (fixup_message) {
685 struct pretty_print_context ctx = {0};
686 struct commit *commit;
687 commit = lookup_commit_reference_by_name(fixup_message);
688 if (!commit)
8a6179bc 689 die(_("could not lookup commit %s"), fixup_message);
d71b8ba7
PN
690 ctx.output_encoding = get_commit_output_encoding();
691 format_commit_message(commit, "fixup! %s\n\n",
692 &sb, &ctx);
693 hook_arg1 = "message";
f5bbc322
KH
694 } else if (!stat(git_path("MERGE_MSG"), &statbuf)) {
695 if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0)
8a6179bc 696 die_errno(_("could not read MERGE_MSG"));
8089c85b 697 hook_arg1 = "merge";
f5bbc322
KH
698 } else if (!stat(git_path("SQUASH_MSG"), &statbuf)) {
699 if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0)
8a6179bc 700 die_errno(_("could not read SQUASH_MSG"));
8089c85b 701 hook_arg1 = "squash";
2140b140 702 } else if (template_file) {
f5bbc322 703 if (strbuf_read_file(&sb, template_file, 0) < 0)
8a6179bc 704 die_errno(_("could not read '%s'"), template_file);
8089c85b 705 hook_arg1 = "template";
8b1ae678 706 clean_message_contents = 0;
f5bbc322
KH
707 }
708
8089c85b 709 /*
37f7a857
JS
710 * The remaining cases don't modify the template message, but
711 * just set the argument(s) to the prepare-commit-msg hook.
8089c85b 712 */
37f7a857 713 else if (whence == FROM_MERGE)
8089c85b 714 hook_arg1 = "merge";
37f7a857
JS
715 else if (whence == FROM_CHERRY_PICK) {
716 hook_arg1 = "commit";
717 hook_arg2 = "CHERRY_PICK_HEAD";
718 }
8089c85b 719
89ac1223
PN
720 if (squash_message) {
721 /*
722 * If squash_commit was used for the commit subject,
723 * then we're possibly hijacking other commit log options.
724 * Reset the hook args to tell the real story.
725 */
726 hook_arg1 = "message";
727 hook_arg2 = "";
728 }
729
37f3012f
JN
730 s->fp = fopen(git_path(commit_editmsg), "w");
731 if (s->fp == NULL)
8a6179bc 732 die_errno(_("could not open '%s'"), git_path(commit_editmsg));
f5bbc322 733
8b1ae678 734 if (clean_message_contents)
5f065737 735 stripspace(&sb, 0);
f5bbc322
KH
736
737 if (signoff) {
f285a2d7 738 struct strbuf sob = STRBUF_INIT;
13208572
JS
739 int i;
740
13208572 741 strbuf_addstr(&sob, sign_off_header);
d9ccfe77
JH
742 strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
743 getenv("GIT_COMMITTER_EMAIL")));
13208572 744 strbuf_addch(&sob, '\n');
13208572
JS
745 for (i = sb.len - 1; i > 0 && sb.buf[i - 1] != '\n'; i--)
746 ; /* do nothing */
2150554b 747 if (prefixcmp(sb.buf + i, sob.buf)) {
e5138436 748 if (!i || !ends_rfc2822_footer(&sb))
2150554b 749 strbuf_addch(&sb, '\n');
13208572 750 strbuf_addbuf(&sb, &sob);
2150554b 751 }
13208572 752 strbuf_release(&sob);
f5bbc322
KH
753 }
754
37f3012f 755 if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
8a6179bc 756 die_errno(_("could not write commit template"));
13208572 757
f5bbc322
KH
758 strbuf_release(&sb);
759
4c28e4ad
JH
760 /* This checks and barfs if author is badly specified */
761 determine_author_info(author_ident);
e83dbe80 762
bb1ae3f6 763 /* This checks if committer ident is explicitly given */
4c28e4ad 764 strbuf_addstr(&committer_ident, git_committer_info(0));
bed575e4 765 if (use_editor && include_status) {
4c28e4ad 766 char *ai_tmp, *ci_tmp;
37f7a857 767 if (whence != FROM_COMMIT)
b926c0d1 768 status_printf_ln(s, GIT_COLOR_NORMAL,
fe8165cd 769 _("\n"
f4784b3e 770 "It looks like you may be committing a %s.\n"
b926c0d1
JN
771 "If this is not correct, please remove the file\n"
772 " %s\n"
773 "and try again.\n"
fe8165cd 774 ""),
37f7a857
JS
775 whence_s(),
776 git_path(whence == FROM_MERGE
777 ? "MERGE_HEAD"
778 : "CHERRY_PICK_HEAD"));
ec84bd00 779
b926c0d1
JN
780 fprintf(s->fp, "\n");
781 status_printf(s, GIT_COLOR_NORMAL,
0b430a17 782 _("Please enter the commit message for your changes."));
ec84bd00 783 if (cleanup_mode == CLEANUP_ALL)
b926c0d1 784 status_printf_more(s, GIT_COLOR_NORMAL,
0b430a17 785 _(" Lines starting\n"
b926c0d1 786 "with '#' will be ignored, and an empty"
0b430a17 787 " message aborts the commit.\n"));
ec84bd00 788 else /* CLEANUP_SPACE, that is. */
b926c0d1 789 status_printf_more(s, GIT_COLOR_NORMAL,
0b430a17 790 _(" Lines starting\n"
b926c0d1 791 "with '#' will be kept; you may remove them"
fdc7c811 792 " yourself if you want to.\n"
0b430a17 793 "An empty message aborts the commit.\n"));
ec84bd00 794 if (only_include_assumed)
b926c0d1
JN
795 status_printf_ln(s, GIT_COLOR_NORMAL,
796 "%s", only_include_assumed);
ec84bd00 797
4c28e4ad
JH
798 ai_tmp = cut_ident_timestamp_part(author_ident->buf);
799 ci_tmp = cut_ident_timestamp_part(committer_ident.buf);
800 if (strcmp(author_ident->buf, committer_ident.buf))
b926c0d1 801 status_printf_ln(s, GIT_COLOR_NORMAL,
fe8165cd
ÆAB
802 _("%s"
803 "Author: %s"),
b926c0d1 804 ident_shown++ ? "" : "\n",
4c28e4ad 805 author_ident->buf);
e83dbe80 806
5aeb3a3a 807 if (!user_ident_sufficiently_given())
b926c0d1 808 status_printf_ln(s, GIT_COLOR_NORMAL,
fe8165cd
ÆAB
809 _("%s"
810 "Committer: %s"),
b926c0d1 811 ident_shown++ ? "" : "\n",
4c28e4ad 812 committer_ident.buf);
bb1ae3f6
SB
813
814 if (ident_shown)
b926c0d1 815 status_printf_ln(s, GIT_COLOR_NORMAL, "");
bb1ae3f6 816
d249b098
JH
817 saved_color_setting = s->use_color;
818 s->use_color = 0;
37f3012f 819 commitable = run_status(s->fp, index_file, prefix, 1, s);
d249b098 820 s->use_color = saved_color_setting;
4c28e4ad
JH
821
822 *ai_tmp = ' ';
823 *ci_tmp = ' ';
ec84bd00 824 } else {
d616a239 825 unsigned char sha1[20];
fbcf1184 826 const char *parent = "HEAD";
7168624c 827
7168624c 828 if (!active_nr && read_cache() < 0)
8a6179bc 829 die(_("Cannot read index"));
7168624c 830
fbcf1184
JH
831 if (amend)
832 parent = "HEAD^1";
833
d616a239 834 if (get_sha1(parent, sha1))
ec84bd00 835 commitable = !!active_nr;
75f3ff2e
SB
836 else
837 commitable = index_differs_from(parent, 0);
ec84bd00 838 }
4c28e4ad 839 strbuf_release(&committer_ident);
d616a239 840
37f3012f 841 fclose(s->fp);
7168624c 842
37f7a857
JS
843 /*
844 * Reject an attempt to record a non-merge empty commit without
845 * explicit --allow-empty. In the cherry-pick case, it may be
846 * empty due to conflict resolution, which the user should okay.
847 */
848 if (!commitable && whence != FROM_MERGE && !allow_empty &&
ec84bd00 849 !(amend && is_a_merge(head_sha1))) {
d249b098 850 run_status(stdout, index_file, prefix, 0, s);
f197ed2f 851 if (amend)
fc88e316 852 fputs(_(empty_amend_advice), stderr);
37f7a857 853 else if (whence == FROM_CHERRY_PICK)
6c80cd29 854 fputs(_(empty_cherry_pick_advice), stderr);
ec84bd00 855 return 0;
7168624c
AR
856 }
857
ec84bd00
PB
858 /*
859 * Re-read the index as pre-commit hook could have updated it,
860 * and write it out as a tree. We must do this before we invoke
861 * the editor and after we invoke run_status above.
862 */
863 discard_cache();
864 read_cache_from(index_file);
865 if (!active_cache_tree)
866 active_cache_tree = cache_tree();
867 if (cache_tree_update(active_cache_tree,
868 active_cache, active_nr, 0, 0) < 0) {
8a6179bc 869 error(_("Error building trees"));
ec84bd00 870 return 0;
7168624c 871 }
f5bbc322 872
8089c85b
PB
873 if (run_hook(index_file, "prepare-commit-msg",
874 git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
875 return 0;
f5bbc322 876
ec84bd00
PB
877 if (use_editor) {
878 char index[PATH_MAX];
66dbfd55
GV
879 const char *env[2] = { NULL };
880 env[0] = index;
ec84bd00 881 snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
7198203a
SB
882 if (launch_editor(git_path(commit_editmsg), NULL, env)) {
883 fprintf(stderr,
8a6179bc 884 _("Please supply the message using either -m or -F option.\n"));
7198203a
SB
885 exit(1);
886 }
ec84bd00 887 }
f5bbc322 888
ec84bd00
PB
889 if (!no_verify &&
890 run_hook(index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
891 return 0;
892 }
f5bbc322 893
ec84bd00 894 return 1;
f5bbc322
KH
895}
896
897/*
6bb6b034
MV
898 * Find out if the message in the strbuf contains only whitespace and
899 * Signed-off-by lines.
f5bbc322 900 */
6bb6b034 901static int message_is_empty(struct strbuf *sb)
f5bbc322 902{
f285a2d7 903 struct strbuf tmpl = STRBUF_INIT;
f5bbc322 904 const char *nl;
6bb6b034 905 int eol, i, start = 0;
f5bbc322 906
5f065737
AR
907 if (cleanup_mode == CLEANUP_NONE && sb->len)
908 return 0;
909
f5bbc322 910 /* See if the template is just a prefix of the message. */
f5bbc322 911 if (template_file && strbuf_read_file(&tmpl, template_file, 0) > 0) {
5f065737 912 stripspace(&tmpl, cleanup_mode == CLEANUP_ALL);
f5bbc322
KH
913 if (start + tmpl.len <= sb->len &&
914 memcmp(tmpl.buf, sb->buf + start, tmpl.len) == 0)
915 start += tmpl.len;
916 }
917 strbuf_release(&tmpl);
918
919 /* Check if the rest is just whitespace and Signed-of-by's. */
920 for (i = start; i < sb->len; i++) {
921 nl = memchr(sb->buf + i, '\n', sb->len - i);
922 if (nl)
923 eol = nl - sb->buf;
924 else
925 eol = sb->len;
926
927 if (strlen(sign_off_header) <= eol - i &&
928 !prefixcmp(sb->buf + i, sign_off_header)) {
929 i = eol;
930 continue;
931 }
932 while (i < eol)
933 if (!isspace(sb->buf[i++]))
934 return 0;
935 }
936
937 return 1;
938}
939
146ea068
JH
940static const char *find_author_by_nickname(const char *name)
941{
942 struct rev_info revs;
943 struct commit *commit;
944 struct strbuf buf = STRBUF_INIT;
945 const char *av[20];
946 int ac = 0;
947
948 init_revisions(&revs, NULL);
949 strbuf_addf(&buf, "--author=%s", name);
950 av[++ac] = "--all";
951 av[++ac] = "-i";
952 av[++ac] = buf.buf;
953 av[++ac] = NULL;
954 setup_revisions(ac, av, &revs, NULL);
955 prepare_revision_walk(&revs);
956 commit = get_revision(&revs);
957 if (commit) {
dd2e794a
TR
958 struct pretty_print_context ctx = {0};
959 ctx.date_mode = DATE_NORMAL;
146ea068 960 strbuf_release(&buf);
dd2e794a 961 format_commit_message(commit, "%an <%ae>", &buf, &ctx);
146ea068
JH
962 return strbuf_detach(&buf, NULL);
963 }
8a6179bc 964 die(_("No existing author found with '%s'"), name);
146ea068
JH
965}
966
76e2f7ce
JH
967
968static void handle_untracked_files_arg(struct wt_status *s)
969{
970 if (!untracked_files_arg)
971 ; /* default already initialized */
972 else if (!strcmp(untracked_files_arg, "no"))
973 s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
974 else if (!strcmp(untracked_files_arg, "normal"))
975 s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
976 else if (!strcmp(untracked_files_arg, "all"))
977 s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
978 else
8a6179bc 979 die(_("Invalid untracked files mode '%s'"), untracked_files_arg);
76e2f7ce
JH
980}
981
37f7a857
JS
982static const char *read_commit_message(const char *name)
983{
984 const char *out_enc, *out;
985 struct commit *commit;
986
987 commit = lookup_commit_reference_by_name(name);
988 if (!commit)
6c80cd29 989 die(_("could not lookup commit %s"), name);
37f7a857
JS
990 out_enc = get_commit_output_encoding();
991 out = logmsg_reencode(commit, out_enc);
992
993 /*
994 * If we failed to reencode the buffer, just copy it
995 * byte for byte so the user can try to fix it up.
996 * This also handles the case where input and output
997 * encodings are identical.
998 */
999 if (out == NULL)
1000 out = xstrdup(commit->buffer);
1001 return out;
1002}
1003
2f02b25f 1004static int parse_and_validate_options(int argc, const char *argv[],
dbd0f5c7 1005 const char * const usage[],
d249b098
JH
1006 const char *prefix,
1007 struct wt_status *s)
f5bbc322
KH
1008{
1009 int f = 0;
1010
37782920
SB
1011 argc = parse_options(argc, argv, prefix, builtin_commit_options, usage,
1012 0);
f5bbc322 1013
146ea068
JH
1014 if (force_author && !strchr(force_author, '>'))
1015 force_author = find_author_by_nickname(force_author);
1016
c51f6cee 1017 if (force_author && renew_authorship)
8a6179bc 1018 die(_("Using both --reset-author and --author does not make sense"));
c51f6cee 1019
d71b8ba7 1020 if (logfile || message.len || use_message || fixup_message)
4803466f 1021 use_editor = 0;
f5bbc322 1022 if (edit_flag)
4803466f 1023 use_editor = 1;
406400ce
PB
1024 if (!use_editor)
1025 setenv("GIT_EDITOR", ":", 1);
f5bbc322
KH
1026
1027 if (get_sha1("HEAD", head_sha1))
1028 initial_commit = 1;
1029
f5bbc322
KH
1030 /* Sanity check options */
1031 if (amend && initial_commit)
8a6179bc 1032 die(_("You have nothing to amend."));
37f7a857 1033 if (amend && whence != FROM_COMMIT)
6c80cd29 1034 die(_("You are in the middle of a %s -- cannot amend."), whence_s());
89ac1223 1035 if (fixup_message && squash_message)
9c227655 1036 die(_("Options --squash and --fixup cannot be used together"));
f5bbc322
KH
1037 if (use_message)
1038 f++;
1039 if (edit_message)
1040 f++;
d71b8ba7
PN
1041 if (fixup_message)
1042 f++;
f5bbc322
KH
1043 if (logfile)
1044 f++;
1045 if (f > 1)
8a6179bc 1046 die(_("Only one of -c/-C/-F/--fixup can be used."));
f9568530 1047 if (message.len && f > 0)
8a6179bc 1048 die((_("Option -m cannot be combined with -c/-C/-F/--fixup.")));
f5bbc322
KH
1049 if (edit_message)
1050 use_message = edit_message;
d71b8ba7 1051 if (amend && !use_message && !fixup_message)
f5bbc322 1052 use_message = "HEAD";
37f7a857 1053 if (!use_message && whence != FROM_CHERRY_PICK && renew_authorship)
8a6179bc 1054 die(_("--reset-author can be used only with -C, -c or --amend."));
f5bbc322 1055 if (use_message) {
37f7a857
JS
1056 use_message_buffer = read_commit_message(use_message);
1057 if (!renew_authorship) {
1058 author_message = use_message;
1059 author_message_buffer = use_message_buffer;
1060 }
1061 }
1062 if (whence == FROM_CHERRY_PICK && !renew_authorship) {
1063 author_message = "CHERRY_PICK_HEAD";
1064 author_message_buffer = read_commit_message(author_message);
f5bbc322
KH
1065 }
1066
b4bd4668
CI
1067 if (patch_interactive)
1068 interactive = 1;
1069
f5bbc322 1070 if (!!also + !!only + !!all + !!interactive > 1)
b4bd4668 1071 die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
f5bbc322 1072 if (argc == 0 && (also || (only && !amend)))
8a6179bc 1073 die(_("No paths with --include/--only does not make sense."));
f5bbc322 1074 if (argc == 0 && only && amend)
8a6179bc 1075 only_include_assumed = _("Clever... amending the last one with dirty index.");
3c5283f8 1076 if (argc > 0 && !also && !only)
8a6179bc 1077 only_include_assumed = _("Explicit paths specified without -i nor -o; assuming --only paths...");
5f065737
AR
1078 if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
1079 cleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;
1080 else if (!strcmp(cleanup_arg, "verbatim"))
1081 cleanup_mode = CLEANUP_NONE;
1082 else if (!strcmp(cleanup_arg, "whitespace"))
1083 cleanup_mode = CLEANUP_SPACE;
1084 else if (!strcmp(cleanup_arg, "strip"))
1085 cleanup_mode = CLEANUP_ALL;
1086 else
8a6179bc 1087 die(_("Invalid cleanup mode %s"), cleanup_arg);
f5bbc322 1088
76e2f7ce 1089 handle_untracked_files_arg(s);
4bfee30a 1090
f5bbc322 1091 if (all && argc > 0)
8a6179bc 1092 die(_("Paths with -a does not make sense."));
f5bbc322 1093
7c9f7038
JK
1094 if (null_termination && status_format == STATUS_FORMAT_LONG)
1095 status_format = STATUS_FORMAT_PORCELAIN;
1096 if (status_format != STATUS_FORMAT_LONG)
1097 dry_run = 1;
1098
f5bbc322
KH
1099 return argc;
1100}
1101
d249b098
JH
1102static int dry_run_commit(int argc, const char **argv, const char *prefix,
1103 struct wt_status *s)
f5bbc322 1104{
f5bbc322 1105 int commitable;
3a5d13a3 1106 const char *index_file;
f5bbc322 1107
3a5d13a3 1108 index_file = prepare_index(argc, argv, prefix, 1);
d249b098 1109 commitable = run_status(stdout, index_file, prefix, 0, s);
3a5d13a3 1110 rollback_index_files();
f5bbc322 1111
3a5d13a3
JH
1112 return commitable ? 0 : 1;
1113}
1114
f766b367
JH
1115static int parse_status_slot(const char *var, int offset)
1116{
1117 if (!strcasecmp(var+offset, "header"))
1118 return WT_STATUS_HEADER;
1d282327
AA
1119 if (!strcasecmp(var+offset, "branch"))
1120 return WT_STATUS_ONBRANCH;
f766b367
JH
1121 if (!strcasecmp(var+offset, "updated")
1122 || !strcasecmp(var+offset, "added"))
1123 return WT_STATUS_UPDATED;
1124 if (!strcasecmp(var+offset, "changed"))
1125 return WT_STATUS_CHANGED;
1126 if (!strcasecmp(var+offset, "untracked"))
1127 return WT_STATUS_UNTRACKED;
1128 if (!strcasecmp(var+offset, "nobranch"))
1129 return WT_STATUS_NOBRANCH;
1130 if (!strcasecmp(var+offset, "unmerged"))
1131 return WT_STATUS_UNMERGED;
8b8e8624 1132 return -1;
f766b367
JH
1133}
1134
1135static int git_status_config(const char *k, const char *v, void *cb)
1136{
1137 struct wt_status *s = cb;
1138
1139 if (!strcmp(k, "status.submodulesummary")) {
1140 int is_bool;
1141 s->submodule_summary = git_config_bool_or_int(k, v, &is_bool);
1142 if (is_bool && s->submodule_summary)
1143 s->submodule_summary = -1;
1144 return 0;
1145 }
1146 if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
e269eb79 1147 s->use_color = git_config_colorbool(k, v);
f766b367
JH
1148 return 0;
1149 }
1150 if (!prefixcmp(k, "status.color.") || !prefixcmp(k, "color.status.")) {
1151 int slot = parse_status_slot(k, 13);
8b8e8624
JK
1152 if (slot < 0)
1153 return 0;
f766b367
JH
1154 if (!v)
1155 return config_error_nonbool(k);
1156 color_parse(v, k, s->color_palette[slot]);
1157 return 0;
1158 }
1159 if (!strcmp(k, "status.relativepaths")) {
1160 s->relative_paths = git_config_bool(k, v);
1161 return 0;
1162 }
1163 if (!strcmp(k, "status.showuntrackedfiles")) {
1164 if (!v)
1165 return config_error_nonbool(k);
1166 else if (!strcmp(v, "no"))
1167 s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
1168 else if (!strcmp(v, "normal"))
1169 s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
1170 else if (!strcmp(v, "all"))
1171 s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
1172 else
8a6179bc 1173 return error(_("Invalid untracked files mode '%s'"), v);
f766b367
JH
1174 return 0;
1175 }
1176 return git_diff_ui_config(k, v, NULL);
1177}
1178
3a5d13a3
JH
1179int cmd_status(int argc, const char **argv, const char *prefix)
1180{
d249b098 1181 struct wt_status s;
4bb6644d 1182 int fd;
76e2f7ce 1183 unsigned char sha1[20];
9e4b7ab6 1184 static struct option builtin_status_options[] = {
fd03881a 1185 OPT__VERBOSE(&verbose, "be verbose"),
dd2be243
JK
1186 OPT_SET_INT('s', "short", &status_format,
1187 "show status concisely", STATUS_FORMAT_SHORT),
05a59a08
DKF
1188 OPT_BOOLEAN('b', "branch", &status_show_branch,
1189 "show branch information"),
6f157871 1190 OPT_SET_INT(0, "porcelain", &status_format,
ba9d7fe1 1191 "machine-readable output",
6f157871 1192 STATUS_FORMAT_PORCELAIN),
173e6c88
JH
1193 OPT_BOOLEAN('z', "null", &null_termination,
1194 "terminate entries with NUL"),
76e2f7ce
JH
1195 { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg,
1196 "mode",
1197 "show untracked files, optional modes: all, normal, no. (Default: all)",
1198 PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
2381e39e
JH
1199 OPT_BOOLEAN(0, "ignored", &show_ignored_in_status,
1200 "show ignored files"),
46a958b3
JL
1201 { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, "when",
1202 "ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)",
1203 PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
76e2f7ce
JH
1204 OPT_END(),
1205 };
1206
5d3dd915
NTND
1207 if (argc == 2 && !strcmp(argv[1], "-h"))
1208 usage_with_options(builtin_status_usage, builtin_status_options);
1209
d249b098 1210 wt_status_prepare(&s);
302ad7a9 1211 gitmodules_config();
d249b098 1212 git_config(git_status_config, &s);
37f7a857 1213 determine_whence(&s);
76e2f7ce 1214 argc = parse_options(argc, argv, prefix,
9e4b7ab6
JH
1215 builtin_status_options,
1216 builtin_status_usage, 0);
000f97bd
BC
1217
1218 if (null_termination && status_format == STATUS_FORMAT_LONG)
1219 status_format = STATUS_FORMAT_PORCELAIN;
1220
76e2f7ce 1221 handle_untracked_files_arg(&s);
2381e39e
JH
1222 if (show_ignored_in_status)
1223 s.show_ignored_files = 1;
76e2f7ce
JH
1224 if (*argv)
1225 s.pathspec = get_pathspec(prefix, argv);
1226
149794dd 1227 read_cache_preload(s.pathspec);
688cd6d2 1228 refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec, NULL, NULL);
4bb6644d
MH
1229
1230 fd = hold_locked_index(&index_lock, 0);
ccdc4ec3
JH
1231 if (0 <= fd)
1232 update_index_if_able(&the_index, &index_lock);
4bb6644d 1233
76e2f7ce 1234 s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
46a958b3 1235 s.ignore_submodule_arg = ignore_submodule_arg;
76e2f7ce
JH
1236 wt_status_collect(&s);
1237
8661768f
JK
1238 if (s.relative_paths)
1239 s.prefix = prefix;
d249b098
JH
1240 if (s.use_color == -1)
1241 s.use_color = git_use_color_default;
38920dd6
MH
1242 if (diff_use_color_default == -1)
1243 diff_use_color_default = git_use_color_default;
1244
dd2be243
JK
1245 switch (status_format) {
1246 case STATUS_FORMAT_SHORT:
05a59a08 1247 wt_shortstatus_print(&s, null_termination, status_show_branch);
dd2be243 1248 break;
6f157871 1249 case STATUS_FORMAT_PORCELAIN:
4a7cc2fd 1250 wt_porcelain_print(&s, null_termination);
6f157871 1251 break;
dd2be243 1252 case STATUS_FORMAT_LONG:
173e6c88 1253 s.verbose = verbose;
46a958b3 1254 s.ignore_submodule_arg = ignore_submodule_arg;
173e6c88 1255 wt_status_print(&s);
dd2be243 1256 break;
173e6c88 1257 }
76e2f7ce 1258 return 0;
f5bbc322
KH
1259}
1260
f5bbc322
KH
1261static void print_summary(const char *prefix, const unsigned char *sha1)
1262{
1263 struct rev_info rev;
1264 struct commit *commit;
49ff9a7a 1265 struct strbuf format = STRBUF_INIT;
c85db254
JK
1266 unsigned char junk_sha1[20];
1267 const char *head = resolve_ref("HEAD", junk_sha1, 0, NULL);
49ff9a7a
JK
1268 struct pretty_print_context pctx = {0};
1269 struct strbuf author_ident = STRBUF_INIT;
1270 struct strbuf committer_ident = STRBUF_INIT;
f5bbc322
KH
1271
1272 commit = lookup_commit(sha1);
1273 if (!commit)
8a6179bc 1274 die(_("couldn't look up newly created commit"));
f5bbc322 1275 if (!commit || parse_commit(commit))
8a6179bc 1276 die(_("could not parse newly created commit"));
f5bbc322 1277
49ff9a7a
JK
1278 strbuf_addstr(&format, "format:%h] %s");
1279
1280 format_commit_message(commit, "%an <%ae>", &author_ident, &pctx);
1281 format_commit_message(commit, "%cn <%ce>", &committer_ident, &pctx);
1282 if (strbuf_cmp(&author_ident, &committer_ident)) {
1283 strbuf_addstr(&format, "\n Author: ");
1284 strbuf_addbuf_percentquote(&format, &author_ident);
1285 }
1a893064 1286 if (!user_ident_sufficiently_given()) {
49ff9a7a
JK
1287 strbuf_addstr(&format, "\n Committer: ");
1288 strbuf_addbuf_percentquote(&format, &committer_ident);
b706fcfe
JK
1289 if (advice_implicit_identity) {
1290 strbuf_addch(&format, '\n');
fc88e316 1291 strbuf_addstr(&format, _(implicit_ident_advice));
b706fcfe 1292 }
49ff9a7a
JK
1293 }
1294 strbuf_release(&author_ident);
1295 strbuf_release(&committer_ident);
1296
f5bbc322
KH
1297 init_revisions(&rev, prefix);
1298 setup_revisions(0, NULL, &rev, NULL);
1299
f5bbc322
KH
1300 rev.diff = 1;
1301 rev.diffopt.output_format =
1302 DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY;
1303
1304 rev.verbose_header = 1;
1305 rev.show_root_diff = 1;
49ff9a7a 1306 get_commit_format(format.buf, &rev);
bf82a150 1307 rev.always_show_header = 0;
3eb2a15e 1308 rev.diffopt.detect_rename = 1;
3eb2a15e 1309 rev.diffopt.break_opt = 0;
15964563 1310 diff_setup_done(&rev.diffopt);
f5bbc322 1311
c5ee71fd 1312 printf("[%s%s ",
c85db254
JK
1313 !prefixcmp(head, "refs/heads/") ?
1314 head + 11 :
1315 !strcmp(head, "HEAD") ?
7f5673d7 1316 _("detached HEAD") :
c85db254 1317 head,
7f5673d7 1318 initial_commit ? _(" (root-commit)") : "");
f5bbc322 1319
bf82a150 1320 if (!log_tree_commit(&rev, commit)) {
a45e1a87
TRC
1321 rev.always_show_header = 1;
1322 rev.use_terminator = 1;
1323 log_tree_commit(&rev, commit);
bf82a150 1324 }
a45e1a87 1325
fc6f19fe 1326 strbuf_release(&format);
f5bbc322
KH
1327}
1328
186458b1 1329static int git_commit_config(const char *k, const char *v, void *cb)
f5bbc322 1330{
d249b098
JH
1331 struct wt_status *s = cb;
1332
984c6e7e 1333 if (!strcmp(k, "commit.template"))
395de250 1334 return git_config_pathname(&template_file, k, v);
bed575e4
JHI
1335 if (!strcmp(k, "commit.status")) {
1336 include_status = git_config_bool(k, v);
1337 return 0;
1338 }
f5bbc322 1339
d249b098 1340 return git_status_config(k, v, s);
f5bbc322
KH
1341}
1342
6f6bee3b
TR
1343static const char post_rewrite_hook[] = "hooks/post-rewrite";
1344
1345static int run_rewrite_hook(const unsigned char *oldsha1,
1346 const unsigned char *newsha1)
1347{
1348 /* oldsha1 SP newsha1 LF NUL */
1349 static char buf[2*40 + 3];
1350 struct child_process proc;
1351 const char *argv[3];
1352 int code;
1353 size_t n;
1354
1355 if (access(git_path(post_rewrite_hook), X_OK) < 0)
1356 return 0;
1357
1358 argv[0] = git_path(post_rewrite_hook);
1359 argv[1] = "amend";
1360 argv[2] = NULL;
1361
1362 memset(&proc, 0, sizeof(proc));
1363 proc.argv = argv;
1364 proc.in = -1;
1365 proc.stdout_to_stderr = 1;
1366
1367 code = start_command(&proc);
1368 if (code)
1369 return code;
1370 n = snprintf(buf, sizeof(buf), "%s %s\n",
1371 sha1_to_hex(oldsha1), sha1_to_hex(newsha1));
1372 write_in_full(proc.in, buf, n);
1373 close(proc.in);
1374 return finish_command(&proc);
1375}
1376
f5bbc322
KH
1377int cmd_commit(int argc, const char **argv, const char *prefix)
1378{
f285a2d7 1379 struct strbuf sb = STRBUF_INIT;
4c28e4ad 1380 struct strbuf author_ident = STRBUF_INIT;
f5bbc322 1381 const char *index_file, *reflog_msg;
99a12694 1382 char *nl, *p;
f5bbc322
KH
1383 unsigned char commit_sha1[20];
1384 struct ref_lock *ref_lock;
6bb6b034 1385 struct commit_list *parents = NULL, **pptr = &parents;
cf10f9fd
MV
1386 struct stat statbuf;
1387 int allow_fast_forward = 1;
d249b098 1388 struct wt_status s;
f5bbc322 1389
5d3dd915
NTND
1390 if (argc == 2 && !strcmp(argv[1], "-h"))
1391 usage_with_options(builtin_commit_usage, builtin_commit_options);
1392
d249b098
JH
1393 wt_status_prepare(&s);
1394 git_config(git_commit_config, &s);
37f7a857 1395 determine_whence(&s);
f5bbc322 1396
d249b098
JH
1397 if (s.use_color == -1)
1398 s.use_color = git_use_color_default;
d249b098
JH
1399 argc = parse_and_validate_options(argc, argv, builtin_commit_usage,
1400 prefix, &s);
3fa509df
JH
1401 if (dry_run) {
1402 if (diff_use_color_default == -1)
1403 diff_use_color_default = git_use_color_default;
d249b098 1404 return dry_run_commit(argc, argv, prefix, &s);
3fa509df 1405 }
50b7e70f 1406 index_file = prepare_index(argc, argv, prefix, 0);
f5bbc322 1407
ec84bd00
PB
1408 /* Set up everything for writing the commit object. This includes
1409 running hooks, writing the trees, and interacting with the user. */
4c28e4ad 1410 if (!prepare_to_commit(index_file, prefix, &s, &author_ident)) {
2888605c 1411 rollback_index_files();
f5bbc322
KH
1412 return 1;
1413 }
1414
f5bbc322 1415 /* Determine parents */
643cb5f7 1416 reflog_msg = getenv("GIT_REFLOG_ACTION");
f5bbc322 1417 if (initial_commit) {
643cb5f7
CC
1418 if (!reflog_msg)
1419 reflog_msg = "commit (initial)";
f5bbc322
KH
1420 } else if (amend) {
1421 struct commit_list *c;
1422 struct commit *commit;
1423
643cb5f7
CC
1424 if (!reflog_msg)
1425 reflog_msg = "commit (amend)";
f5bbc322
KH
1426 commit = lookup_commit(head_sha1);
1427 if (!commit || parse_commit(commit))
8a6179bc 1428 die(_("could not parse HEAD commit"));
f5bbc322
KH
1429
1430 for (c = commit->parents; c; c = c->next)
6bb6b034 1431 pptr = &commit_list_insert(c->item, pptr)->next;
37f7a857 1432 } else if (whence == FROM_MERGE) {
f285a2d7 1433 struct strbuf m = STRBUF_INIT;
f5bbc322
KH
1434 FILE *fp;
1435
643cb5f7
CC
1436 if (!reflog_msg)
1437 reflog_msg = "commit (merge)";
6bb6b034 1438 pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
f5bbc322
KH
1439 fp = fopen(git_path("MERGE_HEAD"), "r");
1440 if (fp == NULL)
8a6179bc 1441 die_errno(_("could not open '%s' for reading"),
d824cbba 1442 git_path("MERGE_HEAD"));
7c3fd25d
LT
1443 while (strbuf_getline(&m, fp, '\n') != EOF) {
1444 unsigned char sha1[20];
1445 if (get_sha1_hex(m.buf, sha1) < 0)
8a6179bc 1446 die(_("Corrupt MERGE_HEAD file (%s)"), m.buf);
6bb6b034 1447 pptr = &commit_list_insert(lookup_commit(sha1), pptr)->next;
7c3fd25d 1448 }
f5bbc322
KH
1449 fclose(fp);
1450 strbuf_release(&m);
cf10f9fd
MV
1451 if (!stat(git_path("MERGE_MODE"), &statbuf)) {
1452 if (strbuf_read_file(&sb, git_path("MERGE_MODE"), 0) < 0)
8a6179bc 1453 die_errno(_("could not read MERGE_MODE"));
cf10f9fd
MV
1454 if (!strcmp(sb.buf, "no-ff"))
1455 allow_fast_forward = 0;
1456 }
1457 if (allow_fast_forward)
1458 parents = reduce_heads(parents);
f5bbc322 1459 } else {
643cb5f7 1460 if (!reflog_msg)
37f7a857
JS
1461 reflog_msg = (whence == FROM_CHERRY_PICK)
1462 ? "commit (cherry-pick)"
1463 : "commit";
6bb6b034 1464 pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
f5bbc322 1465 }
f5bbc322 1466
ec84bd00 1467 /* Finally, get the commit message */
cf10f9fd 1468 strbuf_reset(&sb);
740001a5 1469 if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
0721c314 1470 int saved_errno = errno;
740001a5 1471 rollback_index_files();
8a6179bc 1472 die(_("could not read commit message: %s"), strerror(saved_errno));
740001a5 1473 }
99a12694
KH
1474
1475 /* Truncate the message just before the diff, if any. */
0b38227f
JK
1476 if (verbose) {
1477 p = strstr(sb.buf, "\ndiff --git ");
1478 if (p != NULL)
1479 strbuf_setlen(&sb, p - sb.buf + 1);
1480 }
99a12694 1481
5f065737
AR
1482 if (cleanup_mode != CLEANUP_NONE)
1483 stripspace(&sb, cleanup_mode == CLEANUP_ALL);
c9b5fde7 1484 if (message_is_empty(&sb) && !allow_empty_message) {
2888605c 1485 rollback_index_files();
8a6179bc 1486 fprintf(stderr, _("Aborting commit due to empty commit message.\n"));
fdc7c811 1487 exit(1);
2888605c 1488 }
f5bbc322 1489
6bb6b034 1490 if (commit_tree(sb.buf, active_cache_tree->sha1, parents, commit_sha1,
4c28e4ad 1491 author_ident.buf)) {
2888605c 1492 rollback_index_files();
8a6179bc 1493 die(_("failed to write commit object"));
2888605c 1494 }
4c28e4ad 1495 strbuf_release(&author_ident);
f5bbc322
KH
1496
1497 ref_lock = lock_any_ref_for_update("HEAD",
1498 initial_commit ? NULL : head_sha1,
1499 0);
1500
6bb6b034 1501 nl = strchr(sb.buf, '\n');
741707b1
JS
1502 if (nl)
1503 strbuf_setlen(&sb, nl + 1 - sb.buf);
1504 else
1505 strbuf_addch(&sb, '\n');
741707b1
JS
1506 strbuf_insert(&sb, 0, reflog_msg, strlen(reflog_msg));
1507 strbuf_insert(&sb, strlen(reflog_msg), ": ", 2);
f5bbc322 1508
2888605c
JH
1509 if (!ref_lock) {
1510 rollback_index_files();
8a6179bc 1511 die(_("cannot lock HEAD ref"));
2888605c
JH
1512 }
1513 if (write_ref_sha1(ref_lock, commit_sha1, sb.buf) < 0) {
1514 rollback_index_files();
8a6179bc 1515 die(_("cannot update HEAD ref"));
2888605c 1516 }
f5bbc322 1517
d7e5c0cb 1518 unlink(git_path("CHERRY_PICK_HEAD"));
f5bbc322
KH
1519 unlink(git_path("MERGE_HEAD"));
1520 unlink(git_path("MERGE_MSG"));
cf10f9fd 1521 unlink(git_path("MERGE_MODE"));
5a95b855 1522 unlink(git_path("SQUASH_MSG"));
f5bbc322 1523
5a9dd399 1524 if (commit_index_files())
8a6179bc 1525 die (_("Repository has been updated, but unable to write\n"
5a9dd399 1526 "new_index file. Check that disk is not full or quota is\n"
8a6179bc 1527 "not exceeded, and then \"git reset HEAD\" to recover."));
f5bbc322 1528
cb6020bb 1529 rerere(0);
2888605c 1530 run_hook(get_index_file(), "post-commit", NULL);
6f6bee3b 1531 if (amend && !no_post_rewrite) {
6360d343
TR
1532 struct notes_rewrite_cfg *cfg;
1533 cfg = init_copy_notes_for_rewrite("amend");
1534 if (cfg) {
1535 copy_note_for_rewrite(cfg, head_sha1, commit_sha1);
1536 finish_copy_notes_for_rewrite(cfg);
1537 }
6f6bee3b
TR
1538 run_rewrite_hook(head_sha1, commit_sha1);
1539 }
f5bbc322
KH
1540 if (!quiet)
1541 print_summary(prefix, commit_sha1);
1542
1543 return 0;
1544}