Browse Source

Merge branch 'mv/parseopt-ls-files'

* mv/parseopt-ls-files:
  ls-files: fix broken --no-empty-directory
  t3000: use test_cmp instead of diff
  parse-opt: migrate builtin-ls-files.
  Turn the flags in struct dir_struct into a single variable

Conflicts:
	builtin-ls-files.c
	t/t3000-ls-files-others.sh
maint
Junio C Hamano 16 years ago
parent
commit
de2e3b04cd
  1. 2
      builtin-add.c
  2. 2
      builtin-checkout.c
  3. 4
      builtin-clean.c
  4. 264
      builtin-ls-files.c
  5. 2
      builtin-merge.c
  6. 2
      builtin-read-tree.c
  7. 17
      dir.c
  8. 12
      dir.h
  9. 14
      t/t3000-ls-files-others.sh
  10. 7
      wt-status.c

2
builtin-add.c

@ -104,7 +104,7 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec,
/* Set up the default git porcelain excludes */ /* Set up the default git porcelain excludes */
memset(dir, 0, sizeof(*dir)); memset(dir, 0, sizeof(*dir));
if (!ignored_too) { if (!ignored_too) {
dir->collect_ignored = 1; dir->flags |= DIR_COLLECT_IGNORED;
setup_standard_excludes(dir); setup_standard_excludes(dir);
} }



2
builtin-checkout.c

@ -407,7 +407,7 @@ static int merge_working_tree(struct checkout_opts *opts,
topts.verbose_update = !opts->quiet; topts.verbose_update = !opts->quiet;
topts.fn = twoway_merge; topts.fn = twoway_merge;
topts.dir = xcalloc(1, sizeof(*topts.dir)); topts.dir = xcalloc(1, sizeof(*topts.dir));
topts.dir->show_ignored = 1; topts.dir->flags |= DIR_SHOW_IGNORED;
topts.dir->exclude_per_dir = ".gitignore"; topts.dir->exclude_per_dir = ".gitignore";
tree = parse_tree_indirect(old->commit->object.sha1); tree = parse_tree_indirect(old->commit->object.sha1);
init_tree_desc(&trees[0], tree->buffer, tree->size); init_tree_desc(&trees[0], tree->buffer, tree->size);

4
builtin-clean.c

@ -60,7 +60,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)


memset(&dir, 0, sizeof(dir)); memset(&dir, 0, sizeof(dir));
if (ignored_only) if (ignored_only)
dir.show_ignored = 1; dir.flags |= DIR_SHOW_IGNORED;


if (ignored && ignored_only) if (ignored && ignored_only)
die("-x and -X cannot be used together"); die("-x and -X cannot be used together");
@ -69,7 +69,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
die("clean.requireForce%s set and -n or -f not given; " die("clean.requireForce%s set and -n or -f not given; "
"refusing to clean", config_set ? "" : " not"); "refusing to clean", config_set ? "" : " not");


dir.show_other_directories = 1; dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;


if (!ignored) if (!ignored)
setup_standard_excludes(&dir); setup_standard_excludes(&dir);

264
builtin-ls-files.c

@ -10,6 +10,7 @@
#include "dir.h" #include "dir.h"
#include "builtin.h" #include "builtin.h"
#include "tree.h" #include "tree.h"
#include "parse-options.h"


static int abbrev; static int abbrev;
static int show_deleted; static int show_deleted;
@ -28,6 +29,7 @@ static const char **pathspec;
static int error_unmatch; static int error_unmatch;
static char *ps_matched; static char *ps_matched;
static const char *with_tree; static const char *with_tree;
static int exc_given;


