git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Brandon Williams <bmwill@google.com>
To: git@vger.kernel.org
Cc: Brandon Williams <bmwill@google.com>
Subject: [RFC/PATCH] ls-files: adding support for submodules
Date: Fri,  9 Sep 2016 14:53:24 -0700	[thread overview]
Message-ID: <1473458004-41460-1-git-send-email-bmwill@google.com> (raw)

Allow ls-files to recognize submodules in order to retrieve a list of
files from a repository's submodules.  This is done by forking off a
process to recursively call ls-files on all submodules.

Signed-off-by: Brandon Williams <bmwill@google.com>
---
Hey git developers!

I'm new to the community and this is the first patch for an open source project
that I have worked on.

I'm looking forward to working on the project!
Brandon Williams

 Documentation/git-ls-files.txt         |   7 ++-
 builtin/ls-files.c                     |  58 +++++++++++++++++++
 t/t3007-ls-files-recurse-submodules.sh | 103 +++++++++++++++++++++++++++++++++
 3 files changed, 167 insertions(+), 1 deletion(-)
 create mode 100644 t/t3007-ls-files-recurse-submodules.sh

diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 0d933ac..446209e 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -18,7 +18,8 @@ SYNOPSIS
 		[--exclude-per-directory=<file>]
 		[--exclude-standard]
 		[--error-unmatch] [--with-tree=<tree-ish>]
-		[--full-name] [--abbrev] [--] [<file>...]
+		[--full-name] [--recurse-submodules]
+		[--abbrev] [--] [<file>...]
 
 DESCRIPTION
 -----------
@@ -137,6 +138,10 @@ a space) at the start of each line:
 	option forces paths to be output relative to the project
 	top directory.
 
+--recurse-submodules::
+	Recursively calls ls-files on each submodule in the repository.
+	Currently there is only support for the --cached mode.
+
 --abbrev[=<n>]::
 	Instead of showing the full 40-byte hexadecimal object
 	lines, show only a partial prefix.
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 00ea91a..c428a51 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -14,6 +14,7 @@
 #include "resolve-undo.h"
 #include "string-list.h"
 #include "pathspec.h"
+#include "run-command.h"
 
 static int abbrev;
 static int show_deleted;
@@ -28,6 +29,7 @@ static int show_valid_bit;
 static int line_terminator = '\n';
 static int debug_mode;
 static int show_eol;
+static int recurse_submodules;
 
 static const char *prefix;
 static int max_prefix_len;
@@ -152,6 +154,45 @@ static void show_killed_files(struct dir_struct *dir)
 	}
 }
 
+/**
+ *  Recursively call ls-files on a submodule
+ */
+static void show_gitlink(const struct cache_entry *ce)
+{
+	struct child_process cp = CHILD_PROCESS_INIT;
+	struct strbuf buf = STRBUF_INIT;
+	struct strbuf name = STRBUF_INIT;
+	int submodule_name_len;
+	FILE *fp;
+
+	argv_array_push(&cp.args, "ls-files");
+	argv_array_push(&cp.args, "--recurse-submodules");
+	cp.git_cmd = 1;
+	cp.dir = ce->name;
+	cp.out = -1;
+	start_command(&cp);
+	fp = fdopen(cp.out, "r");
+
+	/*
+	 * The ls-files child process produces filenames relative to
+	 * the submodule. Prefix each line with the submodule path
+	 * to make it relative to the current repository.
+	 */
+	strbuf_addstr(&name, ce->name);
+	strbuf_addch(&name, '/');
+	submodule_name_len = name.len;
+	while (strbuf_getline(&buf, fp) != EOF) {
+		strbuf_addbuf(&name, &buf);
+		write_name(name.buf);
+		strbuf_setlen(&name, submodule_name_len);
+	}
+
+	finish_command(&cp);
+	strbuf_release(&buf);
+	strbuf_release(&name);
+	fclose(fp);
+}
+
 static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 {
 	int len = max_prefix_len;
@@ -163,6 +204,10 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 			    len, ps_matched,
 			    S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode)))
 		return;
