Merge branch 'jk/xdiff-drop-xdl-fast-hash'
[gitweb.git] / builtin / ls-files.c
index 63befed9ea1df8c10cf1fc6a212fc10bd5f72f91..1592290815c8b93701fa9d175d76f7a7ed85f7d2 100644 (file)
@@ -30,6 +30,7 @@ static int line_terminator = '\n';
 static int debug_mode;
 static int show_eol;
 static int recurse_submodules;
+static struct argv_array submodules_options = ARGV_ARRAY_INIT;
 
 static const char *prefix;
 static const char *super_prefix;
@@ -168,6 +169,25 @@ static void show_killed_files(struct dir_struct *dir)
        }
 }
 
+/*
+ * Compile an argv_array with all of the options supported by --recurse_submodules
+ */
+static void compile_submodule_options(const struct dir_struct *dir, int show_tag)
+{
+       if (line_terminator == '\0')
+               argv_array_push(&submodules_options, "-z");
+       if (show_tag)
+               argv_array_push(&submodules_options, "-t");
+       if (show_valid_bit)
+               argv_array_push(&submodules_options, "-v");
+       if (show_cached)
+               argv_array_push(&submodules_options, "--cached");
+       if (show_eol)
+               argv_array_push(&submodules_options, "--eol");
+       if (debug_mode)
+               argv_array_push(&submodules_options, "--debug");
+}
+
 /**
  * Recursively call ls-files on a submodule
  */
@@ -175,6 +195,7 @@ static void show_gitlink(const struct cache_entry *ce)
 {
        struct child_process cp = CHILD_PROCESS_INIT;
        int status;
+       int i;
 
        argv_array_pushf(&cp.args, "--super-prefix=%s%s/",
                         super_prefix ? super_prefix : "",
@@ -182,6 +203,18 @@ static void show_gitlink(const struct cache_entry *ce)
        argv_array_push(&cp.args, "ls-files");
        argv_array_push(&cp.args, "--recurse-submodules");
 
+       /* add supported options */
+       argv_array_pushv(&cp.args, submodules_options.argv);
+
+       /*
+        * Pass in the original pathspec args.  The submodule will be
+        * responsible for prepending the 'submodule_prefix' prior to comparing
+        * against the pathspec for matches.
+        */
+       argv_array_push(&cp.args, "--");
+       for (i = 0; i < pathspec.nr; i++)
+               argv_array_push(&cp.args, pathspec.items[i].original);
+
        cp.git_cmd = 1;
        cp.dir = ce->name;
        status = run_command(&cp);
@@ -200,7 +233,8 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
        if (len >= ce_namelen(ce))
                die("git ls-files: internal error - cache entry not superset of prefix");
 
-       if (recurse_submodules && S_ISGITLINK(ce->ce_mode)) {
+       if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
+           submodule_path_match(&pathspec, name.buf, ps_matched)) {
                show_gitlink(ce);
        } else if (match_pathspec(&pathspec, name.buf, name.len,
                                  len, ps_matched,
@@ -229,7 +263,7 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
                        printf("%s%06o %s %d\t",
                               tag,
                               ce->ce_mode,
-                              find_unique_abbrev(ce->sha1,abbrev),
+                              find_unique_abbrev(ce->oid.hash, abbrev),
                               ce_stage(ce));
                }
                write_eolinfo(ce, ce->name);
@@ -567,27 +601,32 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
        if (require_work_tree && !is_inside_work_tree())
                setup_work_tree();
 
+       if (recurse_submodules)
+               compile_submodule_options(&dir, show_tag);
+
        if (recurse_submodules &&
            (show_stage || show_deleted || show_others || show_unmerged ||
-            show_killed || show_modified || show_resolve_undo ||
-            show_valid_bit || show_tag || show_eol || with_tree ||
-            (line_terminator == '\0')))
+            show_killed || show_modified || show_resolve_undo || with_tree))
                die("ls-files --recurse-submodules unsupported mode");
 
        if (recurse_submodules && error_unmatch)
                die("ls-files --recurse-submodules does not support "
                    "--error-unmatch");
 
-       if (recurse_submodules && argc)
-               die("ls-files --recurse-submodules does not support pathspec");
-
        parse_pathspec(&pathspec, 0,
                       PATHSPEC_PREFER_CWD |
                       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
                       prefix, argv);
 
-       /* Find common prefix for all pathspec's */
-       max_prefix = common_prefix(&pathspec);
+       /*
+        * Find common prefix for all pathspec's
+        * This is used as a performance optimization which unfortunately cannot
+        * be done when recursing into submodules
+        */
+       if (recurse_submodules)
+               max_prefix = NULL;
+       else
+               max_prefix = common_prefix(&pathspec);
        max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
 
        /* Treat unmatching pathspec elements as errors */