static const char *tag_cached = ""; static const char *tag_cached = "";
static const char *tag_unmerged = ""; static const char *tag_unmerged = "";
@ -174,7 +176,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
for (i = 0; i < active_nr; i++) { for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i]; struct cache_entry *ce = active_cache[i];
int dtype = ce_to_dtype(ce); int dtype = ce_to_dtype(ce);
if (excluded(dir, ce->name, &dtype) != dir->show_ignored) if (excluded(dir, ce->name, &dtype) !=
!!(dir->flags & DIR_SHOW_IGNORED))
continue; continue;
if (show_unmerged && !ce_stage(ce)) if (show_unmerged && !ce_stage(ce))
continue; continue;
@ -189,7 +192,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
struct stat st; struct stat st;
int err; int err;
int dtype = ce_to_dtype(ce); int dtype = ce_to_dtype(ce);
if (excluded(dir, ce->name, &dtype) != dir->show_ignored) if (excluded(dir, ce->name, &dtype) !=
!!(dir->flags & DIR_SHOW_IGNORED))
continue; continue;
if (ce->ce_flags & CE_UPDATE) if (ce->ce_flags & CE_UPDATE)
continue; continue;
@ -374,157 +378,139 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_
return errors; return errors;
} }


static const char ls_files_usage[] = static const char * const ls_files_usage[] = {
"git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* " "git ls-files [options] [<file>]*",
"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] " NULL
"[ --exclude-per-directory=<filename> ] [--exclude-standard] " };
"[--full-name] [--abbrev] [--] [<file>]*";
static int option_parse_z(const struct option *opt,
const char *arg, int unset)
{
line_terminator = unset ? '\n' : '\0';

return 0;
}

static int option_parse_exclude(const struct option *opt,
const char *arg, int unset)
{
struct exclude_list *list = opt->value;

exc_given = 1;
add_exclude(arg, "", 0, list);

return 0;
}

static int option_parse_exclude_from(const struct option *opt,
const char *arg, int unset)
{
struct dir_struct *dir = opt->value;

exc_given = 1;
add_excludes_from_file(dir, arg);

return 0;
}

static int option_parse_exclude_standard(const struct option *opt,
const char *arg, int unset)
{
struct dir_struct *dir = opt->value;

exc_given = 1;
setup_standard_excludes(dir);

return 0;
}