+	if (recurse_submodules && S_ISGITLINK(ce->ce_mode)) {
+		show_gitlink(ce);
+		return;
+	}
 
 	if (tag && *tag && show_valid_bit &&
 	    (ce->ce_flags & CE_VALID)) {
@@ -468,6 +513,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		{ OPTION_SET_INT, 0, "full-name", &prefix_len, NULL,
 			N_("make the output relative to the project top directory"),
 			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },
+		OPT_BOOL(0, "recurse-submodules", &recurse_submodules,
+			N_("recurse through submodules")),
 		OPT_BOOL(0, "error-unmatch", &error_unmatch,
 			N_("if any <file> is not in the index, treat this as an error")),
 		OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
@@ -519,6 +566,17 @@ 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 &&
+	    (show_stage || show_deleted || show_others || show_unmerged ||
+	     show_killed || show_modified || show_resolve_undo ||
+	     show_valid_bit || show_tag || show_eol))
+		die("ls-files --recurse-submodules can only be used in "
+		    "--cached mode");
+
+	if (recurse_submodules && argc)
+		die("ls-files --recurse-submodules does not support path "
+		    "arguments");
+
 	parse_pathspec(&pathspec, 0,
 		       PATHSPEC_PREFER_CWD |
 		       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
diff --git a/t/t3007-ls-files-recurse-submodules.sh b/t/t3007-ls-files-recurse-submodules.sh
new file mode 100644
index 0000000..78deded
--- /dev/null
+++ b/t/t3007-ls-files-recurse-submodules.sh
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+test_description='Test ls-files recurse-submodules feature
+
+This test verifies the recurse-submodules feature correctly lists files from
+submodules.
+'
+
+. ./test-lib.sh
+
+test_expect_success 'setup directory structure and submodules' '
+	echo a >a &&
+	mkdir b &&
+	echo b >b/b &&
+	git add a b &&
+	git commit -m "add a and b" &&
+	mkdir submodule &&
+	(
+		cd submodule &&
+		git init &&
+		echo c >c &&
+		git add c &&
+		git commit -m "add c"
+	) &&
+	git submodule add ./submodule &&
+	git commit -m "added submodule"
+'
+
+cat >expect <<EOF
+.gitmodules
+a
+b/b
+submodule/c
+EOF
+
+test_expect_success 'ls-files correctly outputs files in submodule' '
+	git ls-files --recurse-submodules >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'ls-files does not output files not added to a repo' '
+	echo a >not_added &&
+	echo b >b/not_added &&
+	(
+		cd submodule &&
+		echo c >not_added
+	) &&
+	git ls-files --recurse-submodules >actual &&
+	test_cmp expect actual
+'
+
+cat >expect <<EOF
+.gitmodules
+a
+b/b
+submodule/.gitmodules
+submodule/c
+submodule/subsub/d
+EOF
+
+test_expect_success 'ls-files recurses more than 1 level' '
+	(
+		cd submodule &&
+		mkdir subsub &&
+		(
+			cd subsub &&
+			git init &&
+			echo d >d &&
+			git add d &&
+			git commit -m "add d"
+		) &&
+		git submodule add ./subsub &&
+		git commit -m "added subsub"
+	) &&
+	git ls-files --recurse-submodules >actual &&
+	test_cmp expect actual
+'
+
+cat >expect_error <<EOF
+fatal: ls-files --recurse-submodules does not support path arguments
+EOF
+
+test_expect_success 'error when using path arguments' '
+	test_must_fail git ls-files --recurse-submodules b 2>actual &&
+	test_cmp expect_error actual
+'
+
+cat >expect_error <<EOF
+fatal: ls-files --recurse-submodules can only be used in --cached mode
+EOF
+
+test_expect_success 'error when using different modes' '
+	for opt in {v,t}; do
+		test_must_fail git ls-files --recurse-submodules -$opt 2>actual &&
+		test_cmp expect_error actual
+	done &&
+	for opt in {deleted,modified,others,ignored,stage,killed,unmerged,eol}; do
+		test_must_fail git ls-files --recurse-submodules --$opt 2>actual &&
+		test_cmp expect_error actual
+	done
+'
+
+test_done
-- 
2.8.0.rc3.226.g39d4020


             reply	other threads:[~2016-09-09 21:54 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-09 21:53 Brandon Williams [this message]
2016-09-09 22:35 ` [RFC/PATCH] ls-files: adding support for submodules Jeff King
2016-09-09 22:40   ` Junio C Hamano
2016-09-09 23:01 ` Junio C Hamano
2016-09-09 23:47   ` Stefan Beller
2016-09-11 22:10     ` Junio C Hamano
2016-09-12  0:51       ` Jeff King
2016-09-12  0:52         ` Jeff King
2016-09-12 16:01           ` Junio C Hamano
     [not found]             ` <CAKoko1oSEac_Nr1SkRB=dM_r3Jnew1Et2ZKj716iU3JLyHe2GQ@mail.gmail.com>
2016-09-12 17:39               ` Brandon Williams
2016-09-12  1:47       ` Junio C Hamano
2016-09-13  0:33 ` [PATCH v2] " Brandon Williams
2016-09-13  3:35   ` Brandon Williams
2016-09-13 16:31   ` Junio C Hamano
2016-09-15 20:51     ` Junio C Hamano
2016-09-15 20:51       ` [PATCH 1/2] SQUASH??? Junio C Hamano
2016-09-15 20:51       ` [PATCH 2/2] SQUASH??? Undecided Junio C Hamano
2016-09-15 21:12         ` Stefan Beller
2016-09-15 21:37           ` Brandon Williams
2016-09-15 20:57     ` [PATCH v2] ls-files: adding support for submodules Junio C Hamano
2016-09-15 20:58     ` Junio C Hamano
2016-09-15 20:58     ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1473458004-41460-1-git-send-email-bmwill@google.com \
    --to=bmwill@google.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).