X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=ls-files.c;h=e42119c5ee1d0ceffca3d36462fc09cd53d2eef5;hb=9086a18cb81f99fff943b36830396ac8c37c7e9f;hp=1c8ab7398979354def145aa2eee7fc1eb2166d4f;hpb=f732d0b8576303403db2b1824cfd8b5a2fe632ef;p=git.git diff --git a/ls-files.c b/ls-files.c index 1c8ab739..e42119c5 100644 --- a/ls-files.c +++ b/ls-files.c @@ -20,11 +20,14 @@ static int show_unmerged = 0; static int show_modified = 0; static int show_killed = 0; static int show_other_directories = 0; +static int show_valid_bit = 0; static int line_terminator = '\n'; static int prefix_len = 0, prefix_offset = 0; static const char *prefix = NULL; static const char **pathspec = NULL; +static int error_unmatch = 0; +static char *ps_matched = NULL; static const char *tag_cached = ""; static const char *tag_unmerged = ""; @@ -89,11 +92,12 @@ static int add_excludes_from_file_1(const char *fname, close(fd); return 0; } - buf = xmalloc(size); + buf = xmalloc(size+1); if (read(fd, buf, size) != size) goto err; close(fd); + buf[size++] = '\n'; entry = buf; for (i = 0; i < size; i++) { if (buf[i] == '\n') { @@ -276,8 +280,11 @@ static void read_directory(const char *path, const char *base, int baselen) continue; len = strlen(de->d_name); memcpy(fullname + baselen, de->d_name, len+1); - if (excluded(fullname) != show_ignored) - continue; + if (excluded(fullname) != show_ignored) { + if (!show_ignored || DTYPE(de) != DT_DIR) { + continue; + } + } switch (DTYPE(de)) { struct stat st; @@ -325,7 +332,8 @@ static int cmp_name(const void *p1, const void *p2) * Match a pathspec against a filename. The first "len" characters * are the common prefix */ -static int match(const char **spec, const char *filename, int len) +static int match(const char **spec, char *ps_matched, + const char *filename, int len) { const char *m; @@ -333,17 +341,24 @@ static int match(const char **spec, const char *filename, int len) int matchlen = strlen(m + len); if (!matchlen) - return 1; + goto matched; if (!strncmp(m + len, filename + len, matchlen)) { if (m[len + matchlen - 1] == '/') - return 1; + goto matched; switch (filename[len + matchlen]) { case '/': case '\0': - return 1; + goto matched; } } if (!fnmatch(m + len, filename + len, 0)) - return 1; + goto matched; + if (ps_matched) + ps_matched++; + continue; + matched: + if (ps_matched) + *ps_matched = 1; + return 1; } return 0; } @@ -356,7 +371,7 @@ static void show_dir_entry(const char *tag, struct nond_on_fs *ent) if (len >= ent->len) die("git-ls-files: internal error - directory entry not superset of prefix"); - if (pathspec && !match(pathspec, ent->name, len)) + if (pathspec && !match(pathspec, ps_matched, ent->name, len)) return; fputs(tag, stdout); @@ -444,10 +459,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, ce->name, len)) + if (pathspec && !match(pathspec, ps_matched, ce->name, len)) return; - if (tag && *tag && (ce->ce_flags & htons(CE_VALID))) { + if (tag && *tag && show_valid_bit && + (ce->ce_flags & htons(CE_VALID))) { static char alttag[4]; memcpy(alttag, tag, 3); if (isalpha(tag[0])) @@ -612,7 +628,7 @@ static void verify_pathspec(void) } static const char ls_files_usage[] = - "git-ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged|killed|modified])* " + "git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* " "[ --ignored ] [--exclude=] [--exclude-from=] " "[ --exclude-per-directory= ] [--full-name] [--] []*"; @@ -637,13 +653,15 @@ int main(int argc, const char **argv) line_terminator = 0; continue; } - if (!strcmp(arg, "-t")) { + 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")) { @@ -715,6 +733,10 @@ int main(int argc, const char **argv) prefix_offset = 0; continue; } + if (!strcmp(arg, "--error-unmatch")) { + error_unmatch = 1; + continue; + } if (*arg == '-') usage(ls_files_usage); break; @@ -726,6 +748,14 @@ int main(int argc, const char **argv) if (pathspec) verify_pathspec(); + /* Treat unmatching pathspec elements as errors */ + if (pathspec && error_unmatch) { + int num; + for (num = 0; pathspec[num]; num++) + ; + ps_matched = xcalloc(1, num); + } + if (show_ignored && !exc_given) { fprintf(stderr, "%s: --ignored needs some exclude pattern\n", argv[0]); @@ -741,5 +771,21 @@ int main(int argc, const char **argv) if (prefix) prune_cache(); show_files(); + + 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++) { + if (ps_matched[num]) + continue; + error("pathspec '%s' did not match any.", + pathspec[num] + prefix_offset); + errors++; + } + return errors ? 1 : 0; + } + return 0; }