int cmd_ls_files(int argc, const char **argv, const char *prefix) int cmd_ls_files(int argc, const char **argv, const char *prefix)
{ {
int i; int require_work_tree = 0, show_tag = 0;
int exc_given = 0, require_work_tree = 0;
struct dir_struct dir; struct dir_struct dir;
struct option builtin_ls_files_options[] = {
{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
"paths are separated with NUL character",
PARSE_OPT_NOARG, option_parse_z },
OPT_BOOLEAN('t', NULL, &show_tag,
"identify the file status with tags"),
OPT_BOOLEAN('v', NULL, &show_valid_bit,
"use lowercase letters for 'assume unchanged' files"),
OPT_BOOLEAN('c', "cached", &show_cached,
"show cached files in the output (default)"),
OPT_BOOLEAN('d', "deleted", &show_deleted,
"show deleted files in the output"),
OPT_BOOLEAN('m', "modified", &show_modified,
"show modified files in the output"),
OPT_BOOLEAN('o', "others", &show_others,
"show other files in the output"),
OPT_BIT('i', "ignored", &dir.flags,
"show ignored files in the output",
DIR_SHOW_IGNORED),
OPT_BOOLEAN('s', "stage", &show_stage,
"show staged contents' object name in the output"),
OPT_BOOLEAN('k', "killed", &show_killed,
"show files on the filesystem that need to be removed"),
OPT_BIT(0, "directory", &dir.flags,
"show 'other' directories' name only",
DIR_SHOW_OTHER_DIRECTORIES),
OPT_BIT(0, "no-empty-directory", &dir.flags,
"don't show empty directories",
DIR_HIDE_EMPTY_DIRECTORIES),
OPT_BOOLEAN('u', "unmerged", &show_unmerged,
"show unmerged files in the output"),
{ OPTION_CALLBACK, 'x', "exclude", &dir.exclude_list[EXC_CMDL], "pattern",
"skip files matching pattern",
0, option_parse_exclude },
{ OPTION_CALLBACK, 'X', "exclude-from", &dir, "file",
"exclude patterns are read from <file>",
0, option_parse_exclude_from },
OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, "file",
"read additional per-directory exclude patterns in <file>"),
{ OPTION_CALLBACK, 0, "exclude-standard", &dir, NULL,
"add the standard git exclusions",
PARSE_OPT_NOARG, option_parse_exclude_standard },
{ OPTION_SET_INT, 0, "full-name", &prefix_offset, NULL,
"make the output relative to the project top directory",
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },
OPT_BOOLEAN(0, "error-unmatch", &error_unmatch,
"if any <file> is not in the index, treat this as an error"),
OPT_STRING(0, "with-tree", &with_tree, "tree-ish",
"pretend that paths removed since <tree-ish> are still present"),
OPT__ABBREV(&abbrev),
OPT_END()
};


memset(&dir, 0, sizeof(dir)); memset(&dir, 0, sizeof(dir));
if (prefix) if (prefix)
prefix_offset = strlen(prefix); prefix_offset = strlen(prefix);
git_config(git_default_config, NULL); git_config(git_default_config, NULL);


for (i = 1; i < argc; i++) { argc = parse_options(argc, argv, builtin_ls_files_options,
const char *arg = argv[i]; ls_files_usage, 0);

if (show_tag || show_valid_bit) {
if (!strcmp(arg, "--")) { tag_cached = "H ";
i++; tag_unmerged = "M ";
break; tag_removed = "R ";
} tag_modified = "C ";
if (!strcmp(arg, "-z")) { tag_other = "? ";
line_terminator = 0; tag_killed = "K ";
continue;
}
if (!strcmp(arg, "-t") || !strcmp(arg, "-v")) {
tag_cached = "H ";
tag_unmerged = "M ";
tag_removed = "R ";
tag_modified = "C ";
tag_other = "? ";
tag_killed = "K ";
if (arg[1] == 'v')
show_valid_bit = 1;
continue;
}
if (!strcmp(arg, "-c") || !strcmp(arg, "--cached")) {
show_cached = 1;
continue;
}
if (!strcmp(arg, "-d") || !strcmp(arg, "--deleted")) {
show_deleted = 1;
require_work_tree = 1;
continue;
}
if (!strcmp(arg, "-m") || !strcmp(arg, "--modified")) {
show_modified = 1;
require_work_tree = 1;
continue;
}
if (!strcmp(arg, "-o") || !strcmp(arg, "--others")) {
show_others = 1;
require_work_tree = 1;
continue;
}
if (!strcmp(arg, "-i") || !strcmp(arg, "--ignored")) {
dir.show_ignored = 1;
require_work_tree = 1;
continue;
}
if (!strcmp(arg, "-s") || !strcmp(arg, "--stage")) {
show_stage = 1;
continue;
}
if (!strcmp(arg, "-k") || !strcmp(arg, "--killed")) {
show_killed = 1;
require_work_tree = 1;
continue;
}
if (!strcmp(arg, "--directory")) {
dir.show_other_directories = 1;
continue;
}
if (!strcmp(arg, "--no-empty-directory")) {
dir.hide_empty_directories = 1;
continue;
}
if (!strcmp(arg, "-u") || !strcmp(arg, "--unmerged")) {
/* There's no point in showing unmerged unless
* you also show the stage information.
*/
show_stage = 1;
show_unmerged = 1;
continue;
}
if (!strcmp(arg, "-x") && i+1 < argc) {
exc_given = 1;
add_exclude(argv[++i], "", 0, &dir.exclude_list[EXC_CMDL]);
continue;
}
if (!prefixcmp(arg, "--exclude=")) {
exc_given = 1;
add_exclude(arg+10, "", 0, &dir.exclude_list[EXC_CMDL]);
continue;
}
if (!strcmp(arg, "-X") && i+1 < argc) {
exc_given = 1;
add_excludes_from_file(&dir, argv[++i]);
continue;
}
if (!prefixcmp(arg, "--exclude-from=")) {
exc_given = 1;
add_excludes_from_file(&dir, arg+15);
continue;
}
if (!prefixcmp(arg, "--exclude-per-directory=")) {
exc_given = 1;
dir.exclude_per_dir = arg + 24;
continue;
}
if (!strcmp(arg, "--exclude-standard")) {
exc_given = 1;
setup_standard_excludes(&dir);
continue;
}
if (!strcmp(arg, "--full-name")) {
prefix_offset = 0;
continue;
}
if (!strcmp(arg, "--error-unmatch")) {
error_unmatch = 1;
continue;
}
if (!prefixcmp(arg, "--with-tree=")) {
with_tree = arg + 12;
continue;
}
if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg+9, NULL, 10);
if (abbrev && abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;
else if (abbrev > 40)
abbrev = 40;
continue;
}
if (!strcmp(arg, "--abbrev")) {
abbrev = DEFAULT_ABBREV;
continue;
}
if (*arg == '-')
usage(ls_files_usage);
break;
} }
if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed)
require_work_tree = 1;
if (show_unmerged)
/*
* There's no point in showing unmerged unless
* you also show the stage information.
*/
show_stage = 1;
if (dir.exclude_per_dir)
exc_given = 1;


