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.c
This commit is contained in:
@ -74,6 +74,20 @@ OPTIONS
|
|||||||
authorship of the resulting commit now belongs of the committer.
|
authorship of the resulting commit now belongs of the committer.
|
||||||
This also renews the author timestamp.
|
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>::
|
-F <file>::
|
||||||
--file=<file>::
|
--file=<file>::
|
||||||
Take the commit message from the given file. Use '-' to
|
Take the commit message from the given file. Use '-' to
|
||||||
|
@ -8,7 +8,7 @@ git-status - Show the working tree status
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git status' <options>...
|
'git status' [<options>...] [--] [<pathspec>...]
|
||||||
|
|
||||||
DESCRIPTION
|
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
|
third are what you _could_ commit by running 'git-add' before running
|
||||||
`git commit`.
|
`git commit`.
|
||||||
|
|
||||||
The command takes the same set of options as 'git-commit'; it
|
OPTIONS
|
||||||
shows what would be committed if the same options are given to
|
-------
|
||||||
'git-commit'.
|
|
||||||
|
|
||||||
If there is no path that is different between the index file and
|
-s::
|
||||||
the current HEAD commit (i.e., there is nothing to commit by running
|
--short::
|
||||||
`git commit`), the command exits with non-zero status.
|
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
|
OUTPUT
|
||||||
------
|
------
|
||||||
The output from this command is designed to be used as a commit
|
The output from this command is designed to be used as a commit
|
||||||
template comment, and all the output lines are prefixed with '#'.
|
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
|
The paths mentioned in the output, unlike many other git commands, are
|
||||||
made relative to the current directory if you are working in a
|
made relative to the current directory if you are working in a
|
||||||
subdirectory (this is on purpose, to help cutting and pasting). See
|
subdirectory (this is on purpose, to help cutting and pasting). See
|
||||||
the status.relativePaths config option below.
|
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
|
CONFIGURATION
|
||||||
-------------
|
-------------
|
||||||
@ -53,9 +118,9 @@ paths shown are relative to the repository root, not to the current
|
|||||||
directory.
|
directory.
|
||||||
|
|
||||||
If `status.submodulesummary` is set to a non zero number or true (identical
|
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
|
to -1 or an unlimited number), the submodule summary will be enabled for
|
||||||
summary of commits for modified submodules will be shown (see --summary-limit
|
the long format and a summary of commits for modified submodules will be
|
||||||
option of linkgit:git-submodule[1]).
|
shown (see --summary-limit option of linkgit:git-submodule[1]).
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
@ -63,8 +128,7 @@ linkgit:gitignore[5]
|
|||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org> and
|
Written by Junio C Hamano <gitster@pobox.com>.
|
||||||
Junio C Hamano <gitster@pobox.com>.
|
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
--------------
|
--------------
|
||||||
|
124
builtin-commit.c
124
builtin-commit.c
@ -24,6 +24,7 @@
|
|||||||
#include "string-list.h"
|
#include "string-list.h"
|
||||||
#include "rerere.h"
|
#include "rerere.h"
|
||||||
#include "unpack-trees.h"
|
#include "unpack-trees.h"
|
||||||
|
#include "quote.h"
|
||||||
|
|
||||||
static const char * const builtin_commit_usage[] = {
|
static const char * const builtin_commit_usage[] = {
|
||||||
"git commit [options] [--] <filepattern>...",
|
"git commit [options] [--] <filepattern>...",
|
||||||
@ -35,7 +36,7 @@ static const char * const builtin_status_usage[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned char head_sha1[20], merge_head_sha1[20];
|
static unsigned char head_sha1[20];
|
||||||
static char *use_message_buffer;
|
static char *use_message_buffer;
|
||||||
static const char commit_editmsg[] = "COMMIT_EDITMSG";
|
static const char commit_editmsg[] = "COMMIT_EDITMSG";
|
||||||
static struct lock_file index_lock; /* real index */
|
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 const char *only_include_assumed;
|
||||||
static struct strbuf message;
|
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)
|
static int opt_parse_m(const struct option *opt, const char *arg, int unset)
|
||||||
{
|
{
|
||||||
struct strbuf *buf = opt->value;
|
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('o', "only", &only, "commit only specified files"),
|
||||||
OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
|
OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
|
||||||
OPT_BOOLEAN(0, "dry-run", &dry_run, "show what would be committed"),
|
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"),
|
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" },
|
{ 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"),
|
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;
|
commit_style = COMMIT_PARTIAL;
|
||||||
|
|
||||||
if (file_exists(git_path("MERGE_HEAD")))
|
if (in_merge)
|
||||||
die("cannot do a partial commit during a merge.");
|
die("cannot do a partial commit during a merge.");
|
||||||
|
|
||||||
memset(&partial, 0, sizeof(partial));
|
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,
|
static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn,
|
||||||
struct wt_status *s)
|
struct wt_status *s)
|
||||||
{
|
{
|
||||||
|
unsigned char sha1[20];
|
||||||
|
|
||||||
if (s->relative_paths)
|
if (s->relative_paths)
|
||||||
s->prefix = prefix;
|
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->index_file = index_file;
|
||||||
s->fp = fp;
|
s->fp = fp;
|
||||||
s->nowarn = nowarn;
|
s->nowarn = nowarn;
|
||||||
|
s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0;
|
||||||
|
|
||||||
wt_status_print(s);
|
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;
|
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);
|
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[],
|
static int parse_and_validate_options(int argc, const char *argv[],
|
||||||
const char * const usage[],
|
const char * const usage[],
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
@ -761,9 +805,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
|
|||||||
if (get_sha1("HEAD", head_sha1))
|
if (get_sha1("HEAD", head_sha1))
|
||||||
initial_commit = 1;
|
initial_commit = 1;
|
||||||
|
|
||||||
if (!get_sha1("MERGE_HEAD", merge_head_sha1))
|
|
||||||
in_merge = 1;
|
|
||||||
|
|
||||||
/* Sanity check options */
|
/* Sanity check options */
|
||||||
if (amend && initial_commit)
|
if (amend && initial_commit)
|
||||||
die("You have nothing to amend.");
|
die("You have nothing to amend.");
|
||||||
@ -843,22 +884,18 @@ static int parse_and_validate_options(int argc, const char *argv[],
|
|||||||
else
|
else
|
||||||
die("Invalid cleanup mode %s", cleanup_arg);
|
die("Invalid cleanup mode %s", cleanup_arg);
|
||||||
|
|
||||||
if (!untracked_files_arg)
|
handle_untracked_files_arg(s);
|
||||||
; /* 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);
|
|
||||||
|
|
||||||
if (all && argc > 0)
|
if (all && argc > 0)
|
||||||
die("Paths with -a does not make sense.");
|
die("Paths with -a does not make sense.");
|
||||||
else if (interactive && argc > 0)
|
else if (interactive && argc > 0)
|
||||||
die("Paths with --interactive does not make sense.");
|
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;
|
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)
|
int cmd_status(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
struct wt_status s;
|
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);
|
wt_status_prepare(&s);
|
||||||
git_config(git_status_config, &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)
|
if (s.use_color == -1)
|
||||||
s.use_color = git_use_color_default;
|
s.use_color = git_use_color_default;
|
||||||
if (diff_use_color_default == -1)
|
if (diff_use_color_default == -1)
|
||||||
diff_use_color_default = git_use_color_default;
|
diff_use_color_default = git_use_color_default;
|
||||||
|
|
||||||
argc = parse_and_validate_options(argc, argv, builtin_status_usage,
|
switch (status_format) {
|
||||||
prefix, &s);
|
case STATUS_FORMAT_SHORT:
|
||||||
return dry_run_commit(argc, argv, prefix, &s);
|
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)
|
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);
|
wt_status_prepare(&s);
|
||||||
git_config(git_commit_config, &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)
|
if (s.use_color == -1)
|
||||||
s.use_color = git_use_color_default;
|
s.use_color = git_use_color_default;
|
||||||
|
|
||||||
argc = parse_and_validate_options(argc, argv, builtin_commit_usage,
|
argc = parse_and_validate_options(argc, argv, builtin_commit_usage,
|
||||||
prefix, &s);
|
prefix, &s);
|
||||||
if (dry_run) {
|
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 () {
|
word_diff () {
|
||||||
test_must_fail git diff --no-index "$@" pre post > output &&
|
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
|
test_cmp expect output.decrypted
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +39,7 @@ cat > expect <<\EOF
|
|||||||
<WHITE>index 330b04f..5ed8eff 100644<RESET>
|
<WHITE>index 330b04f..5ed8eff 100644<RESET>
|
||||||
<WHITE>--- a/pre<RESET>
|
<WHITE>--- a/pre<RESET>
|
||||||
<WHITE>+++ b/post<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>
|
<RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET>
|
||||||
|
|
||||||
a = b + c<RESET>
|
a = b + c<RESET>
|
||||||
@ -70,9 +60,9 @@ cat > expect <<\EOF
|
|||||||
<WHITE>index 330b04f..5ed8eff 100644<RESET>
|
<WHITE>index 330b04f..5ed8eff 100644<RESET>
|
||||||
<WHITE>--- a/pre<RESET>
|
<WHITE>--- a/pre<RESET>
|
||||||
<WHITE>+++ b/post<RESET>
|
<WHITE>+++ b/post<RESET>
|
||||||
<BROWN>@@ -1 +1 @@<RESET>
|
<CYAN>@@ -1 +1 @@<RESET>
|
||||||
<RED>h(4)<RESET><GREEN>h(4),hh[44]<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>
|
<GREEN>aa = a<RESET>
|
||||||
|
|
||||||
@ -90,7 +80,7 @@ cat > expect <<\EOF
|
|||||||
<WHITE>index 330b04f..5ed8eff 100644<RESET>
|
<WHITE>index 330b04f..5ed8eff 100644<RESET>
|
||||||
<WHITE>--- a/pre<RESET>
|
<WHITE>--- a/pre<RESET>
|
||||||
<WHITE>+++ b/post<RESET>
|
<WHITE>+++ b/post<RESET>
|
||||||
<BROWN>@@ -1,3 +1,7 @@<RESET>
|
<CYAN>@@ -1,3 +1,7 @@<RESET>
|
||||||
h(4),<GREEN>hh<RESET>[44]
|
h(4),<GREEN>hh<RESET>[44]
|
||||||
|
|
||||||
a = b + c<RESET>
|
a = b + c<RESET>
|
||||||
@ -126,7 +116,7 @@ cat > expect <<\EOF
|
|||||||
<WHITE>index 330b04f..5ed8eff 100644<RESET>
|
<WHITE>index 330b04f..5ed8eff 100644<RESET>
|
||||||
<WHITE>--- a/pre<RESET>
|
<WHITE>--- a/pre<RESET>
|
||||||
<WHITE>+++ b/post<RESET>
|
<WHITE>+++ b/post<RESET>
|
||||||
<BROWN>@@ -1,3 +1,7 @@<RESET>
|
<CYAN>@@ -1,3 +1,7 @@<RESET>
|
||||||
h(4)<GREEN>,hh[44]<RESET>
|
h(4)<GREEN>,hh[44]<RESET>
|
||||||
|
|
||||||
a = b + c<RESET>
|
a = b + c<RESET>
|
||||||
@ -168,7 +158,7 @@ cat > expect <<\EOF
|
|||||||
<WHITE>index 330b04f..5ed8eff 100644<RESET>
|
<WHITE>index 330b04f..5ed8eff 100644<RESET>
|
||||||
<WHITE>--- a/pre<RESET>
|
<WHITE>--- a/pre<RESET>
|
||||||
<WHITE>+++ b/post<RESET>
|
<WHITE>+++ b/post<RESET>
|
||||||
<BROWN>@@ -1,3 +1,7 @@<RESET>
|
<CYAN>@@ -1,3 +1,7 @@<RESET>
|
||||||
h(4),<GREEN>hh[44<RESET>]
|
h(4),<GREEN>hh[44<RESET>]
|
||||||
|
|
||||||
a = b + c<RESET>
|
a = b + c<RESET>
|
||||||
@ -190,7 +180,7 @@ cat > expect <<\EOF
|
|||||||
<WHITE>index c29453b..be22f37 100644<RESET>
|
<WHITE>index c29453b..be22f37 100644<RESET>
|
||||||
<WHITE>--- a/pre<RESET>
|
<WHITE>--- a/pre<RESET>
|
||||||
<WHITE>+++ b/post<RESET>
|
<WHITE>+++ b/post<RESET>
|
||||||
<BROWN>@@ -1 +1 @@<RESET>
|
<CYAN>@@ -1 +1 @@<RESET>
|
||||||
aaa (aaa) <GREEN>aaa<RESET>
|
aaa (aaa) <GREEN>aaa<RESET>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
@ -209,7 +199,7 @@ cat > expect <<\EOF
|
|||||||
<WHITE>index 289cb9d..2d06f37 100644<RESET>
|
<WHITE>index 289cb9d..2d06f37 100644<RESET>
|
||||||
<WHITE>--- a/pre<RESET>
|
<WHITE>--- a/pre<RESET>
|
||||||
<WHITE>+++ b/post<RESET>
|
<WHITE>+++ b/post<RESET>
|
||||||
<BROWN>@@ -1 +1 @@<RESET>
|
<CYAN>@@ -1 +1 @@<RESET>
|
||||||
(<RED>:<RESET>
|
(<RED>:<RESET>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ test_expect_success 'status' '
|
|||||||
cd test &&
|
cd test &&
|
||||||
git checkout b1 >/dev/null &&
|
git checkout b1 >/dev/null &&
|
||||||
# reports nothing to commit
|
# reports nothing to commit
|
||||||
test_must_fail git status
|
test_must_fail git commit --dry-run
|
||||||
) >actual &&
|
) >actual &&
|
||||||
grep "have 1 and 1 different" actual
|
grep "have 1 and 1 different" actual
|
||||||
'
|
'
|
||||||
|
@ -31,8 +31,7 @@ test_expect_success 'Report new path with conflict' '
|
|||||||
cat >expect <<EOF
|
cat >expect <<EOF
|
||||||
# On branch side
|
# On branch side
|
||||||
# Unmerged paths:
|
# Unmerged paths:
|
||||||
# (use "git reset HEAD <file>..." to unstage)
|
# (use "git add/rm <file>..." as appropriate to mark resolution)
|
||||||
# (use "git add <file>..." to mark resolution)
|
|
||||||
#
|
#
|
||||||
# deleted by us: foo
|
# deleted by us: foo
|
||||||
#
|
#
|
||||||
@ -50,9 +49,11 @@ test_expect_success 'M/D conflict does not segfault' '
|
|||||||
git rm foo &&
|
git rm foo &&
|
||||||
git commit -m delete &&
|
git commit -m delete &&
|
||||||
test_must_fail git merge master &&
|
test_must_fail git merge master &&
|
||||||
test_must_fail git status > ../actual
|
test_must_fail git commit --dry-run >../actual &&
|
||||||
) &&
|
test_cmp ../expect ../actual &&
|
||||||
test_cmp expect actual
|
git status >../actual &&
|
||||||
|
test_cmp ../expect ../actual
|
||||||
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -19,8 +19,8 @@ test_expect_success 'status clean' '
|
|||||||
git status |
|
git status |
|
||||||
grep "nothing to commit"
|
grep "nothing to commit"
|
||||||
'
|
'
|
||||||
test_expect_success 'status -a clean' '
|
test_expect_success 'commit --dry-run -a clean' '
|
||||||
git status -a |
|
git commit --dry-run -a |
|
||||||
grep "nothing to commit"
|
grep "nothing to commit"
|
||||||
'
|
'
|
||||||
test_expect_success 'rm submodule contents' '
|
test_expect_success 'rm submodule contents' '
|
||||||
@ -31,7 +31,7 @@ test_expect_success 'status clean (empty submodule dir)' '
|
|||||||
grep "nothing to commit"
|
grep "nothing to commit"
|
||||||
'
|
'
|
||||||
test_expect_success 'status -a clean (empty submodule dir)' '
|
test_expect_success 'status -a clean (empty submodule dir)' '
|
||||||
git status -a |
|
git commit --dry-run -a |
|
||||||
grep "nothing to commit"
|
grep "nothing to commit"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
@ -8,26 +8,26 @@ test_description='git status'
|
|||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_expect_success 'setup' '
|
test_expect_success 'setup' '
|
||||||
: > tracked &&
|
: >tracked &&
|
||||||
: > modified &&
|
: >modified &&
|
||||||
mkdir dir1 &&
|
mkdir dir1 &&
|
||||||
: > dir1/tracked &&
|
: >dir1/tracked &&
|
||||||
: > dir1/modified &&
|
: >dir1/modified &&
|
||||||
mkdir dir2 &&
|
mkdir dir2 &&
|
||||||
: > dir1/tracked &&
|
: >dir1/tracked &&
|
||||||
: > dir1/modified &&
|
: >dir1/modified &&
|
||||||
git add . &&
|
git add . &&
|
||||||
|
|
||||||
git status >output &&
|
git status >output &&
|
||||||
|
|
||||||
test_tick &&
|
test_tick &&
|
||||||
git commit -m initial &&
|
git commit -m initial &&
|
||||||
: > untracked &&
|
: >untracked &&
|
||||||
: > dir1/untracked &&
|
: >dir1/untracked &&
|
||||||
: > dir2/untracked &&
|
: >dir2/untracked &&
|
||||||
echo 1 > dir1/modified &&
|
echo 1 >dir1/modified &&
|
||||||
echo 2 > dir2/modified &&
|
echo 2 >dir2/modified &&
|
||||||
echo 3 > dir2/added &&
|
echo 3 >dir2/added &&
|
||||||
git add dir2/added
|
git add dir2/added
|
||||||
'
|
'
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ test_expect_success 'status (1)' '
|
|||||||
|
|
||||||
'
|
'
|
||||||
|
|
||||||
cat > expect << \EOF
|
cat >expect <<\EOF
|
||||||
# On branch master
|
# On branch master
|
||||||
# Changes to be committed:
|
# Changes to be committed:
|
||||||
# (use "git reset HEAD <file>..." to unstage)
|
# (use "git reset HEAD <file>..." to unstage)
|
||||||
@ -63,7 +63,25 @@ EOF
|
|||||||
|
|
||||||
test_expect_success 'status (2)' '
|
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
|
test_cmp expect output
|
||||||
|
|
||||||
'
|
'
|
||||||
@ -85,8 +103,8 @@ cat >expect <<EOF
|
|||||||
EOF
|
EOF
|
||||||
test_expect_success 'status -uno' '
|
test_expect_success 'status -uno' '
|
||||||
mkdir dir3 &&
|
mkdir dir3 &&
|
||||||
: > dir3/untracked1 &&
|
: >dir3/untracked1 &&
|
||||||
: > dir3/untracked2 &&
|
: >dir3/untracked2 &&
|
||||||
git status -uno >output &&
|
git status -uno >output &&
|
||||||
test_cmp expect output
|
test_cmp expect output
|
||||||
'
|
'
|
||||||
@ -97,6 +115,22 @@ test_expect_success 'status (status.showUntrackedFiles no)' '
|
|||||||
test_cmp expect output
|
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
|
cat >expect <<EOF
|
||||||
# On branch master
|
# On branch master
|
||||||
# Changes to be committed:
|
# Changes to be committed:
|
||||||
@ -132,6 +166,29 @@ test_expect_success 'status (status.showUntrackedFiles normal)' '
|
|||||||
test_cmp expect output
|
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
|
cat >expect <<EOF
|
||||||
# On branch master
|
# On branch master
|
||||||
# Changes to be committed:
|
# Changes to be committed:
|
||||||
@ -169,7 +226,30 @@ test_expect_success 'status (status.showUntrackedFiles all)' '
|
|||||||
test_cmp expect output
|
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
|
# On branch master
|
||||||
# Changes to be committed:
|
# Changes to be committed:
|
||||||
# (use "git reset HEAD <file>..." to unstage)
|
# (use "git reset HEAD <file>..." to unstage)
|
||||||
@ -195,12 +275,156 @@ EOF
|
|||||||
|
|
||||||
test_expect_success 'status with relative paths' '
|
test_expect_success 'status with relative paths' '
|
||||||
|
|
||||||
(cd dir1 && git status) > output &&
|
(cd dir1 && git status) >output &&
|
||||||
test_cmp expect 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
|
# On branch master
|
||||||
# Changes to be committed:
|
# Changes to be committed:
|
||||||
# (use "git reset HEAD <file>..." to unstage)
|
# (use "git reset HEAD <file>..." to unstage)
|
||||||
@ -224,10 +448,29 @@ cat > expect << \EOF
|
|||||||
# untracked
|
# untracked
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
||||||
test_expect_success 'status without relative paths' '
|
test_expect_success 'status without relative paths' '
|
||||||
|
|
||||||
git config status.relativePaths false
|
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
|
test_cmp expect output
|
||||||
|
|
||||||
'
|
'
|
||||||
@ -248,8 +491,8 @@ cat <<EOF >expect
|
|||||||
# output
|
# output
|
||||||
# untracked
|
# untracked
|
||||||
EOF
|
EOF
|
||||||
test_expect_success 'status of partial commit excluding new file in index' '
|
test_expect_success 'dry-run of partial commit excluding new file in index' '
|
||||||
git status dir1/modified >output &&
|
git commit --dry-run dir1/modified >output &&
|
||||||
test_cmp expect output
|
test_cmp expect output
|
||||||
'
|
'
|
||||||
|
|
||||||
@ -298,6 +541,28 @@ test_expect_success 'status --untracked-files=all does not show submodule' '
|
|||||||
test_cmp expect output
|
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)
|
head=$(cd sm && git rev-parse --short=7 --verify HEAD)
|
||||||
|
|
||||||
cat >expect <<EOF
|
cat >expect <<EOF
|
||||||
@ -335,6 +600,21 @@ test_expect_success 'status submodule summary' '
|
|||||||
test_cmp expect output
|
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
|
cat >expect <<EOF
|
||||||
# On branch master
|
# On branch master
|
||||||
@ -358,7 +638,23 @@ EOF
|
|||||||
test_expect_success 'status submodule summary (clean submodule)' '
|
test_expect_success 'status submodule summary (clean submodule)' '
|
||||||
git commit -m "commit submodule" &&
|
git commit -m "commit submodule" &&
|
||||||
git config status.submodulesummary 10 &&
|
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
|
test_cmp expect output
|
||||||
'
|
'
|
||||||
|
|
||||||
@ -391,9 +687,9 @@ cat >expect <<EOF
|
|||||||
# output
|
# output
|
||||||
# untracked
|
# untracked
|
||||||
EOF
|
EOF
|
||||||
test_expect_success 'status submodule summary (--amend)' '
|
test_expect_success 'commit --dry-run submodule summary (--amend)' '
|
||||||
git config status.submodulesummary 10 &&
|
git config status.submodulesummary 10 &&
|
||||||
git status --amend >output &&
|
git commit --dry-run --amend >output &&
|
||||||
test_cmp expect output
|
test_cmp expect output
|
||||||
'
|
'
|
||||||
|
|
||||||
|
@ -211,6 +211,17 @@ test_set_editor () {
|
|||||||
export 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 () {
|
test_tick () {
|
||||||
if test -z "${test_tick+set}"
|
if test -z "${test_tick+set}"
|
||||||
then
|
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)
|
static void wt_status_print_unmerged_header(struct wt_status *s)
|
||||||
{
|
{
|
||||||
const char *c = color(WT_STATUS_HEADER, s);
|
const char *c = color(WT_STATUS_HEADER, s);
|
||||||
|
|
||||||
color_fprintf_ln(s->fp, c, "# Unmerged paths:");
|
color_fprintf_ln(s->fp, c, "# Unmerged paths:");
|
||||||
if (!advice_status_hints)
|
if (!advice_status_hints)
|
||||||
return;
|
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);
|
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, "# (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, "#");
|
color_fprintf_ln(s->fp, c, "#");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wt_status_print_cached_header(struct wt_status *s)
|
static void wt_status_print_cached_header(struct wt_status *s)
|
||||||
{
|
{
|
||||||
const char *c = color(WT_STATUS_HEADER, s);
|
const char *c = color(WT_STATUS_HEADER, s);
|
||||||
|
|
||||||
color_fprintf_ln(s->fp, c, "# Changes to be committed:");
|
color_fprintf_ln(s->fp, c, "# Changes to be committed:");
|
||||||
if (!advice_status_hints)
|
if (!advice_status_hints)
|
||||||
return;
|
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);
|
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, "# (use \"git rm --cached <file>...\" to unstage)");
|
||||||
}
|
|
||||||
color_fprintf_ln(s->fp, c, "#");
|
color_fprintf_ln(s->fp, c, "#");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +81,7 @@ static void wt_status_print_dirty_header(struct wt_status *s,
|
|||||||
int has_deleted)
|
int has_deleted)
|
||||||
{
|
{
|
||||||
const char *c = color(WT_STATUS_HEADER, s);
|
const char *c = color(WT_STATUS_HEADER, s);
|
||||||
|
|
||||||
color_fprintf_ln(s->fp, c, "# Changed but not updated:");
|
color_fprintf_ln(s->fp, c, "# Changed but not updated:");
|
||||||
if (!advice_status_hints)
|
if (!advice_status_hints)
|
||||||
return;
|
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.output_format |= DIFF_FORMAT_CALLBACK;
|
||||||
rev.diffopt.format_callback = wt_status_collect_changed_cb;
|
rev.diffopt.format_callback = wt_status_collect_changed_cb;
|
||||||
rev.diffopt.format_callback_data = s;
|
rev.diffopt.format_callback_data = s;
|
||||||
|
rev.prune_data = s->pathspec;
|
||||||
run_diff_files(&rev, 0);
|
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.detect_rename = 1;
|
||||||
rev.diffopt.rename_limit = 200;
|
rev.diffopt.rename_limit = 200;
|
||||||
rev.diffopt.break_opt = 0;
|
rev.diffopt.break_opt = 0;
|
||||||
|
rev.prune_data = s->pathspec;
|
||||||
run_diff_index(&rev, 1);
|
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 wt_status_change_data *d;
|
||||||
struct cache_entry *ce = active_cache[i];
|
struct cache_entry *ce = active_cache[i];
|
||||||
|
|
||||||
|
if (!ce_path_match(ce, s->pathspec))
|
||||||
|
continue;
|
||||||
it = string_list_insert(ce->name, &s->change);
|
it = string_list_insert(ce->name, &s->change);
|
||||||
d = it->util;
|
d = it->util;
|
||||||
if (!d) {
|
if (!d) {
|
||||||
@ -338,6 +348,8 @@ static void wt_status_collect_untracked(struct wt_status *s)
|
|||||||
struct dir_entry *ent = dir.entries[i];
|
struct dir_entry *ent = dir.entries[i];
|
||||||
if (!cache_name_is_other(ent->name, ent->len))
|
if (!cache_name_is_other(ent->name, ent->len))
|
||||||
continue;
|
continue;
|
||||||
|
if (!match_pathspec(s->pathspec, ent->name, ent->len, 0, NULL))
|
||||||
|
continue;
|
||||||
s->workdir_untracked = 1;
|
s->workdir_untracked = 1;
|
||||||
string_list_insert(ent->name, &s->untracked);
|
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)
|
void wt_status_print(struct wt_status *s)
|
||||||
{
|
{
|
||||||
unsigned char sha1[20];
|
|
||||||
const char *branch_color = color(WT_STATUS_HEADER, s);
|
const char *branch_color = color(WT_STATUS_HEADER, s);
|
||||||
|
|
||||||
s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0;
|
|
||||||
if (s->branch) {
|
if (s->branch) {
|
||||||
const char *on_what = "On branch ";
|
const char *on_what = "On branch ";
|
||||||
const char *branch_name = s->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_print_tracking(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
wt_status_collect(s);
|
|
||||||
|
|
||||||
if (s->is_initial) {
|
if (s->is_initial) {
|
||||||
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
|
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "#");
|
||||||
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "# Initial commit");
|
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");
|
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;
|
int is_initial;
|
||||||
char *branch;
|
char *branch;
|
||||||
const char *reference;
|
const char *reference;
|
||||||
|
const char **pathspec;
|
||||||
int verbose;
|
int verbose;
|
||||||
int amend;
|
int amend;
|
||||||
|
int in_merge;
|
||||||
int nowarn;
|
int nowarn;
|
||||||
int use_color;
|
int use_color;
|
||||||
int relative_paths;
|
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_print(struct wt_status *s);
|
||||||
void wt_status_collect(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 */
|
#endif /* STATUS_H */
|
||||||
|
Reference in New Issue
Block a user