notes: convert some accessor functions to struct object_id
[gitweb.git] / builtin / ls-files.c
index 1c0f057d02c55c8449bc9da1f1f01d509bbca8ba..b376afc3124c3240f4f249ccc206efa0b064675e 100644 (file)
@@ -15,6 +15,7 @@
 #include "string-list.h"
 #include "pathspec.h"
 #include "run-command.h"
+#include "submodule.h"
 
 static int abbrev;
 static int show_deleted;
@@ -30,7 +31,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 struct argv_array submodule_options = ARGV_ARRAY_INIT;
 
 static const char *prefix;
 static const char *super_prefix;
@@ -96,7 +97,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
 {
        int len = max_prefix_len;
 
-       if (len >= ent->len)
+       if (len > ent->len)
                die("git ls-files: internal error - directory entry not superset of prefix");
 
        if (!dir_path_match(ent, &pathspec, len, ps_matched))
@@ -172,20 +173,27 @@ 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)
+static void compile_submodule_options(const char **argv,
+                                     const struct dir_struct *dir,
+                                     int show_tag)
 {
        if (line_terminator == '\0')
-               argv_array_push(&submodules_options, "-z");
+               argv_array_push(&submodule_options, "-z");
        if (show_tag)
-               argv_array_push(&submodules_options, "-t");
+               argv_array_push(&submodule_options, "-t");
        if (show_valid_bit)
-               argv_array_push(&submodules_options, "-v");
+               argv_array_push(&submodule_options, "-v");
        if (show_cached)
-               argv_array_push(&submodules_options, "--cached");
+               argv_array_push(&submodule_options, "--cached");
        if (show_eol)
-               argv_array_push(&submodules_options, "--eol");
+               argv_array_push(&submodule_options, "--eol");
        if (debug_mode)
-               argv_array_push(&submodules_options, "--debug");
+               argv_array_push(&submodule_options, "--debug");
+
+       /* Add Pathspecs */
+       argv_array_push(&submodule_options, "--");
+       for (; *argv; argv++)
+               argv_array_push(&submodule_options, *argv);
 }
 
 /**
@@ -195,8 +203,15 @@ static void show_gitlink(const struct cache_entry *ce)
 {
        struct child_process cp = CHILD_PROCESS_INIT;
        int status;
-       int i;
+       char *dir;
+
+       prepare_submodule_repo_env(&cp.env_array);
+       argv_array_push(&cp.env_array, GIT_DIR_ENVIRONMENT);
 
+       if (prefix_len)
+               argv_array_pushf(&cp.env_array, "%s=%s",
+                                GIT_TOPLEVEL_PREFIX_ENVIRONMENT,
+                                prefix);
        argv_array_pushf(&cp.args, "--super-prefix=%s%s/",
                         super_prefix ? super_prefix : "",
                         ce->name);
@@ -204,20 +219,13 @@ static void show_gitlink(const struct cache_entry *ce)
        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);
+       argv_array_pushv(&cp.args, submodule_options.argv);
 
        cp.git_cmd = 1;
-       cp.dir = ce->name;
+       dir = mkpathdup("%s/%s", get_git_work_tree(), ce->name);
+       cp.dir = dir;
        status = run_command(&cp);
+       free(dir);
        if (status)
                exit(status);
 }
@@ -230,7 +238,7 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
                strbuf_addstr(&name, super_prefix);
        strbuf_addstr(&name, ce->name);
 
-       if (len >= ce_namelen(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) &&
@@ -314,7 +322,7 @@ static void show_ru_info(void)
 static int ce_excluded(struct dir_struct *dir, const struct cache_entry *ce)
 {
        int dtype = ce_to_dtype(ce);
-       return is_excluded(dir, ce->name, &dtype);
+       return is_excluded(dir, &the_index, ce->name, &dtype);
 }
 
 static void show_files(struct dir_struct *dir)
@@ -325,7 +333,7 @@ static void show_files(struct dir_struct *dir)
        if (show_others || show_killed) {
                if (!show_others)
                        dir->flags |= DIR_COLLECT_KILLED_ONLY;
-               fill_directory(dir, &pathspec);
+               fill_directory(dir, &the_index, &pathspec);
                if (show_others)
                        show_other_files(dir);
                if (show_killed)
@@ -395,6 +403,25 @@ static void prune_cache(const char *prefix, size_t prefixlen)
        active_nr = last - pos;
 }
 
+static int get_common_prefix_len(const char *common_prefix)
+{
+       int common_prefix_len;
+
+       if (!common_prefix)
+               return 0;
+
+       common_prefix_len = strlen(common_prefix);
+
+       /*
+        * If the prefix has a trailing slash, strip it so that submodules wont
+        * be pruned from the index.
+        */
+       if (common_prefix[common_prefix_len - 1] == '/')
+               common_prefix_len--;
+
+       return common_prefix_len;
+}
+
 /*
  * Read the tree specified with --with-tree option
  * (typically, HEAD) into stage #1 and then
@@ -406,14 +433,14 @@ static void prune_cache(const char *prefix, size_t prefixlen)
 void overlay_tree_on_cache(const char *tree_name, const char *prefix)
 {
        struct tree *tree;
-       unsigned char sha1[20];
+       struct object_id oid;
        struct pathspec pathspec;
        struct cache_entry *last_stage0 = NULL;
        int i;
 
-       if (get_sha1(tree_name, sha1))
+       if (get_oid(tree_name, &oid))
                die("tree-ish %s not found.", tree_name);
-       tree = parse_tree_indirect(sha1);
+       tree = parse_tree_indirect(&oid);
        if (!tree)
                die("bad tree-ish %s", tree_name);
 
@@ -604,7 +631,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
                setup_work_tree();
 
        if (recurse_submodules)
-               compile_submodule_options(&dir, show_tag);
+               compile_submodule_options(argv, &dir, show_tag);
 
        if (recurse_submodules &&
            (show_stage || show_deleted || show_others || show_unmerged ||
@@ -616,8 +643,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
                    "--error-unmatch");
 
        parse_pathspec(&pathspec, 0,
-                      PATHSPEC_PREFER_CWD |
-                      PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
+                      PATHSPEC_PREFER_CWD,
                       prefix, argv);
 
        /*
@@ -629,7 +655,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
                max_prefix = NULL;
        else
                max_prefix = common_prefix(&pathspec);
-       max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
+       max_prefix_len = get_common_prefix_len(max_prefix);
+
+       prune_cache(max_prefix, max_prefix_len);
 
        /* Treat unmatching pathspec elements as errors */
        if (pathspec.nr && error_unmatch)
@@ -643,7 +671,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
              show_killed || show_modified || show_resolve_undo))
                show_cached = 1;
 
-       prune_cache(max_prefix, max_prefix_len);
        if (with_tree) {
                /*
                 * Basic sanity check; show-stages and show-unmerged