Skip to content

Commit

Permalink
Merge branch 'jm/status-ignored-files-list'
Browse files Browse the repository at this point in the history
This is an early version of the latest iteration of what used to
be 08f088c (Merge branch 'show-ignored-directory', 2017-10-23),
i.e.  support for the then-experimental, now-dropped
`--show-ignored-directory` option.

The set of paths output from "git status --ignored" was tied
closely with its "--untracked=<mode>" option, but now it can be
controlled more flexibly.  Most notably, a directory that is
ignored because it is listed to be ignored in the ignore/exclude
mechanism can be handled differently from a directory that ends up
to be ignored only because all files in it are ignored.

* jm/status-ignored-files-list:
  status: test ignored modes
  status: document options to show matching ignored files
  status: report matching ignored and normal untracked
  status: add option to show ignored files differently

Signed-off-by: Johannes Schindelin <[email protected]>
  • Loading branch information
dscho committed Nov 29, 2017
2 parents a9d1d32 + bff9c85 commit 2d67482
Show file tree
Hide file tree
Showing 8 changed files with 360 additions and 18 deletions.
21 changes: 20 additions & 1 deletion Documentation/git-status.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,27 @@ configuration variable documented in linkgit:git-config[1].
(and suppresses the output of submodule summaries when the config option
`status.submoduleSummary` is set).

--ignored::
--ignored[=<mode>]::
Show ignored files as well.
+
The mode parameter is used to specify the handling of ignored files.
It is optional: it defaults to 'traditional'.
+
The possible options are:
+
- 'traditional' - Shows ignored files and directories, unless
--untracked-files=all is specifed, in which case
individual files in ignored directories are
displayed.
- 'no' - Show no ignored files.
- 'matching' - Shows ignored files and directories matching an
ignore pattern.
+
When 'matching' mode is specified, paths that explicity match an
ignored pattern are shown. If a directory matches an ignore pattern,
then it is shown, but not paths contained in the ignored directory. If
a directory does not match an ignore pattern, but all contents are
ignored, then the directory is not shown, but all contents are shown.

-z::
Terminate entries with NUL, instead of LF. This implies
Expand Down
27 changes: 23 additions & 4 deletions Documentation/technical/api-directory-listing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,42 @@ The notable options are:

`flags`::

A bit-field of options (the `*IGNORED*` flags are mutually exclusive):
A bit-field of options:

`DIR_SHOW_IGNORED`:::

Return just ignored files in `entries[]`, not untracked files.
Return just ignored files in `entries[]`, not untracked
files. This flag is mutually exclusive with
`DIR_SHOW_IGNORED_TOO`.