if (require_work_tree && !is_inside_work_tree()) if (require_work_tree && !is_inside_work_tree())
setup_work_tree(); setup_work_tree();


pathspec = get_pathspec(prefix, argv + i); pathspec = get_pathspec(prefix, argv);


/* be nice with submodule patsh ending in a slash */ /* be nice with submodule patsh ending in a slash */
read_cache(); read_cache();
@ -543,7 +529,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
ps_matched = xcalloc(1, num); ps_matched = xcalloc(1, num);
} }


if (dir.show_ignored && !exc_given) { if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given) {
fprintf(stderr, "%s: --ignored needs some exclude pattern\n", fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
argv[0]); argv[0]);
exit(1); exit(1);

2
builtin-merge.c

@ -636,7 +636,7 @@ static int checkout_fast_forward(unsigned char *head, unsigned char *remote)
memset(&opts, 0, sizeof(opts)); memset(&opts, 0, sizeof(opts));
memset(&t, 0, sizeof(t)); memset(&t, 0, sizeof(t));
memset(&dir, 0, sizeof(dir)); memset(&dir, 0, sizeof(dir));
dir.show_ignored = 1; dir.flags |= DIR_SHOW_IGNORED;
dir.exclude_per_dir = ".gitignore"; dir.exclude_per_dir = ".gitignore";
opts.dir = &dir; opts.dir = &dir;



2
builtin-read-tree.c

@ -170,7 +170,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
die("more than one --exclude-per-directory are given."); die("more than one --exclude-per-directory are given.");


dir = xcalloc(1, sizeof(*opts.dir)); dir = xcalloc(1, sizeof(*opts.dir));
dir->show_ignored = 1; dir->flags |= DIR_SHOW_IGNORED;
dir->exclude_per_dir = arg + 24; dir->exclude_per_dir = arg + 24;
opts.dir = dir; opts.dir = dir;
/* We do not need to nor want to do read-directory /* We do not need to nor want to do read-directory

17
dir.c

@ -487,14 +487,14 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
return recurse_into_directory; return recurse_into_directory;


case index_gitdir: case index_gitdir:
if (dir->show_other_directories) if (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)
return ignore_directory; return ignore_directory;
return show_directory; return show_directory;


case index_nonexistent: case index_nonexistent:
if (dir->show_other_directories) if (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)
break; break;
if (!dir->no_gitlinks) { if (!(dir->flags & DIR_NO_GITLINKS)) {
unsigned char sha1[20]; unsigned char sha1[20];
if (resolve_gitlink_ref(dirname, "HEAD", sha1) == 0) if (resolve_gitlink_ref(dirname, "HEAD", sha1) == 0)
return show_directory; return show_directory;
@ -503,7 +503,7 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
} }


/* This is the "show_other_directories" case */ /* This is the "show_other_directories" case */
if (!dir->hide_empty_directories) if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
return show_directory; return show_directory;
if (!read_directory_recursive(dir, dirname, dirname, len, 1, simplify)) if (!read_directory_recursive(dir, dirname, dirname, len, 1, simplify))
return ignore_directory; return ignore_directory;
@ -601,7 +601,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co


dtype = DTYPE(de); dtype = DTYPE(de);
exclude = excluded(dir, fullname, &dtype); exclude = excluded(dir, fullname, &dtype);
if (exclude && dir->collect_ignored if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
&& in_pathspec(fullname, baselen + len, simplify)) && in_pathspec(fullname, baselen + len, simplify))
dir_add_ignored(dir, fullname, baselen + len); dir_add_ignored(dir, fullname, baselen + len);


