git-upload-pack: More efficient usage of the has_sha1 array
[git.git] / ls-files.c
index 0d79104..3085b2f 100644 (file)
@@ -9,6 +9,7 @@
 #include <fnmatch.h>
 
 #include "cache.h"
+#include "quote.h"
 
 static int show_deleted = 0;
 static int show_cached = 0;
@@ -16,6 +17,7 @@ static int show_others = 0;
 static int show_ignored = 0;
 static int show_stage = 0;
 static int show_unmerged = 0;
+static int show_modified = 0;
 static int show_killed = 0;
 static int line_terminator = '\n';
 
@@ -28,8 +30,9 @@ static const char *tag_unmerged = "";
 static const char *tag_removed = "";
 static const char *tag_other = "";
 static const char *tag_killed = "";
+static const char *tag_modified = "";
 
-static char *exclude_per_dir = NULL;
+static const char *exclude_per_dir = NULL;
 
 /* We maintain three exclude pattern lists:
  * EXC_CMDL lists patterns explicitly given on the command line.
@@ -205,7 +208,7 @@ static int excluded(const char *pathname)
 
 struct nond_on_fs {
        int len;
-       char name[];
+       char name[0];
 };
 
 static struct nond_on_fs **dir;
@@ -340,7 +343,9 @@ static void show_dir_entry(const char *tag, struct nond_on_fs *ent)
        if (pathspec && !match(pathspec, ent->name, len))
                return;
 
-       printf("%s%s%c", tag, ent->name + offset, line_terminator);
+       fputs(tag, stdout);
+       write_name_quoted("", ent->name + offset, line_terminator, stdout);
+       putchar(line_terminator);
 }
 
 static void show_killed_files(void)
@@ -403,15 +408,20 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
        if (pathspec && !match(pathspec, ce->name, len))
                return;
 
-       if (!show_stage)
-               printf("%s%s%c", tag, ce->name + offset, line_terminator);
-       else
-               printf("%s%06o %s %d\t%s%c",
+       if (!show_stage) {
+               fputs(tag, stdout);
+               write_name_quoted("", ce->name + offset, line_terminator, stdout);
+               putchar(line_terminator);
+       }
+       else {
+               printf("%s%06o %s %d\t",
                       tag,
                       ntohl(ce->ce_mode),
                       sha1_to_hex(ce->sha1),
-                      ce_stage(ce),
-                      ce->name + offset, line_terminator); 
+                      ce_stage(ce));
+               write_name_quoted("", ce->name + offset, line_terminator, stdout);
+               putchar(line_terminator);
+       }
 }
 
 static void show_files(void)
@@ -443,15 +453,18 @@ static void show_files(void)
                        show_ce_entry(ce_stage(ce) ? tag_unmerged : tag_cached, ce);
                }
        }
-       if (show_deleted) {
+       if (show_deleted | show_modified) {
                for (i = 0; i < active_nr; i++) {
                        struct cache_entry *ce = active_cache[i];
                        struct stat st;
+                       int err;
                        if (excluded(ce->name) != show_ignored)
                                continue;
-                       if (!lstat(ce->name, &st))
-                               continue;
-                       show_ce_entry(tag_removed, ce);
+                       err = lstat(ce->name, &st);
+                       if (show_deleted && err)
+                               show_ce_entry(tag_removed, ce);
+                       if (show_modified && ce_modified(ce, &st))
+                               show_ce_entry(tag_modified, ce);
                }
        }
 }
@@ -523,11 +536,11 @@ static void verify_pathspec(void)
 }
 
 static const char ls_files_usage[] =
-       "git-ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged|killed])* "
+       "git-ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
        "[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
-       "[ --exclude-per-directory=<filename> ]";
+       "[ --exclude-per-directory=<filename> ] [--] [<file>]*";
 
-int main(int argc, char **argv)
+int main(int argc, const char **argv)
 {
        int i;
        int exc_given = 0;
@@ -537,8 +550,12 @@ int main(int argc, char **argv)
                prefix_offset = strlen(prefix);
 
        for (i = 1; i < argc; i++) {
-               char *arg = argv[i];
+               const char *arg = argv[i];
 
+               if (!strcmp(arg, "--")) {
+                       i++;
+                       break;
+               }
                if (!strcmp(arg, "-z")) {
                        line_terminator = 0;
                        continue;
@@ -547,6 +564,7 @@ int main(int argc, char **argv)
                        tag_cached = "H ";
                        tag_unmerged = "M ";
                        tag_removed = "R ";
+                       tag_modified = "C ";
                        tag_other = "? ";
                        tag_killed = "K ";
                        continue;
@@ -559,6 +577,10 @@ int main(int argc, char **argv)
                        show_deleted = 1;
                        continue;
                }
+               if (!strcmp(arg, "-m") || !strcmp(arg, "--modified")) {
+                       show_modified = 1;
+                       continue;
+               }
                if (!strcmp(arg, "-o") || !strcmp(arg, "--others")) {
                        show_others = 1;
                        continue;
@@ -630,7 +652,8 @@ int main(int argc, char **argv)
        }
 
        /* With no flags, we default to showing the cached files */
-       if (!(show_stage | show_deleted | show_others | show_unmerged | show_killed))
+       if (!(show_stage | show_deleted | show_others | show_unmerged |
+             show_killed | show_modified))
                show_cached = 1;
 
        read_cache();