`DIR_SHOW_IGNORED_TOO`:::

Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]`
in addition to untracked files in `entries[]`.
Similar to `DIR_SHOW_IGNORED`, but return ignored files in
`ignored[]` in addition to untracked files in
`entries[]`. This flag is mutually exclusive with
`DIR_SHOW_IGNORED`.

`DIR_KEEP_UNTRACKED_CONTENTS`:::

Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if this is set, the
untracked contents of untracked directories are also returned in
`entries[]`.

`DIR_SHOW_IGNORED_TOO_MODE_MATCHING`:::

Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if
this is set, returns ignored files and directories that match
an exclude pattern. If a directory matches an exclude pattern,
then the directory is returned and the contained paths are
not. A directory that does not match an exclude pattern will
not be returned even if all of its contents are ignored. In
this case, the contents are returned as individual entries.
+
If this is set, files and directories that explicity match an ignore
pattern are reported. Implicity ignored directories (directories that
do not match an ignore pattern, but whose contents are all ignored)
are not reported, instead all of the contents are reported.

`DIR_COLLECT_IGNORED`:::

Special mode for git-add. Return ignored files in `ignored[]` and
Expand Down
31 changes: 25 additions & 6 deletions builtin/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ static int edit_flag = -1; /* unspecified */
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
static int config_commit_verbose = -1; /* unspecified */
static int no_post_rewrite, allow_empty_message;
static char *untracked_files_arg, *force_date, *ignore_submodule_arg;
static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;
static char *sign_commit;

/*
Expand All @@ -139,7 +139,7 @@ static const char *cleanup_arg;
static enum commit_whence whence;
static int sequencer_in_use;
static int use_editor = 1, include_status = 1;
static int show_ignored_in_status, have_option_m;
static int have_option_m;
static struct strbuf message = STRBUF_INIT;

static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED;
Expand Down Expand Up @@ -1075,6 +1075,19 @@ static const char *find_author_by_nickname(const char *name)
die(_("--author '%s' is not 'Name <email>' and matches no existing author"), name);
}

static void handle_ignored_arg(struct wt_status *s)
{
if (!ignored_arg)
; /* default already initialized */
else if (!strcmp(ignored_arg, "traditional"))
s->show_ignored_mode = SHOW_TRADITIONAL_IGNORED;
else if (!strcmp(ignored_arg, "no"))
s->show_ignored_mode = SHOW_NO_IGNORED;
else if (!strcmp(ignored_arg, "matching"))
s->show_ignored_mode = SHOW_MATCHING_IGNORED;
else
die(_("Invalid ignored mode '%s'"), ignored_arg);
}

static void handle_untracked_files_arg(struct wt_status *s)
{
Expand Down Expand Up @@ -1364,8 +1377,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)
N_("mode"),
N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
OPT_BOOL(0, "ignored", &show_ignored_in_status,
N_("show ignored files")),
{ OPTION_STRING, 0, "ignored", &ignored_arg,
N_("mode"),
N_("show ignored files, optional modes: traditional, matching, no. (Default: traditional)"),
PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" },
{ OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),
N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
Expand Down Expand Up @@ -1393,8 +1408,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)
}

handle_untracked_files_arg(&s);
if (show_ignored_in_status)
s.show_ignored_files = 1;
handle_ignored_arg(&s);

if (s.show_ignored_mode == SHOW_MATCHING_IGNORED &&
s.show_untracked_files == SHOW_NO_UNTRACKED_FILES)
die(_("Unsupported combination of ignored and untracked-files arguments"));

parse_pathspec(&s.pathspec, 0,
PATHSPEC_PREFER_FULL,
prefix, argv);
Expand Down
44 changes: 42 additions & 2 deletions dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,30 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
case index_nonexistent:
if (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)
break;
if (exclude &&
(dir->flags & DIR_SHOW_IGNORED_TOO) &&
(dir->flags & DIR_SHOW_IGNORED_TOO_MODE_MATCHING)) {

/*
* This is an excluded directory and we are
* showing ignored paths that match an exclude
* pattern. (e.g. show directory as ignored
* only if it matches an exclude pattern).
* This path will either be 'path_excluded`
* (if we are showing empty directories or if
* the directory is not empty), or will be
* 'path_none' (empty directory, and we are
* not showing empty directories).
*/
if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
return path_excluded;

if (read_directory_recursive(dir, istate, dirname, len,
untracked, 1, 1, pathspec) == path_excluded)
return path_excluded;

return path_none;
}
if (!(dir->flags & DIR_NO_GITLINKS)) {
unsigned char sha1[20];
if (resolve_gitlink_ref(dirname, "HEAD", sha1) == 0)
Expand Down Expand Up @@ -1561,6 +1585,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
{
int exclude;
int has_path_in_index = !!index_file_exists(istate, path->buf, path->len, ignore_case);
enum path_treatment path_treatment;

if (dtype == DT_UNKNOWN)
dtype = get_dtype(de, istate, path->buf, path->len);
Expand Down Expand Up @@ -1607,8 +1632,23 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
return path_none;
case DT_DIR:
strbuf_addch(path, '/');
return treat_directory(dir, istate, untracked, path->buf, path->len,
baselen, exclude, pathspec);
path_treatment = treat_directory(dir, istate, untracked,
path->buf, path->len,
baselen, exclude, pathspec);
/*
* If 1) we only want to return directories that
* match an exclude pattern and 2) this directory does
* not match an exclude pattern but all of its
* contents are excluded, then indicate that we should
* recurse into this directory (instead of marking the
* directory itself as an ignored path).
*/
if (!exclude &&
path_treatment == path_excluded &&
(dir->flags & DIR_SHOW_IGNORED_TOO) &&
(dir->flags & DIR_SHOW_IGNORED_TOO_MODE_MATCHING))
return path_recurse;
return path_treatment;
case DT_REG:
case DT_LNK:
return exclude ? path_excluded : path_untracked;
Expand Down
3 changes: 2 additions & 1 deletion dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ struct dir_struct {
DIR_COLLECT_IGNORED = 1<<4,
DIR_SHOW_IGNORED_TOO = 1<<5,
DIR_COLLECT_KILLED_ONLY = 1<<6,
DIR_KEEP_UNTRACKED_CONTENTS = 1<<7
DIR_KEEP_UNTRACKED_CONTENTS = 1<<7,
DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8
} flags;
struct dir_entry **entries;
struct dir_entry **ignored;
Expand Down
Loading

0 comments on commit 2d67482

Please sign in to comment.