diff options
Diffstat (limited to 'builtin-ls-files.c')
-rw-r--r-- | builtin-ls-files.c | 141 |
1 files changed, 80 insertions, 61 deletions
diff --git a/builtin-ls-files.c b/builtin-ls-files.c index b70da1863b..25dbfb4499 100644 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@ -38,28 +38,28 @@ static const char *tag_modified = ""; /* - * Match a pathspec against a filename. The first "len" characters + * Match a pathspec against a filename. The first "skiplen" characters * are the common prefix */ -static int match(const char **spec, char *ps_matched, - const char *filename, int len) +int pathspec_match(const char **spec, char *ps_matched, + const char *filename, int skiplen) { const char *m; while ((m = *spec++) != NULL) { - int matchlen = strlen(m + len); + int matchlen = strlen(m + skiplen); if (!matchlen) goto matched; - if (!strncmp(m + len, filename + len, matchlen)) { - if (m[len + matchlen - 1] == '/') + if (!strncmp(m + skiplen, filename + skiplen, matchlen)) { + if (m[skiplen + matchlen - 1] == '/') goto matched; - switch (filename[len + matchlen]) { + switch (filename[skiplen + matchlen]) { case '/': case '\0': goto matched; } } - if (!fnmatch(m + len, filename + len, 0)) + if (!fnmatch(m + skiplen, filename + skiplen, 0)) goto matched; if (ps_matched) ps_matched++; @@ -80,7 +80,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent) if (len >= ent->len) die("git-ls-files: internal error - directory entry not superset of prefix"); - if (pathspec && !match(pathspec, ps_matched, ent->name, len)) + if (pathspec && !pathspec_match(pathspec, ps_matched, ent->name, len)) return; fputs(tag, stdout); @@ -185,11 +185,11 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce) if (len >= ce_namelen(ce)) die("git-ls-files: internal error - cache entry not superset of prefix"); - if (pathspec && !match(pathspec, ps_matched, ce->name, len)) + if (pathspec && !pathspec_match(pathspec, ps_matched, ce->name, len)) return; if (tag && *tag && show_valid_bit && - (ce->ce_flags & htons(CE_VALID))) { + (ce->ce_flags & CE_VALID)) { static char alttag[4]; memcpy(alttag, tag, 3); if (isalpha(tag[0])) @@ -210,7 +210,7 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce) } else { printf("%s%06o %s %d\t", tag, - ntohl(ce->ce_mode), + ce->ce_mode, abbrev ? find_unique_abbrev(ce->sha1,abbrev) : sha1_to_hex(ce->sha1), ce_stage(ce)); @@ -238,11 +238,12 @@ static void show_files(struct dir_struct *dir, const char *prefix) if (show_cached | show_stage) { for (i = 0; i < active_nr; i++) { struct cache_entry *ce = active_cache[i]; - if (excluded(dir, ce->name) != dir->show_ignored) + int dtype = ce_to_dtype(ce); + if (excluded(dir, ce->name, &dtype) != dir->show_ignored) continue; if (show_unmerged && !ce_stage(ce)) continue; - if (ce->ce_flags & htons(CE_UPDATE)) + if (ce->ce_flags & CE_UPDATE) continue; show_ce_entry(ce_stage(ce) ? tag_unmerged : tag_cached, ce); } @@ -252,7 +253,8 @@ static void show_files(struct dir_struct *dir, const char *prefix) struct cache_entry *ce = active_cache[i]; struct stat st; int err; - if (excluded(dir, ce->name) != dir->show_ignored) + int dtype = ce_to_dtype(ce); + if (excluded(dir, ce->name, &dtype) != dir->show_ignored) continue; err = lstat(ce->name, &st); if (show_deleted && err) @@ -331,7 +333,7 @@ static const char *verify_pathspec(const char *prefix) * that were given from the command line. We are not * going to write this index out. */ -static void overlay_tree(const char *tree_name, const char *prefix) +void overlay_tree_on_cache(const char *tree_name, const char *prefix) { struct tree *tree; unsigned char sha1[20]; @@ -350,7 +352,7 @@ static void overlay_tree(const char *tree_name, const char *prefix) struct cache_entry *ce = active_cache[i]; if (!ce_stage(ce)) continue; - ce->ce_flags |= htons(CE_STAGEMASK); + ce->ce_flags |= CE_STAGEMASK; } if (prefix) { @@ -379,16 +381,52 @@ static void overlay_tree(const char *tree_name, const char *prefix) */ if (last_stage0 && !strcmp(last_stage0->name, ce->name)) - ce->ce_flags |= htons(CE_UPDATE); + ce->ce_flags |= CE_UPDATE; } } } +int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset) +{ + /* + * Make sure all pathspec matched; otherwise it is an error. + */ + int num, errors = 0; + for (num = 0; pathspec[num]; num++) { + int other, found_dup; + + if (ps_matched[num]) + continue; + /* + * The caller might have fed identical pathspec + * twice. Do not barf on such a mistake. + */ + for (found_dup = other = 0; + !found_dup && pathspec[other]; + other++) { + if (other == num || !ps_matched[other]) + continue; + if (!strcmp(pathspec[other], pathspec[num])) + /* + * Ok, we have a match already. + */ + found_dup = 1; + } + if (found_dup) + continue; + + error("pathspec '%s' did not match any file(s) known to git.", + pathspec[num] + prefix_offset); + errors++; + } + return errors; +} + static const char ls_files_usage[] = "git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* " "[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] " - "[ --exclude-per-directory=<filename> ] [--full-name] [--abbrev] " - "[--] [<file>]*"; + "[ --exclude-per-directory=<filename> ] [--exclude-standard] " + "[--full-name] [--abbrev] [--] [<file>]*"; int cmd_ls_files(int argc, const char **argv, const char *prefix) { @@ -496,6 +534,11 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix) 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; @@ -525,17 +568,23 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix) break; } - if (require_work_tree && !is_inside_work_tree()) { - const char *work_tree = get_git_work_tree(); - if (!work_tree || chdir(work_tree)) - die("This operation must be run in a work tree"); - } + if (require_work_tree && !is_inside_work_tree()) + setup_work_tree(); pathspec = get_pathspec(prefix, argv + i); /* Verify that the pathspec matches the prefix */ - if (pathspec) + if (pathspec) { + if (argc != i) { + int cnt; + for (cnt = 0; pathspec[cnt]; cnt++) + ; + if (cnt != (argc - i)) + exit(1); /* error message already given */ + } prefix = verify_pathspec(prefix); + } else if (argc != i) + exit(1); /* error message already given */ /* Treat unmatching pathspec elements as errors */ if (pathspec && error_unmatch) { @@ -566,47 +615,17 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix) */ if (show_stage || show_unmerged) die("ls-files --with-tree is incompatible with -s or -u"); - overlay_tree(with_tree, prefix); + overlay_tree_on_cache(with_tree, prefix); } show_files(&dir, prefix); if (ps_matched) { - /* We need to make sure all pathspec matched otherwise - * it is an error. - */ - int num, errors = 0; - for (num = 0; pathspec[num]; num++) { - int other, found_dup; - - if (ps_matched[num]) - continue; - /* - * The caller might have fed identical pathspec - * twice. Do not barf on such a mistake. - */ - for (found_dup = other = 0; - !found_dup && pathspec[other]; - other++) { - if (other == num || !ps_matched[other]) - continue; - if (!strcmp(pathspec[other], pathspec[num])) - /* - * Ok, we have a match already. - */ - found_dup = 1; - } - if (found_dup) - continue; - - error("pathspec '%s' did not match any file(s) known to git.", - pathspec[num] + prefix_offset); - errors++; - } - - if (errors) + int bad; + bad = report_path_error(ps_matched, pathspec, prefix_offset); + if (bad) fprintf(stderr, "Did you forget to 'git add'?\n"); - return errors ? 1 : 0; + return bad ? 1 : 0; } return 0; |