Merge branch 'jk/1.7.0-status'
* jk/1.7.0-status: status/commit: do not suggest "reset HEAD <path>" while merging commit/status: "git add <path>" is not necessarily how to resolve commit/status: check $GIT_DIR/MERGE_HEAD only once t7508-status: test all modes with color t7508-status: status --porcelain ignores relative paths setting status: reduce duplicated setup code status: disable color for porcelain format status -s: obey color.status builtin-commit: refactor short-status code into wt-status.c t7508-status.sh: Add tests for status -s status -s: respect the status.relativePaths option docs: note that status configuration affects only long format commit: support alternate status formats status: add --porcelain output format status: refactor format option parsing status: refactor short-mode printing to its own function status: typo fix in usage git status: not "commit --dry-run" anymore git stat -s: short status output git stat: the beginning of "status that is not a dry-run of commit" Conflicts: t/t4034-diff-words.sh wt-status.cmaint
						commit
						c2ff10c98e
					
				|  | @ -74,6 +74,20 @@ OPTIONS | |||
| 	authorship of the resulting commit now belongs of the committer. | ||||
| 	This also renews the author timestamp. | ||||
|  | ||||
| --short:: | ||||
| 	When doing a dry-run, give the output in the short-format. See | ||||
| 	linkgit:git-status[1] for details. Implies `--dry-run`. | ||||
|  | ||||
| --porcelain:: | ||||
| 	When doing a dry-run, give the output in a porcelain-ready | ||||
| 	format. See linkgit:git-status[1] for details. Implies | ||||
| 	`--dry-run`. | ||||
|  | ||||
| -z:: | ||||
| 	When showing `short` or `porcelain` status output, terminate | ||||
| 	entries in the status output with NUL, instead of LF. If no | ||||
| 	format is given, implies the `--porcelain` output format. | ||||
|  | ||||
| -F <file>:: | ||||
| --file=<file>:: | ||||
| 	Take the commit message from the given file.  Use '-' to | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ git-status - Show the working tree status | |||
|  | ||||
| SYNOPSIS | ||||
| -------- | ||||
| 'git status' <options>... | ||||
| 'git status' [<options>...] [--] [<pathspec>...] | ||||
|  | ||||
| DESCRIPTION | ||||
| ----------- | ||||
|  | @ -20,25 +20,90 @@ are what you _would_ commit by running `git commit`; the second and | |||
| third are what you _could_ commit by running 'git-add' before running | ||||
| `git commit`. | ||||
|  | ||||
| The command takes the same set of options as 'git-commit'; it | ||||
| shows what would be committed if the same options are given to | ||||
| 'git-commit'. | ||||
| OPTIONS | ||||
| ------- | ||||
|  | ||||
| If there is no path that is different between the index file and | ||||
| the current HEAD commit (i.e., there is nothing to commit by running | ||||
| `git commit`), the command exits with non-zero status. | ||||
| -s:: | ||||
| --short:: | ||||
| 	Give the output in the short-format. | ||||
|  | ||||
| --porcelain:: | ||||
| 	Give the output in a stable, easy-to-parse format for scripts. | ||||
| 	Currently this is identical to --short output, but is guaranteed | ||||
| 	not to change in the future, making it safe for scripts. | ||||
|  | ||||
| -u[<mode>]:: | ||||
| --untracked-files[=<mode>]:: | ||||
| 	Show untracked files (Default: 'all'). | ||||
| + | ||||
| The mode parameter is optional, and is used to specify | ||||
| the handling of untracked files. The possible options are: | ||||
| + | ||||
| -- | ||||
| 	- 'no'     - Show no untracked files | ||||
| 	- 'normal' - Shows untracked files and directories | ||||
| 	- 'all'    - Also shows individual files in untracked directories. | ||||
| -- | ||||
| + | ||||
| See linkgit:git-config[1] for configuration variable | ||||
| used to change the default for when the option is not | ||||
| specified. | ||||
|  | ||||
| -z:: | ||||
| 	Terminate entries with NUL, instead of LF.  This implies | ||||
| 	the `--porcelain` output format if no other format is given. | ||||
|  | ||||
|  | ||||
| OUTPUT | ||||
| ------ | ||||
| The output from this command is designed to be used as a commit | ||||
| template comment, and all the output lines are prefixed with '#'. | ||||
| The default, long format, is designed to be human readable, | ||||
| verbose and descriptive.  They are subject to change in any time. | ||||
|  | ||||
| The paths mentioned in the output, unlike many other git commands, are | ||||
| made relative to the current directory if you are working in a | ||||
| subdirectory (this is on purpose, to help cutting and pasting). See | ||||
| the status.relativePaths config option below. | ||||
|  | ||||
| In short-format, the status of each path is shown as | ||||
|  | ||||
| 	XY PATH1 -> PATH2 | ||||
|  | ||||
| where `PATH1` is the path in the `HEAD`, and ` -> PATH2` part is | ||||
| shown only when `PATH1` corresponds to a different path in the | ||||
| index/worktree (i.e. renamed). | ||||
|  | ||||
| For unmerged entries, `X` shows the status of stage #2 (i.e. ours) and `Y` | ||||
| shows the status of stage #3 (i.e. theirs). | ||||
|  | ||||
| For entries that do not have conflicts, `X` shows the status of the index, | ||||
| and `Y` shows the status of the work tree.  For untracked paths, `XY` are | ||||
| `??`. | ||||
|  | ||||
|     X          Y     Meaning | ||||
|     ------------------------------------------------- | ||||
|               [MD]   not updated | ||||
|     M        [ MD]   updated in index | ||||
|     A        [ MD]   added to index | ||||
|     D        [ MD]   deleted from index | ||||
|     R        [ MD]   renamed in index | ||||
|     C        [ MD]   copied in index | ||||
|     [MARC]           index and work tree matches | ||||
|     [ MARC]     M    work tree changed since index | ||||
|     [ MARC]     D    deleted in work tree | ||||
|     ------------------------------------------------- | ||||
|     D           D    unmerged, both deleted | ||||
|     A           U    unmerged, added by us | ||||
|     U           D    unmerged, deleted by them | ||||
|     U           A    unmerged, added by them | ||||
|     D           U    unmerged, deleted by us | ||||
|     A           A    unmerged, both added | ||||
|     U           U    unmerged, both modified | ||||
|     ------------------------------------------------- | ||||
|     ?           ?    untracked | ||||
|     ------------------------------------------------- | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | @ -53,9 +118,9 @@ paths shown are relative to the repository root, not to the current | |||
| directory. | ||||
|  | ||||
| If `status.submodulesummary` is set to a non zero number or true (identical | ||||
| to -1 or an unlimited number), the submodule summary will be enabled and a | ||||
| summary of commits for modified submodules will be shown (see --summary-limit | ||||
| option of linkgit:git-submodule[1]). | ||||
| to -1 or an unlimited number), the submodule summary will be enabled for | ||||
| the long format and a summary of commits for modified submodules will be | ||||
| shown (see --summary-limit option of linkgit:git-submodule[1]). | ||||
|  | ||||
| SEE ALSO | ||||
| -------- | ||||
|  | @ -63,8 +128,7 @@ linkgit:gitignore[5] | |||
|  | ||||
| Author | ||||
| ------ | ||||
| Written by Linus Torvalds <torvalds@osdl.org> and | ||||
| Junio C Hamano <gitster@pobox.com>. | ||||
| Written by Junio C Hamano <gitster@pobox.com>. | ||||
|  | ||||
| Documentation | ||||
| -------------- | ||||
|  |  | |||
							
								
								
									
										122
									
								
								builtin-commit.c
								
								
								
								
							
							
						
						
									
										122
									
								
								builtin-commit.c
								
								
								
								
							|  | @ -24,6 +24,7 @@ | |||