@ -609,7 +609,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
* Excluded? If we don't explicitly want to show * Excluded? If we don't explicitly want to show
* ignored files, ignore it * ignored files, ignore it
*/ */
if (exclude && !dir->show_ignored) if (exclude && !(dir->flags & DIR_SHOW_IGNORED))
continue; continue;


if (dtype == DT_UNKNOWN) if (dtype == DT_UNKNOWN)
@ -621,7 +621,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
* even if we don't ignore them, since the * even if we don't ignore them, since the
* directory may contain files that we do.. * directory may contain files that we do..
*/ */
if (!exclude && dir->show_ignored) { if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
if (dtype != DT_DIR) if (dtype != DT_DIR)
continue; continue;
} }
@ -634,7 +634,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
len++; len++;
switch (treat_directory(dir, fullname, baselen + len, simplify)) { switch (treat_directory(dir, fullname, baselen + len, simplify)) {
case show_directory: case show_directory:
if (exclude != dir->show_ignored) if (exclude != !!(dir->flags
& DIR_SHOW_IGNORED))
continue; continue;
break; break;
case recurse_into_directory: case recurse_into_directory:

12
dir.h

@ -34,11 +34,13 @@ struct exclude_stack {
struct dir_struct { struct dir_struct {
int nr, alloc; int nr, alloc;
int ignored_nr, ignored_alloc; int ignored_nr, ignored_alloc;
unsigned int show_ignored:1, enum {
show_other_directories:1, DIR_SHOW_IGNORED = 1<<0,
hide_empty_directories:1, DIR_SHOW_OTHER_DIRECTORIES = 1<<1,
no_gitlinks:1, DIR_HIDE_EMPTY_DIRECTORIES = 1<<2,
collect_ignored:1; DIR_NO_GITLINKS = 1<<3,
DIR_COLLECT_IGNORED = 1<<4
} flags;
struct dir_entry **entries; struct dir_entry **entries;
struct dir_entry **ignored; struct dir_entry **ignored;



14
t/t3000-ls-files-others.sh

@ -13,12 +13,13 @@ filesystem.
path2/file2 - a file in a directory path2/file2 - a file in a directory
path3-junk - a file to confuse things path3-junk - a file to confuse things
path3/file3 - a file in a directory path3/file3 - a file in a directory
path4 - an empty directory
' '
. ./test-lib.sh . ./test-lib.sh


date >path0 date >path0
ln -s xyzzy path1 ln -s xyzzy path1
mkdir path2 path3 mkdir path2 path3 path4
date >path2/file2 date >path2/file2
date >path2-junk date >path2-junk
date >path3/file3 date >path3/file3
@ -28,6 +29,7 @@ git update-index --add path3-junk path3/file3
cat >expected1 <<EOF cat >expected1 <<EOF
expected1 expected1
expected2 expected2
expected3
output output
path0 path0
path1 path1
@ -35,6 +37,8 @@ path2-junk
path2/file2 path2/file2
EOF EOF
sed -e 's|path2/file2|path2/|' <expected1 >expected2 sed -e 's|path2/file2|path2/|' <expected1 >expected2
cat <expected2 >expected3
echo path4/ >>expected2


test_expect_success \ test_expect_success \
'git ls-files --others to show output.' \ 'git ls-files --others to show output.' \
@ -53,4 +57,12 @@ test_expect_success \
'git ls-files --others --directory should not get confused.' \ 'git ls-files --others --directory should not get confused.' \
'test_cmp expected2 output' 'test_cmp expected2 output'


test_expect_success \
'git ls-files --others --directory --no-empty-directory to show output.' \
'git ls-files --others --directory --no-empty-directory >output'

test_expect_success \
'--no-empty-directory hides empty directory' \
'test_cmp expected3 output'

test_done test_done

7
wt-status.c

@ -250,10 +250,9 @@ static void wt_status_print_untracked(struct wt_status *s)


memset(&dir, 0, sizeof(dir)); memset(&dir, 0, sizeof(dir));


if (!s->untracked) { if (!s->untracked)
dir.show_other_directories = 1; dir.flags |=
dir.hide_empty_directories = 1; DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
}
setup_standard_excludes(&dir); setup_standard_excludes(&dir);


read_directory(&dir, ".", "", 0, NULL); read_directory(&dir, ".", "", 0, NULL);

Loading…
Cancel
Save