| #include "string-list.h" | ||||
| #include "rerere.h" | ||||
| #include "unpack-trees.h" | ||||
| #include "quote.h" | ||||
|  | ||||
| static const char * const builtin_commit_usage[] = { | ||||
| 	"git commit [options] [--] <filepattern>...", | ||||
|  | @ -35,7 +36,7 @@ static const char * const builtin_status_usage[] = { | |||
| 	NULL | ||||
| }; | ||||
|  | ||||
| static unsigned char head_sha1[20], merge_head_sha1[20]; | ||||
| static unsigned char head_sha1[20]; | ||||
| static char *use_message_buffer; | ||||
| static const char commit_editmsg[] = "COMMIT_EDITMSG"; | ||||
| static struct lock_file index_lock; /* real index */ | ||||
|  | @ -71,6 +72,13 @@ static int use_editor = 1, initial_commit, in_merge; | |||
| static const char *only_include_assumed; | ||||
| static struct strbuf message; | ||||
|  | ||||
| static int null_termination; | ||||
| static enum { | ||||
| 	STATUS_FORMAT_LONG, | ||||
| 	STATUS_FORMAT_SHORT, | ||||
| 	STATUS_FORMAT_PORCELAIN, | ||||
| } status_format = STATUS_FORMAT_LONG; | ||||
|  | ||||
| static int opt_parse_m(const struct option *opt, const char *arg, int unset) | ||||
| { | ||||
| 	struct strbuf *buf = opt->value; | ||||
|  | @ -105,6 +113,12 @@ static struct option builtin_commit_options[] = { | |||
| 	OPT_BOOLEAN('o', "only", &only, "commit only specified files"), | ||||
| 	OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"), | ||||
| 	OPT_BOOLEAN(0, "dry-run", &dry_run, "show what would be committed"), | ||||
| 	OPT_SET_INT(0, "short", &status_format, "show status concisely", | ||||
| 		    STATUS_FORMAT_SHORT), | ||||
| 	OPT_SET_INT(0, "porcelain", &status_format, | ||||
| 		    "show porcelain output format", STATUS_FORMAT_PORCELAIN), | ||||
| 	OPT_BOOLEAN('z', "null", &null_termination, | ||||
| 		    "terminate entries with NUL"), | ||||
| 	OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"), | ||||
| 	{ 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" }, | ||||
| 	OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"), | ||||
|  | @ -306,7 +320,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int | |||
| 	 */ | ||||
| 	commit_style = COMMIT_PARTIAL; | ||||
|  | ||||
| 	if (file_exists(git_path("MERGE_HEAD"))) | ||||
| 	if (in_merge) | ||||
| 		die("cannot do a partial commit during a merge."); | ||||
|  | ||||
| 	memset(&partial, 0, sizeof(partial)); | ||||
|  | @ -347,6 +361,8 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int | |||
| static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn, | ||||
| 		      struct wt_status *s) | ||||
| { | ||||
| 	unsigned char sha1[20]; | ||||
|  | ||||
| 	if (s->relative_paths) | ||||
| 		s->prefix = prefix; | ||||
|  | ||||
|  | @ -358,8 +374,21 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int | |||
| 	s->index_file = index_file; | ||||
| 	s->fp = fp; | ||||
| 	s->nowarn = nowarn; | ||||
| 	s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0; | ||||
|  | ||||
| 	wt_status_collect(s); | ||||
|  | ||||
| 	switch (status_format) { | ||||
| 	case STATUS_FORMAT_SHORT: | ||||
| 		wt_shortstatus_print(s, null_termination); | ||||
| 		break; | ||||
| 	case STATUS_FORMAT_PORCELAIN: | ||||
| 		wt_porcelain_print(s, null_termination); | ||||
| 		break; | ||||
| 	case STATUS_FORMAT_LONG: | ||||
| 		wt_status_print(s); | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	return s->commitable; | ||||
| } | ||||
|  | @ -735,6 +764,21 @@ static const char *find_author_by_nickname(const char *name) | |||
| 	die("No existing author found with '%s'", name); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void handle_untracked_files_arg(struct wt_status *s) | ||||
| { | ||||
| 	if (!untracked_files_arg) | ||||
| 		; /* default already initialized */ | ||||
| 	else if (!strcmp(untracked_files_arg, "no")) | ||||
| 		s->show_untracked_files = SHOW_NO_UNTRACKED_FILES; | ||||
| 	else if (!strcmp(untracked_files_arg, "normal")) | ||||
| 		s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES; | ||||
| 	else if (!strcmp(untracked_files_arg, "all")) | ||||
| 		s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES; | ||||
| 	else | ||||
| 		die("Invalid untracked files mode '%s'", untracked_files_arg); | ||||
| } | ||||
|  | ||||
| static int parse_and_validate_options(int argc, const char *argv[], | ||||
| 				      const char * const usage[], | ||||
| 				      const char *prefix, | ||||
|  | @ -761,9 +805,6 @@ static int parse_and_validate_options(int argc, const char *argv[], | |||
| 	if (get_sha1("HEAD", head_sha1)) | ||||
| 		initial_commit = 1; | ||||
|  | ||||
| 	if (!get_sha1("MERGE_HEAD", merge_head_sha1)) | ||||
| 		in_merge = 1; | ||||
|  | ||||
| 	/* Sanity check options */ | ||||
| 	if (amend && initial_commit) | ||||
| 		die("You have nothing to amend."); | ||||
|  | @ -843,22 +884,18 @@ static int parse_and_validate_options(int argc, const char *argv[], | |||
| 	else | ||||
| 		die("Invalid cleanup mode %s", cleanup_arg); | ||||
|  | ||||
| 	if (!untracked_files_arg) | ||||
| 		; /* default already initialized */ | ||||
| 	else if (!strcmp(untracked_files_arg, "no")) | ||||
| 		s->show_untracked_files = SHOW_NO_UNTRACKED_FILES; | ||||
| 	else if (!strcmp(untracked_files_arg, "normal")) | ||||
| 		s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES; | ||||
| 	else if (!strcmp(untracked_files_arg, "all")) | ||||
| 		s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES; | ||||
| 	else | ||||
| 		die("Invalid untracked files mode '%s'", untracked_files_arg); | ||||
| 	handle_untracked_files_arg(s); | ||||
|  | ||||
| 	if (all && argc > 0) | ||||
| 		die("Paths with -a does not make sense."); | ||||
| 	else if (interactive && argc > 0) | ||||
| 		die("Paths with --interactive does not make sense."); | ||||
|  | ||||
| 	if (null_termination && status_format == STATUS_FORMAT_LONG) | ||||
| 		status_format = STATUS_FORMAT_PORCELAIN; | ||||
| 	if (status_format != STATUS_FORMAT_LONG) | ||||
| 		dry_run = 1; | ||||
|  | ||||
| 	return argc; | ||||
| } | ||||
|  | ||||
|  | @ -940,17 +977,63 @@ static int git_status_config(const char *k, const char *v, void *cb) | |||
| int cmd_status(int argc, const char **argv, const char *prefix) | ||||
| { | ||||
| 	struct wt_status s; | ||||
| 	unsigned char sha1[20]; | ||||
| 	static struct option builtin_status_options[] = { | ||||
| 		OPT__VERBOSE(&verbose), | ||||
| 		OPT_SET_INT('s', "short", &status_format, | ||||
| 			    "show status concisely", STATUS_FORMAT_SHORT), | ||||
| 		OPT_SET_INT(0, "porcelain", &status_format, | ||||
| 			    "show porcelain output format", | ||||
| 			    STATUS_FORMAT_PORCELAIN), | ||||
| 		OPT_BOOLEAN('z', "null", &null_termination, | ||||
| 			    "terminate entries with NUL"), | ||||
| 		{ 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" }, | ||||
| 		OPT_END(), | ||||
| 	}; | ||||
|  | ||||
| 	if (null_termination && status_format == STATUS_FORMAT_LONG) | ||||
| 		status_format = STATUS_FORMAT_PORCELAIN; | ||||
|  | ||||
| 	wt_status_prepare(&s); | ||||
| 	git_config(git_status_config, &s); | ||||
| 	in_merge = file_exists(git_path("MERGE_HEAD")); | ||||
| 	argc = parse_options(argc, argv, prefix, | ||||
| 			     builtin_status_options, | ||||
| 			     builtin_status_usage, 0); | ||||
| 	handle_untracked_files_arg(&s); | ||||
|  | ||||
| 	if (*argv) | ||||
| 		s.pathspec = get_pathspec(prefix, argv); | ||||
|  | ||||
| 	read_cache(); | ||||
| 	refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED); | ||||
| 	s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0; | ||||
| 	s.in_merge = in_merge; | ||||
| 	wt_status_collect(&s); | ||||
|  | ||||
| 	if (s.relative_paths) | ||||
| 		s.prefix = prefix; | ||||
| 	if (s.use_color == -1) | ||||
| 		s.use_color = git_use_color_default; | ||||
| 	if (diff_use_color_default == -1) | ||||
| 		diff_use_color_default = git_use_color_default; | ||||
|  | ||||
| 	argc = parse_and_validate_options(argc, argv, builtin_status_usage, | ||||
| 					  prefix, &s); | ||||
| 	return dry_run_commit(argc, argv, prefix, &s); | ||||
| 	switch (status_format) { | ||||
| 	case STATUS_FORMAT_SHORT: | ||||
| 		wt_shortstatus_print(&s, null_termination); | ||||
| 		break; | ||||
| 	case STATUS_FORMAT_PORCELAIN: | ||||
| 		wt_porcelain_print(&s, null_termination); | ||||
| 		break; | ||||
| 	case STATUS_FORMAT_LONG: | ||||
| 		s.verbose = verbose; | ||||
| 		wt_status_print(&s); | ||||
| 		break; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void print_summary(const char *prefix, const unsigned char *sha1) | ||||
|  | @ -1026,10 +1109,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix) | |||
|  | ||||
| 	wt_status_prepare(&s); | ||||
| 	git_config(git_commit_config, &s); | ||||
| 	in_merge = file_exists(git_path("MERGE_HEAD")); | ||||
| 	s.in_merge = in_merge; | ||||
|  | ||||
| 	if (s.use_color == -1) | ||||
| 		s.use_color = git_use_color_default; | ||||
|  | ||||
| 	argc = parse_and_validate_options(argc, argv, builtin_commit_usage, | ||||
| 					  prefix, &s); | ||||
| 	if (dry_run) { | ||||
|  |  | |||
|  | @ -12,19 +12,9 @@ test_expect_success setup ' | |||
|  | ||||
| ' | ||||
|  | ||||
| decrypt_color () { | ||||
| 	sed \ | ||||
| 		-e 's/.\[1m/<WHITE>/g' \ | ||||
| 		-e 's/.\[31m/<RED>/g' \ | ||||
| 		-e 's/.\[32m/<GREEN>/g' \ | ||||
| 		-e 's/.\[35m/<MAGENTA>/g' \ | ||||
| 		-e 's/.\[36m/<BROWN>/g' \ | ||||
| 		-e 's/.\[m/<RESET>/g' | ||||
| } | ||||
|  | ||||
| word_diff () { | ||||
| 	test_must_fail git diff --no-index "$@" pre post > output && | ||||
| 	decrypt_color < output > output.decrypted && | ||||
| 	test_decode_color <output >output.decrypted && | ||||
| 	test_cmp expect output.decrypted | ||||
| } | ||||
|  | ||||
|  | @ -49,7 +39,7 @@ cat > expect <<\EOF | |||
| <WHITE>index 330b04f..5ed8eff 100644<RESET> | ||||
| <WHITE>--- a/pre<RESET> | ||||
| <WHITE>+++ b/post<RESET> | ||||
| <BROWN>@@ -1,3 +1,7 @@<RESET> | ||||
| <CYAN>@@ -1,3 +1,7 @@<RESET> | ||||
| <RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET> | ||||
|  | ||||
| a = b + c<RESET> | ||||
|  | @ -70,9 +60,9 @@ cat > expect <<\EOF | |||
| <WHITE>index 330b04f..5ed8eff 100644<RESET> | ||||
| <WHITE>--- a/pre<RESET> | ||||
| <WHITE>+++ b/post<RESET> | ||||
| <BROWN>@@ -1 +1 @@<RESET> | ||||
| <CYAN>@@ -1 +1 @@<RESET> | ||||
| <RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET> | ||||
| <BROWN>@@ -3,0 +4,4 @@<RESET> <RESET><MAGENTA>a = b + c<RESET> | ||||
| <CYAN>@@ -3,0 +4,4 @@<RESET> <RESET><MAGENTA>a = b + c<RESET> | ||||
|  | ||||
| <GREEN>aa = a<RESET> | ||||
|  | ||||
|  | @ -90,7 +80,7 @@ cat > expect <<\EOF | |||
| <WHITE>index 330b04f..5ed8eff 100644<RESET> | ||||
| <WHITE>--- a/pre<RESET> | ||||
| <WHITE>+++ b/post<RESET> | ||||
| <BROWN>@@ -1,3 +1,7 @@<RESET> | ||||
| <CYAN>@@ -1,3 +1,7 @@<RESET> | ||||
| h(4),<GREEN>hh<RESET>[44] | ||||
|  | ||||
| a = b + c<RESET> | ||||
|  | @ -126,7 +116,7 @@ cat > expect <<\EOF | |||
| <WHITE>index 330b04f..5ed8eff 100644<RESET> | ||||
| <WHITE>--- a/pre<RESET> | ||||
| <WHITE>+++ b/post<RESET> | ||||
| <BROWN>@@ -1,3 +1,7 @@<RESET> | ||||
| <CYAN>@@ -1,3 +1,7 @@<RESET> | ||||
| h(4)<GREEN>,hh[44]<RESET> | ||||
|  | ||||
| a = b + c<RESET> | ||||
|  | @ -168,7 +158,7 @@ cat > expect <<\EOF | |||
| <WHITE>index 330b04f..5ed8eff 100644<RESET> | ||||
| <WHITE>--- a/pre<RESET> | ||||
| <WHITE>+++ b/post<RESET> | ||||
| <BROWN>@@ -1,3 +1,7 @@<RESET> | ||||
| <CYAN>@@ -1,3 +1,7 @@<RESET> | ||||
| h(4),<GREEN>hh[44<RESET>] | ||||
|  | ||||
| a = b + c<RESET> | ||||
|  | @ -190,7 +180,7 @@ cat > expect <<\EOF | |||
| <WHITE>index c29453b..be22f37 100644<RESET> | ||||
| <WHITE>--- a/pre<RESET> | ||||
| <WHITE>+++ b/post<RESET> | ||||
| <BROWN>@@ -1 +1 @@<RESET> | ||||
| <CYAN>@@ -1 +1 @@<RESET> | ||||
| aaa (aaa) <GREEN>aaa<RESET> | ||||
| EOF | ||||
|  | ||||
|  | @ -209,7 +199,7 @@ cat > expect <<\EOF | |||
| <WHITE>index 289cb9d..2d06f37 100644<RESET> | ||||
| <WHITE>--- a/pre<RESET> | ||||
| <WHITE>+++ b/post<RESET> | ||||
| <BROWN>@@ -1 +1 @@<RESET> | ||||
| <CYAN>@@ -1 +1 @@<RESET> | ||||
| (<RED>:<RESET> | ||||
| EOF | ||||
|  | ||||
|  |  | |||
|  | @ -69,7 +69,7 @@ test_expect_success 'status' ' | |||
| 		cd test && | ||||
| 		git checkout b1 >/dev/null && | ||||
| 		# reports nothing to commit | ||||
| 		test_must_fail git status | ||||
| 		test_must_fail git commit --dry-run | ||||
| 	) >actual && | ||||
| 	grep "have 1 and 1 different" actual | ||||
| ' | ||||
|  |  | |||
|  | @ -31,8 +31,7 @@ test_expect_success 'Report new path with conflict' ' | |||
| cat >expect <<EOF | ||||
| # On branch side | ||||
| # Unmerged paths: | ||||
| #   (use "git reset HEAD <file>..." to unstage) | ||||
| #   (use "git add <file>..." to mark resolution) | ||||
| #   (use "git add/rm <file>..." as appropriate to mark resolution) | ||||
| # | ||||
| #	deleted by us:      foo | ||||
| # | ||||
|  | @ -50,9 +49,11 @@ test_expect_success 'M/D conflict does not segfault' ' | |||
| 		git rm foo && | ||||
| 		git commit -m delete && | ||||
| 		test_must_fail git merge master && | ||||
| 		test_must_fail git status > ../actual | ||||
| 	) && | ||||
| 	test_cmp expect actual | ||||
| 		test_must_fail git commit --dry-run >../actual && | ||||
| 		test_cmp ../expect ../actual && | ||||
| 		git status >../actual && | ||||
| 		test_cmp ../expect ../actual | ||||
| 	) | ||||
| ' | ||||
|  | ||||
| test_done | ||||
|  |  | |||
|  | @ -19,8 +19,8 @@ test_expect_success 'status clean' ' | |||
| 	git status | | ||||
| 	grep "nothing to commit" | ||||
| ' | ||||
| test_expect_success 'status -a clean' ' | ||||
| 	git status -a | | ||||
| test_expect_success 'commit --dry-run -a clean' ' | ||||
| 	git commit --dry-run -a | | ||||
| 	grep "nothing to commit" | ||||
| ' | ||||
| test_expect_success 'rm submodule contents' ' | ||||
|  | @ -31,7 +31,7 @@ test_expect_success 'status clean (empty submodule dir)' ' | |||
| 	grep "nothing to commit" | ||||
| ' | ||||
| test_expect_success 'status -a clean (empty submodule dir)' ' | ||||
| 	git status -a | | ||||
| 	git commit --dry-run -a | | ||||
| 	grep "nothing to commit" | ||||
| ' | ||||
|  | ||||
|  |  | |||
|  | @ -8,26 +8,26 @@ test_description='git status' | |||
| . ./test-lib.sh | ||||
|  | ||||
| test_expect_success 'setup' ' | ||||
| 	: > tracked && | ||||
| 	: > modified && | ||||
| 	: >tracked && | ||||
| 	: >modified && | ||||
| 	mkdir dir1 && | ||||
| 	: > dir1/tracked && | ||||
| 	: > dir1/modified && | ||||
| 	: >dir1/tracked && | ||||
| 	: >dir1/modified && | ||||
| 	mkdir dir2 && | ||||
| 	: > dir1/tracked && | ||||
| 	: > dir1/modified && | ||||
| 	: >dir1/tracked && | ||||
| 	: >dir1/modified && | ||||
| 	git add . && | ||||
|  | ||||
| 	git status >output && | ||||
|  | ||||
| 	test_tick && | ||||
| 	git commit -m initial && | ||||
| 	: > untracked && | ||||
| 	: > dir1/untracked && | ||||
| 	: > dir2/untracked && | ||||
| 	echo 1 > dir1/modified && | ||||
| 	echo 2 > dir2/modified && | ||||
| 	echo 3 > dir2/added && | ||||
| 	: >untracked && | ||||
| 	: >dir1/untracked && | ||||
| 	: >dir2/untracked && | ||||
| 	echo 1 >dir1/modified && | ||||
| 	echo 2 >dir2/modified && | ||||
| 	echo 3 >dir2/added && | ||||
| 	git add dir2/added | ||||
| ' | ||||
|  | ||||
|  | @ -37,7 +37,7 @@ test_expect_success 'status (1)' ' | |||
|  | ||||
| ' | ||||
|  | ||||
| cat > expect << \EOF | ||||
| cat >expect <<\EOF | ||||
| # On branch master | ||||
| # Changes to be committed: | ||||
| #   (use "git reset HEAD <file>..." to unstage) | ||||
|  | @ -63,7 +63,25 @@ EOF | |||
|  | ||||
| test_expect_success 'status (2)' ' | ||||
|  | ||||
| 	git status > output && | ||||
| 	git status >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | ||||
| cat >expect <<\EOF | ||||
|  M dir1/modified | ||||
| A  dir2/added | ||||
| ?? dir1/untracked | ||||
| ?? dir2/modified | ||||
| ?? dir2/untracked | ||||
| ?? expect | ||||
| ?? output | ||||
| ?? untracked | ||||
| EOF | ||||
|  | ||||
| test_expect_success 'status -s (2)' ' | ||||
|  | ||||
| 	git status -s >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | @ -85,8 +103,8 @@ cat >expect <<EOF | |||
| EOF | ||||
| test_expect_success 'status -uno' ' | ||||
| 	mkdir dir3 && | ||||
| 	: > dir3/untracked1 && | ||||
| 	: > dir3/untracked2 && | ||||
| 	: >dir3/untracked1 && | ||||
| 	: >dir3/untracked2 && | ||||
| 	git status -uno >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | @ -97,6 +115,22 @@ test_expect_success 'status (status.showUntrackedFiles no)' ' | |||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| cat >expect << EOF | ||||
|  M dir1/modified | ||||
| A  dir2/added | ||||
| EOF | ||||
| test_expect_success 'status -s -uno' ' | ||||
| 	git config --unset status.showuntrackedfiles | ||||
| 	git status -s -uno >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| test_expect_success 'status -s (status.showUntrackedFiles no)' ' | ||||
| 	git config status.showuntrackedfiles no | ||||
| 	git status -s >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| cat >expect <<EOF | ||||
| # On branch master | ||||
| # Changes to be committed: | ||||
|  | @ -132,6 +166,29 @@ test_expect_success 'status (status.showUntrackedFiles normal)' ' | |||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| cat >expect <<EOF | ||||
|  M dir1/modified | ||||
| A  dir2/added | ||||
| ?? dir1/untracked | ||||
| ?? dir2/modified | ||||
| ?? dir2/untracked | ||||
| ?? dir3/ | ||||
| ?? expect | ||||
| ?? output | ||||
| ?? untracked | ||||
| EOF | ||||
| test_expect_success 'status -s -unormal' ' | ||||
| 	git config --unset status.showuntrackedfiles | ||||
| 	git status -s -unormal >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| test_expect_success 'status -s (status.showUntrackedFiles normal)' ' | ||||
| 	git config status.showuntrackedfiles normal | ||||
| 	git status -s >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| cat >expect <<EOF | ||||
| # On branch master | ||||
| # Changes to be committed: | ||||
|  | @ -169,7 +226,30 @@ test_expect_success 'status (status.showUntrackedFiles all)' ' | |||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| cat > expect << \EOF | ||||
| cat >expect <<EOF | ||||
|  M dir1/modified | ||||
| A  dir2/added | ||||
| ?? dir1/untracked | ||||
| ?? dir2/modified | ||||
| ?? dir2/untracked | ||||
| ?? expect | ||||
| ?? output | ||||
| ?? untracked | ||||
| EOF | ||||
| test_expect_success 'status -s -uall' ' | ||||
| 	git config --unset status.showuntrackedfiles | ||||
| 	git status -s -uall >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
| test_expect_success 'status -s (status.showUntrackedFiles all)' ' | ||||
| 	git config status.showuntrackedfiles all | ||||
| 	git status -s >output && | ||||
| 	rm -rf dir3 && | ||||
| 	git config --unset status.showuntrackedfiles && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| cat >expect <<\EOF | ||||
| # On branch master | ||||
| # Changes to be committed: | ||||
| #   (use "git reset HEAD <file>..." to unstage) | ||||
|  | @ -195,12 +275,156 @@ EOF | |||
|  | ||||
| test_expect_success 'status with relative paths' ' | ||||
|  | ||||
| 	(cd dir1 && git status) > output && | ||||
| 	(cd dir1 && git status) >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | ||||
| cat > expect << \EOF | ||||
| cat >expect <<\EOF | ||||
|  M modified | ||||
| A  ../dir2/added | ||||
| ?? untracked | ||||
| ?? ../dir2/modified | ||||
| ?? ../dir2/untracked | ||||
| ?? ../expect | ||||
| ?? ../output | ||||
| ?? ../untracked | ||||
| EOF | ||||
| test_expect_success 'status -s with relative paths' ' | ||||
|  | ||||
| 	(cd dir1 && git status -s) >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | ||||
| cat >expect <<\EOF | ||||
|  M dir1/modified | ||||
| A  dir2/added | ||||
| ?? dir1/untracked | ||||
| ?? dir2/modified | ||||
| ?? dir2/untracked | ||||
| ?? expect | ||||
| ?? output | ||||
| ?? untracked | ||||
| EOF | ||||
|  | ||||
| test_expect_success 'status --porcelain ignores relative paths setting' ' | ||||
|  | ||||
| 	(cd dir1 && git status --porcelain) >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | ||||
| test_expect_success 'setup unique colors' ' | ||||
|  | ||||
| 	git config status.color.untracked blue | ||||
|  | ||||
| ' | ||||
|  | ||||
| cat >expect <<\EOF | ||||
| # On branch master | ||||
| # Changes to be committed: | ||||
| #   (use "git reset HEAD <file>..." to unstage) | ||||
| # | ||||
| #	<GREEN>new file:   dir2/added<RESET> | ||||
| # | ||||
| # Changed but not updated: | ||||
| #   (use "git add <file>..." to update what will be committed) | ||||
| #   (use "git checkout -- <file>..." to discard changes in working directory) | ||||
| # | ||||
| #	<RED>modified:   dir1/modified<RESET> | ||||
| # | ||||
| # Untracked files: | ||||
| #   (use "git add <file>..." to include in what will be committed) | ||||
| # | ||||
| #	<BLUE>dir1/untracked<RESET> | ||||
| #	<BLUE>dir2/modified<RESET> | ||||
| #	<BLUE>dir2/untracked<RESET> | ||||
| #	<BLUE>expect<RESET> | ||||
| #	<BLUE>output<RESET> | ||||
| #	<BLUE>untracked<RESET> | ||||
| EOF | ||||
|  | ||||
| test_expect_success 'status with color.ui' ' | ||||
|  | ||||
| 	git config color.ui always && | ||||
| 	git status | test_decode_color >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | ||||
| test_expect_success 'status with color.status' ' | ||||
|  | ||||
| 	git config --unset color.ui && | ||||
| 	git config color.status always && | ||||
| 	git status | test_decode_color >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | ||||
| cat >expect <<\EOF | ||||
|  <RED>M<RESET> dir1/modified | ||||
| <GREEN>A<RESET>  dir2/added | ||||
| <BLUE>??<RESET> dir1/untracked | ||||
| <BLUE>??<RESET> dir2/modified | ||||
| <BLUE>??<RESET> dir2/untracked | ||||
| <BLUE>??<RESET> expect | ||||
| <BLUE>??<RESET> output | ||||
| <BLUE>??<RESET> untracked | ||||
| EOF | ||||
|  | ||||
| test_expect_success 'status -s with color.ui' ' | ||||
|  | ||||
| 	git config --unset color.status && | ||||
| 	git config color.ui always && | ||||
| 	git status -s | test_decode_color >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | ||||
| test_expect_success 'status -s with color.status' ' | ||||
|  | ||||
| 	git config --unset color.ui && | ||||
| 	git config color.status always && | ||||
| 	git status -s | test_decode_color >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | ||||
| cat >expect <<\EOF | ||||
|  M dir1/modified | ||||
| A  dir2/added | ||||
| ?? dir1/untracked | ||||
| ?? dir2/modified | ||||
| ?? dir2/untracked | ||||
| ?? expect | ||||
| ?? output | ||||
| ?? untracked | ||||
| EOF | ||||
|  | ||||
| test_expect_success 'status --porcelain ignores color.ui' ' | ||||
|  | ||||
| 	git config --unset color.status && | ||||
| 	git config color.ui always && | ||||
| 	git status --porcelain | test_decode_color >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | ||||
| test_expect_success 'status --porcelain ignores color.status' ' | ||||
|  | ||||
| 	git config --unset color.ui && | ||||
| 	git config color.status always && | ||||
| 	git status --porcelain | test_decode_color >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | ||||
| # recover unconditionally from color tests | ||||
| git config --unset color.status | ||||
| git config --unset color.ui | ||||
|  | ||||
| cat >expect <<\EOF | ||||
| # On branch master | ||||
| # Changes to be committed: | ||||
| #   (use "git reset HEAD <file>..." to unstage) | ||||
|  | @ -224,10 +448,29 @@ cat > expect << \EOF | |||
| #	untracked | ||||
| EOF | ||||
|  | ||||
|  | ||||
| test_expect_success 'status without relative paths' ' | ||||
|  | ||||
| 	git config status.relativePaths false | ||||
| 	(cd dir1 && git status) > output && | ||||
| 	(cd dir1 && git status) >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | ||||
| cat >expect <<\EOF | ||||
|  M dir1/modified | ||||
| A  dir2/added | ||||
| ?? dir1/untracked | ||||
| ?? dir2/modified | ||||
| ?? dir2/untracked | ||||
| ?? expect | ||||
| ?? output | ||||
| ?? untracked | ||||
| EOF | ||||
|  | ||||
| test_expect_success 'status -s without relative paths' ' | ||||
|  | ||||
| 	(cd dir1 && git status -s) >output && | ||||
| 	test_cmp expect output | ||||
|  | ||||
| ' | ||||
|  | @ -248,8 +491,8 @@ cat <<EOF >expect | |||
| #	output | ||||
| #	untracked | ||||
| EOF | ||||
| test_expect_success 'status of partial commit excluding new file in index' ' | ||||
| 	git status dir1/modified >output && | ||||
| test_expect_success 'dry-run of partial commit excluding new file in index' ' | ||||
| 	git commit --dry-run dir1/modified >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
|  | @ -298,6 +541,28 @@ test_expect_success 'status --untracked-files=all does not show submodule' ' | |||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| cat >expect <<EOF | ||||
|  M dir1/modified | ||||
| A  dir2/added | ||||
| A  sm | ||||
| ?? dir1/untracked | ||||
| ?? dir2/modified | ||||
| ?? dir2/untracked | ||||
| ?? expect | ||||
| ?? output | ||||
| ?? untracked | ||||
| EOF | ||||
| test_expect_success 'status -s submodule summary is disabled by default' ' | ||||
| 	git status -s >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| # we expect the same as the previous test | ||||
| test_expect_success 'status -s --untracked-files=all does not show submodule' ' | ||||
| 	git status -s --untracked-files=all >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| head=$(cd sm && git rev-parse --short=7 --verify HEAD) | ||||
|  | ||||
| cat >expect <<EOF | ||||
|  | @ -335,6 +600,21 @@ test_expect_success 'status submodule summary' ' | |||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| cat >expect <<EOF | ||||
|  M dir1/modified | ||||
| A  dir2/added | ||||
| A  sm | ||||
| ?? dir1/untracked | ||||
| ?? dir2/modified | ||||
| ?? dir2/untracked | ||||
| ?? expect | ||||
| ?? output | ||||
| ?? untracked | ||||
| EOF | ||||
| test_expect_success 'status -s submodule summary' ' | ||||
| 	git status -s >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| cat >expect <<EOF | ||||
| # On branch master | ||||
|  | @ -358,7 +638,23 @@ EOF | |||
| test_expect_success 'status submodule summary (clean submodule)' ' | ||||
| 	git commit -m "commit submodule" && | ||||
| 	git config status.submodulesummary 10 && | ||||
| 	test_must_fail git status >output && | ||||
| 	test_must_fail git commit --dry-run >output && | ||||
| 	test_cmp expect output && | ||||
| 	git status >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
| cat >expect <<EOF | ||||
|  M dir1/modified | ||||
| ?? dir1/untracked | ||||
| ?? dir2/modified | ||||
| ?? dir2/untracked | ||||
| ?? expect | ||||
| ?? output | ||||
| ?? untracked | ||||
| EOF | ||||
| test_expect_success 'status -s submodule summary (clean submodule)' ' | ||||
| 	git status -s >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
|  | @ -391,9 +687,9 @@ cat >expect <<EOF | |||
| #	output | ||||
| #	untracked | ||||
| EOF | ||||
| test_expect_success 'status submodule summary (--amend)' ' | ||||
| test_expect_success 'commit --dry-run submodule summary (--amend)' ' | ||||
| 	git config status.submodulesummary 10 && | ||||
| 	git status --amend >output && | ||||
| 	git commit --dry-run --amend >output && | ||||
| 	test_cmp expect output | ||||
| ' | ||||
|  | ||||
|  |  | |||
|  | @ -211,6 +211,17 @@ test_set_editor () { | |||
| 	export EDITOR | ||||
| } | ||||
|  | ||||
| test_decode_color () { | ||||
| 	sed	-e 's/.\[1m/<WHITE>/g' \ | ||||
| 		-e 's/.\[31m/<RED>/g' \ | ||||
| 		-e 's/.\[32m/<GREEN>/g' \ | ||||
| 		-e 's/.\[33m/<YELLOW>/g' \ | ||||
| 		-e 's/.\[34m/<BLUE>/g' \ | ||||
| 		-e 's/.\[35m/<MAGENTA>/g' \ | ||||
| 		-e 's/.\[36m/<CYAN>/g' \ | ||||
| 		-e 's/.\[m/<RESET>/g' | ||||
| } | ||||
|  | ||||
| test_tick () { | ||||
| 	if test -z "${test_tick+set}" | ||||
| 	then | ||||
|  |  | |||
							
								
								
									
										130
									
								
								wt-status.c
								
								
								
								
							
							
						
						
									
										130
									
								
								wt-status.c
								
								
								
								
							|  | @ -47,28 +47,33 @@ void wt_status_prepare(struct wt_status *s) | |||
| static void wt_status_print_unmerged_header(struct wt_status *s) | ||||
| { | ||||
| 	const char *c = color(WT_STATUS_HEADER, s); | ||||
|  | ||||
| 	color_fprintf_ln(s->fp, c, "# Unmerged paths:"); | ||||
| 	if (!advice_status_hints) | ||||
| 		return; | ||||
| 	if (!s->is_initial) | ||||
| 	if (s->in_merge) | ||||
| 		; | ||||
| 	else if (!s->is_initial) | ||||
| 		color_fprintf_ln(s->fp, c, "#   (use \"git reset %s <file>...\" to unstage)", s->reference); | ||||
| 	else | ||||
| 		color_fprintf_ln(s->fp, c, "#   (use \"git rm --cached <file>...\" to unstage)"); | ||||
| 	color_fprintf_ln(s->fp, c, "#   (use \"git add <file>...\" to mark resolution)"); | ||||
| 	color_fprintf_ln(s->fp, c, "#   (use \"git add/rm <file>...\" as appropriate to mark resolution)"); | ||||
| 	color_fprintf_ln(s->fp, c, "#"); | ||||
| } | ||||
|  | ||||
| static void wt_status_print_cached_header(struct wt_status *s) | ||||
| { | ||||
| 	const char *c = color(WT_STATUS_HEADER, s); | ||||
|  | ||||
| 	color_fprintf_ln(s->fp, c, "# Changes to be committed:"); | ||||
| 	if (!advice_status_hints) | ||||
| 		return; | ||||
| 	if (!s->is_initial) { | ||||
| 	if (s->in_merge) | ||||
| 		; /* NEEDSWORK: use "git reset --unresolve"??? */ | ||||
| 	else if (!s->is_initial) | ||||
| 		color_fprintf_ln(s->fp, c, "#   (use \"git reset %s <file>...\" to unstage)", s->reference); | ||||
| 	} else { | ||||
| 	else | ||||
| 		color_fprintf_ln(s->fp, c, "#   (use \"git rm --cached <file>...\" to unstage)"); | ||||
| 	} | ||||
| 	color_fprintf_ln(s->fp, c, "#"); | ||||
| } | ||||
|  | ||||
|  | @ -76,6 +81,7 @@ static void wt_status_print_dirty_header(struct wt_status *s, | |||
| 					 int has_deleted) | ||||
| { | ||||
| 	const char *c = color(WT_STATUS_HEADER, s); | ||||
|  | ||||
| 	color_fprintf_ln(s->fp, c, "# Changed but not updated:"); | ||||
| 	if (!advice_status_hints) | ||||
| 		return; | ||||
|  | @ -277,6 +283,7 @@ static void wt_status_collect_changes_worktree(struct wt_status *s) | |||
| 	rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK; | ||||
| 	rev.diffopt.format_callback = wt_status_collect_changed_cb; | ||||
| 	rev.diffopt.format_callback_data = s; | ||||
| 	rev.prune_data = s->pathspec; | ||||
| 	run_diff_files(&rev, 0); | ||||
| } | ||||
|  | ||||
|  | @ -293,6 +300,7 @@ static void wt_status_collect_changes_index(struct wt_status *s) | |||
| 	rev.diffopt.detect_rename = 1; | ||||
| 	rev.diffopt.rename_limit = 200; | ||||
| 	rev.diffopt.break_opt = 0; | ||||
| 	rev.prune_data = s->pathspec; | ||||
| 	run_diff_index(&rev, 1); | ||||
| } | ||||
|  | ||||
|  | @ -305,6 +313,8 @@ static void wt_status_collect_changes_initial(struct wt_status *s) | |||
| 		struct wt_status_change_data *d; | ||||
| 		struct cache_entry *ce = active_cache[i]; | ||||
|  | ||||
| 		if (!ce_path_match(ce, s->pathspec)) | ||||
| 			continue; | ||||
| 		it = string_list_insert(ce->name, &s->change); | ||||
| 		d = it->util; | ||||
| 		if (!d) { | ||||
|  | @ -338,6 +348,8 @@ static void wt_status_collect_untracked(struct wt_status *s) | |||
| 		struct dir_entry *ent = dir.entries[i]; | ||||
| 		if (!cache_name_is_other(ent->name, ent->len)) | ||||
| 			continue; | ||||
| 		if (!match_pathspec(s->pathspec, ent->name, ent->len, 0, NULL)) | ||||
| 			continue; | ||||
| 		s->workdir_untracked = 1; | ||||
| 		string_list_insert(ent->name, &s->untracked); | ||||
| 	} | ||||
|  | @ -541,10 +553,8 @@ static void wt_status_print_tracking(struct wt_status *s) | |||
|  | ||||
| void wt_status_print(struct wt_status *s) | ||||
| { | ||||
| 	unsigned char sha1[20]; | ||||
| 	const char *branch_color = color(WT_STATUS_HEADER, s); | ||||
|  | ||||
| 	s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0; | ||||
| 	if (s->branch) { | ||||
| 		const char *on_what = "On branch "; | ||||
| 		const char *branch_name = s->branch; | ||||
|  | @ -561,8 +571,6 @@ void wt_status_print(struct wt_status *s) | |||
| 			wt_status_print_tracking(s); | ||||
| 	} | ||||
|  | ||||
| 	wt_status_collect(s); | ||||
|  | ||||
| 	if (s->is_initial) { | ||||
| 		color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#"); | ||||
| 		color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "# Initial commit"); | ||||
|  | @ -598,3 +606,107 @@ void wt_status_print(struct wt_status *s) | |||
| 			printf("nothing to commit (working directory clean)\n"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void wt_shortstatus_unmerged(int null_termination, struct string_list_item *it, | ||||
| 			   struct wt_status *s) | ||||
| { | ||||
| 	struct wt_status_change_data *d = it->util; | ||||
| 	const char *how = "??"; | ||||
|  | ||||
| 	switch (d->stagemask) { | ||||
| 	case 1: how = "DD"; break; /* both deleted */ | ||||
| 	case 2: how = "AU"; break; /* added by us */ | ||||
| 	case 3: how = "UD"; break; /* deleted by them */ | ||||
| 	case 4: how = "UA"; break; /* added by them */ | ||||
| 	case 5: how = "DU"; break; /* deleted by us */ | ||||
| 	case 6: how = "AA"; break; /* both added */ | ||||
| 	case 7: how = "UU"; break; /* both modified */ | ||||
| 	} | ||||
| 	color_fprintf(s->fp, color(WT_STATUS_UNMERGED, s), "%s", how); | ||||
| 	if (null_termination) { | ||||
| 		fprintf(stdout, " %s%c", it->string, 0); | ||||
| 	} else { | ||||
| 		struct strbuf onebuf = STRBUF_INIT; | ||||
| 		const char *one; | ||||
| 		one = quote_path(it->string, -1, &onebuf, s->prefix); | ||||
| 		printf(" %s\n", one); | ||||
| 		strbuf_release(&onebuf); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void wt_shortstatus_status(int null_termination, struct string_list_item *it, | ||||
| 			 struct wt_status *s) | ||||
| { | ||||
| 	struct wt_status_change_data *d = it->util; | ||||
|  | ||||
| 	if (d->index_status) | ||||
| 		color_fprintf(s->fp, color(WT_STATUS_UPDATED, s), "%c", d->index_status); | ||||
| 	else | ||||
| 		putchar(' '); | ||||
| 	if (d->worktree_status) | ||||
| 		color_fprintf(s->fp, color(WT_STATUS_CHANGED, s), "%c", d->worktree_status); | ||||
| 	else | ||||
| 		putchar(' '); | ||||
| 	putchar(' '); | ||||
| 	if (null_termination) { | ||||
| 		fprintf(stdout, "%s%c", it->string, 0); | ||||
| 		if (d->head_path) | ||||
| 			fprintf(stdout, "%s%c", d->head_path, 0); | ||||
| 	} else { | ||||
| 		struct strbuf onebuf = STRBUF_INIT; | ||||
| 		const char *one; | ||||
| 		if (d->head_path) { | ||||
| 			one = quote_path(d->head_path, -1, &onebuf, s->prefix); | ||||
| 			printf("%s -> ", one); | ||||
| 			strbuf_release(&onebuf); | ||||
| 		} | ||||
| 		one = quote_path(it->string, -1, &onebuf, s->prefix); | ||||
| 		printf("%s\n", one); | ||||
| 		strbuf_release(&onebuf); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void wt_shortstatus_untracked(int null_termination, struct string_list_item *it, | ||||
| 			    struct wt_status *s) | ||||
| { | ||||
| 	if (null_termination) { | ||||
| 		fprintf(stdout, "?? %s%c", it->string, 0); | ||||
| 	} else { | ||||
| 		struct strbuf onebuf = STRBUF_INIT; | ||||
| 		const char *one; | ||||
| 		one = quote_path(it->string, -1, &onebuf, s->prefix); | ||||
| 		color_fprintf(s->fp, color(WT_STATUS_UNTRACKED, s), "??"); | ||||
| 		printf(" %s\n", one); | ||||
| 		strbuf_release(&onebuf); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void wt_shortstatus_print(struct wt_status *s, int null_termination) | ||||
| { | ||||
| 	int i; | ||||
| 	for (i = 0; i < s->change.nr; i++) { | ||||
| 		struct wt_status_change_data *d; | ||||
| 		struct string_list_item *it; | ||||
|  | ||||
| 		it = &(s->change.items[i]); | ||||
| 		d = it->util; | ||||
| 		if (d->stagemask) | ||||
| 			wt_shortstatus_unmerged(null_termination, it, s); | ||||
| 		else | ||||
| 			wt_shortstatus_status(null_termination, it, s); | ||||
| 	} | ||||
| 	for (i = 0; i < s->untracked.nr; i++) { | ||||
| 		struct string_list_item *it; | ||||
|  | ||||
| 		it = &(s->untracked.items[i]); | ||||
| 		wt_shortstatus_untracked(null_termination, it, s); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void wt_porcelain_print(struct wt_status *s, int null_termination) | ||||
| { | ||||
| 	s->use_color = 0; | ||||
| 	s->relative_paths = 0; | ||||
| 	s->prefix = NULL; | ||||
| 	wt_shortstatus_print(s, null_termination); | ||||
| } | ||||
|  |  | |||
|  | @ -31,8 +31,10 @@ struct wt_status { | |||
| 	int is_initial; | ||||
| 	char *branch; | ||||
| 	const char *reference; | ||||
| 	const char **pathspec; | ||||
| 	int verbose; | ||||
| 	int amend; | ||||
| 	int in_merge; | ||||
| 	int nowarn; | ||||
| 	int use_color; | ||||
| 	int relative_paths; | ||||
|  | @ -55,4 +57,7 @@ void wt_status_prepare(struct wt_status *s); | |||
| void wt_status_print(struct wt_status *s); | ||||
| void wt_status_collect(struct wt_status *s); | ||||
|  | ||||
| void wt_shortstatus_print(struct wt_status *s, int null_termination); | ||||
| void wt_porcelain_print(struct wt_status *s, int null_termination); | ||||
|  | ||||
| #endif /* STATUS_H */ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano