All of lore.kernel.org
 help / color / mirror / Atom feed
* [GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C
@ 2021-08-05  7:19 Atharva Raykar
  2021-08-05  7:19 ` [GSoC] [PATCH 1/8] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
                   ` (8 more replies)
  0 siblings, 9 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:19 UTC (permalink / raw)
  To: git
  Cc: Atharva Raykar, Ævar Arnfjörð Bjarmason,
	Emily Shaffer, Jonathan Nieder, Junio C Hamano, Christian Couder,
	Shourya Shukla, Kaartic Sivaraam, Eric Sunshine,
	Prathamesh Chavan, Đoàn Trần Công Danh,
	Rafael Silva

NOTE: This series uses the change introduced by 'ar/submodule-add-config'[1]

This series completes the conversion of all the important shell logic in
'submodule add' to C, by wrapping it in a submodule--helper builtin subcommand
called 'add'.

The first 4 patches are preparatory patches. The refactors mostly involve
exposing interfaces to C that were only previously usable as shell subcommands.

Then we have a patch that translates the shell code to C, faithfully reproducing
the behaviour before the conversion.

The last 3 patches are cleanup patches. Our conversions have introduced a lot of
dead code, all of them being 'submodule--helper' subcommands that have no
further use, as we have C interfaces for these already. We remove these
subcommands.

A question about the cache API used in [PATCH 5/8]:
  What is the difference between 'read_cache()' and 'read_cache_preload()'? [2]
  Which one is more appropriate for use in 'die_on_index_match()'?

Fetch-it-Via:
git fetch https://github.com/tfidfwastaken/git submodule-helper-add-list-1

Footnotes
=========

[1] https://lore.kernel.org/git/20210801063352.50813-1-raykar.ath@gmail.com/
[2] More about this question has been detailed in this section of my blog:
http://atharvaraykar.me/gitnotes/week5#some-challenges-with-the-changes-that-are-cooking

I'll quote it here for convenience:

> Before iterating through the cache entries of the index, you need to populate
> it.
>
> There’s two functions for this: read_cache() and read_cache_preload(). I have
> used the latter in my code. The thing is, when I swap it with the former, I
> could not find any change in the behaviour of my code. They appear to function
> equivalently.
>
> I understand that the *_preload() variant takes a pathspec which preloads index
> contents that match the pathspec in parallel. I don’t know what passing NULL to
> it does. Moreover, does this imply that read_cache() loads the cache on-demand,
> ie, it does no preloading?
>
> I am not sure about what exactly are their differences, and when is one variant
> preferred over the other.

Atharva Raykar (8):
  submodule--helper: refactor resolve_relative_url() helper
  submodule--helper: remove repeated code in sync_submodule()
  dir: libify and export helper functions from clone.c
  submodule--helper: remove constness of sm_path
  submodule--helper: convert the bulk of cmd_add() to C
  submodule--helper: remove add-clone subcommand
  submodule--helper: remove add-config subcommand
  submodule--helper: remove resolve-relative-url subcommand

 builtin/clone.c             | 118 +-------------
 builtin/submodule--helper.c | 304 +++++++++++++++++++-----------------
 dir.c                       | 114 ++++++++++++++
 dir.h                       |   3 +
 git-submodule.sh            |  96 +-----------
 5 files changed, 278 insertions(+), 357 deletions(-)

-- 
2.32.0


^ permalink raw reply	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH 1/8] submodule--helper: refactor resolve_relative_url() helper
  2021-08-05  7:19 [GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
@ 2021-08-05  7:19 ` Atharva Raykar
  2021-08-05  7:19 ` [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:19 UTC (permalink / raw)
  To: git
  Cc: Atharva Raykar, Ævar Arnfjörð Bjarmason,
	Emily Shaffer, Jonathan Nieder, Junio C Hamano, Christian Couder,
	Shourya Shukla, Kaartic Sivaraam, Eric Sunshine,
	Prathamesh Chavan, Đoàn Trần Công Danh,
	Rafael Silva

Refactor the helper function to resolve a relative url, by reusing the
existing `compute_submodule_clone_url()` function.

`compute_submodule_clone_url()` performs the same work that
`resolve_relative_url()` is doing, so we eliminate this code repetition
by moving the former function's definition up, and calling it inside
`resolve_relative_url()`.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 61 +++++++++++++++----------------------
 1 file changed, 25 insertions(+), 36 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2d2d8ac637..f4b496bac6 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -199,33 +199,46 @@ static char *relative_url(const char *remote_url,
 	return strbuf_detach(&sb, NULL);
 }
 
+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
+{
+	char *remoteurl, *relurl;
+	char *remote = get_default_remote();
+	struct strbuf remotesb = STRBUF_INIT;
+
+	strbuf_addf(&remotesb, "remote.%s.url", remote);
+	if (git_config_get_string(remotesb.buf, &remoteurl)) {
+		if (!quiet)
+			warning(_("could not look up configuration '%s'. "
+				  "Assuming this repository is its own "
+				  "authoritative upstream."),
+				remotesb.buf);
+		remoteurl = xgetcwd();
+	}
+	relurl = relative_url(remoteurl, rel_url, up_path);
+
+	free(remote);
+	free(remoteurl);
+	strbuf_release(&remotesb);
+
+	return relurl;
+}
+
 static int resolve_relative_url(int argc, const char **argv, const char *prefix)
 {
-	char *remoteurl = NULL;
-	char *remote = get_default_remote();
 	const char *up_path = NULL;
 	char *res;
 	const char *url;
-	struct strbuf sb = STRBUF_INIT;
 
 	if (argc != 2 && argc != 3)
 		die("resolve-relative-url only accepts one or two arguments");
 
 	url = argv[1];
-	strbuf_addf(&sb, "remote.%s.url", remote);
-	free(remote);
-
-	if (git_config_get_string(sb.buf, &remoteurl))
-		/* the repository is its own authoritative upstream */
-		remoteurl = xgetcwd();
-
 	if (argc == 3)
 		up_path = argv[2];
 
-	res = relative_url(remoteurl, url, up_path);
+	res = compute_submodule_clone_url(url, up_path, 1);
 	puts(res);
 	free(res);
-	free(remoteurl);
 	return 0;
 }
 
@@ -590,30 +603,6 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
-{
-	char *remoteurl, *relurl;
-	char *remote = get_default_remote();
-	struct strbuf remotesb = STRBUF_INIT;
-
-	strbuf_addf(&remotesb, "remote.%s.url", remote);
-	if (git_config_get_string(remotesb.buf, &remoteurl)) {
-		if (!quiet)
-			warning(_("could not look up configuration '%s'. "
-				  "Assuming this repository is its own "
-				  "authoritative upstream."),
-				remotesb.buf);
-		remoteurl = xgetcwd();
-	}
-	relurl = relative_url(remoteurl, rel_url, up_path);
-
-	free(remote);
-	free(remoteurl);
-	strbuf_release(&remotesb);
-
-	return relurl;
-}
-
 struct init_cb {
 	const char *prefix;
 	unsigned int flags;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule()
  2021-08-05  7:19 [GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
  2021-08-05  7:19 ` [GSoC] [PATCH 1/8] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
@ 2021-08-05  7:19 ` Atharva Raykar
  2021-08-06  0:53   ` Đoàn Trần Công Danh
  2021-08-05  7:19 ` [GSoC] [PATCH 3/8] dir: libify and export helper functions from clone.c Atharva Raykar
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:19 UTC (permalink / raw)
  To: git
  Cc: Atharva Raykar, Ævar Arnfjörð Bjarmason,
	Emily Shaffer, Jonathan Nieder, Junio C Hamano, Christian Couder,
	Shourya Shukla, Kaartic Sivaraam, Eric Sunshine,
	Prathamesh Chavan, Đoàn Trần Công Danh,
	Rafael Silva

This part of `sync_submodule()` is doing the same thing that
`compute_submodule_clone_url()` is doing. Let's reuse that helper here.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f4b496bac6..9b676c12f8 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,
 	if (sub && sub->url) {
 		if (starts_with_dot_dot_slash(sub->url) ||
 		    starts_with_dot_slash(sub->url)) {
-			char *remote_url, *up_path;
-			char *remote = get_default_remote();
-			strbuf_addf(&sb, "remote.%s.url", remote);
-
-			if (git_config_get_string(sb.buf, &remote_url))
-				remote_url = xgetcwd();
-
-			up_path = get_up_path(path);
-			sub_origin_url = relative_url(remote_url, sub->url, up_path);
-			super_config_url = relative_url(remote_url, sub->url, NULL);
-
-			free(remote);
+			char *up_path = get_up_path(path);
+			sub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);
+			super_config_url = compute_submodule_clone_url(sub->url, NULL, 1);
 			free(up_path);
-			free(remote_url);
 		} else {
 			sub_origin_url = xstrdup(sub->url);
 			super_config_url = xstrdup(sub->url);
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH 3/8] dir: libify and export helper functions from clone.c
  2021-08-05  7:19 [GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
  2021-08-05  7:19 ` [GSoC] [PATCH 1/8] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
  2021-08-05  7:19 ` [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
@ 2021-08-05  7:19 ` Atharva Raykar
  2021-08-05  7:19 ` [GSoC] [PATCH 4/8] submodule--helper: remove constness of sm_path Atharva Raykar
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:19 UTC (permalink / raw)
  To: git
  Cc: Atharva Raykar, Ævar Arnfjörð Bjarmason,
	Emily Shaffer, Jonathan Nieder, Junio C Hamano, Christian Couder,
	Shourya Shukla, Kaartic Sivaraam, Eric Sunshine,
	Prathamesh Chavan, Đoàn Trần Công Danh,
	Rafael Silva, Shourya Shukla

These functions can be useful to other parts of Git. Let's move them to
dir.c, while renaming them to be make their functionality more explicit.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <shouryashukla.oo@gmail.com>
---
 builtin/clone.c | 118 +-----------------------------------------------
 dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++
 dir.h           |   3 ++
 3 files changed, 119 insertions(+), 116 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 66fe66679c..b9b59a838f 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -217,120 +217,6 @@ static char *get_repo_path(const char *repo, int *is_bundle)
 	return canon;
 }
 
-static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
-{
-	const char *end = repo + strlen(repo), *start, *ptr;
-	size_t len;
-	char *dir;
-
-	/*
-	 * Skip scheme.
-	 */
-	start = strstr(repo, "://");
-	if (start == NULL)
-		start = repo;
-	else
-		start += 3;
-
-	/*
-	 * Skip authentication data. The stripping does happen
-	 * greedily, such that we strip up to the last '@' inside
-	 * the host part.
-	 */
-	for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
-		if (*ptr == '@')
-			start = ptr + 1;
-	}
-
-	/*
-	 * Strip trailing spaces, slashes and /.git
-	 */
-	while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
-		end--;
-	if (end - start > 5 && is_dir_sep(end[-5]) &&
-	    !strncmp(end - 4, ".git", 4)) {
-		end -= 5;
-		while (start < end && is_dir_sep(end[-1]))
-			end--;
-	}
-
-	/*
-	 * Strip trailing port number if we've got only a
-	 * hostname (that is, there is no dir separator but a
-	 * colon). This check is required such that we do not
-	 * strip URI's like '/foo/bar:2222.git', which should
-	 * result in a dir '2222' being guessed due to backwards
-	 * compatibility.
-	 */
-	if (memchr(start, '/', end - start) == NULL
-	    && memchr(start, ':', end - start) != NULL) {
-		ptr = end;
-		while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
-			ptr--;
-		if (start < ptr && ptr[-1] == ':')
-			end = ptr - 1;
-	}
-
-	/*
-	 * Find last component. To remain backwards compatible we
-	 * also regard colons as path separators, such that
-	 * cloning a repository 'foo:bar.git' would result in a
-	 * directory 'bar' being guessed.
-	 */
-	ptr = end;
-	while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
-		ptr--;
-	start = ptr;
-
-	/*
-	 * Strip .{bundle,git}.
-	 */
-	len = end - start;
-	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
-
-	if (!len || (len == 1 && *start == '/'))
-		die(_("No directory name could be guessed.\n"
-		      "Please specify a directory on the command line"));
-
-	if (is_bare)
-		dir = xstrfmt("%.*s.git", (int)len, start);
-	else
-		dir = xstrndup(start, len);
-	/*
-	 * Replace sequences of 'control' characters and whitespace
-	 * with one ascii space, remove leading and trailing spaces.
-	 */
-	if (*dir) {
-		char *out = dir;
-		int prev_space = 1 /* strip leading whitespace */;
-		for (end = dir; *end; ++end) {
-			char ch = *end;
-			if ((unsigned char)ch < '\x20')
-				ch = '\x20';
-			if (isspace(ch)) {
-				if (prev_space)
-					continue;
-				prev_space = 1;
-			} else
-				prev_space = 0;
-			*out++ = ch;
-		}
-		*out = '\0';
-		if (out > dir && prev_space)
-			out[-1] = '\0';
-	}
-	return dir;
-}
-
-static void strip_trailing_slashes(char *dir)
-{
-	char *end = dir + strlen(dir);
-
-	while (dir < end - 1 && is_dir_sep(end[-1]))
-		end--;
-	*end = '\0';
-}
-
 static int add_one_reference(struct string_list_item *item, void *cb_data)
 {
 	struct strbuf err = STRBUF_INIT;
@@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	if (argc == 2)
 		dir = xstrdup(argv[1]);
 	else
-		dir = guess_dir_name(repo_name, is_bundle, option_bare);
-	strip_trailing_slashes(dir);
+		dir = guess_dir_name_from_git_url(repo_name, is_bundle, option_bare);
+	strip_dir_trailing_slashes(dir);
 
 	dest_exists = path_exists(dir);
 	if (dest_exists && !is_empty_dir(dir))
diff --git a/dir.c b/dir.c
index 03c4d21267..84b47c4dbc 100644
--- a/dir.c
+++ b/dir.c
@@ -2970,6 +2970,120 @@ int is_empty_dir(const char *path)
 	return ret;
 }
 
+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare)
+{
+	const char *end = repo + strlen(repo), *start, *ptr;
+	size_t len;
+	char *dir;
+
+	/*
+	 * Skip scheme.
+	 */
+	start = strstr(repo, "://");
+	if (start == NULL)
+		start = repo;
+	else
+		start += 3;
+
+	/*
+	 * Skip authentication data. The stripping does happen
+	 * greedily, such that we strip up to the last '@' inside
+	 * the host part.
+	 */
+	for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
+		if (*ptr == '@')
+			start = ptr + 1;
+	}
+
+	/*
+	 * Strip trailing spaces, slashes and /.git
+	 */
+	while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
+		end--;
+	if (end - start > 5 && is_dir_sep(end[-5]) &&
+	    !strncmp(end - 4, ".git", 4)) {
+		end -= 5;
+		while (start < end && is_dir_sep(end[-1]))
+			end--;
+	}
+
+	/*
+	 * Strip trailing port number if we've got only a
+	 * hostname (that is, there is no dir separator but a
+	 * colon). This check is required such that we do not
+	 * strip URI's like '/foo/bar:2222.git', which should
+	 * result in a dir '2222' being guessed due to backwards
+	 * compatibility.
+	 */
+	if (memchr(start, '/', end - start) == NULL
+	    && memchr(start, ':', end - start) != NULL) {
+		ptr = end;
+		while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
+			ptr--;
+		if (start < ptr && ptr[-1] == ':')
+			end = ptr - 1;
+	}
+
+	/*
+	 * Find last component. To remain backwards compatible we
+	 * also regard colons as path separators, such that
+	 * cloning a repository 'foo:bar.git' would result in a
+	 * directory 'bar' being guessed.
+	 */
+	ptr = end;
+	while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
+		ptr--;
+	start = ptr;
+
+	/*
+	 * Strip .{bundle,git}.
+	 */
+	len = end - start;
+	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
+
+	if (!len || (len == 1 && *start == '/'))
+		die(_("No directory name could be guessed.\n"
+		      "Please specify a directory on the command line"));
+
+	if (is_bare)
+		dir = xstrfmt("%.*s.git", (int)len, start);
+	else
+		dir = xstrndup(start, len);
+	/*
+	 * Replace sequences of 'control' characters and whitespace
+	 * with one ascii space, remove leading and trailing spaces.
+	 */
+	if (*dir) {
+		char *out = dir;
+		int prev_space = 1 /* strip leading whitespace */;
+		for (end = dir; *end; ++end) {
+			char ch = *end;
+			if ((unsigned char)ch < '\x20')
+				ch = '\x20';
+			if (isspace(ch)) {
+				if (prev_space)
+					continue;
+				prev_space = 1;
+			} else
+				prev_space = 0;
+			*out++ = ch;
+		}
+		*out = '\0';
+		if (out > dir && prev_space)
+			out[-1] = '\0';
+	}
+	return dir;
+}
+
+void strip_dir_trailing_slashes(char *dir)
+{
+	char *end = dir + strlen(dir);
+
+	while (dir < end - 1 && is_dir_sep(end[-1]))
+		end--;
+	*end = '\0';
+}
+
 static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
 {
 	DIR *dir;
diff --git a/dir.h b/dir.h
index b3e1a54a97..76441dde2d 100644
--- a/dir.h
+++ b/dir.h
@@ -453,6 +453,9 @@ static inline int is_dot_or_dotdot(const char *name)
 
 int is_empty_dir(const char *dir);
 
+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare);
+void strip_dir_trailing_slashes(char *dir);
+
 void setup_standard_excludes(struct dir_struct *dir);
 
 char *get_sparse_checkout_filename(void);
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH 4/8] submodule--helper: remove constness of sm_path
  2021-08-05  7:19 [GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                   ` (2 preceding siblings ...)
  2021-08-05  7:19 ` [GSoC] [PATCH 3/8] dir: libify and export helper functions from clone.c Atharva Raykar
@ 2021-08-05  7:19 ` Atharva Raykar
  2021-08-05  7:19 ` [GSoC] [PATCH 5/8] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:19 UTC (permalink / raw)
  To: git
  Cc: Atharva Raykar, Ævar Arnfjörð Bjarmason,
	Emily Shaffer, Jonathan Nieder, Junio C Hamano, Christian Couder,
	Shourya Shukla, Kaartic Sivaraam, Eric Sunshine,
	Prathamesh Chavan, Đoàn Trần Công Danh,
	Rafael Silva

This is needed so that it can be modified by normalize_path_copy() in
the next patch.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 9b676c12f8..99aabf1078 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2748,7 +2748,7 @@ struct add_data {
 	const char *prefix;
 	const char *branch;
 	const char *reference_path;
-	const char *sm_path;
+	char *sm_path;
 	const char *sm_name;
 	const char *repo;
 	const char *realrepo;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH 5/8] submodule--helper: convert the bulk of cmd_add() to C
  2021-08-05  7:19 [GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                   ` (3 preceding siblings ...)
  2021-08-05  7:19 ` [GSoC] [PATCH 4/8] submodule--helper: remove constness of sm_path Atharva Raykar
@ 2021-08-05  7:19 ` Atharva Raykar
  2021-08-05  7:19 ` [GSoC] [PATCH 6/8] submodule--helper: remove add-clone subcommand Atharva Raykar
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:19 UTC (permalink / raw)
  To: git
  Cc: Atharva Raykar, Ævar Arnfjörð Bjarmason,
	Emily Shaffer, Jonathan Nieder, Junio C Hamano, Christian Couder,
	Shourya Shukla, Kaartic Sivaraam, Eric Sunshine,
	Prathamesh Chavan, Đoàn Trần Công Danh,
	Rafael Silva

Introduce the 'add' subcommand to `submodule--helper.c` that does all
the work 'submodule add' past the parsing of flags.

As with the previous conversions, this is meant to be a faithful
conversion with no modification to the behaviour of `submodule add`.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Helped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
Based-on-patch-by: Shourya Shukla <periperidip@gmail.com>
Based-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>
---
 builtin/submodule--helper.c | 160 ++++++++++++++++++++++++++++++++++++
 git-submodule.sh            |  96 +---------------------
 2 files changed, 162 insertions(+), 94 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 99aabf1078..05ae9ebe50 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3046,6 +3046,165 @@ static int add_config(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+static void die_on_index_match(const char *path, int force)
+{
+	struct pathspec ps;
+	const char *args[] = { path, NULL };
+	parse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);
+
+	if (read_cache_preload(NULL) < 0)
+		die(_("index file corrupt"));
+
+	if (ps.nr) {
+		int i;
+		char *ps_matched = xcalloc(ps.nr, 1);
+
+		/* TODO: audit for interaction with sparse-index. */
+		ensure_full_index(&the_index);
+
+		/*
+		 * Since there is only one pathspec, we just need
+		 * need to check ps_matched[0] to know if a cache
+		 * entry matched.
+		 */
+		for (i = 0; i < active_nr; i++) {
+			ce_path_match(&the_index, active_cache[i], &ps,
+				      ps_matched);
+
+			if (ps_matched[0]) {
+				if (!force)
+					die(_("'%s' already exists in the index"),
+					    path);
+				if (!S_ISGITLINK(active_cache[i]->ce_mode))
+					die(_("'%s' already exists in the index "
+					      "and is not a submodule"), path);
+				break;
+			}
+		}
+		free(ps_matched);
+	}
+}
+
+static void die_on_repo_without_commits(const char *path)
+{
+	struct strbuf sb = STRBUF_INIT;
+	strbuf_addstr(&sb, path);
+	if (is_nonbare_repository_dir(&sb)) {
+		struct object_id oid;
+		if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
+			die(_("'%s' does not have a commit checked out"), path);
+	}
+}
+
+static int module_add(int argc, const char **argv, const char *prefix)
+{
+	int force = 0, quiet = 0, progress = 0, dissociate = 0;
+	struct add_data add_data = ADD_DATA_INIT;
+
+	struct option options[] = {
+		OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
+			   N_("branch of repository to add as submodule")),
+		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
+			   PARSE_OPT_NOCOMPLETE),
+		OPT__QUIET(&quiet, N_("print only error messages")),
+		OPT_BOOL(0, "progress", &progress, N_("force cloning progress")),
+		OPT_STRING(0, "reference", &add_data.reference_path, N_("repository"),
+			   N_("reference repository")),
+		OPT_BOOL(0, "dissociate", &dissociate, N_("borrow the objects from reference repositories")),
+		OPT_STRING(0, "name", &add_data.sm_name, N_("name"),
+			   N_("sets the submodule’s name to the given string "
+			      "instead of defaulting to its path")),
+		OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
+		OPT_END()
+	};
+
+	const char *const usage[] = {
+		N_("git submodule--helper add [<options>] [--] <repository> [<path>]"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, options, usage, 0);
+
+	if (!is_writing_gitmodules_ok())
+		die(_("please make sure that the .gitmodules file is in the working tree"));
+
+	if (prefix && *prefix &&
+	    add_data.reference_path && !is_absolute_path(add_data.reference_path))
+		add_data.reference_path = xstrfmt("%s%s", prefix, add_data.reference_path);
+
+	if (argc == 0 || argc > 2)
+		usage_with_options(usage, options);
+
+	add_data.repo = argv[0];
+	if (argc == 1)
+		add_data.sm_path = guess_dir_name_from_git_url(add_data.repo, 0, 0);
+	else
+		add_data.sm_path = xstrdup(argv[1]);
+
+	if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
+		add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
+
+	if (starts_with_dot_dot_slash(add_data.repo) ||
+	    starts_with_dot_slash(add_data.repo)) {
+		if (prefix)
+			die(_("Relative path can only be used from the toplevel "
+			      "of the working tree"));
+
+		/* dereference source url relative to parent's url */
+		add_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);
+	} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {
+		add_data.realrepo = add_data.repo;
+	} else {
+		die(_("repo URL: '%s' must be absolute or begin with ./|../"),
+		    add_data.repo);
+	}
+
+	/*
+	 * normalize path:
+	 * multiple //; leading ./; /./; /../;
+	 */
+	normalize_path_copy(add_data.sm_path, add_data.sm_path);
+	strip_dir_trailing_slashes(add_data.sm_path);
+
+	die_on_index_match(add_data.sm_path, force);
+	die_on_repo_without_commits(add_data.sm_path);
+
+	if (!force) {
+		int exit_code = -1;
+		struct strbuf sb = STRBUF_INIT;
+		struct child_process cp = CHILD_PROCESS_INIT;
+		cp.git_cmd = 1;
+		cp.no_stdout = 1;
+		strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
+			     "--no-warn-embedded-repo", add_data.sm_path, NULL);
+		if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
+			strbuf_complete_line(&sb);
+			fputs(sb.buf, stderr);
+			return exit_code;
+		}
+		strbuf_release(&sb);
+	}
+
+	if(!add_data.sm_name)
+		add_data.sm_name = add_data.sm_path;
+
+	if (check_submodule_name(add_data.sm_name))
+		die(_("'%s' is not a valid submodule name"), add_data.sm_name);
+
+	add_data.prefix = prefix;
+	add_data.force = !!force;
+	add_data.quiet = !!quiet;
+	add_data.progress = !!progress;
+	add_data.dissociate = !!dissociate;
+
+	if (add_submodule(&add_data))
+		return 1;
+	configure_added_submodule(&add_data);
+	free(add_data.sm_path);
+
+	return 0;
+}
+
 #define SUPPORT_SUPER_PREFIX (1<<0)
 
 struct cmd_struct {
@@ -3060,6 +3219,7 @@ static struct cmd_struct commands[] = {
 	{"clone", module_clone, 0},
 	{"add-clone", add_clone, 0},
 	{"add-config", add_config, 0},
+	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
 	{"update-clone", update_clone, 0},
 	{"ensure-core-worktree", ensure_core_worktree, 0},
diff --git a/git-submodule.sh b/git-submodule.sh
index 8c219ef382..1070540525 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -145,104 +145,12 @@ cmd_add()
 		shift
 	done
 
-	if ! git submodule--helper config --check-writeable >/dev/null 2>&1
+	if test -z "$1"
 	then
-		 die "fatal: $(eval_gettext "please make sure that the .gitmodules file is in the working tree")"
-	fi
-
-	if test -n "$reference_path"
-	then
-		is_absolute_path "$reference_path" ||
-		reference_path="$wt_prefix$reference_path"
-
-		reference="--reference=$reference_path"
-	fi
-
-	repo=$1
-	sm_path=$2
-
-	if test -z "$sm_path"; then
-		sm_path=$(printf '%s\n' "$repo" |
-			sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
-	fi
-
-	if test -z "$repo" || test -z "$sm_path"; then
 		usage
 	fi
 
-	is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
-
-	# assure repo is absolute or relative to parent
-	case "$repo" in
-	./*|../*)
-		test -z "$wt_prefix" ||
-		die "fatal: $(gettext "Relative path can only be used from the toplevel of the working tree")"
-
-		# dereference source url relative to parent's url
-		realrepo=$(git submodule--helper resolve-relative-url "$repo") || exit
-		;;
-	*:*|/*)
-		# absolute url
-		realrepo=$repo
-		;;
-	*)
-		die "fatal: $(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
-	;;
-	esac
-
-	# normalize path:
-	# multiple //; leading ./; /./; /../; trailing /
-	sm_path=$(printf '%s/\n' "$sm_path" |
-		sed -e '
-			s|//*|/|g
-			s|^\(\./\)*||
-			s|/\(\./\)*|/|g
-			:start
-			s|\([^/]*\)/\.\./||
-			tstart
-			s|/*$||
-		')
-	if test -z "$force"
-	then
-		git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
-		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index")"
-	else
-		git ls-files -s "$sm_path" | sane_grep -v "^160000" > /dev/null 2>&1 &&
-		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
-	fi
-
-	if test -d "$sm_path" &&
-		test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null)
-	then
-	    git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null ||
-	    die "fatal: $(eval_gettext "'\$sm_path' does not have a commit checked out")"
-	fi
-
-	if test -z "$force"
-	then
-	    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" 2>&1 >/dev/null)
-	    res=$?
-	    if test $res -ne 0
-	    then
-		 echo >&2 "$dryerr"
-		 exit $res
-	    fi
-	fi
-
-	if test -n "$custom_name"
-	then
-		sm_name="$custom_name"
-	else
-		sm_name="$sm_path"
-	fi
-
-	if ! git submodule--helper check-name "$sm_name"
-	then
-		die "fatal: $(eval_gettext "'$sm_name' is not a valid submodule name")"
-	fi
-
-	git submodule--helper add-clone ${GIT_QUIET:+--quiet} ${force:+"--force"} ${progress:+"--progress"} ${branch:+--branch "$branch"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit
-	git submodule--helper add-config ${force:+--force} ${branch:+--branch "$branch"} --url "$repo" --resolved-url "$realrepo" --path "$sm_path" --name "$sm_name"
+	git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper add ${GIT_QUIET:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@"
 }
 
 #
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH 6/8] submodule--helper: remove add-clone subcommand
  2021-08-05  7:19 [GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                   ` (4 preceding siblings ...)
  2021-08-05  7:19 ` [GSoC] [PATCH 5/8] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
@ 2021-08-05  7:19 ` Atharva Raykar
  2021-08-05  7:19 ` [GSoC] [PATCH 7/8] submodule--helper: remove add-config subcommand Atharva Raykar
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:19 UTC (permalink / raw)
  To: git
  Cc: Atharva Raykar, Ævar Arnfjörð Bjarmason,
	Emily Shaffer, Jonathan Nieder, Junio C Hamano, Christian Couder,
	Shourya Shukla, Kaartic Sivaraam, Eric Sunshine,
	Prathamesh Chavan, Đoàn Trần Công Danh,
	Rafael Silva

We no longer need this subcommand, as all of its functionality is being
called by the newly-introduced `module_add()` directly within C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 60 -------------------------------------
 1 file changed, 60 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 05ae9ebe50..700cc8bbeb 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2860,65 +2860,6 @@ static int add_submodule(const struct add_data *add_data)
 	return 0;
 }
 
-static int add_clone(int argc, const char **argv, const char *prefix)
-{
-	int force = 0, quiet = 0, dissociate = 0, progress = 0;
-	struct add_data add_data = ADD_DATA_INIT;
-
-	struct option options[] = {
-		OPT_STRING('b', "branch", &add_data.branch,
-			   N_("branch"),
-			   N_("branch of repository to checkout on cloning")),
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("alternative anchor for relative paths")),
-		OPT_STRING(0, "path", &add_data.sm_path,
-			   N_("path"),
-			   N_("where the new submodule will be cloned to")),
-		OPT_STRING(0, "name", &add_data.sm_name,
-			   N_("string"),
-			   N_("name of the new submodule")),
-		OPT_STRING(0, "url", &add_data.realrepo,
-			   N_("string"),
-			   N_("url where to clone the submodule from")),
-		OPT_STRING(0, "reference", &add_data.reference_path,
-			   N_("repo"),
-			   N_("reference repository")),
-		OPT_BOOL(0, "dissociate", &dissociate,
-			 N_("use --reference only while cloning")),
-		OPT_INTEGER(0, "depth", &add_data.depth,
-			    N_("depth for shallow clones")),
-		OPT_BOOL(0, "progress", &progress,
-			 N_("force cloning progress")),
-		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT__QUIET(&quiet, "suppress output for cloning a submodule"),
-		OPT_END()
-	};
-
-	const char *const usage[] = {
-		N_("git submodule--helper add-clone [<options>...] "
-		   "--url <url> --path <path> --name <name>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (argc != 0)
-		usage_with_options(usage, options);
-
-	add_data.prefix = prefix;
-	add_data.progress = !!progress;
-	add_data.dissociate = !!dissociate;
-	add_data.force = !!force;
-	add_data.quiet = !!quiet;
-
-	if (add_submodule(&add_data))
-		return 1;
-
-	return 0;
-}
-
 static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
 {
 	char *key;
@@ -3217,7 +3158,6 @@ static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
 	{"name", module_name, 0},
 	{"clone", module_clone, 0},
-	{"add-clone", add_clone, 0},
 	{"add-config", add_config, 0},
 	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH 7/8] submodule--helper: remove add-config subcommand
  2021-08-05  7:19 [GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                   ` (5 preceding siblings ...)
  2021-08-05  7:19 ` [GSoC] [PATCH 6/8] submodule--helper: remove add-clone subcommand Atharva Raykar
@ 2021-08-05  7:19 ` Atharva Raykar
  2021-08-05  7:19 ` [GSoC] [PATCH 8/8] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:19 UTC (permalink / raw)
  To: git
  Cc: Atharva Raykar, Ævar Arnfjörð Bjarmason,
	Emily Shaffer, Jonathan Nieder, Junio C Hamano, Christian Couder,
	Shourya Shukla, Kaartic Sivaraam, Eric Sunshine,
	Prathamesh Chavan, Đoàn Trần Công Danh,
	Rafael Silva

Also no longer needed is this subcommand, as all of its functionality is
being called by the newly-introduced `module_add()` directly within C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 49 -------------------------------------
 1 file changed, 49 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 700cc8bbeb..da83e8e2a5 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2939,54 +2939,6 @@ static void configure_added_submodule(struct add_data *add_data)
 	}
 }
 
-static int add_config(int argc, const char **argv, const char *prefix)
-{
-	int force = 0;
-	struct add_data add_data = ADD_DATA_INIT;
-
-	struct option options[] = {
-		OPT_STRING('b', "branch", &add_data.branch,
-			   N_("branch"),
-			   N_("branch of repository to store in "
-			      "the submodule configuration")),
-		OPT_STRING(0, "url", &add_data.repo,
-			   N_("string"),
-			   N_("url to clone submodule from")),
-		OPT_STRING(0, "resolved-url", &add_data.realrepo,
-			   N_("string"),
-			   N_("url to clone the submodule from, after it has "
-			      "been dereferenced relative to parent's url, "
-			      "in the case where <url> is a relative url")),
-		OPT_STRING(0, "path", &add_data.sm_path,
-			   N_("path"),
-			   N_("where the new submodule will be cloned to")),
-		OPT_STRING(0, "name", &add_data.sm_name,
-			   N_("string"),
-			   N_("name of the new submodule")),
-		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_END()
-	};
-
-	const char *const usage[] = {
-		N_("git submodule--helper add-config "
-		   "[--force|-f] [--branch|-b <branch>] "
-		   "--url <url> --resolved-url <resolved-url> "
-		   "--path <path> --name <name>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (argc)
-		usage_with_options(usage, options);
-
-	add_data.force = !!force;
-	configure_added_submodule(&add_data);
-
-	return 0;
-}
-
 static void die_on_index_match(const char *path, int force)
 {
 	struct pathspec ps;
@@ -3158,7 +3110,6 @@ static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
 	{"name", module_name, 0},
 	{"clone", module_clone, 0},
-	{"add-config", add_config, 0},
 	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
 	{"update-clone", update_clone, 0},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH 8/8] submodule--helper: remove resolve-relative-url subcommand
  2021-08-05  7:19 [GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                   ` (6 preceding siblings ...)
  2021-08-05  7:19 ` [GSoC] [PATCH 7/8] submodule--helper: remove add-config subcommand Atharva Raykar
@ 2021-08-05  7:19 ` Atharva Raykar
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:19 UTC (permalink / raw)
  To: git
  Cc: Atharva Raykar, Ævar Arnfjörð Bjarmason,
	Emily Shaffer, Jonathan Nieder, Junio C Hamano, Christian Couder,
	Shourya Shukla, Kaartic Sivaraam, Eric Sunshine,
	Prathamesh Chavan, Đoàn Trần Công Danh,
	Rafael Silva

The shell subcommand `resolve-relative-url` is no longer required, as
its last caller has been removed when it was converted to C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 20 --------------------
 1 file changed, 20 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index da83e8e2a5..514891a22f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -223,25 +223,6 @@ static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat
 	return relurl;
 }
 
-static int resolve_relative_url(int argc, const char **argv, const char *prefix)
-{
-	const char *up_path = NULL;
-	char *res;
-	const char *url;
-
-	if (argc != 2 && argc != 3)
-		die("resolve-relative-url only accepts one or two arguments");
-
-	url = argv[1];
-	if (argc == 3)
-		up_path = argv[2];
-
-	res = compute_submodule_clone_url(url, up_path, 1);
-	puts(res);
-	free(res);
-	return 0;
-}
-
 static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)
 {
 	char *remoteurl, *res;
@@ -3115,7 +3096,6 @@ static struct cmd_struct commands[] = {
 	{"update-clone", update_clone, 0},
 	{"ensure-core-worktree", ensure_core_worktree, 0},
 	{"relative-path", resolve_relative_path, 0},
-	{"resolve-relative-url", resolve_relative_url, 0},
 	{"resolve-relative-url-test", resolve_relative_url_test, 0},
 	{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
 	{"init", module_init, SUPPORT_SUPER_PREFIX},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C
  2021-08-05  7:19 [GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                   ` (7 preceding siblings ...)
  2021-08-05  7:19 ` [GSoC] [PATCH 8/8] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
@ 2021-08-05  7:40 ` Atharva Raykar
  2021-08-05  7:40   ` [GSoC] [PATCH v2 1/9] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
                     ` (9 more replies)
  8 siblings, 10 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:40 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

I missed the adding the first patch of this series, so I am re-sending with the
missing commit included.

No change since v1, except for the inclusion of 75edf24186 (submodule--helper:
add options for compute_submodule_clone_url(), 2021-07-06) at the beginning.

I am including the cover letter of v1 as-is, so the discussion can start from
here, with minor edits to reflect the accurate counts of the patches:

---8<------8<------8<------8<------8<---

NOTE: This series uses the change introduced by 'ar/submodule-add-config'[1]

This series completes the conversion of all the important shell logic in
'submodule add' to C, by wrapping it in a submodule--helper builtin subcommand
called 'add'.

The first 5 patches are preparatory patches. The refactors mostly involve
exposing interfaces to C that were only previously usable as shell subcommands.

Then we have a patch that translates the shell code to C, faithfully reproducing
the behaviour before the conversion.

The last 3 patches are cleanup patches. Our conversions have introduced a lot of
dead code, all of them being 'submodule--helper' subcommands that have no
further use, as we have C interfaces for these already. We remove these
subcommands.

A question about the cache API used in [PATCH 5/9]:
  What is the difference between 'read_cache()' and 'read_cache_preload()'? [2]
  Which one is more appropriate for use in 'die_on_index_match()'?

Fetch-it-Via:
git fetch https://github.com/tfidfwastaken/git submodule-helper-add-list-1

Footnotes
=========

[1] https://lore.kernel.org/git/20210801063352.50813-1-raykar.ath@gmail.com/
[2] More about this question has been detailed in this section of my blog:
http://atharvaraykar.me/gitnotes/week5#some-challenges-with-the-changes-that-are-cooking

I'll quote it here for convenience:

> Before iterating through the cache entries of the index, you need to populate
> it.
>
> There’s two functions for this: read_cache() and read_cache_preload(). I have
> used the latter in my code. The thing is, when I swap it with the former, I
> could not find any change in the behaviour of my code. They appear to function
> equivalently.
>
> I understand that the *_preload() variant takes a pathspec which preloads index
> contents that match the pathspec in parallel. I don’t know what passing NULL to
> it does. Moreover, does this imply that read_cache() loads the cache on-demand,
> ie, it does no preloading?
>
> I am not sure about what exactly are their differences, and when is one variant
> preferred over the other.

--->8------>8------>8------>8------>8---

Atharva Raykar (9):
  submodule--helper: add options for compute_submodule_clone_url()
  submodule--helper: refactor resolve_relative_url() helper
  submodule--helper: remove repeated code in sync_submodule()
  dir: libify and export helper functions from clone.c
  submodule--helper: remove constness of sm_path
  submodule--helper: convert the bulk of cmd_add() to C
  submodule--helper: remove add-clone subcommand
  submodule--helper: remove add-config subcommand
  submodule--helper: remove resolve-relative-url subcommand

 builtin/clone.c             | 118 +-------------
 builtin/submodule--helper.c | 304 +++++++++++++++++++-----------------
 dir.c                       | 114 ++++++++++++++
 dir.h                       |   3 +
 git-submodule.sh            |  96 +-----------
 5 files changed, 280 insertions(+), 355 deletions(-)

-- 
2.32.0


^ permalink raw reply	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v2 1/9] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
@ 2021-08-05  7:40   ` Atharva Raykar
  2021-08-05 20:05     ` Junio C Hamano
  2021-08-05  7:40   ` [GSoC] [PATCH v2 2/9] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
                     ` (8 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:40 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Let's modify the interface to `compute_submodule_clone_url()` function
by adding two more arguments, so that we can reuse this in various parts
of `submodule--helper.c` that follow a common pattern, which is--read
the remote url configuration of the superproject and then call
`relative_url()`.

This function is nearly identical to `resolve_relative_url()`, the only
difference being the extra warning message. We can add a quiet flag to
it, to suppress that warning when not needed, and then refactor
`resolve_relative_url()` by using this function, something we will do in
the next patch.

Having this functionality factored out will be useful for converting the
rest of `submodule add` in subsequent patches.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6891480013..2d2d8ac637 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -590,7 +590,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static char *compute_submodule_clone_url(const char *rel_url)
+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
 {
 	char *remoteurl, *relurl;
 	char *remote = get_default_remote();
@@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)
 
 	strbuf_addf(&remotesb, "remote.%s.url", remote);
 	if (git_config_get_string(remotesb.buf, &remoteurl)) {
-		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
+		if (!quiet)
+			warning(_("could not look up configuration '%s'. "
+				  "Assuming this repository is its own "
+				  "authoritative upstream."),
+				remotesb.buf);
 		remoteurl = xgetcwd();
 	}
-	relurl = relative_url(remoteurl, rel_url, NULL);
+	relurl = relative_url(remoteurl, rel_url, up_path);
 
 	free(remote);
 	free(remoteurl);
@@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(url) ||
 		    starts_with_dot_slash(url)) {
 			char *oldurl = url;
-			url = compute_submodule_clone_url(oldurl);
+			url = compute_submodule_clone_url(oldurl, NULL, 0);
 			free(oldurl);
 		}
 
@@ -2134,7 +2138,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	if (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {
 		if (starts_with_dot_slash(sub->url) ||
 		    starts_with_dot_dot_slash(sub->url)) {
-			url = compute_submodule_clone_url(sub->url);
+			url = compute_submodule_clone_url(sub->url, NULL, 0);
 			need_free_url = 1;
 		} else
 			url = sub->url;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v2 2/9] submodule--helper: refactor resolve_relative_url() helper
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
  2021-08-05  7:40   ` [GSoC] [PATCH v2 1/9] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
@ 2021-08-05  7:40   ` Atharva Raykar
  2021-08-05 20:13     ` Junio C Hamano
  2021-08-05  7:40   ` [GSoC] [PATCH v2 3/9] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
                     ` (7 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:40 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Refactor the helper function to resolve a relative url, by reusing the
existing `compute_submodule_clone_url()` function.

`compute_submodule_clone_url()` performs the same work that
`resolve_relative_url()` is doing, so we eliminate this code repetition
by moving the former function's definition up, and calling it inside
`resolve_relative_url()`.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 61 +++++++++++++++----------------------
 1 file changed, 25 insertions(+), 36 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2d2d8ac637..f4b496bac6 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -199,33 +199,46 @@ static char *relative_url(const char *remote_url,
 	return strbuf_detach(&sb, NULL);
 }
 
+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
+{
+	char *remoteurl, *relurl;
+	char *remote = get_default_remote();
+	struct strbuf remotesb = STRBUF_INIT;
+
+	strbuf_addf(&remotesb, "remote.%s.url", remote);
+	if (git_config_get_string(remotesb.buf, &remoteurl)) {
+		if (!quiet)
+			warning(_("could not look up configuration '%s'. "
+				  "Assuming this repository is its own "
+				  "authoritative upstream."),
+				remotesb.buf);
+		remoteurl = xgetcwd();
+	}
+	relurl = relative_url(remoteurl, rel_url, up_path);
+
+	free(remote);
+	free(remoteurl);
+	strbuf_release(&remotesb);
+
+	return relurl;
+}
+
 static int resolve_relative_url(int argc, const char **argv, const char *prefix)
 {
-	char *remoteurl = NULL;
-	char *remote = get_default_remote();
 	const char *up_path = NULL;
 	char *res;
 	const char *url;
-	struct strbuf sb = STRBUF_INIT;
 
 	if (argc != 2 && argc != 3)
 		die("resolve-relative-url only accepts one or two arguments");
 
 	url = argv[1];
-	strbuf_addf(&sb, "remote.%s.url", remote);
-	free(remote);
-
-	if (git_config_get_string(sb.buf, &remoteurl))
-		/* the repository is its own authoritative upstream */
-		remoteurl = xgetcwd();
-
 	if (argc == 3)
 		up_path = argv[2];
 
-	res = relative_url(remoteurl, url, up_path);
+	res = compute_submodule_clone_url(url, up_path, 1);
 	puts(res);
 	free(res);
-	free(remoteurl);
 	return 0;
 }
 
@@ -590,30 +603,6 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
-{
-	char *remoteurl, *relurl;
-	char *remote = get_default_remote();
-	struct strbuf remotesb = STRBUF_INIT;
-
-	strbuf_addf(&remotesb, "remote.%s.url", remote);
-	if (git_config_get_string(remotesb.buf, &remoteurl)) {
-		if (!quiet)
-			warning(_("could not look up configuration '%s'. "
-				  "Assuming this repository is its own "
-				  "authoritative upstream."),
-				remotesb.buf);
-		remoteurl = xgetcwd();
-	}
-	relurl = relative_url(remoteurl, rel_url, up_path);
-
-	free(remote);
-	free(remoteurl);
-	strbuf_release(&remotesb);
-
-	return relurl;
-}
-
 struct init_cb {
 	const char *prefix;
 	unsigned int flags;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v2 3/9] submodule--helper: remove repeated code in sync_submodule()
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
  2021-08-05  7:40   ` [GSoC] [PATCH v2 1/9] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
  2021-08-05  7:40   ` [GSoC] [PATCH v2 2/9] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
@ 2021-08-05  7:40   ` Atharva Raykar
  2021-08-05 20:20     ` Junio C Hamano
  2021-08-05  7:40   ` [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c Atharva Raykar
                     ` (6 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:40 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

This part of `sync_submodule()` is doing the same thing that
`compute_submodule_clone_url()` is doing. Let's reuse that helper here.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f4b496bac6..9b676c12f8 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,
 	if (sub && sub->url) {
 		if (starts_with_dot_dot_slash(sub->url) ||
 		    starts_with_dot_slash(sub->url)) {
-			char *remote_url, *up_path;
-			char *remote = get_default_remote();
-			strbuf_addf(&sb, "remote.%s.url", remote);
-
-			if (git_config_get_string(sb.buf, &remote_url))
-				remote_url = xgetcwd();
-
-			up_path = get_up_path(path);
-			sub_origin_url = relative_url(remote_url, sub->url, up_path);
-			super_config_url = relative_url(remote_url, sub->url, NULL);
-
-			free(remote);
+			char *up_path = get_up_path(path);
+			sub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);
+			super_config_url = compute_submodule_clone_url(sub->url, NULL, 1);
 			free(up_path);
-			free(remote_url);
 		} else {
 			sub_origin_url = xstrdup(sub->url);
 			super_config_url = xstrdup(sub->url);
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
                     ` (2 preceding siblings ...)
  2021-08-05  7:40   ` [GSoC] [PATCH v2 3/9] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
@ 2021-08-05  7:40   ` Atharva Raykar
  2021-08-05 20:37     ` Junio C Hamano
  2021-08-05  7:40   ` [GSoC] [PATCH v2 5/9] submodule--helper: remove constness of sm_path Atharva Raykar
                     ` (5 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:40 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine, Shourya Shukla

These functions can be useful to other parts of Git. Let's move them to
dir.c, while renaming them to be make their functionality more explicit.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <shouryashukla.oo@gmail.com>
---
 builtin/clone.c | 118 +-----------------------------------------------
 dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++
 dir.h           |   3 ++
 3 files changed, 119 insertions(+), 116 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 66fe66679c..b9b59a838f 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -217,120 +217,6 @@ static char *get_repo_path(const char *repo, int *is_bundle)
 	return canon;
 }
 
-static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
-{
-	const char *end = repo + strlen(repo), *start, *ptr;
-	size_t len;
-	char *dir;
-
-	/*
-	 * Skip scheme.
-	 */
-	start = strstr(repo, "://");
-	if (start == NULL)
-		start = repo;
-	else
-		start += 3;
-
-	/*
-	 * Skip authentication data. The stripping does happen
-	 * greedily, such that we strip up to the last '@' inside
-	 * the host part.
-	 */
-	for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
-		if (*ptr == '@')
-			start = ptr + 1;
-	}
-
-	/*
-	 * Strip trailing spaces, slashes and /.git
-	 */
-	while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
-		end--;
-	if (end - start > 5 && is_dir_sep(end[-5]) &&
-	    !strncmp(end - 4, ".git", 4)) {
-		end -= 5;
-		while (start < end && is_dir_sep(end[-1]))
-			end--;
-	}
-
-	/*
-	 * Strip trailing port number if we've got only a
-	 * hostname (that is, there is no dir separator but a
-	 * colon). This check is required such that we do not
-	 * strip URI's like '/foo/bar:2222.git', which should
-	 * result in a dir '2222' being guessed due to backwards
-	 * compatibility.
-	 */
-	if (memchr(start, '/', end - start) == NULL
-	    && memchr(start, ':', end - start) != NULL) {
-		ptr = end;
-		while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
-			ptr--;
-		if (start < ptr && ptr[-1] == ':')
-			end = ptr - 1;
-	}
-
-	/*
-	 * Find last component. To remain backwards compatible we
-	 * also regard colons as path separators, such that
-	 * cloning a repository 'foo:bar.git' would result in a
-	 * directory 'bar' being guessed.
-	 */
-	ptr = end;
-	while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
-		ptr--;
-	start = ptr;
-
-	/*
-	 * Strip .{bundle,git}.
-	 */
-	len = end - start;
-	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
-
-	if (!len || (len == 1 && *start == '/'))
-		die(_("No directory name could be guessed.\n"
-		      "Please specify a directory on the command line"));
-
-	if (is_bare)
-		dir = xstrfmt("%.*s.git", (int)len, start);
-	else
-		dir = xstrndup(start, len);
-	/*
-	 * Replace sequences of 'control' characters and whitespace
-	 * with one ascii space, remove leading and trailing spaces.
-	 */
-	if (*dir) {
-		char *out = dir;
-		int prev_space = 1 /* strip leading whitespace */;
-		for (end = dir; *end; ++end) {
-			char ch = *end;
-			if ((unsigned char)ch < '\x20')
-				ch = '\x20';
-			if (isspace(ch)) {
-				if (prev_space)
-					continue;
-				prev_space = 1;
-			} else
-				prev_space = 0;
-			*out++ = ch;
-		}
-		*out = '\0';
-		if (out > dir && prev_space)
-			out[-1] = '\0';
-	}
-	return dir;
-}
-
-static void strip_trailing_slashes(char *dir)
-{
-	char *end = dir + strlen(dir);
-
-	while (dir < end - 1 && is_dir_sep(end[-1]))
-		end--;
-	*end = '\0';
-}
-
 static int add_one_reference(struct string_list_item *item, void *cb_data)
 {
 	struct strbuf err = STRBUF_INIT;
@@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	if (argc == 2)
 		dir = xstrdup(argv[1]);
 	else
-		dir = guess_dir_name(repo_name, is_bundle, option_bare);
-	strip_trailing_slashes(dir);
+		dir = guess_dir_name_from_git_url(repo_name, is_bundle, option_bare);
+	strip_dir_trailing_slashes(dir);
 
 	dest_exists = path_exists(dir);
 	if (dest_exists && !is_empty_dir(dir))
diff --git a/dir.c b/dir.c
index 03c4d21267..84b47c4dbc 100644
--- a/dir.c
+++ b/dir.c
@@ -2970,6 +2970,120 @@ int is_empty_dir(const char *path)
 	return ret;
 }
 
+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare)
+{
+	const char *end = repo + strlen(repo), *start, *ptr;
+	size_t len;
+	char *dir;
+
+	/*
+	 * Skip scheme.
+	 */
+	start = strstr(repo, "://");
+	if (start == NULL)
+		start = repo;
+	else
+		start += 3;
+
+	/*
+	 * Skip authentication data. The stripping does happen
+	 * greedily, such that we strip up to the last '@' inside
+	 * the host part.
+	 */
+	for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
+		if (*ptr == '@')
+			start = ptr + 1;
+	}
+
+	/*
+	 * Strip trailing spaces, slashes and /.git
+	 */
+	while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
+		end--;
+	if (end - start > 5 && is_dir_sep(end[-5]) &&
+	    !strncmp(end - 4, ".git", 4)) {
+		end -= 5;
+		while (start < end && is_dir_sep(end[-1]))
+			end--;
+	}
+
+	/*
+	 * Strip trailing port number if we've got only a
+	 * hostname (that is, there is no dir separator but a
+	 * colon). This check is required such that we do not
+	 * strip URI's like '/foo/bar:2222.git', which should
+	 * result in a dir '2222' being guessed due to backwards
+	 * compatibility.
+	 */
+	if (memchr(start, '/', end - start) == NULL
+	    && memchr(start, ':', end - start) != NULL) {
+		ptr = end;
+		while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
+			ptr--;
+		if (start < ptr && ptr[-1] == ':')
+			end = ptr - 1;
+	}
+
+	/*
+	 * Find last component. To remain backwards compatible we
+	 * also regard colons as path separators, such that
+	 * cloning a repository 'foo:bar.git' would result in a
+	 * directory 'bar' being guessed.
+	 */
+	ptr = end;
+	while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
+		ptr--;
+	start = ptr;
+
+	/*
+	 * Strip .{bundle,git}.
+	 */
+	len = end - start;
+	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
+
+	if (!len || (len == 1 && *start == '/'))
+		die(_("No directory name could be guessed.\n"
+		      "Please specify a directory on the command line"));
+
+	if (is_bare)
+		dir = xstrfmt("%.*s.git", (int)len, start);
+	else
+		dir = xstrndup(start, len);
+	/*
+	 * Replace sequences of 'control' characters and whitespace
+	 * with one ascii space, remove leading and trailing spaces.
+	 */
+	if (*dir) {
+		char *out = dir;
+		int prev_space = 1 /* strip leading whitespace */;
+		for (end = dir; *end; ++end) {
+			char ch = *end;
+			if ((unsigned char)ch < '\x20')
+				ch = '\x20';
+			if (isspace(ch)) {
+				if (prev_space)
+					continue;
+				prev_space = 1;
+			} else
+				prev_space = 0;
+			*out++ = ch;
+		}
+		*out = '\0';
+		if (out > dir && prev_space)
+			out[-1] = '\0';
+	}
+	return dir;
+}
+
+void strip_dir_trailing_slashes(char *dir)
+{
+	char *end = dir + strlen(dir);
+
+	while (dir < end - 1 && is_dir_sep(end[-1]))
+		end--;
+	*end = '\0';
+}
+
 static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
 {
 	DIR *dir;
diff --git a/dir.h b/dir.h
index b3e1a54a97..76441dde2d 100644
--- a/dir.h
+++ b/dir.h
@@ -453,6 +453,9 @@ static inline int is_dot_or_dotdot(const char *name)
 
 int is_empty_dir(const char *dir);
 
+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare);
+void strip_dir_trailing_slashes(char *dir);
+
 void setup_standard_excludes(struct dir_struct *dir);
 
 char *get_sparse_checkout_filename(void);
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v2 5/9] submodule--helper: remove constness of sm_path
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
                     ` (3 preceding siblings ...)
  2021-08-05  7:40   ` [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c Atharva Raykar
@ 2021-08-05  7:40   ` Atharva Raykar
  2021-08-05 20:40     ` Junio C Hamano
  2021-08-05  7:40   ` [GSoC] [PATCH v2 6/9] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
                     ` (4 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:40 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

This is needed so that it can be modified by normalize_path_copy() in
the next patch.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 9b676c12f8..99aabf1078 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2748,7 +2748,7 @@ struct add_data {
 	const char *prefix;
 	const char *branch;
 	const char *reference_path;
-	const char *sm_path;
+	char *sm_path;
 	const char *sm_name;
 	const char *repo;
 	const char *realrepo;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v2 6/9] submodule--helper: convert the bulk of cmd_add() to C
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
                     ` (4 preceding siblings ...)
  2021-08-05  7:40   ` [GSoC] [PATCH v2 5/9] submodule--helper: remove constness of sm_path Atharva Raykar
@ 2021-08-05  7:40   ` Atharva Raykar
  2021-08-06  1:14     ` Đoàn Trần Công Danh
  2021-08-05  7:40   ` [GSoC] [PATCH v2 7/9] submodule--helper: remove add-clone subcommand Atharva Raykar
                     ` (3 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:40 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Introduce the 'add' subcommand to `submodule--helper.c` that does all
the work 'submodule add' past the parsing of flags.

As with the previous conversions, this is meant to be a faithful
conversion with no modification to the behaviour of `submodule add`.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Helped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
Based-on-patch-by: Shourya Shukla <periperidip@gmail.com>
Based-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>
---
 builtin/submodule--helper.c | 160 ++++++++++++++++++++++++++++++++++++
 git-submodule.sh            |  96 +---------------------
 2 files changed, 162 insertions(+), 94 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 99aabf1078..05ae9ebe50 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3046,6 +3046,165 @@ static int add_config(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+static void die_on_index_match(const char *path, int force)
+{
+	struct pathspec ps;
+	const char *args[] = { path, NULL };
+	parse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);
+
+	if (read_cache_preload(NULL) < 0)
+		die(_("index file corrupt"));
+
+	if (ps.nr) {
+		int i;
+		char *ps_matched = xcalloc(ps.nr, 1);
+
+		/* TODO: audit for interaction with sparse-index. */
+		ensure_full_index(&the_index);
+
+		/*
+		 * Since there is only one pathspec, we just need
+		 * need to check ps_matched[0] to know if a cache
+		 * entry matched.
+		 */
+		for (i = 0; i < active_nr; i++) {
+			ce_path_match(&the_index, active_cache[i], &ps,
+				      ps_matched);
+
+			if (ps_matched[0]) {
+				if (!force)
+					die(_("'%s' already exists in the index"),
+					    path);
+				if (!S_ISGITLINK(active_cache[i]->ce_mode))
+					die(_("'%s' already exists in the index "
+					      "and is not a submodule"), path);
+				break;
+			}
+		}
+		free(ps_matched);
+	}
+}
+
+static void die_on_repo_without_commits(const char *path)
+{
+	struct strbuf sb = STRBUF_INIT;
+	strbuf_addstr(&sb, path);
+	if (is_nonbare_repository_dir(&sb)) {
+		struct object_id oid;
+		if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
+			die(_("'%s' does not have a commit checked out"), path);
+	}
+}
+
+static int module_add(int argc, const char **argv, const char *prefix)
+{
+	int force = 0, quiet = 0, progress = 0, dissociate = 0;
+	struct add_data add_data = ADD_DATA_INIT;
+
+	struct option options[] = {
+		OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
+			   N_("branch of repository to add as submodule")),
+		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
+			   PARSE_OPT_NOCOMPLETE),
+		OPT__QUIET(&quiet, N_("print only error messages")),
+		OPT_BOOL(0, "progress", &progress, N_("force cloning progress")),
+		OPT_STRING(0, "reference", &add_data.reference_path, N_("repository"),
+			   N_("reference repository")),
+		OPT_BOOL(0, "dissociate", &dissociate, N_("borrow the objects from reference repositories")),
+		OPT_STRING(0, "name", &add_data.sm_name, N_("name"),
+			   N_("sets the submodule’s name to the given string "
+			      "instead of defaulting to its path")),
+		OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
+		OPT_END()
+	};
+
+	const char *const usage[] = {
+		N_("git submodule--helper add [<options>] [--] <repository> [<path>]"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, options, usage, 0);
+
+	if (!is_writing_gitmodules_ok())
+		die(_("please make sure that the .gitmodules file is in the working tree"));
+
+	if (prefix && *prefix &&
+	    add_data.reference_path && !is_absolute_path(add_data.reference_path))
+		add_data.reference_path = xstrfmt("%s%s", prefix, add_data.reference_path);
+
+	if (argc == 0 || argc > 2)
+		usage_with_options(usage, options);
+
+	add_data.repo = argv[0];
+	if (argc == 1)
+		add_data.sm_path = guess_dir_name_from_git_url(add_data.repo, 0, 0);
+	else
+		add_data.sm_path = xstrdup(argv[1]);
+
+	if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
+		add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
+
+	if (starts_with_dot_dot_slash(add_data.repo) ||
+	    starts_with_dot_slash(add_data.repo)) {
+		if (prefix)
+			die(_("Relative path can only be used from the toplevel "
+			      "of the working tree"));
+
+		/* dereference source url relative to parent's url */
+		add_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);
+	} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {
+		add_data.realrepo = add_data.repo;
+	} else {
+		die(_("repo URL: '%s' must be absolute or begin with ./|../"),
+		    add_data.repo);
+	}
+
+	/*
+	 * normalize path:
+	 * multiple //; leading ./; /./; /../;
+	 */
+	normalize_path_copy(add_data.sm_path, add_data.sm_path);
+	strip_dir_trailing_slashes(add_data.sm_path);
+
+	die_on_index_match(add_data.sm_path, force);
+	die_on_repo_without_commits(add_data.sm_path);
+
+	if (!force) {
+		int exit_code = -1;
+		struct strbuf sb = STRBUF_INIT;
+		struct child_process cp = CHILD_PROCESS_INIT;
+		cp.git_cmd = 1;
+		cp.no_stdout = 1;
+		strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
+			     "--no-warn-embedded-repo", add_data.sm_path, NULL);
+		if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
+			strbuf_complete_line(&sb);
+			fputs(sb.buf, stderr);
+			return exit_code;
+		}
+		strbuf_release(&sb);
+	}
+
+	if(!add_data.sm_name)
+		add_data.sm_name = add_data.sm_path;
+
+	if (check_submodule_name(add_data.sm_name))
+		die(_("'%s' is not a valid submodule name"), add_data.sm_name);
+
+	add_data.prefix = prefix;
+	add_data.force = !!force;
+	add_data.quiet = !!quiet;
+	add_data.progress = !!progress;
+	add_data.dissociate = !!dissociate;
+
+	if (add_submodule(&add_data))
+		return 1;
+	configure_added_submodule(&add_data);
+	free(add_data.sm_path);
+
+	return 0;
+}
+
 #define SUPPORT_SUPER_PREFIX (1<<0)
 
 struct cmd_struct {
@@ -3060,6 +3219,7 @@ static struct cmd_struct commands[] = {
 	{"clone", module_clone, 0},
 	{"add-clone", add_clone, 0},
 	{"add-config", add_config, 0},
+	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
 	{"update-clone", update_clone, 0},
 	{"ensure-core-worktree", ensure_core_worktree, 0},
diff --git a/git-submodule.sh b/git-submodule.sh
index 8c219ef382..1070540525 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -145,104 +145,12 @@ cmd_add()
 		shift
 	done
 
-	if ! git submodule--helper config --check-writeable >/dev/null 2>&1
+	if test -z "$1"
 	then
-		 die "fatal: $(eval_gettext "please make sure that the .gitmodules file is in the working tree")"
-	fi
-
-	if test -n "$reference_path"
-	then
-		is_absolute_path "$reference_path" ||
-		reference_path="$wt_prefix$reference_path"
-
-		reference="--reference=$reference_path"
-	fi
-
-	repo=$1
-	sm_path=$2
-
-	if test -z "$sm_path"; then
-		sm_path=$(printf '%s\n' "$repo" |
-			sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
-	fi
-
-	if test -z "$repo" || test -z "$sm_path"; then
 		usage
 	fi
 
-	is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
-
-	# assure repo is absolute or relative to parent
-	case "$repo" in
-	./*|../*)
-		test -z "$wt_prefix" ||
-		die "fatal: $(gettext "Relative path can only be used from the toplevel of the working tree")"
-
-		# dereference source url relative to parent's url
-		realrepo=$(git submodule--helper resolve-relative-url "$repo") || exit
-		;;
-	*:*|/*)
-		# absolute url
-		realrepo=$repo
-		;;
-	*)
-		die "fatal: $(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
-	;;
-	esac
-
-	# normalize path:
-	# multiple //; leading ./; /./; /../; trailing /
-	sm_path=$(printf '%s/\n' "$sm_path" |
-		sed -e '
-			s|//*|/|g
-			s|^\(\./\)*||
-			s|/\(\./\)*|/|g
-			:start
-			s|\([^/]*\)/\.\./||
-			tstart
-			s|/*$||
-		')
-	if test -z "$force"
-	then
-		git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
-		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index")"
-	else
-		git ls-files -s "$sm_path" | sane_grep -v "^160000" > /dev/null 2>&1 &&
-		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
-	fi
-
-	if test -d "$sm_path" &&
-		test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null)
-	then
-	    git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null ||
-	    die "fatal: $(eval_gettext "'\$sm_path' does not have a commit checked out")"
-	fi
-
-	if test -z "$force"
-	then
-	    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" 2>&1 >/dev/null)
-	    res=$?
-	    if test $res -ne 0
-	    then
-		 echo >&2 "$dryerr"
-		 exit $res
-	    fi
-	fi
-
-	if test -n "$custom_name"
-	then
-		sm_name="$custom_name"
-	else
-		sm_name="$sm_path"
-	fi
-
-	if ! git submodule--helper check-name "$sm_name"
-	then
-		die "fatal: $(eval_gettext "'$sm_name' is not a valid submodule name")"
-	fi
-
-	git submodule--helper add-clone ${GIT_QUIET:+--quiet} ${force:+"--force"} ${progress:+"--progress"} ${branch:+--branch "$branch"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit
-	git submodule--helper add-config ${force:+--force} ${branch:+--branch "$branch"} --url "$repo" --resolved-url "$realrepo" --path "$sm_path" --name "$sm_name"
+	git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper add ${GIT_QUIET:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@"
 }
 
 #
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v2 7/9] submodule--helper: remove add-clone subcommand
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
                     ` (5 preceding siblings ...)
  2021-08-05  7:40   ` [GSoC] [PATCH v2 6/9] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
@ 2021-08-05  7:40   ` Atharva Raykar
  2021-08-05  7:40   ` [GSoC] [PATCH v2 8/9] submodule--helper: remove add-config subcommand Atharva Raykar
                     ` (2 subsequent siblings)
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:40 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

We no longer need this subcommand, as all of its functionality is being
called by the newly-introduced `module_add()` directly within C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 60 -------------------------------------
 1 file changed, 60 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 05ae9ebe50..700cc8bbeb 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2860,65 +2860,6 @@ static int add_submodule(const struct add_data *add_data)
 	return 0;
 }
 
-static int add_clone(int argc, const char **argv, const char *prefix)
-{
-	int force = 0, quiet = 0, dissociate = 0, progress = 0;
-	struct add_data add_data = ADD_DATA_INIT;
-
-	struct option options[] = {
-		OPT_STRING('b', "branch", &add_data.branch,
-			   N_("branch"),
-			   N_("branch of repository to checkout on cloning")),
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("alternative anchor for relative paths")),
-		OPT_STRING(0, "path", &add_data.sm_path,
-			   N_("path"),
-			   N_("where the new submodule will be cloned to")),
-		OPT_STRING(0, "name", &add_data.sm_name,
-			   N_("string"),
-			   N_("name of the new submodule")),
-		OPT_STRING(0, "url", &add_data.realrepo,
-			   N_("string"),
-			   N_("url where to clone the submodule from")),
-		OPT_STRING(0, "reference", &add_data.reference_path,
-			   N_("repo"),
-			   N_("reference repository")),
-		OPT_BOOL(0, "dissociate", &dissociate,
-			 N_("use --reference only while cloning")),
-		OPT_INTEGER(0, "depth", &add_data.depth,
-			    N_("depth for shallow clones")),
-		OPT_BOOL(0, "progress", &progress,
-			 N_("force cloning progress")),
-		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT__QUIET(&quiet, "suppress output for cloning a submodule"),
-		OPT_END()
-	};
-
-	const char *const usage[] = {
-		N_("git submodule--helper add-clone [<options>...] "
-		   "--url <url> --path <path> --name <name>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (argc != 0)
-		usage_with_options(usage, options);
-
-	add_data.prefix = prefix;
-	add_data.progress = !!progress;
-	add_data.dissociate = !!dissociate;
-	add_data.force = !!force;
-	add_data.quiet = !!quiet;
-
-	if (add_submodule(&add_data))
-		return 1;
-
-	return 0;
-}
-
 static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
 {
 	char *key;
@@ -3217,7 +3158,6 @@ static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
 	{"name", module_name, 0},
 	{"clone", module_clone, 0},
-	{"add-clone", add_clone, 0},
 	{"add-config", add_config, 0},
 	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v2 8/9] submodule--helper: remove add-config subcommand
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
                     ` (6 preceding siblings ...)
  2021-08-05  7:40   ` [GSoC] [PATCH v2 7/9] submodule--helper: remove add-clone subcommand Atharva Raykar
@ 2021-08-05  7:40   ` Atharva Raykar
  2021-08-05  7:40   ` [GSoC] [PATCH v2 9/9] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
  2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:40 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Also no longer needed is this subcommand, as all of its functionality is
being called by the newly-introduced `module_add()` directly within C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 49 -------------------------------------
 1 file changed, 49 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 700cc8bbeb..da83e8e2a5 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2939,54 +2939,6 @@ static void configure_added_submodule(struct add_data *add_data)
 	}
 }
 
-static int add_config(int argc, const char **argv, const char *prefix)
-{
-	int force = 0;
-	struct add_data add_data = ADD_DATA_INIT;
-
-	struct option options[] = {
-		OPT_STRING('b', "branch", &add_data.branch,
-			   N_("branch"),
-			   N_("branch of repository to store in "
-			      "the submodule configuration")),
-		OPT_STRING(0, "url", &add_data.repo,
-			   N_("string"),
-			   N_("url to clone submodule from")),
-		OPT_STRING(0, "resolved-url", &add_data.realrepo,
-			   N_("string"),
-			   N_("url to clone the submodule from, after it has "
-			      "been dereferenced relative to parent's url, "
-			      "in the case where <url> is a relative url")),
-		OPT_STRING(0, "path", &add_data.sm_path,
-			   N_("path"),
-			   N_("where the new submodule will be cloned to")),
-		OPT_STRING(0, "name", &add_data.sm_name,
-			   N_("string"),
-			   N_("name of the new submodule")),
-		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_END()
-	};
-
-	const char *const usage[] = {
-		N_("git submodule--helper add-config "
-		   "[--force|-f] [--branch|-b <branch>] "
-		   "--url <url> --resolved-url <resolved-url> "
-		   "--path <path> --name <name>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (argc)
-		usage_with_options(usage, options);
-
-	add_data.force = !!force;
-	configure_added_submodule(&add_data);
-
-	return 0;
-}
-
 static void die_on_index_match(const char *path, int force)
 {
 	struct pathspec ps;
@@ -3158,7 +3110,6 @@ static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
 	{"name", module_name, 0},
 	{"clone", module_clone, 0},
-	{"add-config", add_config, 0},
 	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
 	{"update-clone", update_clone, 0},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v2 9/9] submodule--helper: remove resolve-relative-url subcommand
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
                     ` (7 preceding siblings ...)
  2021-08-05  7:40   ` [GSoC] [PATCH v2 8/9] submodule--helper: remove add-config subcommand Atharva Raykar
@ 2021-08-05  7:40   ` Atharva Raykar
  2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-05  7:40 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

The shell subcommand `resolve-relative-url` is no longer required, as
its last caller has been removed when it was converted to C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 20 --------------------
 1 file changed, 20 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index da83e8e2a5..514891a22f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -223,25 +223,6 @@ static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat
 	return relurl;
 }
 
-static int resolve_relative_url(int argc, const char **argv, const char *prefix)
-{
-	const char *up_path = NULL;
-	char *res;
-	const char *url;
-
-	if (argc != 2 && argc != 3)
-		die("resolve-relative-url only accepts one or two arguments");
-
-	url = argv[1];
-	if (argc == 3)
-		up_path = argv[2];
-
-	res = compute_submodule_clone_url(url, up_path, 1);
-	puts(res);
-	free(res);
-	return 0;
-}
-
 static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)
 {
 	char *remoteurl, *res;
@@ -3115,7 +3096,6 @@ static struct cmd_struct commands[] = {
 	{"update-clone", update_clone, 0},
 	{"ensure-core-worktree", ensure_core_worktree, 0},
 	{"relative-path", resolve_relative_path, 0},
-	{"resolve-relative-url", resolve_relative_url, 0},
 	{"resolve-relative-url-test", resolve_relative_url_test, 0},
 	{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
 	{"init", module_init, SUPPORT_SUPER_PREFIX},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v2 1/9] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-05  7:40   ` [GSoC] [PATCH v2 1/9] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
@ 2021-08-05 20:05     ` Junio C Hamano
  0 siblings, 0 replies; 78+ messages in thread
From: Junio C Hamano @ 2021-08-05 20:05 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Atharva Raykar <raykar.ath@gmail.com> writes:

> -static char *compute_submodule_clone_url(const char *rel_url)
> +static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
>  {
>  	char *remoteurl, *relurl;
>  	char *remote = get_default_remote();
> @@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)
>  
>  	strbuf_addf(&remotesb, "remote.%s.url", remote);
>  	if (git_config_get_string(remotesb.buf, &remoteurl)) {
> -		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
> +		if (!quiet)
> +			warning(_("could not look up configuration '%s'. "
> +				  "Assuming this repository is its own "
> +				  "authoritative upstream."),
> +				remotesb.buf);
>  		remoteurl = xgetcwd();
>  	}
> -	relurl = relative_url(remoteurl, rel_url, NULL);
> +	relurl = relative_url(remoteurl, rel_url, up_path);

OK, so we can optionally operate silently, and also tell
relative_url the path the URL should be made relative to.

Existing callers, of course, should pass NULL and 0 as these
optional features are new, as we can see below.

>  	free(remote);
>  	free(remoteurl);
> @@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,
>  		if (starts_with_dot_dot_slash(url) ||
>  		    starts_with_dot_slash(url)) {
>  			char *oldurl = url;
> -			url = compute_submodule_clone_url(oldurl);
> +			url = compute_submodule_clone_url(oldurl, NULL, 0);
>  			free(oldurl);
>  		}
>  
> @@ -2134,7 +2138,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
>  	if (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {
>  		if (starts_with_dot_slash(sub->url) ||
>  		    starts_with_dot_dot_slash(sub->url)) {
> -			url = compute_submodule_clone_url(sub->url);
> +			url = compute_submodule_clone_url(sub->url, NULL, 0);
>  			need_free_url = 1;
>  		} else
>  			url = sub->url;

All makes sense.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v2 2/9] submodule--helper: refactor resolve_relative_url() helper
  2021-08-05  7:40   ` [GSoC] [PATCH v2 2/9] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
@ 2021-08-05 20:13     ` Junio C Hamano
  0 siblings, 0 replies; 78+ messages in thread
From: Junio C Hamano @ 2021-08-05 20:13 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Atharva Raykar <raykar.ath@gmail.com> writes:

> Refactor the helper function to resolve a relative url, by reusing the
> existing `compute_submodule_clone_url()` function.
>
> `compute_submodule_clone_url()` performs the same work that
> `resolve_relative_url()` is doing, so we eliminate this code repetition
> by moving the former function's definition up, and calling it inside
> `resolve_relative_url()`.

Looking good.

> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Shourya Shukla <periperidip@gmail.com>
> ---
>  builtin/submodule--helper.c | 61 +++++++++++++++----------------------
>  1 file changed, 25 insertions(+), 36 deletions(-)

This step is easier to see with "show --patience --color-moved" to
see that compute_submodule_clone_url() has only been moved without
any change.  And the actual change is much smaller than what the
diffstat suggests above (11 lines lost, 1 line updated, if I counted
correctly).

Nicely done.


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v2 3/9] submodule--helper: remove repeated code in sync_submodule()
  2021-08-05  7:40   ` [GSoC] [PATCH v2 3/9] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
@ 2021-08-05 20:20     ` Junio C Hamano
  0 siblings, 0 replies; 78+ messages in thread
From: Junio C Hamano @ 2021-08-05 20:20 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Atharva Raykar <raykar.ath@gmail.com> writes:

> This part of `sync_submodule()` is doing the same thing that
> `compute_submodule_clone_url()` is doing. Let's reuse that helper here.
>
> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Shourya Shukla <periperidip@gmail.com>
> ---
>  builtin/submodule--helper.c | 16 +++-------------
>  1 file changed, 3 insertions(+), 13 deletions(-)

The original used the result of get_default_remote() twice before
freeing it, but now all that code to allocate and free remote is
contained in compute_submodule_clone_url(), which mean swe allocate,
use, and free twice.  In exchange, our logic here works at a higher
level of abstraction, which is a big plus.

Nice.

> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index f4b496bac6..9b676c12f8 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,
>  	if (sub && sub->url) {
>  		if (starts_with_dot_dot_slash(sub->url) ||
>  		    starts_with_dot_slash(sub->url)) {
> -			char *remote_url, *up_path;
> -			char *remote = get_default_remote();
> -			strbuf_addf(&sb, "remote.%s.url", remote);
> -
> -			if (git_config_get_string(sb.buf, &remote_url))
> -				remote_url = xgetcwd();
> -
> -			up_path = get_up_path(path);
> -			sub_origin_url = relative_url(remote_url, sub->url, up_path);
> -			super_config_url = relative_url(remote_url, sub->url, NULL);
> -
> -			free(remote);
> +			char *up_path = get_up_path(path);
> +			sub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);
> +			super_config_url = compute_submodule_clone_url(sub->url, NULL, 1);
>  			free(up_path);
> -			free(remote_url);
>  		} else {
>  			sub_origin_url = xstrdup(sub->url);
>  			super_config_url = xstrdup(sub->url);

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c
  2021-08-05  7:40   ` [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c Atharva Raykar
@ 2021-08-05 20:37     ` Junio C Hamano
  2021-08-06 11:12       ` Atharva Raykar
  0 siblings, 1 reply; 78+ messages in thread
From: Junio C Hamano @ 2021-08-05 20:37 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine, Shourya Shukla

Atharva Raykar <raykar.ath@gmail.com> writes:

> These functions can be useful to other parts of Git. Let's move them to
> dir.c, while renaming them to be make their functionality more explicit.

Hmph, guess_dir_name_from_git_url() is not all that more clarifying
than the original, at least to me.  For a file-scope static helper,
it probably was good enough with a short name with no function doc,
but we should describe what it does in comments in dir.h and come up
with a suitable name, taking input from that description.

> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Shourya Shukla <shouryashukla.oo@gmail.com>
> ---
>  builtin/clone.c | 118 +-----------------------------------------------
>  dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++
>  dir.h           |   3 ++
>  3 files changed, 119 insertions(+), 116 deletions(-)

Again "show --color-moved" helps to see that these two helper
functions are moved across files without any change other than the
names, which is good.

> @@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  	if (argc == 2)
>  		dir = xstrdup(argv[1]);
>  	else
> -		dir = guess_dir_name(repo_name, is_bundle, option_bare);
> -	strip_trailing_slashes(dir);
> +		dir = guess_dir_name_from_git_url(repo_name, is_bundle, option_bare);
> +	strip_dir_trailing_slashes(dir);

So, what does this new public helper function guess?  The name of
the function says it guesses a directory name, but it is not just
any directory name, but a directory with some specific meaning.

Here repo_name has the URL the user gave "git clone", and even
though there are some code before this part that computed on the
variable, it hasn't been modified.  And "from_git_url" is a good way
to indicate that that is one of the input the function uses to guess
the name of "the directory with some unknown specific meaning".

I think this codepath wants the new directory to create as the
result of "git clone" operation in "dir".  So, even though I still
do not have a good answer to the earlier "this is not just any
directory but with some specific meaning---what is it?" question,
adjectives that are appropriate for the "directory" to answer it
may be along the lines of "new", "resulting", "cloned", etc.

> diff --git a/dir.h b/dir.h
> index b3e1a54a97..76441dde2d 100644
> --- a/dir.h
> +++ b/dir.h
> @@ -453,6 +453,9 @@ static inline int is_dot_or_dotdot(const char *name)
>  
>  int is_empty_dir(const char *dir);
>  

We would want docstring here for the function (and possibly rename
the function to clarify what kind of "dir" we are talking about).


> +char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare);
> +void strip_dir_trailing_slashes(char *dir);
> +
>  void setup_standard_excludes(struct dir_struct *dir);
>  
>  char *get_sparse_checkout_filename(void);

Thanks.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v2 5/9] submodule--helper: remove constness of sm_path
  2021-08-05  7:40   ` [GSoC] [PATCH v2 5/9] submodule--helper: remove constness of sm_path Atharva Raykar
@ 2021-08-05 20:40     ` Junio C Hamano
  2021-08-06 11:16       ` Atharva Raykar
  0 siblings, 1 reply; 78+ messages in thread
From: Junio C Hamano @ 2021-08-05 20:40 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Atharva Raykar <raykar.ath@gmail.com> writes:

> This is needed so that it can be modified by normalize_path_copy() in
> the next patch.

This is a hard-to-judge change.  With this alone, we cannot tell if
somebody has already looked at the member (and possibly saved the
pointer elsewhere) before "the next patch" starts modifying the
member in the struct.  It probably should be done in a single patch
to demonstrate why it is needed and how existing users of the field
are OK with this change.

>
> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Shourya Shukla <periperidip@gmail.com>
> ---
>  builtin/submodule--helper.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 9b676c12f8..99aabf1078 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2748,7 +2748,7 @@ struct add_data {
>  	const char *prefix;
>  	const char *branch;
>  	const char *reference_path;
> -	const char *sm_path;
> +	char *sm_path;
>  	const char *sm_name;
>  	const char *repo;
>  	const char *realrepo;

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule()
  2021-08-05  7:19 ` [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
@ 2021-08-06  0:53   ` Đoàn Trần Công Danh
  2021-08-06  9:06     ` Christian Couder
  0 siblings, 1 reply; 78+ messages in thread
From: Đoàn Trần Công Danh @ 2021-08-06  0:53 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: git, Ævar Arnfjörð Bjarmason, Emily Shaffer,
	Jonathan Nieder, Junio C Hamano, Christian Couder,
	Shourya Shukla, Kaartic Sivaraam, Eric Sunshine,
	Prathamesh Chavan, Rafael Silva

On 2021-08-05 12:49:11+0530, Atharva Raykar <raykar.ath@gmail.com> wrote:
> This part of `sync_submodule()` is doing the same thing that
> `compute_submodule_clone_url()` is doing. Let's reuse that helper here.
> 
> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Shourya Shukla <periperidip@gmail.com>
> ---
>  builtin/submodule--helper.c | 16 +++-------------
>  1 file changed, 3 insertions(+), 13 deletions(-)
> 
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index f4b496bac6..9b676c12f8 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,
>  	if (sub && sub->url) {
>  		if (starts_with_dot_dot_slash(sub->url) ||
>  		    starts_with_dot_slash(sub->url)) {
> -			char *remote_url, *up_path;
> -			char *remote = get_default_remote();
> -			strbuf_addf(&sb, "remote.%s.url", remote);
> -
> -			if (git_config_get_string(sb.buf, &remote_url))
> -				remote_url = xgetcwd();
> -
> -			up_path = get_up_path(path);
> -			sub_origin_url = relative_url(remote_url, sub->url, up_path);
> -			super_config_url = relative_url(remote_url, sub->url, NULL);
> -
> -			free(remote);
> +			char *up_path = get_up_path(path);
> +			sub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);
> +			super_config_url = compute_submodule_clone_url(sub->url, NULL, 1);

While previous patch is definitely a refactoring, this patch add small
overhead to the system, the new code will query (then free())
git_config_get_string() and/or xgetcwd() one more time in the second
compute_submodule_clone_url()

I think the abstraction overhead is not that big, though.

>  			free(up_path);
> -			free(remote_url);
>  		} else {
>  			sub_origin_url = xstrdup(sub->url);
>  			super_config_url = xstrdup(sub->url);
> -- 
> 2.32.0
> 

-- 
Danh

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v2 6/9] submodule--helper: convert the bulk of cmd_add() to C
  2021-08-05  7:40   ` [GSoC] [PATCH v2 6/9] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
@ 2021-08-06  1:14     ` Đoàn Trần Công Danh
  2021-08-06 11:33       ` Atharva Raykar
  0 siblings, 1 reply; 78+ messages in thread
From: Đoàn Trần Công Danh @ 2021-08-06  1:14 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: avarab, christian.couder, emilyshaffer, git, gitster, jrnieder,
	kaartic.sivaraam, pc44800, periperidip, rafaeloliveira.cs,
	sunshine

On 2021-08-05 13:10:51+0530, Atharva Raykar <raykar.ath@gmail.com> wrote:
> Introduce the 'add' subcommand to `submodule--helper.c` that does all
> the work 'submodule add' past the parsing of flags.
> 
> As with the previous conversions, this is meant to be a faithful
> conversion with no modification to the behaviour of `submodule add`.
> 
> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Helped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>
> Mentored-by: Shourya Shukla <periperidip@gmail.com>
> Based-on-patch-by: Shourya Shukla <periperidip@gmail.com>
> Based-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>
> ---
>  builtin/submodule--helper.c | 160 ++++++++++++++++++++++++++++++++++++
>  git-submodule.sh            |  96 +---------------------
>  2 files changed, 162 insertions(+), 94 deletions(-)
> 
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 99aabf1078..05ae9ebe50 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -3046,6 +3046,165 @@ static int add_config(int argc, const char **argv, const char *prefix)
>  	return 0;
>  }
>  
> +static void die_on_index_match(const char *path, int force)
> +{
> +	struct pathspec ps;
> +	const char *args[] = { path, NULL };
> +	parse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);
> +
> +	if (read_cache_preload(NULL) < 0)
> +		die(_("index file corrupt"));
> +
> +	if (ps.nr) {
> +		int i;
> +		char *ps_matched = xcalloc(ps.nr, 1);
> +
> +		/* TODO: audit for interaction with sparse-index. */
> +		ensure_full_index(&the_index);
> +
> +		/*
> +		 * Since there is only one pathspec, we just need
> +		 * need to check ps_matched[0] to know if a cache
> +		 * entry matched.
> +		 */
> +		for (i = 0; i < active_nr; i++) {
> +			ce_path_match(&the_index, active_cache[i], &ps,
> +				      ps_matched);
> +
> +			if (ps_matched[0]) {
> +				if (!force)
> +					die(_("'%s' already exists in the index"),
> +					    path);
> +				if (!S_ISGITLINK(active_cache[i]->ce_mode))
> +					die(_("'%s' already exists in the index "
> +					      "and is not a submodule"), path);
> +				break;
> +			}
> +		}
> +		free(ps_matched);
> +	}
> +}
> +
> +static void die_on_repo_without_commits(const char *path)
> +{
> +	struct strbuf sb = STRBUF_INIT;
> +	strbuf_addstr(&sb, path);
> +	if (is_nonbare_repository_dir(&sb)) {
> +		struct object_id oid;
> +		if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
> +			die(_("'%s' does not have a commit checked out"), path);
> +	}
> +}
> +
> +static int module_add(int argc, const char **argv, const char *prefix)
> +{
> +	int force = 0, quiet = 0, progress = 0, dissociate = 0;
> +	struct add_data add_data = ADD_DATA_INIT;
> +
> +	struct option options[] = {
> +		OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
> +			   N_("branch of repository to add as submodule")),
> +		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
> +			   PARSE_OPT_NOCOMPLETE),
> +		OPT__QUIET(&quiet, N_("print only error messages")),
> +		OPT_BOOL(0, "progress", &progress, N_("force cloning progress")),
> +		OPT_STRING(0, "reference", &add_data.reference_path, N_("repository"),
> +			   N_("reference repository")),
> +		OPT_BOOL(0, "dissociate", &dissociate, N_("borrow the objects from reference repositories")),
> +		OPT_STRING(0, "name", &add_data.sm_name, N_("name"),
> +			   N_("sets the submodule’s name to the given string "
> +			      "instead of defaulting to its path")),
> +		OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
> +		OPT_END()
> +	};
> +
> +	const char *const usage[] = {
> +		N_("git submodule--helper add [<options>] [--] <repository> [<path>]"),
> +		NULL
> +	};
> +
> +	argc = parse_options(argc, argv, prefix, options, usage, 0);
> +
> +	if (!is_writing_gitmodules_ok())
> +		die(_("please make sure that the .gitmodules file is in the working tree"));
> +
> +	if (prefix && *prefix &&
> +	    add_data.reference_path && !is_absolute_path(add_data.reference_path))
> +		add_data.reference_path = xstrfmt("%s%s", prefix, add_data.reference_path);
> +
> +	if (argc == 0 || argc > 2)
> +		usage_with_options(usage, options);
> +
> +	add_data.repo = argv[0];
> +	if (argc == 1)
> +		add_data.sm_path = guess_dir_name_from_git_url(add_data.repo, 0, 0);
> +	else
> +		add_data.sm_path = xstrdup(argv[1]);

add_data.sm_path is allocated in this block (regardless of legs).

> +	if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
> +		add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
> +
> +	if (starts_with_dot_dot_slash(add_data.repo) ||
> +	    starts_with_dot_slash(add_data.repo)) {
> +		if (prefix)
> +			die(_("Relative path can only be used from the toplevel "
> +			      "of the working tree"));
> +
> +		/* dereference source url relative to parent's url */
> +		add_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);
> +	} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {
> +		add_data.realrepo = add_data.repo;
> +	} else {
> +		die(_("repo URL: '%s' must be absolute or begin with ./|../"),
> +		    add_data.repo);
> +	}
> +
> +	/*
> +	 * normalize path:
> +	 * multiple //; leading ./; /./; /../;
> +	 */
> +	normalize_path_copy(add_data.sm_path, add_data.sm_path);
> +	strip_dir_trailing_slashes(add_data.sm_path);
> +
> +	die_on_index_match(add_data.sm_path, force);
> +	die_on_repo_without_commits(add_data.sm_path);
> +
> +	if (!force) {
> +		int exit_code = -1;
> +		struct strbuf sb = STRBUF_INIT;
> +		struct child_process cp = CHILD_PROCESS_INIT;
> +		cp.git_cmd = 1;
> +		cp.no_stdout = 1;
> +		strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
> +			     "--no-warn-embedded-repo", add_data.sm_path, NULL);
> +		if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
> +			strbuf_complete_line(&sb);
> +			fputs(sb.buf, stderr);
> +			return exit_code;

But, we don't free it when return from here.

> +		}
> +		strbuf_release(&sb);
> +	}
> +
> +	if(!add_data.sm_name)
> +		add_data.sm_name = add_data.sm_path;
> +
> +	if (check_submodule_name(add_data.sm_name))
> +		die(_("'%s' is not a valid submodule name"), add_data.sm_name);
> +
> +	add_data.prefix = prefix;
> +	add_data.force = !!force;
> +	add_data.quiet = !!quiet;
> +	add_data.progress = !!progress;
> +	add_data.dissociate = !!dissociate;
> +
> +	if (add_submodule(&add_data))
> +		return 1;

And here.

> +	configure_added_submodule(&add_data);
> +	free(add_data.sm_path);

However, it will be free()-d here, is it intended?

I think we may use UNLEAK above (for now) because we will exit process
after this function.

However, I anticipated we may need to do more stuffs after this
function in the future.

> +
> +	return 0;
> +}
> +
>  #define SUPPORT_SUPER_PREFIX (1<<0)
>  
>  struct cmd_struct {
> @@ -3060,6 +3219,7 @@ static struct cmd_struct commands[] = {
>  	{"clone", module_clone, 0},
>  	{"add-clone", add_clone, 0},
>  	{"add-config", add_config, 0},
> +	{"add", module_add, SUPPORT_SUPER_PREFIX},
>  	{"update-module-mode", module_update_module_mode, 0},
>  	{"update-clone", update_clone, 0},
>  	{"ensure-core-worktree", ensure_core_worktree, 0},
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 8c219ef382..1070540525 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -145,104 +145,12 @@ cmd_add()
>  		shift
>  	done
>  
> -	if ! git submodule--helper config --check-writeable >/dev/null 2>&1
> +	if test -z "$1"
>  	then
> -		 die "fatal: $(eval_gettext "please make sure that the .gitmodules file is in the working tree")"
> -	fi
> -
> -	if test -n "$reference_path"
> -	then
> -		is_absolute_path "$reference_path" ||
> -		reference_path="$wt_prefix$reference_path"
> -
> -		reference="--reference=$reference_path"
> -	fi
> -
> -	repo=$1
> -	sm_path=$2
> -
> -	if test -z "$sm_path"; then
> -		sm_path=$(printf '%s\n' "$repo" |
> -			sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
> -	fi
> -
> -	if test -z "$repo" || test -z "$sm_path"; then
>  		usage
>  	fi
>  
> -	is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
> -
> -	# assure repo is absolute or relative to parent
> -	case "$repo" in
> -	./*|../*)
> -		test -z "$wt_prefix" ||
> -		die "fatal: $(gettext "Relative path can only be used from the toplevel of the working tree")"
> -
> -		# dereference source url relative to parent's url
> -		realrepo=$(git submodule--helper resolve-relative-url "$repo") || exit
> -		;;
> -	*:*|/*)
> -		# absolute url
> -		realrepo=$repo
> -		;;
> -	*)
> -		die "fatal: $(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
> -	;;
> -	esac
> -
> -	# normalize path:
> -	# multiple //; leading ./; /./; /../; trailing /
> -	sm_path=$(printf '%s/\n' "$sm_path" |
> -		sed -e '
> -			s|//*|/|g
> -			s|^\(\./\)*||
> -			s|/\(\./\)*|/|g
> -			:start
> -			s|\([^/]*\)/\.\./||
> -			tstart
> -			s|/*$||
> -		')
> -	if test -z "$force"
> -	then
> -		git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
> -		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index")"
> -	else
> -		git ls-files -s "$sm_path" | sane_grep -v "^160000" > /dev/null 2>&1 &&
> -		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
> -	fi
> -
> -	if test -d "$sm_path" &&
> -		test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null)
> -	then
> -	    git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null ||
> -	    die "fatal: $(eval_gettext "'\$sm_path' does not have a commit checked out")"
> -	fi
> -
> -	if test -z "$force"
> -	then
> -	    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" 2>&1 >/dev/null)
> -	    res=$?
> -	    if test $res -ne 0
> -	    then
> -		 echo >&2 "$dryerr"
> -		 exit $res
> -	    fi
> -	fi
> -
> -	if test -n "$custom_name"
> -	then
> -		sm_name="$custom_name"
> -	else
> -		sm_name="$sm_path"
> -	fi
> -
> -	if ! git submodule--helper check-name "$sm_name"
> -	then
> -		die "fatal: $(eval_gettext "'$sm_name' is not a valid submodule name")"
> -	fi
> -
> -	git submodule--helper add-clone ${GIT_QUIET:+--quiet} ${force:+"--force"} ${progress:+"--progress"} ${branch:+--branch "$branch"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit
> -	git submodule--helper add-config ${force:+--force} ${branch:+--branch "$branch"} --url "$repo" --resolved-url "$realrepo" --path "$sm_path" --name "$sm_name"
> +	git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper add ${GIT_QUIET:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@"
>  }
>  
>  #
> -- 
> 2.32.0
> 

-- 
Danh

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule()
  2021-08-06  0:53   ` Đoàn Trần Công Danh
@ 2021-08-06  9:06     ` Christian Couder
  2021-08-06 10:06       ` Atharva Raykar
  2021-08-06 16:21       ` Junio C Hamano
  0 siblings, 2 replies; 78+ messages in thread
From: Christian Couder @ 2021-08-06  9:06 UTC (permalink / raw)
  To: Đoàn Trần Công Danh
  Cc: Atharva Raykar, git, Ævar Arnfjörð Bjarmason,
	Emily Shaffer, Jonathan Nieder, Junio C Hamano, Shourya Shukla,
	Kaartic Sivaraam, Eric Sunshine, Prathamesh Chavan, Rafael Silva

On Fri, Aug 6, 2021 at 2:54 AM Đoàn Trần Công Danh <congdanhqx@gmail.com> wrote:

> While previous patch is definitely a refactoring, this patch add small
> overhead to the system, the new code will query (then free())
> git_config_get_string() and/or xgetcwd() one more time in the second
> compute_submodule_clone_url()
>
> I think the abstraction overhead is not that big, though.

Yeah, Junio made basically the same comment. So it would be nice if
the commit message could mention we are adding a very small overhead
in exchange for code simplification (10 lines removed).

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule()
  2021-08-06  9:06     ` Christian Couder
@ 2021-08-06 10:06       ` Atharva Raykar
  2021-08-06 16:21       ` Junio C Hamano
  1 sibling, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 10:06 UTC (permalink / raw)
  To: Christian Couder
  Cc: Đoàn Trần Công Danh, git,
	Ævar Arnfjörð Bjarmason, Emily Shaffer,
	Jonathan Nieder, Junio C Hamano, Shourya Shukla,
	Kaartic Sivaraam, Eric Sunshine, Prathamesh Chavan, Rafael Silva


Christian Couder <christian.couder@gmail.com> writes:

> On Fri, Aug 6, 2021 at 2:54 AM Đoàn Trần Công Danh <congdanhqx@gmail.com> wrote:
>
>> While previous patch is definitely a refactoring, this patch add small
>> overhead to the system, the new code will query (then free())
>> git_config_get_string() and/or xgetcwd() one more time in the second
>> compute_submodule_clone_url()
>>
>> I think the abstraction overhead is not that big, though.
>
> Yeah, Junio made basically the same comment. So it would be nice if
> the commit message could mention we are adding a very small overhead
> in exchange for code simplification (10 lines removed).

Okay, that makes sense.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c
  2021-08-05 20:37     ` Junio C Hamano
@ 2021-08-06 11:12       ` Atharva Raykar
  2021-08-06 16:36         ` Junio C Hamano
  0 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 11:12 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine, Shourya Shukla


Junio C Hamano <gitster@pobox.com> writes:

> Atharva Raykar <raykar.ath@gmail.com> writes:
>
>> These functions can be useful to other parts of Git. Let's move them to
>> dir.c, while renaming them to be make their functionality more explicit.
>
> Hmph, guess_dir_name_from_git_url() is not all that more clarifying
> than the original, at least to me.  For a file-scope static helper,
> it probably was good enough with a short name with no function doc,
> but we should describe what it does in comments in dir.h and come up
> with a suitable name, taking input from that description.
>
> [...]
>
>> @@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>>  	if (argc == 2)
>>  		dir = xstrdup(argv[1]);
>>  	else
>> -		dir = guess_dir_name(repo_name, is_bundle, option_bare);
>> -	strip_trailing_slashes(dir);
>> +		dir = guess_dir_name_from_git_url(repo_name, is_bundle, option_bare);
>> +	strip_dir_trailing_slashes(dir);
>
> So, what does this new public helper function guess?  The name of
> the function says it guesses a directory name, but it is not just
> any directory name, but a directory with some specific meaning.
>
> Here repo_name has the URL the user gave "git clone", and even
> though there are some code before this part that computed on the
> variable, it hasn't been modified.  And "from_git_url" is a good way
> to indicate that that is one of the input the function uses to guess
> the name of "the directory with some unknown specific meaning".
>
> I think this codepath wants the new directory to create as the
> result of "git clone" operation in "dir".  So, even though I still
> do not have a good answer to the earlier "this is not just any
> directory but with some specific meaning---what is it?" question,
> adjectives that are appropriate for the "directory" to answer it
> may be along the lines of "new", "resulting", "cloned", etc.

Naming things is hard...

Maybe the right phrase would be 'target directory'? We are creating a
target directory name by looking at the "humanish" part of the Git URL.

I think the intention of all callers of this function is to get a
"default" directory name which will be used as the target of some
operation in the absence of the user providing one.

So maybe the name could be: 'guess_target_dir_from_git_url()'

This would make sense for any operation now or in the future that wants
to reuse this functionality.

>> diff --git a/dir.h b/dir.h
>> index b3e1a54a97..76441dde2d 100644
>> --- a/dir.h
>> +++ b/dir.h
>> @@ -453,6 +453,9 @@ static inline int is_dot_or_dotdot(const char *name)
>>
>>  int is_empty_dir(const char *dir);
>>
>
> We would want docstring here for the function (and possibly rename
> the function to clarify what kind of "dir" we are talking about).

Okay, I will add it.

>> +char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare);
>> +void strip_dir_trailing_slashes(char *dir);
>> +
>>  void setup_standard_excludes(struct dir_struct *dir);
>>
>>  char *get_sparse_checkout_filename(void);
>
> Thanks.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v2 5/9] submodule--helper: remove constness of sm_path
  2021-08-05 20:40     ` Junio C Hamano
@ 2021-08-06 11:16       ` Atharva Raykar
  0 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 11:16 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine


Junio C Hamano <gitster@pobox.com> writes:

> Atharva Raykar <raykar.ath@gmail.com> writes:
>
>> This is needed so that it can be modified by normalize_path_copy() in
>> the next patch.
>
> This is a hard-to-judge change.  With this alone, we cannot tell if
> somebody has already looked at the member (and possibly saved the
> pointer elsewhere) before "the next patch" starts modifying the
> member in the struct.  It probably should be done in a single patch
> to demonstrate why it is needed and how existing users of the field
> are OK with this change.

Okay, I will move this to the next patch.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v2 6/9] submodule--helper: convert the bulk of cmd_add() to C
  2021-08-06  1:14     ` Đoàn Trần Công Danh
@ 2021-08-06 11:33       ` Atharva Raykar
  0 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 11:33 UTC (permalink / raw)
  To: Đoàn Trần Công Danh
  Cc: avarab, christian.couder, emilyshaffer, git, gitster, jrnieder,
	kaartic.sivaraam, pc44800, periperidip, rafaeloliveira.cs,
	sunshine


Đoàn Trần Công Danh <congdanhqx@gmail.com> writes:

> On 2021-08-05 13:10:51+0530, Atharva Raykar <raykar.ath@gmail.com> wrote:
>> [...]
>> +		add_data.sm_path = xstrdup(argv[1]);
>
> add_data.sm_path is allocated in this block (regardless of legs).
>
>> [...]
>> +		if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
>> +			strbuf_complete_line(&sb);
>> +			fputs(sb.buf, stderr);
>> +			return exit_code;
>
> But, we don't free it when return from here.
>
>> [...]
>> +
>> +	if (add_submodule(&add_data))
>> +		return 1;
>
> And here.
>
>> +	configure_added_submodule(&add_data);
>> +	free(add_data.sm_path);
>
> However, it will be free()-d here, is it intended?

Yeah I meant to have it free()'d wherever possible, although I suppose
it isn't strictly necessary since we exit.

> I think we may use UNLEAK above (for now) because we will exit process
> after this function.
>
> However, I anticipated we may need to do more stuffs after this
> function in the future.

Right. So it's better I ensure that it's freed properly everywhere.

>> [...]
>> --
>> 2.32.0
>>

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C
  2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
                     ` (8 preceding siblings ...)
  2021-08-05  7:40   ` [GSoC] [PATCH v2 9/9] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
@ 2021-08-06 12:01   ` Atharva Raykar
  2021-08-06 12:01     ` [GSoC] [PATCH v3 1/8] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
                       ` (8 more replies)
  9 siblings, 9 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 12:01 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Changes since v2:

* Mention the small overhead introduced in [2/8] in the commit message.
* Attempt a more descriptive name for the libified dir helper. Add a docstring
  to explain it as well.
* Combine the "unconstification of sm_path" patch into the next one.

Atharva Raykar (8):
  submodule--helper: add options for compute_submodule_clone_url()
  submodule--helper: refactor resolve_relative_url() helper
  submodule--helper: remove repeated code in sync_submodule()
  dir: libify and export helper functions from clone.c
  submodule--helper: convert the bulk of cmd_add() to C
  submodule--helper: remove add-clone subcommand
  submodule--helper: remove add-config subcommand
  submodule--helper: remove resolve-relative-url subcommand

 builtin/clone.c             | 118 +-------------
 builtin/submodule--helper.c | 307 +++++++++++++++++++-----------------
 dir.c                       | 114 +++++++++++++
 dir.h                       |  11 ++
 git-submodule.sh            |  96 +----------
 5 files changed, 291 insertions(+), 355 deletions(-)

Range-diff against v2:
-:  ---------- > 1:  75edf24186 submodule--helper: add options for compute_submodule_clone_url()
-:  ---------- > 2:  8e7a3e727a submodule--helper: refactor resolve_relative_url() helper
1:  d8ee0bc450 ! 3:  82961ddd02 submodule--helper: remove repeated code in sync_submodule()
    @@ Commit message
         This part of `sync_submodule()` is doing the same thing that
         `compute_submodule_clone_url()` is doing. Let's reuse that helper here.
     
    +    Note that this change adds a small overhead where we allocate and free
    +    the 'remote' twice, but that is a small price to pay for the higher
    +    level of abstraction we get.
    +
         Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
         Mentored-by: Christian Couder <christian.couder@gmail.com>
         Mentored-by: Shourya Shukla <periperidip@gmail.com>
2:  6ac470d86f ! 4:  99d139375d dir: libify and export helper functions from clone.c
    @@ Commit message
     
         Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
         Mentored-by: Christian Couder <christian.couder@gmail.com>
    -    Mentored-by: Shourya Shukla <shouryashukla.oo@gmail.com>
    +    Mentored-by: Shourya Shukla <periperidip@gmail.com>
     
      ## builtin/clone.c ##
     @@ builtin/clone.c: static char *get_repo_path(const char *repo, int *is_bundle)
    @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
      	else
     -		dir = guess_dir_name(repo_name, is_bundle, option_bare);
     -	strip_trailing_slashes(dir);
    -+		dir = guess_dir_name_from_git_url(repo_name, is_bundle, option_bare);
    ++		dir = guess_target_dir_from_git_url(repo_name, is_bundle, option_bare);
     +	strip_dir_trailing_slashes(dir);
      
      	dest_exists = path_exists(dir);
    @@ dir.c: int is_empty_dir(const char *path)
      	return ret;
      }
      
    -+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare)
    ++char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare)
     +{
     +	const char *end = repo + strlen(repo), *start, *ptr;
     +	size_t len;
    @@ dir.h: static inline int is_dot_or_dotdot(const char *name)
      
      int is_empty_dir(const char *dir);
      
    -+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare);
    ++/*
    ++ * Retrieve a target directory name by reading "humanish" part of the
    ++ * given Git URL.
    ++ *
    ++ * For example:
    ++ * 	/path/to/repo.git => "repo"
    ++ * 	host.xz.foo/.git => "foo"
    ++ */
    ++char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare);
     +void strip_dir_trailing_slashes(char *dir);
     +
      void setup_standard_excludes(struct dir_struct *dir);
3:  c0b264a4e8 < -:  ---------- submodule--helper: remove constness of sm_path
4:  f61124327f ! 5:  11eea777ba submodule--helper: convert the bulk of cmd_add() to C
    @@ Commit message
         Introduce the 'add' subcommand to `submodule--helper.c` that does all
         the work 'submodule add' past the parsing of flags.
     
    +    We also remove the constness of the sm_path field of the `add_data`
    +    struct. This is needed so that it can be modified by
    +    normalize_path_copy().
    +
         As with the previous conversions, this is meant to be a faithful
         conversion with no modification to the behaviour of `submodule add`.
     
    @@ Commit message
         Based-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>
     
      ## builtin/submodule--helper.c ##
    +@@ builtin/submodule--helper.c: struct add_data {
    + 	const char *prefix;
    + 	const char *branch;
    + 	const char *reference_path;
    +-	const char *sm_path;
    ++	char *sm_path;
    + 	const char *sm_name;
    + 	const char *repo;
    + 	const char *realrepo;
     @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv, const char *prefix)
      	return 0;
      }
    @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv,
     +
     +	add_data.repo = argv[0];
     +	if (argc == 1)
    -+		add_data.sm_path = guess_dir_name_from_git_url(add_data.repo, 0, 0);
    ++		add_data.sm_path = guess_target_dir_from_git_url(add_data.repo, 0, 0);
     +	else
     +		add_data.sm_path = xstrdup(argv[1]);
     +
    @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv,
     +		if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
     +			strbuf_complete_line(&sb);
     +			fputs(sb.buf, stderr);
    ++			free(add_data.sm_path);
     +			return exit_code;
     +		}
     +		strbuf_release(&sb);
    @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv,
     +	add_data.progress = !!progress;
     +	add_data.dissociate = !!dissociate;
     +
    -+	if (add_submodule(&add_data))
    ++	if (add_submodule(&add_data)) {
    ++		free(add_data.sm_path);
     +		return 1;
    ++	}
     +	configure_added_submodule(&add_data);
     +	free(add_data.sm_path);
     +
5:  0c37bf84c3 = 6:  51393cd99b submodule--helper: remove add-clone subcommand
6:  d7e0db2565 = 7:  50cedcd8a8 submodule--helper: remove add-config subcommand
7:  6dd7cb1e18 = 8:  02558da532 submodule--helper: remove resolve-relative-url subcommand
-- 
2.32.0


^ permalink raw reply	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v3 1/8] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
@ 2021-08-06 12:01     ` Atharva Raykar
  2021-08-06 12:01     ` [GSoC] [PATCH v3 2/8] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
                       ` (7 subsequent siblings)
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 12:01 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Let's modify the interface to `compute_submodule_clone_url()` function
by adding two more arguments, so that we can reuse this in various parts
of `submodule--helper.c` that follow a common pattern, which is--read
the remote url configuration of the superproject and then call
`relative_url()`.

This function is nearly identical to `resolve_relative_url()`, the only
difference being the extra warning message. We can add a quiet flag to
it, to suppress that warning when not needed, and then refactor
`resolve_relative_url()` by using this function, something we will do in
the next patch.

Having this functionality factored out will be useful for converting the
rest of `submodule add` in subsequent patches.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6891480013..2d2d8ac637 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -590,7 +590,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static char *compute_submodule_clone_url(const char *rel_url)
+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
 {
 	char *remoteurl, *relurl;
 	char *remote = get_default_remote();
@@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)
 
 	strbuf_addf(&remotesb, "remote.%s.url", remote);
 	if (git_config_get_string(remotesb.buf, &remoteurl)) {
-		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
+		if (!quiet)
+			warning(_("could not look up configuration '%s'. "
+				  "Assuming this repository is its own "
+				  "authoritative upstream."),
+				remotesb.buf);
 		remoteurl = xgetcwd();
 	}
-	relurl = relative_url(remoteurl, rel_url, NULL);
+	relurl = relative_url(remoteurl, rel_url, up_path);
 
 	free(remote);
 	free(remoteurl);
@@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(url) ||
 		    starts_with_dot_slash(url)) {
 			char *oldurl = url;
-			url = compute_submodule_clone_url(oldurl);
+			url = compute_submodule_clone_url(oldurl, NULL, 0);
 			free(oldurl);
 		}
 
@@ -2134,7 +2138,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	if (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {
 		if (starts_with_dot_slash(sub->url) ||
 		    starts_with_dot_dot_slash(sub->url)) {
-			url = compute_submodule_clone_url(sub->url);
+			url = compute_submodule_clone_url(sub->url, NULL, 0);
 			need_free_url = 1;
 		} else
 			url = sub->url;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v3 2/8] submodule--helper: refactor resolve_relative_url() helper
  2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
  2021-08-06 12:01     ` [GSoC] [PATCH v3 1/8] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
@ 2021-08-06 12:01     ` Atharva Raykar
  2021-08-06 12:01     ` [GSoC] [PATCH v3 3/8] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
                       ` (6 subsequent siblings)
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 12:01 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Refactor the helper function to resolve a relative url, by reusing the
existing `compute_submodule_clone_url()` function.

`compute_submodule_clone_url()` performs the same work that
`resolve_relative_url()` is doing, so we eliminate this code repetition
by moving the former function's definition up, and calling it inside
`resolve_relative_url()`.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 61 +++++++++++++++----------------------
 1 file changed, 25 insertions(+), 36 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2d2d8ac637..f4b496bac6 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -199,33 +199,46 @@ static char *relative_url(const char *remote_url,
 	return strbuf_detach(&sb, NULL);
 }
 
+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
+{
+	char *remoteurl, *relurl;
+	char *remote = get_default_remote();
+	struct strbuf remotesb = STRBUF_INIT;
+
+	strbuf_addf(&remotesb, "remote.%s.url", remote);
+	if (git_config_get_string(remotesb.buf, &remoteurl)) {
+		if (!quiet)
+			warning(_("could not look up configuration '%s'. "
+				  "Assuming this repository is its own "
+				  "authoritative upstream."),
+				remotesb.buf);
+		remoteurl = xgetcwd();
+	}
+	relurl = relative_url(remoteurl, rel_url, up_path);
+
+	free(remote);
+	free(remoteurl);
+	strbuf_release(&remotesb);
+
+	return relurl;
+}
+
 static int resolve_relative_url(int argc, const char **argv, const char *prefix)
 {
-	char *remoteurl = NULL;
-	char *remote = get_default_remote();
 	const char *up_path = NULL;
 	char *res;
 	const char *url;
-	struct strbuf sb = STRBUF_INIT;
 
 	if (argc != 2 && argc != 3)
 		die("resolve-relative-url only accepts one or two arguments");
 
 	url = argv[1];
-	strbuf_addf(&sb, "remote.%s.url", remote);
-	free(remote);
-
-	if (git_config_get_string(sb.buf, &remoteurl))
-		/* the repository is its own authoritative upstream */
-		remoteurl = xgetcwd();
-
 	if (argc == 3)
 		up_path = argv[2];
 
-	res = relative_url(remoteurl, url, up_path);
+	res = compute_submodule_clone_url(url, up_path, 1);
 	puts(res);
 	free(res);
-	free(remoteurl);
 	return 0;
 }
 
@@ -590,30 +603,6 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
-{
-	char *remoteurl, *relurl;
-	char *remote = get_default_remote();
-	struct strbuf remotesb = STRBUF_INIT;
-
-	strbuf_addf(&remotesb, "remote.%s.url", remote);
-	if (git_config_get_string(remotesb.buf, &remoteurl)) {
-		if (!quiet)
-			warning(_("could not look up configuration '%s'. "
-				  "Assuming this repository is its own "
-				  "authoritative upstream."),
-				remotesb.buf);
-		remoteurl = xgetcwd();
-	}
-	relurl = relative_url(remoteurl, rel_url, up_path);
-
-	free(remote);
-	free(remoteurl);
-	strbuf_release(&remotesb);
-
-	return relurl;
-}
-
 struct init_cb {
 	const char *prefix;
 	unsigned int flags;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v3 3/8] submodule--helper: remove repeated code in sync_submodule()
  2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
  2021-08-06 12:01     ` [GSoC] [PATCH v3 1/8] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
  2021-08-06 12:01     ` [GSoC] [PATCH v3 2/8] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
@ 2021-08-06 12:01     ` Atharva Raykar
  2021-08-06 12:01     ` [GSoC] [PATCH v3 4/8] dir: libify and export helper functions from clone.c Atharva Raykar
                       ` (5 subsequent siblings)
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 12:01 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

This part of `sync_submodule()` is doing the same thing that
`compute_submodule_clone_url()` is doing. Let's reuse that helper here.

Note that this change adds a small overhead where we allocate and free
the 'remote' twice, but that is a small price to pay for the higher
level of abstraction we get.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f4b496bac6..9b676c12f8 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,
 	if (sub && sub->url) {
 		if (starts_with_dot_dot_slash(sub->url) ||
 		    starts_with_dot_slash(sub->url)) {
-			char *remote_url, *up_path;
-			char *remote = get_default_remote();
-			strbuf_addf(&sb, "remote.%s.url", remote);
-
-			if (git_config_get_string(sb.buf, &remote_url))
-				remote_url = xgetcwd();
-
-			up_path = get_up_path(path);
-			sub_origin_url = relative_url(remote_url, sub->url, up_path);
-			super_config_url = relative_url(remote_url, sub->url, NULL);
-
-			free(remote);
+			char *up_path = get_up_path(path);
+			sub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);
+			super_config_url = compute_submodule_clone_url(sub->url, NULL, 1);
 			free(up_path);
-			free(remote_url);
 		} else {
 			sub_origin_url = xstrdup(sub->url);
 			super_config_url = xstrdup(sub->url);
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v3 4/8] dir: libify and export helper functions from clone.c
  2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                       ` (2 preceding siblings ...)
  2021-08-06 12:01     ` [GSoC] [PATCH v3 3/8] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
@ 2021-08-06 12:01     ` Atharva Raykar
  2021-08-06 12:01     ` [GSoC] [PATCH v3 5/8] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
                       ` (4 subsequent siblings)
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 12:01 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

These functions can be useful to other parts of Git. Let's move them to
dir.c, while renaming them to be make their functionality more explicit.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/clone.c | 118 +-----------------------------------------------
 dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++
 dir.h           |  11 +++++
 3 files changed, 127 insertions(+), 116 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 66fe66679c..fab0a3cef6 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -217,120 +217,6 @@ static char *get_repo_path(const char *repo, int *is_bundle)
 	return canon;
 }
 
-static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
-{
-	const char *end = repo + strlen(repo), *start, *ptr;
-	size_t len;
-	char *dir;
-
-	/*
-	 * Skip scheme.
-	 */
-	start = strstr(repo, "://");
-	if (start == NULL)
-		start = repo;
-	else
-		start += 3;
-
-	/*
-	 * Skip authentication data. The stripping does happen
-	 * greedily, such that we strip up to the last '@' inside
-	 * the host part.
-	 */
-	for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
-		if (*ptr == '@')
-			start = ptr + 1;
-	}
-
-	/*
-	 * Strip trailing spaces, slashes and /.git
-	 */
-	while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
-		end--;
-	if (end - start > 5 && is_dir_sep(end[-5]) &&
-	    !strncmp(end - 4, ".git", 4)) {
-		end -= 5;
-		while (start < end && is_dir_sep(end[-1]))
-			end--;
-	}
-
-	/*
-	 * Strip trailing port number if we've got only a
-	 * hostname (that is, there is no dir separator but a
-	 * colon). This check is required such that we do not
-	 * strip URI's like '/foo/bar:2222.git', which should
-	 * result in a dir '2222' being guessed due to backwards
-	 * compatibility.
-	 */
-	if (memchr(start, '/', end - start) == NULL
-	    && memchr(start, ':', end - start) != NULL) {
-		ptr = end;
-		while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
-			ptr--;
-		if (start < ptr && ptr[-1] == ':')
-			end = ptr - 1;
-	}
-
-	/*
-	 * Find last component. To remain backwards compatible we
-	 * also regard colons as path separators, such that
-	 * cloning a repository 'foo:bar.git' would result in a
-	 * directory 'bar' being guessed.
-	 */
-	ptr = end;
-	while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
-		ptr--;
-	start = ptr;
-
-	/*
-	 * Strip .{bundle,git}.
-	 */
-	len = end - start;
-	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
-
-	if (!len || (len == 1 && *start == '/'))
-		die(_("No directory name could be guessed.\n"
-		      "Please specify a directory on the command line"));
-
-	if (is_bare)
-		dir = xstrfmt("%.*s.git", (int)len, start);
-	else
-		dir = xstrndup(start, len);
-	/*
-	 * Replace sequences of 'control' characters and whitespace
-	 * with one ascii space, remove leading and trailing spaces.
-	 */
-	if (*dir) {
-		char *out = dir;
-		int prev_space = 1 /* strip leading whitespace */;
-		for (end = dir; *end; ++end) {
-			char ch = *end;
-			if ((unsigned char)ch < '\x20')
-				ch = '\x20';
-			if (isspace(ch)) {
-				if (prev_space)
-					continue;
-				prev_space = 1;
-			} else
-				prev_space = 0;
-			*out++ = ch;
-		}
-		*out = '\0';
-		if (out > dir && prev_space)
-			out[-1] = '\0';
-	}
-	return dir;
-}
-
-static void strip_trailing_slashes(char *dir)
-{
-	char *end = dir + strlen(dir);
-
-	while (dir < end - 1 && is_dir_sep(end[-1]))
-		end--;
-	*end = '\0';
-}
-
 static int add_one_reference(struct string_list_item *item, void *cb_data)
 {
 	struct strbuf err = STRBUF_INIT;
@@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	if (argc == 2)
 		dir = xstrdup(argv[1]);
 	else
-		dir = guess_dir_name(repo_name, is_bundle, option_bare);
-	strip_trailing_slashes(dir);
+		dir = guess_target_dir_from_git_url(repo_name, is_bundle, option_bare);
+	strip_dir_trailing_slashes(dir);
 
 	dest_exists = path_exists(dir);
 	if (dest_exists && !is_empty_dir(dir))
diff --git a/dir.c b/dir.c
index 03c4d21267..9a9ab135c4 100644
--- a/dir.c
+++ b/dir.c
@@ -2970,6 +2970,120 @@ int is_empty_dir(const char *path)
 	return ret;
 }
 
+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare)
+{
+	const char *end = repo + strlen(repo), *start, *ptr;
+	size_t len;
+	char *dir;
+
+	/*
+	 * Skip scheme.
+	 */
+	start = strstr(repo, "://");
+	if (start == NULL)
+		start = repo;
+	else
+		start += 3;
+
+	/*
+	 * Skip authentication data. The stripping does happen
+	 * greedily, such that we strip up to the last '@' inside
+	 * the host part.
+	 */
+	for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
+		if (*ptr == '@')
+			start = ptr + 1;
+	}
+
+	/*
+	 * Strip trailing spaces, slashes and /.git
+	 */
+	while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
+		end--;
+	if (end - start > 5 && is_dir_sep(end[-5]) &&
+	    !strncmp(end - 4, ".git", 4)) {
+		end -= 5;
+		while (start < end && is_dir_sep(end[-1]))
+			end--;
+	}
+
+	/*
+	 * Strip trailing port number if we've got only a
+	 * hostname (that is, there is no dir separator but a
+	 * colon). This check is required such that we do not
+	 * strip URI's like '/foo/bar:2222.git', which should
+	 * result in a dir '2222' being guessed due to backwards
+	 * compatibility.
+	 */
+	if (memchr(start, '/', end - start) == NULL
+	    && memchr(start, ':', end - start) != NULL) {
+		ptr = end;
+		while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
+			ptr--;
+		if (start < ptr && ptr[-1] == ':')
+			end = ptr - 1;
+	}
+
+	/*
+	 * Find last component. To remain backwards compatible we
+	 * also regard colons as path separators, such that
+	 * cloning a repository 'foo:bar.git' would result in a
+	 * directory 'bar' being guessed.
+	 */
+	ptr = end;
+	while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
+		ptr--;
+	start = ptr;
+
+	/*
+	 * Strip .{bundle,git}.
+	 */
+	len = end - start;
+	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
+
+	if (!len || (len == 1 && *start == '/'))
+		die(_("No directory name could be guessed.\n"
+		      "Please specify a directory on the command line"));
+
+	if (is_bare)
+		dir = xstrfmt("%.*s.git", (int)len, start);
+	else
+		dir = xstrndup(start, len);
+	/*
+	 * Replace sequences of 'control' characters and whitespace
+	 * with one ascii space, remove leading and trailing spaces.
+	 */
+	if (*dir) {
+		char *out = dir;
+		int prev_space = 1 /* strip leading whitespace */;
+		for (end = dir; *end; ++end) {
+			char ch = *end;
+			if ((unsigned char)ch < '\x20')
+				ch = '\x20';
+			if (isspace(ch)) {
+				if (prev_space)
+					continue;
+				prev_space = 1;
+			} else
+				prev_space = 0;
+			*out++ = ch;
+		}
+		*out = '\0';
+		if (out > dir && prev_space)
+			out[-1] = '\0';
+	}
+	return dir;
+}
+
+void strip_dir_trailing_slashes(char *dir)
+{
+	char *end = dir + strlen(dir);
+
+	while (dir < end - 1 && is_dir_sep(end[-1]))
+		end--;
+	*end = '\0';
+}
+
 static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
 {
 	DIR *dir;
diff --git a/dir.h b/dir.h
index b3e1a54a97..6f0abdfe04 100644
--- a/dir.h
+++ b/dir.h
@@ -453,6 +453,17 @@ static inline int is_dot_or_dotdot(const char *name)
 
 int is_empty_dir(const char *dir);
 
+/*
+ * Retrieve a target directory name by reading "humanish" part of the
+ * given Git URL.
+ *
+ * For example:
+ * 	/path/to/repo.git => "repo"
+ * 	host.xz.foo/.git => "foo"
+ */
+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare);
+void strip_dir_trailing_slashes(char *dir);
+
 void setup_standard_excludes(struct dir_struct *dir);
 
 char *get_sparse_checkout_filename(void);
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v3 5/8] submodule--helper: convert the bulk of cmd_add() to C
  2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                       ` (3 preceding siblings ...)
  2021-08-06 12:01     ` [GSoC] [PATCH v3 4/8] dir: libify and export helper functions from clone.c Atharva Raykar
@ 2021-08-06 12:01     ` Atharva Raykar
  2021-08-06 12:01     ` [GSoC] [PATCH v3 6/8] submodule--helper: remove add-clone subcommand Atharva Raykar
                       ` (3 subsequent siblings)
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 12:01 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Introduce the 'add' subcommand to `submodule--helper.c` that does all
the work 'submodule add' past the parsing of flags.

We also remove the constness of the sm_path field of the `add_data`
struct. This is needed so that it can be modified by
normalize_path_copy().

As with the previous conversions, this is meant to be a faithful
conversion with no modification to the behaviour of `submodule add`.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Helped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
Based-on-patch-by: Shourya Shukla <periperidip@gmail.com>
Based-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>
---
 builtin/submodule--helper.c | 165 +++++++++++++++++++++++++++++++++++-
 git-submodule.sh            |  96 +--------------------
 2 files changed, 166 insertions(+), 95 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 9b676c12f8..f31e5a9bde 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2748,7 +2748,7 @@ struct add_data {
 	const char *prefix;
 	const char *branch;
 	const char *reference_path;
-	const char *sm_path;
+	char *sm_path;
 	const char *sm_name;
 	const char *repo;
 	const char *realrepo;
@@ -3046,6 +3046,168 @@ static int add_config(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+static void die_on_index_match(const char *path, int force)
+{
+	struct pathspec ps;
+	const char *args[] = { path, NULL };
+	parse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);
+
+	if (read_cache_preload(NULL) < 0)
+		die(_("index file corrupt"));
+
+	if (ps.nr) {
+		int i;
+		char *ps_matched = xcalloc(ps.nr, 1);
+
+		/* TODO: audit for interaction with sparse-index. */
+		ensure_full_index(&the_index);
+
+		/*
+		 * Since there is only one pathspec, we just need
+		 * need to check ps_matched[0] to know if a cache
+		 * entry matched.
+		 */
+		for (i = 0; i < active_nr; i++) {
+			ce_path_match(&the_index, active_cache[i], &ps,
+				      ps_matched);
+
+			if (ps_matched[0]) {
+				if (!force)
+					die(_("'%s' already exists in the index"),
+					    path);
+				if (!S_ISGITLINK(active_cache[i]->ce_mode))
+					die(_("'%s' already exists in the index "
+					      "and is not a submodule"), path);
+				break;
+			}
+		}
+		free(ps_matched);
+	}
+}
+
+static void die_on_repo_without_commits(const char *path)
+{
+	struct strbuf sb = STRBUF_INIT;
+	strbuf_addstr(&sb, path);
+	if (is_nonbare_repository_dir(&sb)) {
+		struct object_id oid;
+		if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
+			die(_("'%s' does not have a commit checked out"), path);
+	}
+}
+
+static int module_add(int argc, const char **argv, const char *prefix)
+{
+	int force = 0, quiet = 0, progress = 0, dissociate = 0;
+	struct add_data add_data = ADD_DATA_INIT;
+
+	struct option options[] = {
+		OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
+			   N_("branch of repository to add as submodule")),
+		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
+			   PARSE_OPT_NOCOMPLETE),
+		OPT__QUIET(&quiet, N_("print only error messages")),
+		OPT_BOOL(0, "progress", &progress, N_("force cloning progress")),
+		OPT_STRING(0, "reference", &add_data.reference_path, N_("repository"),
+			   N_("reference repository")),
+		OPT_BOOL(0, "dissociate", &dissociate, N_("borrow the objects from reference repositories")),
+		OPT_STRING(0, "name", &add_data.sm_name, N_("name"),
+			   N_("sets the submodule’s name to the given string "
+			      "instead of defaulting to its path")),
+		OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
+		OPT_END()
+	};
+
+	const char *const usage[] = {
+		N_("git submodule--helper add [<options>] [--] <repository> [<path>]"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, options, usage, 0);
+
+	if (!is_writing_gitmodules_ok())
+		die(_("please make sure that the .gitmodules file is in the working tree"));
+
+	if (prefix && *prefix &&
+	    add_data.reference_path && !is_absolute_path(add_data.reference_path))
+		add_data.reference_path = xstrfmt("%s%s", prefix, add_data.reference_path);
+
+	if (argc == 0 || argc > 2)
+		usage_with_options(usage, options);
+
+	add_data.repo = argv[0];
+	if (argc == 1)
+		add_data.sm_path = guess_target_dir_from_git_url(add_data.repo, 0, 0);
+	else
+		add_data.sm_path = xstrdup(argv[1]);
+
+	if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
+		add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
+
+	if (starts_with_dot_dot_slash(add_data.repo) ||
+	    starts_with_dot_slash(add_data.repo)) {
+		if (prefix)
+			die(_("Relative path can only be used from the toplevel "
+			      "of the working tree"));
+
+		/* dereference source url relative to parent's url */
+		add_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);
+	} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {
+		add_data.realrepo = add_data.repo;
+	} else {
+		die(_("repo URL: '%s' must be absolute or begin with ./|../"),
+		    add_data.repo);
+	}
+
+	/*
+	 * normalize path:
+	 * multiple //; leading ./; /./; /../;
+	 */
+	normalize_path_copy(add_data.sm_path, add_data.sm_path);
+	strip_dir_trailing_slashes(add_data.sm_path);
+
+	die_on_index_match(add_data.sm_path, force);
+	die_on_repo_without_commits(add_data.sm_path);
+
+	if (!force) {
+		int exit_code = -1;
+		struct strbuf sb = STRBUF_INIT;
+		struct child_process cp = CHILD_PROCESS_INIT;
+		cp.git_cmd = 1;
+		cp.no_stdout = 1;
+		strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
+			     "--no-warn-embedded-repo", add_data.sm_path, NULL);
+		if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
+			strbuf_complete_line(&sb);
+			fputs(sb.buf, stderr);
+			free(add_data.sm_path);
+			return exit_code;
+		}
+		strbuf_release(&sb);
+	}
+
+	if(!add_data.sm_name)
+		add_data.sm_name = add_data.sm_path;
+
+	if (check_submodule_name(add_data.sm_name))
+		die(_("'%s' is not a valid submodule name"), add_data.sm_name);
+
+	add_data.prefix = prefix;
+	add_data.force = !!force;
+	add_data.quiet = !!quiet;
+	add_data.progress = !!progress;
+	add_data.dissociate = !!dissociate;
+
+	if (add_submodule(&add_data)) {
+		free(add_data.sm_path);
+		return 1;
+	}
+	configure_added_submodule(&add_data);
+	free(add_data.sm_path);
+
+	return 0;
+}
+
 #define SUPPORT_SUPER_PREFIX (1<<0)
 
 struct cmd_struct {
@@ -3060,6 +3222,7 @@ static struct cmd_struct commands[] = {
 	{"clone", module_clone, 0},
 	{"add-clone", add_clone, 0},
 	{"add-config", add_config, 0},
+	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
 	{"update-clone", update_clone, 0},
 	{"ensure-core-worktree", ensure_core_worktree, 0},
diff --git a/git-submodule.sh b/git-submodule.sh
index 8c219ef382..1070540525 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -145,104 +145,12 @@ cmd_add()
 		shift
 	done
 
-	if ! git submodule--helper config --check-writeable >/dev/null 2>&1
+	if test -z "$1"
 	then
-		 die "fatal: $(eval_gettext "please make sure that the .gitmodules file is in the working tree")"
-	fi
-
-	if test -n "$reference_path"
-	then
-		is_absolute_path "$reference_path" ||
-		reference_path="$wt_prefix$reference_path"
-
-		reference="--reference=$reference_path"
-	fi
-
-	repo=$1
-	sm_path=$2
-
-	if test -z "$sm_path"; then
-		sm_path=$(printf '%s\n' "$repo" |
-			sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
-	fi
-
-	if test -z "$repo" || test -z "$sm_path"; then
 		usage
 	fi
 
-	is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
-
-	# assure repo is absolute or relative to parent
-	case "$repo" in
-	./*|../*)
-		test -z "$wt_prefix" ||
-		die "fatal: $(gettext "Relative path can only be used from the toplevel of the working tree")"
-
-		# dereference source url relative to parent's url
-		realrepo=$(git submodule--helper resolve-relative-url "$repo") || exit
-		;;
-	*:*|/*)
-		# absolute url
-		realrepo=$repo
-		;;
-	*)
-		die "fatal: $(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
-	;;
-	esac
-
-	# normalize path:
-	# multiple //; leading ./; /./; /../; trailing /
-	sm_path=$(printf '%s/\n' "$sm_path" |
-		sed -e '
-			s|//*|/|g
-			s|^\(\./\)*||
-			s|/\(\./\)*|/|g
-			:start
-			s|\([^/]*\)/\.\./||
-			tstart
-			s|/*$||
-		')
-	if test -z "$force"
-	then
-		git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
-		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index")"
-	else
-		git ls-files -s "$sm_path" | sane_grep -v "^160000" > /dev/null 2>&1 &&
-		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
-	fi
-
-	if test -d "$sm_path" &&
-		test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null)
-	then
-	    git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null ||
-	    die "fatal: $(eval_gettext "'\$sm_path' does not have a commit checked out")"
-	fi
-
-	if test -z "$force"
-	then
-	    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" 2>&1 >/dev/null)
-	    res=$?
-	    if test $res -ne 0
-	    then
-		 echo >&2 "$dryerr"
-		 exit $res
-	    fi
-	fi
-
-	if test -n "$custom_name"
-	then
-		sm_name="$custom_name"
-	else
-		sm_name="$sm_path"
-	fi
-
-	if ! git submodule--helper check-name "$sm_name"
-	then
-		die "fatal: $(eval_gettext "'$sm_name' is not a valid submodule name")"
-	fi
-
-	git submodule--helper add-clone ${GIT_QUIET:+--quiet} ${force:+"--force"} ${progress:+"--progress"} ${branch:+--branch "$branch"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit
-	git submodule--helper add-config ${force:+--force} ${branch:+--branch "$branch"} --url "$repo" --resolved-url "$realrepo" --path "$sm_path" --name "$sm_name"
+	git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper add ${GIT_QUIET:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@"
 }
 
 #
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v3 6/8] submodule--helper: remove add-clone subcommand
  2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                       ` (4 preceding siblings ...)
  2021-08-06 12:01     ` [GSoC] [PATCH v3 5/8] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
@ 2021-08-06 12:01     ` Atharva Raykar
  2021-08-06 12:01     ` [GSoC] [PATCH v3 7/8] submodule--helper: remove add-config subcommand Atharva Raykar
                       ` (2 subsequent siblings)
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 12:01 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

We no longer need this subcommand, as all of its functionality is being
called by the newly-introduced `module_add()` directly within C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 60 -------------------------------------
 1 file changed, 60 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f31e5a9bde..1257066a0f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2860,65 +2860,6 @@ static int add_submodule(const struct add_data *add_data)
 	return 0;
 }
 
-static int add_clone(int argc, const char **argv, const char *prefix)
-{
-	int force = 0, quiet = 0, dissociate = 0, progress = 0;
-	struct add_data add_data = ADD_DATA_INIT;
-
-	struct option options[] = {
-		OPT_STRING('b', "branch", &add_data.branch,
-			   N_("branch"),
-			   N_("branch of repository to checkout on cloning")),
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("alternative anchor for relative paths")),
-		OPT_STRING(0, "path", &add_data.sm_path,
-			   N_("path"),
-			   N_("where the new submodule will be cloned to")),
-		OPT_STRING(0, "name", &add_data.sm_name,
-			   N_("string"),
-			   N_("name of the new submodule")),
-		OPT_STRING(0, "url", &add_data.realrepo,
-			   N_("string"),
-			   N_("url where to clone the submodule from")),
-		OPT_STRING(0, "reference", &add_data.reference_path,
-			   N_("repo"),
-			   N_("reference repository")),
-		OPT_BOOL(0, "dissociate", &dissociate,
-			 N_("use --reference only while cloning")),
-		OPT_INTEGER(0, "depth", &add_data.depth,
-			    N_("depth for shallow clones")),
-		OPT_BOOL(0, "progress", &progress,
-			 N_("force cloning progress")),
-		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT__QUIET(&quiet, "suppress output for cloning a submodule"),
-		OPT_END()
-	};
-
-	const char *const usage[] = {
-		N_("git submodule--helper add-clone [<options>...] "
-		   "--url <url> --path <path> --name <name>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (argc != 0)
-		usage_with_options(usage, options);
-
-	add_data.prefix = prefix;
-	add_data.progress = !!progress;
-	add_data.dissociate = !!dissociate;
-	add_data.force = !!force;
-	add_data.quiet = !!quiet;
-
-	if (add_submodule(&add_data))
-		return 1;
-
-	return 0;
-}
-
 static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
 {
 	char *key;
@@ -3220,7 +3161,6 @@ static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
 	{"name", module_name, 0},
 	{"clone", module_clone, 0},
-	{"add-clone", add_clone, 0},
 	{"add-config", add_config, 0},
 	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v3 7/8] submodule--helper: remove add-config subcommand
  2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                       ` (5 preceding siblings ...)
  2021-08-06 12:01     ` [GSoC] [PATCH v3 6/8] submodule--helper: remove add-clone subcommand Atharva Raykar
@ 2021-08-06 12:01     ` Atharva Raykar
  2021-08-06 12:01     ` [GSoC] [PATCH v3 8/8] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 12:01 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Also no longer needed is this subcommand, as all of its functionality is
being called by the newly-introduced `module_add()` directly within C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 49 -------------------------------------
 1 file changed, 49 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 1257066a0f..a858c2be29 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2939,54 +2939,6 @@ static void configure_added_submodule(struct add_data *add_data)
 	}
 }
 
-static int add_config(int argc, const char **argv, const char *prefix)
-{
-	int force = 0;
-	struct add_data add_data = ADD_DATA_INIT;
-
-	struct option options[] = {
-		OPT_STRING('b', "branch", &add_data.branch,
-			   N_("branch"),
-			   N_("branch of repository to store in "
-			      "the submodule configuration")),
-		OPT_STRING(0, "url", &add_data.repo,
-			   N_("string"),
-			   N_("url to clone submodule from")),
-		OPT_STRING(0, "resolved-url", &add_data.realrepo,
-			   N_("string"),
-			   N_("url to clone the submodule from, after it has "
-			      "been dereferenced relative to parent's url, "
-			      "in the case where <url> is a relative url")),
-		OPT_STRING(0, "path", &add_data.sm_path,
-			   N_("path"),
-			   N_("where the new submodule will be cloned to")),
-		OPT_STRING(0, "name", &add_data.sm_name,
-			   N_("string"),
-			   N_("name of the new submodule")),
-		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_END()
-	};
-
-	const char *const usage[] = {
-		N_("git submodule--helper add-config "
-		   "[--force|-f] [--branch|-b <branch>] "
-		   "--url <url> --resolved-url <resolved-url> "
-		   "--path <path> --name <name>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (argc)
-		usage_with_options(usage, options);
-
-	add_data.force = !!force;
-	configure_added_submodule(&add_data);
-
-	return 0;
-}
-
 static void die_on_index_match(const char *path, int force)
 {
 	struct pathspec ps;
@@ -3161,7 +3113,6 @@ static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
 	{"name", module_name, 0},
 	{"clone", module_clone, 0},
-	{"add-config", add_config, 0},
 	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
 	{"update-clone", update_clone, 0},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v3 8/8] submodule--helper: remove resolve-relative-url subcommand
  2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                       ` (6 preceding siblings ...)
  2021-08-06 12:01     ` [GSoC] [PATCH v3 7/8] submodule--helper: remove add-config subcommand Atharva Raykar
@ 2021-08-06 12:01     ` Atharva Raykar
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
  8 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-06 12:01 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

The shell subcommand `resolve-relative-url` is no longer required, as
its last caller has been removed when it was converted to C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 20 --------------------
 1 file changed, 20 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index a858c2be29..9772435959 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -223,25 +223,6 @@ static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat
 	return relurl;
 }
 
-static int resolve_relative_url(int argc, const char **argv, const char *prefix)
-{
-	const char *up_path = NULL;
-	char *res;
-	const char *url;
-
-	if (argc != 2 && argc != 3)
-		die("resolve-relative-url only accepts one or two arguments");
-
-	url = argv[1];
-	if (argc == 3)
-		up_path = argv[2];
-
-	res = compute_submodule_clone_url(url, up_path, 1);
-	puts(res);
-	free(res);
-	return 0;
-}
-
 static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)
 {
 	char *remoteurl, *res;
@@ -3118,7 +3099,6 @@ static struct cmd_struct commands[] = {
 	{"update-clone", update_clone, 0},
 	{"ensure-core-worktree", ensure_core_worktree, 0},
 	{"relative-path", resolve_relative_path, 0},
-	{"resolve-relative-url", resolve_relative_url, 0},
 	{"resolve-relative-url-test", resolve_relative_url_test, 0},
 	{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
 	{"init", module_init, SUPPORT_SUPER_PREFIX},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule()
  2021-08-06  9:06     ` Christian Couder
  2021-08-06 10:06       ` Atharva Raykar
@ 2021-08-06 16:21       ` Junio C Hamano
  1 sibling, 0 replies; 78+ messages in thread
From: Junio C Hamano @ 2021-08-06 16:21 UTC (permalink / raw)
  To: Christian Couder
  Cc: Đoàn Trần Công Danh, Atharva Raykar, git,
	Ævar Arnfjörð Bjarmason, Emily Shaffer,
	Jonathan Nieder, Shourya Shukla, Kaartic Sivaraam, Eric Sunshine,
	Prathamesh Chavan, Rafael Silva

Christian Couder <christian.couder@gmail.com> writes:

> On Fri, Aug 6, 2021 at 2:54 AM Đoàn Trần Công Danh <congdanhqx@gmail.com> wrote:
>
>> While previous patch is definitely a refactoring, this patch add small
>> overhead to the system, the new code will query (then free())
>> git_config_get_string() and/or xgetcwd() one more time in the second
>> compute_submodule_clone_url()
>>
>> I think the abstraction overhead is not that big, though.
>
> Yeah, Junio made basically the same comment. So it would be nice if
> the commit message could mention we are adding a very small overhead
> in exchange for code simplification (10 lines removed).

If you guys want to, I wouldn't stop, but my comment was just a
thinking-aloud observation, not a suggestion to add to the proposed
log message.

Thanks.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c
  2021-08-06 11:12       ` Atharva Raykar
@ 2021-08-06 16:36         ` Junio C Hamano
  2021-08-07  7:15           ` Atharva Raykar
  0 siblings, 1 reply; 78+ messages in thread
From: Junio C Hamano @ 2021-08-06 16:36 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine, Shourya Shukla

Atharva Raykar <raykar.ath@gmail.com> writes:

> Naming things is hard...

Absolutely.

> Maybe the right phrase would be 'target directory'? We are creating a
> target directory name by looking at the "humanish" part of the Git URL.
>
> I think the intention of all callers of this function is to get a
> "default" directory name which will be used as the target of some
> operation in the absence of the user providing one.
>
> So maybe the name could be: 'guess_target_dir_from_git_url()'

I have no immediate objection to the name.  

Just to see how people (including you) may react to a name from a
completely different line of thinking, let me throw this, though.

How does git_url_basename() sound?  

Instead of saying what we'd use it for (i.e. as the name for the
directory getting created), we say what we compute.  We take a
URL-looking thing that is used by Git, and we compute something like
basename() but that is tailored for Git (e.g. unlike "basename
a/b/c.git" that yields "c.git", we give "c" for "a/b/c.git".
Likewise "<scheme>://a/b/c/.git" won't yield ".git", we compute
"c").

Having said that, I think guess_target_dir_from_git_url() is clear
enough.

> This would make sense for any operation now or in the future that wants
> to reuse this functionality.

That is mostly for you to decide.   I can help you sanity check the
proposed name(s) with existing callers, but you'd be a better judge
for callers you'll be adding ;-)

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c
  2021-08-06 16:36         ` Junio C Hamano
@ 2021-08-07  7:15           ` Atharva Raykar
  0 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-07  7:15 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine, Shourya Shukla


Junio C Hamano <gitster@pobox.com> writes:

> Atharva Raykar <raykar.ath@gmail.com> writes:
>
>> Naming things is hard...
>
> Absolutely.
>
>> Maybe the right phrase would be 'target directory'? We are creating a
>> target directory name by looking at the "humanish" part of the Git URL.
>>
>> I think the intention of all callers of this function is to get a
>> "default" directory name which will be used as the target of some
>> operation in the absence of the user providing one.
>>
>> So maybe the name could be: 'guess_target_dir_from_git_url()'
>
> I have no immediate objection to the name.
>
> Just to see how people (including you) may react to a name from a
> completely different line of thinking, let me throw this, though.
>
> How does git_url_basename() sound?
>
> Instead of saying what we'd use it for (i.e. as the name for the
> directory getting created), we say what we compute.  We take a
> URL-looking thing that is used by Git, and we compute something like
> basename() but that is tailored for Git (e.g. unlike "basename
> a/b/c.git" that yields "c.git", we give "c" for "a/b/c.git".
> Likewise "<scheme>://a/b/c/.git" won't yield ".git", we compute
> "c").
>
> Having said that, I think guess_target_dir_from_git_url() is clear
> enough.

Even though the name I suggested is clear enough, I liked your
suggestion a lot more. Not only is it more succinct, but it also opens
up the future possibility that the basename of a Git URL might be used
for purposes other than finding a directory name.

>> This would make sense for any operation now or in the future that wants
>> to reuse this functionality.
>
> That is mostly for you to decide.   I can help you sanity check the
> proposed name(s) with existing callers, but you'd be a better judge
> for callers you'll be adding ;-)

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C
  2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                       ` (7 preceding siblings ...)
  2021-08-06 12:01     ` [GSoC] [PATCH v3 8/8] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
@ 2021-08-07  7:16     ` Atharva Raykar
  2021-08-07  7:16       ` [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
                         ` (9 more replies)
  8 siblings, 10 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-07  7:16 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Changes since v3:

* Rename the libified dir helper and update the docstring.

Atharva Raykar (8):
  submodule--helper: add options for compute_submodule_clone_url()
  submodule--helper: refactor resolve_relative_url() helper
  submodule--helper: remove repeated code in sync_submodule()
  dir: libify and export helper functions from clone.c
  submodule--helper: convert the bulk of cmd_add() to C
  submodule--helper: remove add-clone subcommand
  submodule--helper: remove add-config subcommand
  submodule--helper: remove resolve-relative-url subcommand

 builtin/clone.c             | 118 +-------------
 builtin/submodule--helper.c | 307 +++++++++++++++++++-----------------
 dir.c                       | 114 +++++++++++++
 dir.h                       |  10 ++
 git-submodule.sh            |  96 +----------
 5 files changed, 290 insertions(+), 355 deletions(-)

Range-diff against v3:
-:  ---------- > 1:  75edf24186 submodule--helper: add options for compute_submodule_clone_url()
-:  ---------- > 2:  8e7a3e727a submodule--helper: refactor resolve_relative_url() helper
-:  ---------- > 3:  82961ddd02 submodule--helper: remove repeated code in sync_submodule()
1:  99d139375d ! 4:  fa97d6801e dir: libify and export helper functions from clone.c
    @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
      	else
     -		dir = guess_dir_name(repo_name, is_bundle, option_bare);
     -	strip_trailing_slashes(dir);
    -+		dir = guess_target_dir_from_git_url(repo_name, is_bundle, option_bare);
    ++		dir = git_url_basename(repo_name, is_bundle, option_bare);
     +	strip_dir_trailing_slashes(dir);
      
      	dest_exists = path_exists(dir);
    @@ dir.c: int is_empty_dir(const char *path)
      	return ret;
      }
      
    -+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare)
    ++char *git_url_basename(const char *repo, int is_bundle, int is_bare)
     +{
     +	const char *end = repo + strlen(repo), *start, *ptr;
     +	size_t len;
    @@ dir.h: static inline int is_dot_or_dotdot(const char *name)
      int is_empty_dir(const char *dir);
      
     +/*
    -+ * Retrieve a target directory name by reading "humanish" part of the
    -+ * given Git URL.
    ++ * Retrieve the "humanish" basename of the given Git URL.
     + *
     + * For example:
     + * 	/path/to/repo.git => "repo"
     + * 	host.xz.foo/.git => "foo"
     + */
    -+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare);
    ++char *git_url_basename(const char *repo, int is_bundle, int is_bare);
     +void strip_dir_trailing_slashes(char *dir);
     +
      void setup_standard_excludes(struct dir_struct *dir);
2:  11eea777ba ! 5:  a3aa25518d submodule--helper: convert the bulk of cmd_add() to C
    @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv,
     +
     +	add_data.repo = argv[0];
     +	if (argc == 1)
    -+		add_data.sm_path = guess_target_dir_from_git_url(add_data.repo, 0, 0);
    ++		add_data.sm_path = git_url_basename(add_data.repo, 0, 0);
     +	else
     +		add_data.sm_path = xstrdup(argv[1]);
     +
3:  51393cd99b = 6:  9667159d4b submodule--helper: remove add-clone subcommand
4:  50cedcd8a8 = 7:  dc87b5627a submodule--helper: remove add-config subcommand
5:  02558da532 = 8:  ea08e4fbad submodule--helper: remove resolve-relative-url subcommand
-- 
2.32.0


^ permalink raw reply	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
@ 2021-08-07  7:16       ` Atharva Raykar
  2021-08-08 17:41         ` Kaartic Sivaraam
  2021-08-07  7:16       ` [GSoC] [PATCH v4 2/8] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
                         ` (8 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-07  7:16 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Let's modify the interface to `compute_submodule_clone_url()` function
by adding two more arguments, so that we can reuse this in various parts
of `submodule--helper.c` that follow a common pattern, which is--read
the remote url configuration of the superproject and then call
`relative_url()`.

This function is nearly identical to `resolve_relative_url()`, the only
difference being the extra warning message. We can add a quiet flag to
it, to suppress that warning when not needed, and then refactor
`resolve_relative_url()` by using this function, something we will do in
the next patch.

Having this functionality factored out will be useful for converting the
rest of `submodule add` in subsequent patches.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6891480013..2d2d8ac637 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -590,7 +590,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static char *compute_submodule_clone_url(const char *rel_url)
+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
 {
 	char *remoteurl, *relurl;
 	char *remote = get_default_remote();
@@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)
 
 	strbuf_addf(&remotesb, "remote.%s.url", remote);
 	if (git_config_get_string(remotesb.buf, &remoteurl)) {
-		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
+		if (!quiet)
+			warning(_("could not look up configuration '%s'. "
+				  "Assuming this repository is its own "
+				  "authoritative upstream."),
+				remotesb.buf);
 		remoteurl = xgetcwd();
 	}
-	relurl = relative_url(remoteurl, rel_url, NULL);
+	relurl = relative_url(remoteurl, rel_url, up_path);
 
 	free(remote);
 	free(remoteurl);
@@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(url) ||
 		    starts_with_dot_slash(url)) {
 			char *oldurl = url;
-			url = compute_submodule_clone_url(oldurl);
+			url = compute_submodule_clone_url(oldurl, NULL, 0);
 			free(oldurl);
 		}
 
@@ -2134,7 +2138,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	if (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {
 		if (starts_with_dot_slash(sub->url) ||
 		    starts_with_dot_dot_slash(sub->url)) {
-			url = compute_submodule_clone_url(sub->url);
+			url = compute_submodule_clone_url(sub->url, NULL, 0);
 			need_free_url = 1;
 		} else
 			url = sub->url;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v4 2/8] submodule--helper: refactor resolve_relative_url() helper
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
  2021-08-07  7:16       ` [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
@ 2021-08-07  7:16       ` Atharva Raykar
  2021-08-07  7:16       ` [GSoC] [PATCH v4 3/8] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
                         ` (7 subsequent siblings)
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-07  7:16 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Refactor the helper function to resolve a relative url, by reusing the
existing `compute_submodule_clone_url()` function.

`compute_submodule_clone_url()` performs the same work that
`resolve_relative_url()` is doing, so we eliminate this code repetition
by moving the former function's definition up, and calling it inside
`resolve_relative_url()`.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 61 +++++++++++++++----------------------
 1 file changed, 25 insertions(+), 36 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2d2d8ac637..f4b496bac6 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -199,33 +199,46 @@ static char *relative_url(const char *remote_url,
 	return strbuf_detach(&sb, NULL);
 }
 
+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
+{
+	char *remoteurl, *relurl;
+	char *remote = get_default_remote();
+	struct strbuf remotesb = STRBUF_INIT;
+
+	strbuf_addf(&remotesb, "remote.%s.url", remote);
+	if (git_config_get_string(remotesb.buf, &remoteurl)) {
+		if (!quiet)
+			warning(_("could not look up configuration '%s'. "
+				  "Assuming this repository is its own "
+				  "authoritative upstream."),
+				remotesb.buf);
+		remoteurl = xgetcwd();
+	}
+	relurl = relative_url(remoteurl, rel_url, up_path);
+
+	free(remote);
+	free(remoteurl);
+	strbuf_release(&remotesb);
+
+	return relurl;
+}
+
 static int resolve_relative_url(int argc, const char **argv, const char *prefix)
 {
-	char *remoteurl = NULL;
-	char *remote = get_default_remote();
 	const char *up_path = NULL;
 	char *res;
 	const char *url;
-	struct strbuf sb = STRBUF_INIT;
 
 	if (argc != 2 && argc != 3)
 		die("resolve-relative-url only accepts one or two arguments");
 
 	url = argv[1];
-	strbuf_addf(&sb, "remote.%s.url", remote);
-	free(remote);
-
-	if (git_config_get_string(sb.buf, &remoteurl))
-		/* the repository is its own authoritative upstream */
-		remoteurl = xgetcwd();
-
 	if (argc == 3)
 		up_path = argv[2];
 
-	res = relative_url(remoteurl, url, up_path);
+	res = compute_submodule_clone_url(url, up_path, 1);
 	puts(res);
 	free(res);
-	free(remoteurl);
 	return 0;
 }
 
@@ -590,30 +603,6 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
-{
-	char *remoteurl, *relurl;
-	char *remote = get_default_remote();
-	struct strbuf remotesb = STRBUF_INIT;
-
-	strbuf_addf(&remotesb, "remote.%s.url", remote);
-	if (git_config_get_string(remotesb.buf, &remoteurl)) {
-		if (!quiet)
-			warning(_("could not look up configuration '%s'. "
-				  "Assuming this repository is its own "
-				  "authoritative upstream."),
-				remotesb.buf);
-		remoteurl = xgetcwd();
-	}
-	relurl = relative_url(remoteurl, rel_url, up_path);
-
-	free(remote);
-	free(remoteurl);
-	strbuf_release(&remotesb);
-
-	return relurl;
-}
-
 struct init_cb {
 	const char *prefix;
 	unsigned int flags;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v4 3/8] submodule--helper: remove repeated code in sync_submodule()
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
  2021-08-07  7:16       ` [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
  2021-08-07  7:16       ` [GSoC] [PATCH v4 2/8] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
@ 2021-08-07  7:16       ` Atharva Raykar
  2021-08-08 19:00         ` Kaartic Sivaraam
  2021-08-07  7:16       ` [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c Atharva Raykar
                         ` (6 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-07  7:16 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

This part of `sync_submodule()` is doing the same thing that
`compute_submodule_clone_url()` is doing. Let's reuse that helper here.

Note that this change adds a small overhead where we allocate and free
the 'remote' twice, but that is a small price to pay for the higher
level of abstraction we get.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f4b496bac6..9b676c12f8 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,
 	if (sub && sub->url) {
 		if (starts_with_dot_dot_slash(sub->url) ||
 		    starts_with_dot_slash(sub->url)) {
-			char *remote_url, *up_path;
-			char *remote = get_default_remote();
-			strbuf_addf(&sb, "remote.%s.url", remote);
-
-			if (git_config_get_string(sb.buf, &remote_url))
-				remote_url = xgetcwd();
-
-			up_path = get_up_path(path);
-			sub_origin_url = relative_url(remote_url, sub->url, up_path);
-			super_config_url = relative_url(remote_url, sub->url, NULL);
-
-			free(remote);
+			char *up_path = get_up_path(path);
+			sub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);
+			super_config_url = compute_submodule_clone_url(sub->url, NULL, 1);
 			free(up_path);
-			free(remote_url);
 		} else {
 			sub_origin_url = xstrdup(sub->url);
 			super_config_url = xstrdup(sub->url);
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                         ` (2 preceding siblings ...)
  2021-08-07  7:16       ` [GSoC] [PATCH v4 3/8] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
@ 2021-08-07  7:16       ` Atharva Raykar
  2021-08-08 19:23         ` Kaartic Sivaraam
  2021-08-07  7:16       ` [GSoC] [PATCH v4 5/8] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
                         ` (5 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-07  7:16 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

These functions can be useful to other parts of Git. Let's move them to
dir.c, while renaming them to be make their functionality more explicit.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/clone.c | 118 +-----------------------------------------------
 dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++
 dir.h           |  10 ++++
 3 files changed, 126 insertions(+), 116 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 66fe66679c..5ba24b7ae7 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -217,120 +217,6 @@ static char *get_repo_path(const char *repo, int *is_bundle)
 	return canon;
 }
 
-static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
-{
-	const char *end = repo + strlen(repo), *start, *ptr;
-	size_t len;
-	char *dir;
-
-	/*
-	 * Skip scheme.
-	 */
-	start = strstr(repo, "://");
-	if (start == NULL)
-		start = repo;
-	else
-		start += 3;
-
-	/*
-	 * Skip authentication data. The stripping does happen
-	 * greedily, such that we strip up to the last '@' inside
-	 * the host part.
-	 */
-	for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
-		if (*ptr == '@')
-			start = ptr + 1;
-	}
-
-	/*
-	 * Strip trailing spaces, slashes and /.git
-	 */
-	while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
-		end--;
-	if (end - start > 5 && is_dir_sep(end[-5]) &&
-	    !strncmp(end - 4, ".git", 4)) {
-		end -= 5;
-		while (start < end && is_dir_sep(end[-1]))
-			end--;
-	}
-
-	/*
-	 * Strip trailing port number if we've got only a
-	 * hostname (that is, there is no dir separator but a
-	 * colon). This check is required such that we do not
-	 * strip URI's like '/foo/bar:2222.git', which should
-	 * result in a dir '2222' being guessed due to backwards
-	 * compatibility.
-	 */
-	if (memchr(start, '/', end - start) == NULL
-	    && memchr(start, ':', end - start) != NULL) {
-		ptr = end;
-		while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
-			ptr--;
-		if (start < ptr && ptr[-1] == ':')
-			end = ptr - 1;
-	}
-
-	/*
-	 * Find last component. To remain backwards compatible we
-	 * also regard colons as path separators, such that
-	 * cloning a repository 'foo:bar.git' would result in a
-	 * directory 'bar' being guessed.
-	 */
-	ptr = end;
-	while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
-		ptr--;
-	start = ptr;
-
-	/*
-	 * Strip .{bundle,git}.
-	 */
-	len = end - start;
-	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
-
-	if (!len || (len == 1 && *start == '/'))
-		die(_("No directory name could be guessed.\n"
-		      "Please specify a directory on the command line"));
-
-	if (is_bare)
-		dir = xstrfmt("%.*s.git", (int)len, start);
-	else
-		dir = xstrndup(start, len);
-	/*
-	 * Replace sequences of 'control' characters and whitespace
-	 * with one ascii space, remove leading and trailing spaces.
-	 */
-	if (*dir) {
-		char *out = dir;
-		int prev_space = 1 /* strip leading whitespace */;
-		for (end = dir; *end; ++end) {
-			char ch = *end;
-			if ((unsigned char)ch < '\x20')
-				ch = '\x20';
-			if (isspace(ch)) {
-				if (prev_space)
-					continue;
-				prev_space = 1;
-			} else
-				prev_space = 0;
-			*out++ = ch;
-		}
-		*out = '\0';
-		if (out > dir && prev_space)
-			out[-1] = '\0';
-	}
-	return dir;
-}
-
-static void strip_trailing_slashes(char *dir)
-{
-	char *end = dir + strlen(dir);
-
-	while (dir < end - 1 && is_dir_sep(end[-1]))
-		end--;
-	*end = '\0';
-}
-
 static int add_one_reference(struct string_list_item *item, void *cb_data)
 {
 	struct strbuf err = STRBUF_INIT;
@@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	if (argc == 2)
 		dir = xstrdup(argv[1]);
 	else
-		dir = guess_dir_name(repo_name, is_bundle, option_bare);
-	strip_trailing_slashes(dir);
+		dir = git_url_basename(repo_name, is_bundle, option_bare);
+	strip_dir_trailing_slashes(dir);
 
 	dest_exists = path_exists(dir);
 	if (dest_exists && !is_empty_dir(dir))
diff --git a/dir.c b/dir.c
index 03c4d21267..6d26db3189 100644
--- a/dir.c
+++ b/dir.c
@@ -2970,6 +2970,120 @@ int is_empty_dir(const char *path)
 	return ret;
 }
 
+char *git_url_basename(const char *repo, int is_bundle, int is_bare)
+{
+	const char *end = repo + strlen(repo), *start, *ptr;
+	size_t len;
+	char *dir;
+
+	/*
+	 * Skip scheme.
+	 */
+	start = strstr(repo, "://");
+	if (start == NULL)
+		start = repo;
+	else
+		start += 3;
+
+	/*
+	 * Skip authentication data. The stripping does happen
+	 * greedily, such that we strip up to the last '@' inside
+	 * the host part.
+	 */
+	for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
+		if (*ptr == '@')
+			start = ptr + 1;
+	}
+
+	/*
+	 * Strip trailing spaces, slashes and /.git
+	 */
+	while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
+		end--;
+	if (end - start > 5 && is_dir_sep(end[-5]) &&
+	    !strncmp(end - 4, ".git", 4)) {
+		end -= 5;
+		while (start < end && is_dir_sep(end[-1]))
+			end--;
+	}
+
+	/*
+	 * Strip trailing port number if we've got only a
+	 * hostname (that is, there is no dir separator but a
+	 * colon). This check is required such that we do not
+	 * strip URI's like '/foo/bar:2222.git', which should
+	 * result in a dir '2222' being guessed due to backwards
+	 * compatibility.
+	 */
+	if (memchr(start, '/', end - start) == NULL
+	    && memchr(start, ':', end - start) != NULL) {
+		ptr = end;
+		while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
+			ptr--;
+		if (start < ptr && ptr[-1] == ':')
+			end = ptr - 1;
+	}
+
+	/*
+	 * Find last component. To remain backwards compatible we
+	 * also regard colons as path separators, such that
+	 * cloning a repository 'foo:bar.git' would result in a
+	 * directory 'bar' being guessed.
+	 */
+	ptr = end;
+	while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
+		ptr--;
+	start = ptr;
+
+	/*
+	 * Strip .{bundle,git}.
+	 */
+	len = end - start;
+	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
+
+	if (!len || (len == 1 && *start == '/'))
+		die(_("No directory name could be guessed.\n"
+		      "Please specify a directory on the command line"));
+
+	if (is_bare)
+		dir = xstrfmt("%.*s.git", (int)len, start);
+	else
+		dir = xstrndup(start, len);
+	/*
+	 * Replace sequences of 'control' characters and whitespace
+	 * with one ascii space, remove leading and trailing spaces.
+	 */
+	if (*dir) {
+		char *out = dir;
+		int prev_space = 1 /* strip leading whitespace */;
+		for (end = dir; *end; ++end) {
+			char ch = *end;
+			if ((unsigned char)ch < '\x20')
+				ch = '\x20';
+			if (isspace(ch)) {
+				if (prev_space)
+					continue;
+				prev_space = 1;
+			} else
+				prev_space = 0;
+			*out++ = ch;
+		}
+		*out = '\0';
+		if (out > dir && prev_space)
+			out[-1] = '\0';
+	}
+	return dir;
+}
+
+void strip_dir_trailing_slashes(char *dir)
+{
+	char *end = dir + strlen(dir);
+
+	while (dir < end - 1 && is_dir_sep(end[-1]))
+		end--;
+	*end = '\0';
+}
+
 static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
 {
 	DIR *dir;
diff --git a/dir.h b/dir.h
index b3e1a54a97..a4a6fd7371 100644
--- a/dir.h
+++ b/dir.h
@@ -453,6 +453,16 @@ static inline int is_dot_or_dotdot(const char *name)
 
 int is_empty_dir(const char *dir);
 
+/*
+ * Retrieve the "humanish" basename of the given Git URL.
+ *
+ * For example:
+ * 	/path/to/repo.git => "repo"
+ * 	host.xz.foo/.git => "foo"
+ */
+char *git_url_basename(const char *repo, int is_bundle, int is_bare);
+void strip_dir_trailing_slashes(char *dir);
+
 void setup_standard_excludes(struct dir_struct *dir);
 
 char *get_sparse_checkout_filename(void);
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v4 5/8] submodule--helper: convert the bulk of cmd_add() to C
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                         ` (3 preceding siblings ...)
  2021-08-07  7:16       ` [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c Atharva Raykar
@ 2021-08-07  7:16       ` Atharva Raykar
  2021-08-07  7:16       ` [GSoC] [PATCH v4 6/8] submodule--helper: remove add-clone subcommand Atharva Raykar
                         ` (4 subsequent siblings)
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-07  7:16 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Introduce the 'add' subcommand to `submodule--helper.c` that does all
the work 'submodule add' past the parsing of flags.

We also remove the constness of the sm_path field of the `add_data`
struct. This is needed so that it can be modified by
normalize_path_copy().

As with the previous conversions, this is meant to be a faithful
conversion with no modification to the behaviour of `submodule add`.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Helped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
Based-on-patch-by: Shourya Shukla <periperidip@gmail.com>
Based-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>
---
 builtin/submodule--helper.c | 165 +++++++++++++++++++++++++++++++++++-
 git-submodule.sh            |  96 +--------------------
 2 files changed, 166 insertions(+), 95 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 9b676c12f8..3aa3ae8b61 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2748,7 +2748,7 @@ struct add_data {
 	const char *prefix;
 	const char *branch;
 	const char *reference_path;
-	const char *sm_path;
+	char *sm_path;
 	const char *sm_name;
 	const char *repo;
 	const char *realrepo;
@@ -3046,6 +3046,168 @@ static int add_config(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+static void die_on_index_match(const char *path, int force)
+{
+	struct pathspec ps;
+	const char *args[] = { path, NULL };
+	parse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);
+
+	if (read_cache_preload(NULL) < 0)
+		die(_("index file corrupt"));
+
+	if (ps.nr) {
+		int i;
+		char *ps_matched = xcalloc(ps.nr, 1);
+
+		/* TODO: audit for interaction with sparse-index. */
+		ensure_full_index(&the_index);
+
+		/*
+		 * Since there is only one pathspec, we just need
+		 * need to check ps_matched[0] to know if a cache
+		 * entry matched.
+		 */
+		for (i = 0; i < active_nr; i++) {
+			ce_path_match(&the_index, active_cache[i], &ps,
+				      ps_matched);
+
+			if (ps_matched[0]) {
+				if (!force)
+					die(_("'%s' already exists in the index"),
+					    path);
+				if (!S_ISGITLINK(active_cache[i]->ce_mode))
+					die(_("'%s' already exists in the index "
+					      "and is not a submodule"), path);
+				break;
+			}
+		}
+		free(ps_matched);
+	}
+}
+
+static void die_on_repo_without_commits(const char *path)
+{
+	struct strbuf sb = STRBUF_INIT;
+	strbuf_addstr(&sb, path);
+	if (is_nonbare_repository_dir(&sb)) {
+		struct object_id oid;
+		if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
+			die(_("'%s' does not have a commit checked out"), path);
+	}
+}
+
+static int module_add(int argc, const char **argv, const char *prefix)
+{
+	int force = 0, quiet = 0, progress = 0, dissociate = 0;
+	struct add_data add_data = ADD_DATA_INIT;
+
+	struct option options[] = {
+		OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
+			   N_("branch of repository to add as submodule")),
+		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
+			   PARSE_OPT_NOCOMPLETE),
+		OPT__QUIET(&quiet, N_("print only error messages")),
+		OPT_BOOL(0, "progress", &progress, N_("force cloning progress")),
+		OPT_STRING(0, "reference", &add_data.reference_path, N_("repository"),
+			   N_("reference repository")),
+		OPT_BOOL(0, "dissociate", &dissociate, N_("borrow the objects from reference repositories")),
+		OPT_STRING(0, "name", &add_data.sm_name, N_("name"),
+			   N_("sets the submodule’s name to the given string "
+			      "instead of defaulting to its path")),
+		OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
+		OPT_END()
+	};
+
+	const char *const usage[] = {
+		N_("git submodule--helper add [<options>] [--] <repository> [<path>]"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, options, usage, 0);
+
+	if (!is_writing_gitmodules_ok())
+		die(_("please make sure that the .gitmodules file is in the working tree"));
+
+	if (prefix && *prefix &&
+	    add_data.reference_path && !is_absolute_path(add_data.reference_path))
+		add_data.reference_path = xstrfmt("%s%s", prefix, add_data.reference_path);
+
+	if (argc == 0 || argc > 2)
+		usage_with_options(usage, options);
+
+	add_data.repo = argv[0];
+	if (argc == 1)
+		add_data.sm_path = git_url_basename(add_data.repo, 0, 0);
+	else
+		add_data.sm_path = xstrdup(argv[1]);
+
+	if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
+		add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
+
+	if (starts_with_dot_dot_slash(add_data.repo) ||
+	    starts_with_dot_slash(add_data.repo)) {
+		if (prefix)
+			die(_("Relative path can only be used from the toplevel "
+			      "of the working tree"));
+
+		/* dereference source url relative to parent's url */
+		add_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);
+	} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {
+		add_data.realrepo = add_data.repo;
+	} else {
+		die(_("repo URL: '%s' must be absolute or begin with ./|../"),
+		    add_data.repo);
+	}
+
+	/*
+	 * normalize path:
+	 * multiple //; leading ./; /./; /../;
+	 */
+	normalize_path_copy(add_data.sm_path, add_data.sm_path);
+	strip_dir_trailing_slashes(add_data.sm_path);
+
+	die_on_index_match(add_data.sm_path, force);
+	die_on_repo_without_commits(add_data.sm_path);
+
+	if (!force) {
+		int exit_code = -1;
+		struct strbuf sb = STRBUF_INIT;
+		struct child_process cp = CHILD_PROCESS_INIT;
+		cp.git_cmd = 1;
+		cp.no_stdout = 1;
+		strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
+			     "--no-warn-embedded-repo", add_data.sm_path, NULL);
+		if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
+			strbuf_complete_line(&sb);
+			fputs(sb.buf, stderr);
+			free(add_data.sm_path);
+			return exit_code;
+		}
+		strbuf_release(&sb);
+	}
+
+	if(!add_data.sm_name)
+		add_data.sm_name = add_data.sm_path;
+
+	if (check_submodule_name(add_data.sm_name))
+		die(_("'%s' is not a valid submodule name"), add_data.sm_name);
+
+	add_data.prefix = prefix;
+	add_data.force = !!force;
+	add_data.quiet = !!quiet;
+	add_data.progress = !!progress;
+	add_data.dissociate = !!dissociate;
+
+	if (add_submodule(&add_data)) {
+		free(add_data.sm_path);
+		return 1;
+	}
+	configure_added_submodule(&add_data);
+	free(add_data.sm_path);
+
+	return 0;
+}
+
 #define SUPPORT_SUPER_PREFIX (1<<0)
 
 struct cmd_struct {
@@ -3060,6 +3222,7 @@ static struct cmd_struct commands[] = {
 	{"clone", module_clone, 0},
 	{"add-clone", add_clone, 0},
 	{"add-config", add_config, 0},
+	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
 	{"update-clone", update_clone, 0},
 	{"ensure-core-worktree", ensure_core_worktree, 0},
diff --git a/git-submodule.sh b/git-submodule.sh
index 8c219ef382..1070540525 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -145,104 +145,12 @@ cmd_add()
 		shift
 	done
 
-	if ! git submodule--helper config --check-writeable >/dev/null 2>&1
+	if test -z "$1"
 	then
-		 die "fatal: $(eval_gettext "please make sure that the .gitmodules file is in the working tree")"
-	fi
-
-	if test -n "$reference_path"
-	then
-		is_absolute_path "$reference_path" ||
-		reference_path="$wt_prefix$reference_path"
-
-		reference="--reference=$reference_path"
-	fi
-
-	repo=$1
-	sm_path=$2
-
-	if test -z "$sm_path"; then
-		sm_path=$(printf '%s\n' "$repo" |
-			sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
-	fi
-
-	if test -z "$repo" || test -z "$sm_path"; then
 		usage
 	fi
 
-	is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
-
-	# assure repo is absolute or relative to parent
-	case "$repo" in
-	./*|../*)
-		test -z "$wt_prefix" ||
-		die "fatal: $(gettext "Relative path can only be used from the toplevel of the working tree")"
-
-		# dereference source url relative to parent's url
-		realrepo=$(git submodule--helper resolve-relative-url "$repo") || exit
-		;;
-	*:*|/*)
-		# absolute url
-		realrepo=$repo
-		;;
-	*)
-		die "fatal: $(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
-	;;
-	esac
-
-	# normalize path:
-	# multiple //; leading ./; /./; /../; trailing /
-	sm_path=$(printf '%s/\n' "$sm_path" |
-		sed -e '
-			s|//*|/|g
-			s|^\(\./\)*||
-			s|/\(\./\)*|/|g
-			:start
-			s|\([^/]*\)/\.\./||
-			tstart
-			s|/*$||
-		')
-	if test -z "$force"
-	then
-		git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
-		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index")"
-	else
-		git ls-files -s "$sm_path" | sane_grep -v "^160000" > /dev/null 2>&1 &&
-		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
-	fi
-
-	if test -d "$sm_path" &&
-		test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null)
-	then
-	    git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null ||
-	    die "fatal: $(eval_gettext "'\$sm_path' does not have a commit checked out")"
-	fi
-
-	if test -z "$force"
-	then
-	    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" 2>&1 >/dev/null)
-	    res=$?
-	    if test $res -ne 0
-	    then
-		 echo >&2 "$dryerr"
-		 exit $res
-	    fi
-	fi
-
-	if test -n "$custom_name"
-	then
-		sm_name="$custom_name"
-	else
-		sm_name="$sm_path"
-	fi
-
-	if ! git submodule--helper check-name "$sm_name"
-	then
-		die "fatal: $(eval_gettext "'$sm_name' is not a valid submodule name")"
-	fi
-
-	git submodule--helper add-clone ${GIT_QUIET:+--quiet} ${force:+"--force"} ${progress:+"--progress"} ${branch:+--branch "$branch"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit
-	git submodule--helper add-config ${force:+--force} ${branch:+--branch "$branch"} --url "$repo" --resolved-url "$realrepo" --path "$sm_path" --name "$sm_name"
+	git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper add ${GIT_QUIET:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@"
 }
 
 #
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v4 6/8] submodule--helper: remove add-clone subcommand
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                         ` (4 preceding siblings ...)
  2021-08-07  7:16       ` [GSoC] [PATCH v4 5/8] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
@ 2021-08-07  7:16       ` Atharva Raykar
  2021-08-07  7:16       ` [GSoC] [PATCH v4 7/8] submodule--helper: remove add-config subcommand Atharva Raykar
                         ` (3 subsequent siblings)
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-07  7:16 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

We no longer need this subcommand, as all of its functionality is being
called by the newly-introduced `module_add()` directly within C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 60 -------------------------------------
 1 file changed, 60 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 3aa3ae8b61..5932438d65 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2860,65 +2860,6 @@ static int add_submodule(const struct add_data *add_data)
 	return 0;
 }
 
-static int add_clone(int argc, const char **argv, const char *prefix)
-{
-	int force = 0, quiet = 0, dissociate = 0, progress = 0;
-	struct add_data add_data = ADD_DATA_INIT;
-
-	struct option options[] = {
-		OPT_STRING('b', "branch", &add_data.branch,
-			   N_("branch"),
-			   N_("branch of repository to checkout on cloning")),
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("alternative anchor for relative paths")),
-		OPT_STRING(0, "path", &add_data.sm_path,
-			   N_("path"),
-			   N_("where the new submodule will be cloned to")),
-		OPT_STRING(0, "name", &add_data.sm_name,
-			   N_("string"),
-			   N_("name of the new submodule")),
-		OPT_STRING(0, "url", &add_data.realrepo,
-			   N_("string"),
-			   N_("url where to clone the submodule from")),
-		OPT_STRING(0, "reference", &add_data.reference_path,
-			   N_("repo"),
-			   N_("reference repository")),
-		OPT_BOOL(0, "dissociate", &dissociate,
-			 N_("use --reference only while cloning")),
-		OPT_INTEGER(0, "depth", &add_data.depth,
-			    N_("depth for shallow clones")),
-		OPT_BOOL(0, "progress", &progress,
-			 N_("force cloning progress")),
-		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT__QUIET(&quiet, "suppress output for cloning a submodule"),
-		OPT_END()
-	};
-
-	const char *const usage[] = {
-		N_("git submodule--helper add-clone [<options>...] "
-		   "--url <url> --path <path> --name <name>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (argc != 0)
-		usage_with_options(usage, options);
-
-	add_data.prefix = prefix;
-	add_data.progress = !!progress;
-	add_data.dissociate = !!dissociate;
-	add_data.force = !!force;
-	add_data.quiet = !!quiet;
-
-	if (add_submodule(&add_data))
-		return 1;
-
-	return 0;
-}
-
 static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
 {
 	char *key;
@@ -3220,7 +3161,6 @@ static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
 	{"name", module_name, 0},
 	{"clone", module_clone, 0},
-	{"add-clone", add_clone, 0},
 	{"add-config", add_config, 0},
 	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v4 7/8] submodule--helper: remove add-config subcommand
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                         ` (5 preceding siblings ...)
  2021-08-07  7:16       ` [GSoC] [PATCH v4 6/8] submodule--helper: remove add-clone subcommand Atharva Raykar
@ 2021-08-07  7:16       ` Atharva Raykar
  2021-08-07  7:16       ` [GSoC] [PATCH v4 8/8] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
                         ` (2 subsequent siblings)
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-07  7:16 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Also no longer needed is this subcommand, as all of its functionality is
being called by the newly-introduced `module_add()` directly within C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 49 -------------------------------------
 1 file changed, 49 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 5932438d65..d526423a0c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2939,54 +2939,6 @@ static void configure_added_submodule(struct add_data *add_data)
 	}
 }
 
-static int add_config(int argc, const char **argv, const char *prefix)
-{
-	int force = 0;
-	struct add_data add_data = ADD_DATA_INIT;
-
-	struct option options[] = {
-		OPT_STRING('b', "branch", &add_data.branch,
-			   N_("branch"),
-			   N_("branch of repository to store in "
-			      "the submodule configuration")),
-		OPT_STRING(0, "url", &add_data.repo,
-			   N_("string"),
-			   N_("url to clone submodule from")),
-		OPT_STRING(0, "resolved-url", &add_data.realrepo,
-			   N_("string"),
-			   N_("url to clone the submodule from, after it has "
-			      "been dereferenced relative to parent's url, "
-			      "in the case where <url> is a relative url")),
-		OPT_STRING(0, "path", &add_data.sm_path,
-			   N_("path"),
-			   N_("where the new submodule will be cloned to")),
-		OPT_STRING(0, "name", &add_data.sm_name,
-			   N_("string"),
-			   N_("name of the new submodule")),
-		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_END()
-	};
-
-	const char *const usage[] = {
-		N_("git submodule--helper add-config "
-		   "[--force|-f] [--branch|-b <branch>] "
-		   "--url <url> --resolved-url <resolved-url> "
-		   "--path <path> --name <name>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (argc)
-		usage_with_options(usage, options);
-
-	add_data.force = !!force;
-	configure_added_submodule(&add_data);
-
-	return 0;
-}
-
 static void die_on_index_match(const char *path, int force)
 {
 	struct pathspec ps;
@@ -3161,7 +3113,6 @@ static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
 	{"name", module_name, 0},
 	{"clone", module_clone, 0},
-	{"add-config", add_config, 0},
 	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
 	{"update-clone", update_clone, 0},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v4 8/8] submodule--helper: remove resolve-relative-url subcommand
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                         ` (6 preceding siblings ...)
  2021-08-07  7:16       ` [GSoC] [PATCH v4 7/8] submodule--helper: remove add-config subcommand Atharva Raykar
@ 2021-08-07  7:16       ` Atharva Raykar
  2021-08-08 18:01       ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Kaartic Sivaraam
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-07  7:16 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

The shell subcommand `resolve-relative-url` is no longer required, as
its last caller has been removed when it was converted to C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 20 --------------------
 1 file changed, 20 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d526423a0c..bc123d7aaf 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -223,25 +223,6 @@ static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat
 	return relurl;
 }
 
-static int resolve_relative_url(int argc, const char **argv, const char *prefix)
-{
-	const char *up_path = NULL;
-	char *res;
-	const char *url;
-
-	if (argc != 2 && argc != 3)
-		die("resolve-relative-url only accepts one or two arguments");
-
-	url = argv[1];
-	if (argc == 3)
-		up_path = argv[2];
-
-	res = compute_submodule_clone_url(url, up_path, 1);
-	puts(res);
-	free(res);
-	return 0;
-}
-
 static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)
 {
 	char *remoteurl, *res;
@@ -3118,7 +3099,6 @@ static struct cmd_struct commands[] = {
 	{"update-clone", update_clone, 0},
 	{"ensure-core-worktree", ensure_core_worktree, 0},
 	{"relative-path", resolve_relative_path, 0},
-	{"resolve-relative-url", resolve_relative_url, 0},
 	{"resolve-relative-url-test", resolve_relative_url_test, 0},
 	{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
 	{"init", module_init, SUPPORT_SUPER_PREFIX},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-07  7:16       ` [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
@ 2021-08-08 17:41         ` Kaartic Sivaraam
  2021-08-08 18:26           ` Kaartic Sivaraam
  0 siblings, 1 reply; 78+ messages in thread
From: Kaartic Sivaraam @ 2021-08-08 17:41 UTC (permalink / raw)
  To: Atharva Raykar, Junio C Hamano
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, pc44800, periperidip, rafaeloliveira.cs, sunshine

On 07/08/21 12:46 pm, Atharva Raykar wrote:
> Let's modify the interface to `compute_submodule_clone_url()` function
> by adding two more arguments, so that we can reuse this in various parts
> of `submodule--helper.c` that follow a common pattern, which is--read
> the remote url configuration of the superproject and then call
> `relative_url()`.
> 
> This function is nearly identical to `resolve_relative_url()`, the only
> difference being the extra warning message. We can add a quiet flag to
> it, ...

It took me a while to figure what "it" meant in the above sentence. Does it
refer to `compute_submodule_clone_url` or `resolve_relative_url`. After one
sees the patch and takes a look at `resolve_relative_url`, it's clear the "it"
indeed does refer to `resolve_relative_url`. But it might worth clarifying this
in the commit message itself.

Certainly not worth a re-roll on its own. May be Junio could amend this while queing ?


> ...  to suppress that warning when not needed, and then refactor
> `resolve_relative_url()` by using this function, something we will do in
> the next patch.
> 
> Having this functionality factored out will be useful for converting the
> rest of `submodule add` in subsequent patches.
> 
> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Shourya Shukla <periperidip@gmail.com>

Otherwise, this looks good.

-- 
Sivaraam

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                         ` (7 preceding siblings ...)
  2021-08-07  7:16       ` [GSoC] [PATCH v4 8/8] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
@ 2021-08-08 18:01       ` Kaartic Sivaraam
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
  9 siblings, 0 replies; 78+ messages in thread
From: Kaartic Sivaraam @ 2021-08-08 18:01 UTC (permalink / raw)
  To: Atharva Raykar, gitster
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git,
	jrnieder, pc44800, periperidip, rafaeloliveira.cs, sunshine

On 07/08/21 12:46 pm, Atharva Raykar wrote:
> Changes since v3:
> 
> * Rename the libified dir helper and update the docstring.
>

Just a note. I'm not really sure about this yet, the fact
that this series depends on the change introduced by
'ar/submodule-add-config'[1] might be worth mentioning in
re-rolls too. This could help the maintainer to easily identify
the topic dependency :-)

[1]: https://lore.kernel.org/git/20210801063352.50813-1-raykar.ath@gmail.com/

And ...

> Atharva Raykar (8):
>    submodule--helper: add options for compute_submodule_clone_url()
>    submodule--helper: refactor resolve_relative_url() helper
>    submodule--helper: remove repeated code in sync_submodule()
>    dir: libify and export helper functions from clone.c
>    submodule--helper: convert the bulk of cmd_add() to C
>    submodule--helper: remove add-clone subcommand
>    submodule--helper: remove add-config subcommand
>    submodule--helper: remove resolve-relative-url subcommand
> 
>   builtin/clone.c             | 118 +-------------
>   builtin/submodule--helper.c | 307 +++++++++++++++++++-----------------
>   dir.c                       | 114 +++++++++++++
>   dir.h                       |  10 ++
>   git-submodule.sh            |  96 +----------
>   5 files changed, 290 insertions(+), 355 deletions(-)
> 
> Range-diff against v3:

Thanks for consistently including a useful range-diff!

-- 
Sivaraam

> -:  ---------- > 1:  75edf24186 submodule--helper: add options for compute_submodule_clone_url()
> -:  ---------- > 2:  8e7a3e727a submodule--helper: refactor resolve_relative_url() helper
> -:  ---------- > 3:  82961ddd02 submodule--helper: remove repeated code in sync_submodule()
> 1:  99d139375d ! 4:  fa97d6801e dir: libify and export helper functions from clone.c
>      @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
>        	else
>       -		dir = guess_dir_name(repo_name, is_bundle, option_bare);
>       -	strip_trailing_slashes(dir);
>      -+		dir = guess_target_dir_from_git_url(repo_name, is_bundle, option_bare);
>      ++		dir = git_url_basename(repo_name, is_bundle, option_bare);
>       +	strip_dir_trailing_slashes(dir);
>        
>        	dest_exists = path_exists(dir);
>      @@ dir.c: int is_empty_dir(const char *path)
>        	return ret;
>        }
>        
>      -+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare)
>      ++char *git_url_basename(const char *repo, int is_bundle, int is_bare)
>       +{
>       +	const char *end = repo + strlen(repo), *start, *ptr;
>       +	size_t len;
>      @@ dir.h: static inline int is_dot_or_dotdot(const char *name)
>        int is_empty_dir(const char *dir);
>        
>       +/*
>      -+ * Retrieve a target directory name by reading "humanish" part of the
>      -+ * given Git URL.
>      ++ * Retrieve the "humanish" basename of the given Git URL.
>       + *
>       + * For example:
>       + * 	/path/to/repo.git => "repo"
>       + * 	host.xz.foo/.git => "foo"
>       + */
>      -+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare);
>      ++char *git_url_basename(const char *repo, int is_bundle, int is_bare);
>       +void strip_dir_trailing_slashes(char *dir);
>       +
>        void setup_standard_excludes(struct dir_struct *dir);
> 2:  11eea777ba ! 5:  a3aa25518d submodule--helper: convert the bulk of cmd_add() to C
>      @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv,
>       +
>       +	add_data.repo = argv[0];
>       +	if (argc == 1)
>      -+		add_data.sm_path = guess_target_dir_from_git_url(add_data.repo, 0, 0);
>      ++		add_data.sm_path = git_url_basename(add_data.repo, 0, 0);
>       +	else
>       +		add_data.sm_path = xstrdup(argv[1]);
>       +
> 3:  51393cd99b = 6:  9667159d4b submodule--helper: remove add-clone subcommand
> 4:  50cedcd8a8 = 7:  dc87b5627a submodule--helper: remove add-config subcommand
> 5:  02558da532 = 8:  ea08e4fbad submodule--helper: remove resolve-relative-url subcommand
> 

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-08 17:41         ` Kaartic Sivaraam
@ 2021-08-08 18:26           ` Kaartic Sivaraam
  2021-08-09  7:29             ` Atharva Raykar
  0 siblings, 1 reply; 78+ messages in thread
From: Kaartic Sivaraam @ 2021-08-08 18:26 UTC (permalink / raw)
  To: Atharva Raykar, Junio C Hamano
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git,
	jrnieder, pc44800, periperidip, rafaeloliveira.cs, sunshine

On 08/08/21 11:11 pm, Kaartic Sivaraam wrote:
> On 07/08/21 12:46 pm, Atharva Raykar wrote:
>> Let's modify the interface to `compute_submodule_clone_url()` function
>> by adding two more arguments, so that we can reuse this in various parts
>> of `submodule--helper.c` that follow a common pattern, which is--read
>> the remote url configuration of the superproject and then call
>> `relative_url()`.
>>
>> This function is nearly identical to `resolve_relative_url()`, the only
>> difference being the extra warning message. We can add a quiet flag to
>> it, ...
> 
> It took me a while to figure what "it" meant in the above sentence. Does it
> refer to `compute_submodule_clone_url` or `resolve_relative_url`. After one
> sees the patch and takes a look at `resolve_relative_url`, it's clear the "it"
> indeed does refer to `resolve_relative_url`. But it might worth clarifying this
> in the commit message itself.
> 
> Certainly not worth a re-roll on its own. May be Junio could amend this while queing ?
> 
Actually, I just noticed two other things which might be re-roll worthy. Read on ...

> -static char *compute_submodule_clone_url(const char *rel_url)
> +static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
>  {
>  	char *remoteurl, *relurl;

I know this isn't new code. But there's already an argument names
'rel_url'. So, a variable named 'relurl' in the same scope is making it
hard to distinguish between these two. Could you also try distinguishing
these better by renaming 'relurl' to 'res' or something else?

>  	char *remote = get_default_remote();
> @@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)
>  
>  	strbuf_addf(&remotesb, "remote.%s.url", remote);
>  	if (git_config_get_string(remotesb.buf, &remoteurl)) {
> -		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
> +		if (!quiet)
> +			warning(_("could not look up configuration '%s'. "
> +				  "Assuming this repository is its own "
> +				  "authoritative upstream."),
> +				remotesb.buf);
>  		remoteurl = xgetcwd();
>  	}
> -	relurl = relative_url(remoteurl, rel_url, NULL);
> +	relurl = relative_url(remoteurl, rel_url, up_path);

After reading 2/8 of the series, I just noticed that 'remoteurl' is always
initialized in 'resolve_realtive_url'. It is either initialized to the return
value of 'xgetcwd' or retains its assigned value of 'NULL'. But it looks
like that's not the case here. 'remoteurl' could be used uninitialized
when the above if block does not get executed which in turn could result in
weird behaviour in case 'remoteurl' gets a value of anything other than 'NULL'
at runtime.

This again has nothing to do with the change done in this patch. Regardless, it
looks like something worth correcting. Thus, I thought of pointing it out.

>  
>  	free(remote);
>  	free(remoteurl);
> @@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,
>  		if (starts_with_dot_dot_slash(url) ||
>  		    starts_with_dot_slash(url)) {
>  			char *oldurl = url;
> -			url = compute_submodule_clone_url(oldurl);
> +			url = compute_submodule_clone_url(oldurl, NULL, 0);
>  			free(oldurl);
>  		}
>


-- 
Sivaraam

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 3/8] submodule--helper: remove repeated code in sync_submodule()
  2021-08-07  7:16       ` [GSoC] [PATCH v4 3/8] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
@ 2021-08-08 19:00         ` Kaartic Sivaraam
  2021-08-09  7:36           ` Atharva Raykar
  0 siblings, 1 reply; 78+ messages in thread
From: Kaartic Sivaraam @ 2021-08-08 19:00 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, pc44800, periperidip, rafaeloliveira.cs, sunshine

On 07/08/21 12:46 pm, Atharva Raykar wrote:
> This part of `sync_submodule()` is doing the same thing that
> `compute_submodule_clone_url()` is doing. Let's reuse that helper here.
> 

Nice to see more code redundancy being removed. Now that we're using
'compute_submodule_clone_url' in multiple places, I'm starting to
wonder if the name still suits the helper. Yeah, I just started yet
another naming discussion ;-) I guess this one wouldn't be tough though.
It feels to me like 'resolve_relative_url' is a good enough name that
doesn't mislead readers by having 'clone_url' in its name. In case anyone
else has better name suggestions, they are indeed very welcome to suggest
those :-)

Once there's agreement on a particular name, I think the helper function
could be renamed. Possibly in a new patch next to this one.

> Note that this change adds a small overhead where we allocate and free
> the 'remote' twice, but that is a small price to pay for the higher
> level of abstraction we get.
> 
> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Shourya Shukla <periperidip@gmail.com>
> ---
>   builtin/submodule--helper.c | 16 +++-------------
>   1 file changed, 3 insertions(+), 13 deletions(-)
> 
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index f4b496bac6..9b676c12f8 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,
>   	if (sub && sub->url) {
>   		if (starts_with_dot_dot_slash(sub->url) ||
>   		    starts_with_dot_slash(sub->url)) {
> -			char *remote_url, *up_path;
> -			char *remote = get_default_remote();
> -			strbuf_addf(&sb, "remote.%s.url", remote);
> -
> -			if (git_config_get_string(sb.buf, &remote_url))
> -				remote_url = xgetcwd();
> -
> -			up_path = get_up_path(path);
> -			sub_origin_url = relative_url(remote_url, sub->url, up_path);
> -			super_config_url = relative_url(remote_url, sub->url, NULL);
> -
> -			free(remote);
> +			char *up_path = get_up_path(path);
> +			sub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);
> +			super_config_url = compute_submodule_clone_url(sub->url, NULL, 1);
>   			free(up_path);
> -			free(remote_url);
>   		} else {
>   			sub_origin_url = xstrdup(sub->url);
>   			super_config_url = xstrdup(sub->url);
> 


-- 
Sivaraam

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c
  2021-08-07  7:16       ` [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c Atharva Raykar
@ 2021-08-08 19:23         ` Kaartic Sivaraam
  2021-08-09  8:02           ` Atharva Raykar
  0 siblings, 1 reply; 78+ messages in thread
From: Kaartic Sivaraam @ 2021-08-08 19:23 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, pc44800, periperidip, rafaeloliveira.cs, sunshine

On 07/08/21 12:46 pm, Atharva Raykar wrote:
>> [ ... ]
>
> diff --git a/dir.h b/dir.h
> index b3e1a54a97..a4a6fd7371 100644
> --- a/dir.h
> +++ b/dir.h
> @@ -453,6 +453,16 @@ static inline int is_dot_or_dotdot(const char *name)
>   
>   int is_empty_dir(const char *dir);
>   
> +/*
> + * Retrieve the "humanish" basename of the given Git URL.
> + *
> + * For example:
> + * 	/path/to/repo.git => "repo"
> + * 	host.xz.foo/.git => "foo"
> + */

Are you sure about the examples here? I just tried and ...

   - '/path/to/repo.git' gave me 'repo' like you said

.. but ..

   - 'host.xz.foo/.git' gives me 'host.xz.foo' instead of 'foo'.
     I think you meant to have 'host.xz/foo.git' in the example.

Also, here's another example that might be useful to mention in the docstring:

   - 'http://example.com/user/bar.baz' => 'bar.baz'

> +char *git_url_basename(const char *repo, int is_bundle, int is_bare);
> +void strip_dir_trailing_slashes(char *dir);
> +
>   void setup_standard_excludes(struct dir_struct *dir);
>   
>   char *get_sparse_checkout_filename(void);
> 

-- 
Sivaraam

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-08 18:26           ` Kaartic Sivaraam
@ 2021-08-09  7:29             ` Atharva Raykar
  2021-08-09  8:47               ` Atharva Raykar
  0 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-09  7:29 UTC (permalink / raw)
  To: Kaartic Sivaraam
  Cc: Junio C Hamano, avarab, christian.couder, congdanhqx,
	emilyshaffer, git, jrnieder, pc44800, periperidip,
	rafaeloliveira.cs, sunshine


Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:

> On 08/08/21 11:11 pm, Kaartic Sivaraam wrote:
>> On 07/08/21 12:46 pm, Atharva Raykar wrote:
>>> [...]
>> It took me a while to figure what "it" meant in the above sentence. Does it
>> refer to `compute_submodule_clone_url` or `resolve_relative_url`. After one
>> sees the patch and takes a look at `resolve_relative_url`, it's clear the "it"
>> indeed does refer to `resolve_relative_url`. But it might worth clarifying this
>> in the commit message itself.
>> Certainly not worth a re-roll on its own. May be Junio could amend this while
>> queing ?
>>
> Actually, I just noticed two other things which might be re-roll worthy. Read on ...

I'll keep re-rolling till the code is good, it's never a problem ;-)

>> -static char *compute_submodule_clone_url(const char *rel_url)
>> +static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
>>  {
>>  	char *remoteurl, *relurl;
>
> I know this isn't new code. But there's already an argument names
> 'rel_url'. So, a variable named 'relurl' in the same scope is making it
> hard to distinguish between these two. Could you also try distinguishing
> these better by renaming 'relurl' to 'res' or something else?

Okay.

>>  	char *remote = get_default_remote();
>> @@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)
>>   	strbuf_addf(&remotesb, "remote.%s.url", remote);
>>  	if (git_config_get_string(remotesb.buf, &remoteurl)) {
>> -		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
>> +		if (!quiet)
>> +			warning(_("could not look up configuration '%s'. "
>> +				  "Assuming this repository is its own "
>> +				  "authoritative upstream."),
>> +				remotesb.buf);
>>  		remoteurl = xgetcwd();
>>  	}
>> -	relurl = relative_url(remoteurl, rel_url, NULL);
>> +	relurl = relative_url(remoteurl, rel_url, up_path);
>
> After reading 2/8 of the series, I just noticed that 'remoteurl' is always
> initialized in 'resolve_realtive_url'. It is either initialized to the return
> value of 'xgetcwd' or retains its assigned value of 'NULL'. But it looks
> like that's not the case here. 'remoteurl' could be used uninitialized
> when the above if block does not get executed which in turn could result in
> weird behaviour in case 'remoteurl' gets a value of anything other than 'NULL'
> at runtime.
>
> This again has nothing to do with the change done in this patch. Regardless, it
> looks like something worth correcting. Thus, I thought of pointing it out.
>

Right. I agree it should be corrected.

>>   	free(remote);
>>  	free(remoteurl);
>> @@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,
>>  		if (starts_with_dot_dot_slash(url) ||
>>  		    starts_with_dot_slash(url)) {
>>  			char *oldurl = url;
>> -			url = compute_submodule_clone_url(oldurl);
>> +			url = compute_submodule_clone_url(oldurl, NULL, 0);
>>  			free(oldurl);
>>  		}
>>

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 3/8] submodule--helper: remove repeated code in sync_submodule()
  2021-08-08 19:00         ` Kaartic Sivaraam
@ 2021-08-09  7:36           ` Atharva Raykar
  0 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-09  7:36 UTC (permalink / raw)
  To: Kaartic Sivaraam
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, pc44800, periperidip, rafaeloliveira.cs, sunshine


Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:

> On 07/08/21 12:46 pm, Atharva Raykar wrote:
>> This part of `sync_submodule()` is doing the same thing that
>> `compute_submodule_clone_url()` is doing. Let's reuse that helper here.
>>
>
> Nice to see more code redundancy being removed. Now that we're using
> 'compute_submodule_clone_url' in multiple places, I'm starting to
> wonder if the name still suits the helper. Yeah, I just started yet
> another naming discussion ;-) I guess this one wouldn't be tough though.
> It feels to me like 'resolve_relative_url' is a good enough name that
> doesn't mislead readers by having 'clone_url' in its name. In case anyone
> else has better name suggestions, they are indeed very welcome to suggest
> those :-)
>
> Once there's agreement on a particular name, I think the helper function
> could be renamed. Possibly in a new patch next to this one.

I don't mind the rename back to resolve_relative_url(), although it
definitely has to come in a separate patch. I didn't want to create a
situation where readers will be confused about what actually happened
with that function. I felt a thing might happen if I repurpose it from
subcommand to internal helper in the same patch.

>> Note that this change adds a small overhead where we allocate and free
>> the 'remote' twice, but that is a small price to pay for the higher
>> level of abstraction we get.
>> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
>> Mentored-by: Christian Couder <christian.couder@gmail.com>
>> Mentored-by: Shourya Shukla <periperidip@gmail.com>
>> ---
>>   builtin/submodule--helper.c | 16 +++-------------
>>   1 file changed, 3 insertions(+), 13 deletions(-)
>> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
>> index f4b496bac6..9b676c12f8 100644
>> --- a/builtin/submodule--helper.c
>> +++ b/builtin/submodule--helper.c
>> @@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,
>>   	if (sub && sub->url) {
>>   		if (starts_with_dot_dot_slash(sub->url) ||
>>   		    starts_with_dot_slash(sub->url)) {
>> -			char *remote_url, *up_path;
>> -			char *remote = get_default_remote();
>> -			strbuf_addf(&sb, "remote.%s.url", remote);
>> -
>> -			if (git_config_get_string(sb.buf, &remote_url))
>> -				remote_url = xgetcwd();
>> -
>> -			up_path = get_up_path(path);
>> -			sub_origin_url = relative_url(remote_url, sub->url, up_path);
>> -			super_config_url = relative_url(remote_url, sub->url, NULL);
>> -
>> -			free(remote);
>> +			char *up_path = get_up_path(path);
>> +			sub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);
>> +			super_config_url = compute_submodule_clone_url(sub->url, NULL, 1);
>>   			free(up_path);
>> -			free(remote_url);
>>   		} else {
>>   			sub_origin_url = xstrdup(sub->url);
>>   			super_config_url = xstrdup(sub->url);
>>

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c
  2021-08-08 19:23         ` Kaartic Sivaraam
@ 2021-08-09  8:02           ` Atharva Raykar
  2021-08-10 17:53             ` Kaartic Sivaraam
  0 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-09  8:02 UTC (permalink / raw)
  To: Kaartic Sivaraam
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, pc44800, periperidip, rafaeloliveira.cs, sunshine


Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:

> On 07/08/21 12:46 pm, Atharva Raykar wrote:
>>> [ ... ]
>>
>> diff --git a/dir.h b/dir.h
>> index b3e1a54a97..a4a6fd7371 100644
>> --- a/dir.h
>> +++ b/dir.h
>> @@ -453,6 +453,16 @@ static inline int is_dot_or_dotdot(const char *name)
>>     int is_empty_dir(const char *dir);
>>   +/*
>> + * Retrieve the "humanish" basename of the given Git URL.
>> + *
>> + * For example:
>> + * 	/path/to/repo.git => "repo"
>> + * 	host.xz.foo/.git => "foo"
>> + */
>
> Are you sure about the examples here? I just tried and ...
>
>   - '/path/to/repo.git' gave me 'repo' like you said
>
> .. but ..
>
>   - 'host.xz.foo/.git' gives me 'host.xz.foo' instead of 'foo'.
>     I think you meant to have 'host.xz/foo.git' in the example.

Yikes! I meant 'host.xz:foo/.git'. That should give us 'foo'. Thanks for
the correction.

> Also, here's another example that might be useful to mention in the docstring:
>
>   - 'http://example.com/user/bar.baz' => 'bar.baz'

Yeah, especially since that's probably the most familiar example for
most end users.

>> +char *git_url_basename(const char *repo, int is_bundle, int is_bare);
>> +void strip_dir_trailing_slashes(char *dir);
>> +
>>   void setup_standard_excludes(struct dir_struct *dir);
>>     char *get_sparse_checkout_filename(void);
>>

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-09  7:29             ` Atharva Raykar
@ 2021-08-09  8:47               ` Atharva Raykar
  2021-08-10 17:36                 ` Kaartic Sivaraam
  0 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-09  8:47 UTC (permalink / raw)
  To: Kaartic Sivaraam
  Cc: Junio C Hamano, avarab, christian.couder, congdanhqx,
	emilyshaffer, git, jrnieder, pc44800, periperidip,
	rafaeloliveira.cs, sunshine


Atharva Raykar <raykar.ath@gmail.com> writes:

> Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:
>
>> On 08/08/21 11:11 pm, Kaartic Sivaraam wrote:
>>> On 07/08/21 12:46 pm, Atharva Raykar wrote:
>>> [...]
>>>  	char *remote = get_default_remote();
>>> @@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)
>>>   	strbuf_addf(&remotesb, "remote.%s.url", remote);
>>>  	if (git_config_get_string(remotesb.buf, &remoteurl)) {
>>> -		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
>>> +		if (!quiet)
>>> +			warning(_("could not look up configuration '%s'. "
>>> +				  "Assuming this repository is its own "
>>> +				  "authoritative upstream."),
>>> +				remotesb.buf);
>>>  		remoteurl = xgetcwd();
>>>  	}
>>> -	relurl = relative_url(remoteurl, rel_url, NULL);
>>> +	relurl = relative_url(remoteurl, rel_url, up_path);
>>
>> After reading 2/8 of the series, I just noticed that 'remoteurl' is always
>> initialized in 'resolve_realtive_url'. It is either initialized to the return
>> value of 'xgetcwd' or retains its assigned value of 'NULL'. But it looks
>> like that's not the case here. 'remoteurl' could be used uninitialized
>> when the above if block does not get executed which in turn could result in
>> weird behaviour in case 'remoteurl' gets a value of anything other than 'NULL'
>> at runtime.
>>
>> This again has nothing to do with the change done in this patch. Regardless, it
>> looks like something worth correcting. Thus, I thought of pointing it out.
>>
>
> Right. I agree it should be corrected.

Actually on having another look, I'm not sure if we need to assign NULL
to 'remoteurl' at all.

The 'if (git_config_get_string(...))' on success will allocate
'remoteurl'. If it fails, it will be given the return value of
'xgetcwd()'. There is nothing in the config API docs that suggest a
success mode for the git_config_get_*() functions that will assign
nothing to the buffer we give it. Therefore, by the time we get to the
variable's first use in the 'relative_url()' function, we are guaranteed
to have a well-defined value.

It seems to me that the original 'resolve_relative_url()' had an
unnecessary NULL initialization.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v5 0/9] submodule: convert the rest of 'add' to C
  2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
                         ` (8 preceding siblings ...)
  2021-08-08 18:01       ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Kaartic Sivaraam
@ 2021-08-10 11:46       ` Atharva Raykar
  2021-08-10 11:46         ` [GSoC] [PATCH v5 1/9] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
                           ` (9 more replies)
  9 siblings, 10 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-10 11:46 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

NOTE: This series uses (ar/submodule-add-config):
https://lore.kernel.org/git/20210806140431.92018-1-raykar.ath@gmail.com/

Since v4:
* Rename a local variable in 'compute_submodule_clone_url()' to reduce ambiguity.
* Add a new patch that renames 'compute_submodule_clone_url()' to
  'resolve_relative_url()' to better convey its use. We add it at the end after
  the 'resolve-relative-url' subcommand is removed so that there is no confusion
  as to what that function name binds to.
* Fix incorrect example in the docstring for 'git_url_basename()'. Also add
  another example for more clarity.

Also since this query of mine got buried in the revisions, I shall include it
here again:

Questions about the cache API used in [PATCH 5/9]:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1. What is the difference between 'read_cache()' and 'read_cache_preload()'?
     From what I can tell, the latter optimistically preloads the index stat
     data. Is there any reason to use 'read_cache()' over
     'read_cache_preload()'?
  2. Which one is more appropriate for use in 'die_on_index_match()'?

Fetch-it-Via:
git fetch https://github.com/tfidfwastaken/git submodule-helper-add-list-5

Atharva Raykar (9):
  submodule--helper: add options for compute_submodule_clone_url()
  submodule--helper: refactor resolve_relative_url() helper
  submodule--helper: remove repeated code in sync_submodule()
  dir: libify and export helper functions from clone.c
  submodule--helper: convert the bulk of cmd_add() to C
  submodule--helper: remove add-clone subcommand
  submodule--helper: remove add-config subcommand
  submodule--helper: remove resolve-relative-url subcommand
  submodule--helper: rename compute_submodule_clone_url()

 builtin/clone.c             | 118 +-------------
 builtin/submodule--helper.c | 307 +++++++++++++++++++-----------------
 dir.c                       | 114 +++++++++++++
 dir.h                       |  11 ++
 git-submodule.sh            |  96 +----------
 5 files changed, 291 insertions(+), 355 deletions(-)

Range-diff against v4:
 1:  75edf24186 !  1:  78e19c4b01 submodule--helper: add options for compute_submodule_clone_url()
    @@ Commit message
         `resolve_relative_url()` by using this function, something we will do in
         the next patch.
     
    +    We also rename the local variable 'relurl' to avoid potential confusion
    +    with the 'rel_url' parameter while we are at it.
    +
         Having this functionality factored out will be useful for converting the
         rest of `submodule add` in subsequent patches.
     
    @@ builtin/submodule--helper.c: static int module_foreach(int argc, const char **ar
     -static char *compute_submodule_clone_url(const char *rel_url)
     +static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
      {
    - 	char *remoteurl, *relurl;
    +-	char *remoteurl, *relurl;
    ++	char *remoteurl, *resolved_url;
      	char *remote = get_default_remote();
    -@@ builtin/submodule--helper.c: static char *compute_submodule_clone_url(const char *rel_url)
    + 	struct strbuf remotesb = STRBUF_INIT;
      
      	strbuf_addf(&remotesb, "remote.%s.url", remote);
      	if (git_config_get_string(remotesb.buf, &remoteurl)) {
    @@ builtin/submodule--helper.c: static char *compute_submodule_clone_url(const char
      		remoteurl = xgetcwd();
      	}
     -	relurl = relative_url(remoteurl, rel_url, NULL);
    -+	relurl = relative_url(remoteurl, rel_url, up_path);
    ++	resolved_url = relative_url(remoteurl, rel_url, up_path);
      
      	free(remote);
      	free(remoteurl);
    + 	strbuf_release(&remotesb);
    + 
    +-	return relurl;
    ++	return resolved_url;
    + }
    + 
    + struct init_cb {
     @@ builtin/submodule--helper.c: static void init_submodule(const char *path, const char *prefix,
      		if (starts_with_dot_dot_slash(url) ||
      		    starts_with_dot_slash(url)) {
 2:  8e7a3e727a !  2:  faadf74ec1 submodule--helper: refactor resolve_relative_url() helper
    @@ builtin/submodule--helper.c: static char *relative_url(const char *remote_url,
     +static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
      {
     -	char *remoteurl = NULL;
    -+	char *remoteurl, *relurl;
    ++	char *remoteurl, *resolved_url;
      	char *remote = get_default_remote();
     +	struct strbuf remotesb = STRBUF_INIT;
     +
    @@ builtin/submodule--helper.c: static char *relative_url(const char *remote_url,
     +				remotesb.buf);
     +		remoteurl = xgetcwd();
     +	}
    -+	relurl = relative_url(remoteurl, rel_url, up_path);
    ++	resolved_url = relative_url(remoteurl, rel_url, up_path);
     +
     +	free(remote);
     +	free(remoteurl);
     +	strbuf_release(&remotesb);
     +
    -+	return relurl;
    ++	return resolved_url;
     +}
     +
     +static int resolve_relative_url(int argc, const char **argv, const char *prefix)
    @@ builtin/submodule--helper.c: static int module_foreach(int argc, const char **ar
      
     -static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
     -{
    --	char *remoteurl, *relurl;
    +-	char *remoteurl, *resolved_url;
     -	char *remote = get_default_remote();
     -	struct strbuf remotesb = STRBUF_INIT;
     -
    @@ builtin/submodule--helper.c: static int module_foreach(int argc, const char **ar
     -				remotesb.buf);
     -		remoteurl = xgetcwd();
     -	}
    --	relurl = relative_url(remoteurl, rel_url, up_path);
    +-	resolved_url = relative_url(remoteurl, rel_url, up_path);
     -
     -	free(remote);
     -	free(remoteurl);
     -	strbuf_release(&remotesb);
     -
    --	return relurl;
    +-	return resolved_url;
     -}
     -
      struct init_cb {
 3:  82961ddd02 =  3:  d2127bd09a submodule--helper: remove repeated code in sync_submodule()
 4:  fa97d6801e !  4:  4b05f93def dir: libify and export helper functions from clone.c
    @@ dir.h: static inline int is_dot_or_dotdot(const char *name)
     + *
     + * For example:
     + * 	/path/to/repo.git => "repo"
    -+ * 	host.xz.foo/.git => "foo"
    ++ * 	host.xz:foo/.git => "foo"
    ++ * 	http://example.com/user/bar.baz => "bar.baz"
     + */
     +char *git_url_basename(const char *repo, int is_bundle, int is_bare);
     +void strip_dir_trailing_slashes(char *dir);
 5:  a3aa25518d =  5:  1491a011b0 submodule--helper: convert the bulk of cmd_add() to C
 6:  9667159d4b =  6:  5d5d07a6ba submodule--helper: remove add-clone subcommand
 7:  dc87b5627a =  7:  0ea27c2a15 submodule--helper: remove add-config subcommand
 8:  ea08e4fbad !  8:  6bd2571f73 submodule--helper: remove resolve-relative-url subcommand
    @@ Commit message
     
      ## builtin/submodule--helper.c ##
     @@ builtin/submodule--helper.c: static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat
    - 	return relurl;
    + 	return resolved_url;
      }
      
     -static int resolve_relative_url(int argc, const char **argv, const char *prefix)
 -:  ---------- >  9:  14a05a0c1d submodule--helper: rename compute_submodule_clone_url()
-- 
2.32.0


^ permalink raw reply	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v5 1/9] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
@ 2021-08-10 11:46         ` Atharva Raykar
  2021-08-11  6:44           ` Bagas Sanjaya
  2021-08-10 11:46         ` [GSoC] [PATCH v5 2/9] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
                           ` (8 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Atharva Raykar @ 2021-08-10 11:46 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Let's modify the interface to `compute_submodule_clone_url()` function
by adding two more arguments, so that we can reuse this in various parts
of `submodule--helper.c` that follow a common pattern, which is--read
the remote url configuration of the superproject and then call
`relative_url()`.

This function is nearly identical to `resolve_relative_url()`, the only
difference being the extra warning message. We can add a quiet flag to
it, to suppress that warning when not needed, and then refactor
`resolve_relative_url()` by using this function, something we will do in
the next patch.

We also rename the local variable 'relurl' to avoid potential confusion
with the 'rel_url' parameter while we are at it.

Having this functionality factored out will be useful for converting the
rest of `submodule add` in subsequent patches.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6891480013..d850b30fce 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -590,24 +590,28 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static char *compute_submodule_clone_url(const char *rel_url)
+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
 {
-	char *remoteurl, *relurl;
+	char *remoteurl, *resolved_url;
 	char *remote = get_default_remote();
 	struct strbuf remotesb = STRBUF_INIT;
 
 	strbuf_addf(&remotesb, "remote.%s.url", remote);
 	if (git_config_get_string(remotesb.buf, &remoteurl)) {
-		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
+		if (!quiet)
+			warning(_("could not look up configuration '%s'. "
+				  "Assuming this repository is its own "
+				  "authoritative upstream."),
+				remotesb.buf);
 		remoteurl = xgetcwd();
 	}
-	relurl = relative_url(remoteurl, rel_url, NULL);
+	resolved_url = relative_url(remoteurl, rel_url, up_path);
 
 	free(remote);
 	free(remoteurl);
 	strbuf_release(&remotesb);
 
-	return relurl;
+	return resolved_url;
 }
 
 struct init_cb {
@@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(url) ||
 		    starts_with_dot_slash(url)) {
 			char *oldurl = url;
-			url = compute_submodule_clone_url(oldurl);
+			url = compute_submodule_clone_url(oldurl, NULL, 0);
 			free(oldurl);
 		}
 
@@ -2134,7 +2138,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	if (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {
 		if (starts_with_dot_slash(sub->url) ||
 		    starts_with_dot_dot_slash(sub->url)) {
-			url = compute_submodule_clone_url(sub->url);
+			url = compute_submodule_clone_url(sub->url, NULL, 0);
 			need_free_url = 1;
 		} else
 			url = sub->url;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v5 2/9] submodule--helper: refactor resolve_relative_url() helper
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
  2021-08-10 11:46         ` [GSoC] [PATCH v5 1/9] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
@ 2021-08-10 11:46         ` Atharva Raykar
  2021-08-10 11:46         ` [GSoC] [PATCH v5 3/9] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
                           ` (7 subsequent siblings)
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-10 11:46 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Refactor the helper function to resolve a relative url, by reusing the
existing `compute_submodule_clone_url()` function.

`compute_submodule_clone_url()` performs the same work that
`resolve_relative_url()` is doing, so we eliminate this code repetition
by moving the former function's definition up, and calling it inside
`resolve_relative_url()`.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 61 +++++++++++++++----------------------
 1 file changed, 25 insertions(+), 36 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d850b30fce..fe126cdee9 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -199,33 +199,46 @@ static char *relative_url(const char *remote_url,
 	return strbuf_detach(&sb, NULL);
 }
 
+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
+{
+	char *remoteurl, *resolved_url;
+	char *remote = get_default_remote();
+	struct strbuf remotesb = STRBUF_INIT;
+
+	strbuf_addf(&remotesb, "remote.%s.url", remote);
+	if (git_config_get_string(remotesb.buf, &remoteurl)) {
+		if (!quiet)
+			warning(_("could not look up configuration '%s'. "
+				  "Assuming this repository is its own "
+				  "authoritative upstream."),
+				remotesb.buf);
+		remoteurl = xgetcwd();
+	}
+	resolved_url = relative_url(remoteurl, rel_url, up_path);
+
+	free(remote);
+	free(remoteurl);
+	strbuf_release(&remotesb);
+
+	return resolved_url;
+}
+
 static int resolve_relative_url(int argc, const char **argv, const char *prefix)
 {
-	char *remoteurl = NULL;
-	char *remote = get_default_remote();
 	const char *up_path = NULL;
 	char *res;
 	const char *url;
-	struct strbuf sb = STRBUF_INIT;
 
 	if (argc != 2 && argc != 3)
 		die("resolve-relative-url only accepts one or two arguments");
 
 	url = argv[1];
-	strbuf_addf(&sb, "remote.%s.url", remote);
-	free(remote);
-
-	if (git_config_get_string(sb.buf, &remoteurl))
-		/* the repository is its own authoritative upstream */
-		remoteurl = xgetcwd();
-
 	if (argc == 3)
 		up_path = argv[2];
 
-	res = relative_url(remoteurl, url, up_path);
+	res = compute_submodule_clone_url(url, up_path, 1);
 	puts(res);
 	free(res);
-	free(remoteurl);
 	return 0;
 }
 
@@ -590,30 +603,6 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
-{
-	char *remoteurl, *resolved_url;
-	char *remote = get_default_remote();
-	struct strbuf remotesb = STRBUF_INIT;
-
-	strbuf_addf(&remotesb, "remote.%s.url", remote);
-	if (git_config_get_string(remotesb.buf, &remoteurl)) {
-		if (!quiet)
-			warning(_("could not look up configuration '%s'. "
-				  "Assuming this repository is its own "
-				  "authoritative upstream."),
-				remotesb.buf);
-		remoteurl = xgetcwd();
-	}
-	resolved_url = relative_url(remoteurl, rel_url, up_path);
-
-	free(remote);
-	free(remoteurl);
-	strbuf_release(&remotesb);
-
-	return resolved_url;
-}
-
 struct init_cb {
 	const char *prefix;
 	unsigned int flags;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v5 3/9] submodule--helper: remove repeated code in sync_submodule()
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
  2021-08-10 11:46         ` [GSoC] [PATCH v5 1/9] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
  2021-08-10 11:46         ` [GSoC] [PATCH v5 2/9] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
@ 2021-08-10 11:46         ` Atharva Raykar
  2021-08-10 11:46         ` [GSoC] [PATCH v5 4/9] dir: libify and export helper functions from clone.c Atharva Raykar
                           ` (6 subsequent siblings)
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-10 11:46 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

This part of `sync_submodule()` is doing the same thing that
`compute_submodule_clone_url()` is doing. Let's reuse that helper here.

Note that this change adds a small overhead where we allocate and free
the 'remote' twice, but that is a small price to pay for the higher
level of abstraction we get.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fe126cdee9..da77248948 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,
 	if (sub && sub->url) {
 		if (starts_with_dot_dot_slash(sub->url) ||
 		    starts_with_dot_slash(sub->url)) {
-			char *remote_url, *up_path;
-			char *remote = get_default_remote();
-			strbuf_addf(&sb, "remote.%s.url", remote);
-
-			if (git_config_get_string(sb.buf, &remote_url))
-				remote_url = xgetcwd();
-
-			up_path = get_up_path(path);
-			sub_origin_url = relative_url(remote_url, sub->url, up_path);
-			super_config_url = relative_url(remote_url, sub->url, NULL);
-
-			free(remote);
+			char *up_path = get_up_path(path);
+			sub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);
+			super_config_url = compute_submodule_clone_url(sub->url, NULL, 1);
 			free(up_path);
-			free(remote_url);
 		} else {
 			sub_origin_url = xstrdup(sub->url);
 			super_config_url = xstrdup(sub->url);
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v5 4/9] dir: libify and export helper functions from clone.c
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
                           ` (2 preceding siblings ...)
  2021-08-10 11:46         ` [GSoC] [PATCH v5 3/9] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
@ 2021-08-10 11:46         ` Atharva Raykar
  2021-08-10 11:46         ` [GSoC] [PATCH v5 5/9] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
                           ` (5 subsequent siblings)
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-10 11:46 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

These functions can be useful to other parts of Git. Let's move them to
dir.c, while renaming them to be make their functionality more explicit.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/clone.c | 118 +-----------------------------------------------
 dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++
 dir.h           |  11 +++++
 3 files changed, 127 insertions(+), 116 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 66fe66679c..5ba24b7ae7 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -217,120 +217,6 @@ static char *get_repo_path(const char *repo, int *is_bundle)
 	return canon;
 }
 
-static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
-{
-	const char *end = repo + strlen(repo), *start, *ptr;
-	size_t len;
-	char *dir;
-
-	/*
-	 * Skip scheme.
-	 */
-	start = strstr(repo, "://");
-	if (start == NULL)
-		start = repo;
-	else
-		start += 3;
-
-	/*
-	 * Skip authentication data. The stripping does happen
-	 * greedily, such that we strip up to the last '@' inside
-	 * the host part.
-	 */
-	for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
-		if (*ptr == '@')
-			start = ptr + 1;
-	}
-
-	/*
-	 * Strip trailing spaces, slashes and /.git
-	 */
-	while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
-		end--;
-	if (end - start > 5 && is_dir_sep(end[-5]) &&
-	    !strncmp(end - 4, ".git", 4)) {
-		end -= 5;
-		while (start < end && is_dir_sep(end[-1]))
-			end--;
-	}
-
-	/*
-	 * Strip trailing port number if we've got only a
-	 * hostname (that is, there is no dir separator but a
-	 * colon). This check is required such that we do not
-	 * strip URI's like '/foo/bar:2222.git', which should
-	 * result in a dir '2222' being guessed due to backwards
-	 * compatibility.
-	 */
-	if (memchr(start, '/', end - start) == NULL
-	    && memchr(start, ':', end - start) != NULL) {
-		ptr = end;
-		while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
-			ptr--;
-		if (start < ptr && ptr[-1] == ':')
-			end = ptr - 1;
-	}
-
-	/*
-	 * Find last component. To remain backwards compatible we
-	 * also regard colons as path separators, such that
-	 * cloning a repository 'foo:bar.git' would result in a
-	 * directory 'bar' being guessed.
-	 */
-	ptr = end;
-	while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
-		ptr--;
-	start = ptr;
-
-	/*
-	 * Strip .{bundle,git}.
-	 */
-	len = end - start;
-	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
-
-	if (!len || (len == 1 && *start == '/'))
-		die(_("No directory name could be guessed.\n"
-		      "Please specify a directory on the command line"));
-
-	if (is_bare)
-		dir = xstrfmt("%.*s.git", (int)len, start);
-	else
-		dir = xstrndup(start, len);
-	/*
-	 * Replace sequences of 'control' characters and whitespace
-	 * with one ascii space, remove leading and trailing spaces.
-	 */
-	if (*dir) {
-		char *out = dir;
-		int prev_space = 1 /* strip leading whitespace */;
-		for (end = dir; *end; ++end) {
-			char ch = *end;
-			if ((unsigned char)ch < '\x20')
-				ch = '\x20';
-			if (isspace(ch)) {
-				if (prev_space)
-					continue;
-				prev_space = 1;
-			} else
-				prev_space = 0;
-			*out++ = ch;
-		}
-		*out = '\0';
-		if (out > dir && prev_space)
-			out[-1] = '\0';
-	}
-	return dir;
-}
-
-static void strip_trailing_slashes(char *dir)
-{
-	char *end = dir + strlen(dir);
-
-	while (dir < end - 1 && is_dir_sep(end[-1]))
-		end--;
-	*end = '\0';
-}
-
 static int add_one_reference(struct string_list_item *item, void *cb_data)
 {
 	struct strbuf err = STRBUF_INIT;
@@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	if (argc == 2)
 		dir = xstrdup(argv[1]);
 	else
-		dir = guess_dir_name(repo_name, is_bundle, option_bare);
-	strip_trailing_slashes(dir);
+		dir = git_url_basename(repo_name, is_bundle, option_bare);
+	strip_dir_trailing_slashes(dir);
 
 	dest_exists = path_exists(dir);
 	if (dest_exists && !is_empty_dir(dir))
diff --git a/dir.c b/dir.c
index 03c4d21267..6d26db3189 100644
--- a/dir.c
+++ b/dir.c
@@ -2970,6 +2970,120 @@ int is_empty_dir(const char *path)
 	return ret;
 }
 
+char *git_url_basename(const char *repo, int is_bundle, int is_bare)
+{
+	const char *end = repo + strlen(repo), *start, *ptr;
+	size_t len;
+	char *dir;
+
+	/*
+	 * Skip scheme.
+	 */
+	start = strstr(repo, "://");
+	if (start == NULL)
+		start = repo;
+	else
+		start += 3;
+
+	/*
+	 * Skip authentication data. The stripping does happen
+	 * greedily, such that we strip up to the last '@' inside
+	 * the host part.
+	 */
+	for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
+		if (*ptr == '@')
+			start = ptr + 1;
+	}
+
+	/*
+	 * Strip trailing spaces, slashes and /.git
+	 */
+	while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
+		end--;
+	if (end - start > 5 && is_dir_sep(end[-5]) &&
+	    !strncmp(end - 4, ".git", 4)) {
+		end -= 5;
+		while (start < end && is_dir_sep(end[-1]))
+			end--;
+	}
+
+	/*
+	 * Strip trailing port number if we've got only a
+	 * hostname (that is, there is no dir separator but a
+	 * colon). This check is required such that we do not
+	 * strip URI's like '/foo/bar:2222.git', which should
+	 * result in a dir '2222' being guessed due to backwards
+	 * compatibility.
+	 */
+	if (memchr(start, '/', end - start) == NULL
+	    && memchr(start, ':', end - start) != NULL) {
+		ptr = end;
+		while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
+			ptr--;
+		if (start < ptr && ptr[-1] == ':')
+			end = ptr - 1;
+	}
+
+	/*
+	 * Find last component. To remain backwards compatible we
+	 * also regard colons as path separators, such that
+	 * cloning a repository 'foo:bar.git' would result in a
+	 * directory 'bar' being guessed.
+	 */
+	ptr = end;
+	while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
+		ptr--;
+	start = ptr;
+
+	/*
+	 * Strip .{bundle,git}.
+	 */
+	len = end - start;
+	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
+
+	if (!len || (len == 1 && *start == '/'))
+		die(_("No directory name could be guessed.\n"
+		      "Please specify a directory on the command line"));
+
+	if (is_bare)
+		dir = xstrfmt("%.*s.git", (int)len, start);
+	else
+		dir = xstrndup(start, len);
+	/*
+	 * Replace sequences of 'control' characters and whitespace
+	 * with one ascii space, remove leading and trailing spaces.
+	 */
+	if (*dir) {
+		char *out = dir;
+		int prev_space = 1 /* strip leading whitespace */;
+		for (end = dir; *end; ++end) {
+			char ch = *end;
+			if ((unsigned char)ch < '\x20')
+				ch = '\x20';
+			if (isspace(ch)) {
+				if (prev_space)
+					continue;
+				prev_space = 1;
+			} else
+				prev_space = 0;
+			*out++ = ch;
+		}
+		*out = '\0';
+		if (out > dir && prev_space)
+			out[-1] = '\0';
+	}
+	return dir;
+}
+
+void strip_dir_trailing_slashes(char *dir)
+{
+	char *end = dir + strlen(dir);
+
+	while (dir < end - 1 && is_dir_sep(end[-1]))
+		end--;
+	*end = '\0';
+}
+
 static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
 {
 	DIR *dir;
diff --git a/dir.h b/dir.h
index b3e1a54a97..63ff04f5ac 100644
--- a/dir.h
+++ b/dir.h
@@ -453,6 +453,17 @@ static inline int is_dot_or_dotdot(const char *name)
 
 int is_empty_dir(const char *dir);
 
+/*
+ * Retrieve the "humanish" basename of the given Git URL.
+ *
+ * For example:
+ * 	/path/to/repo.git => "repo"
+ * 	host.xz:foo/.git => "foo"
+ * 	http://example.com/user/bar.baz => "bar.baz"
+ */
+char *git_url_basename(const char *repo, int is_bundle, int is_bare);
+void strip_dir_trailing_slashes(char *dir);
+
 void setup_standard_excludes(struct dir_struct *dir);
 
 char *get_sparse_checkout_filename(void);
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v5 5/9] submodule--helper: convert the bulk of cmd_add() to C
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
                           ` (3 preceding siblings ...)
  2021-08-10 11:46         ` [GSoC] [PATCH v5 4/9] dir: libify and export helper functions from clone.c Atharva Raykar
@ 2021-08-10 11:46         ` Atharva Raykar
  2021-08-10 11:46         ` [GSoC] [PATCH v5 6/9] submodule--helper: remove add-clone subcommand Atharva Raykar
                           ` (4 subsequent siblings)
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-10 11:46 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Introduce the 'add' subcommand to `submodule--helper.c` that does all
the work 'submodule add' past the parsing of flags.

We also remove the constness of the sm_path field of the `add_data`
struct. This is needed so that it can be modified by
normalize_path_copy().

As with the previous conversions, this is meant to be a faithful
conversion with no modification to the behaviour of `submodule add`.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Helped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
Based-on-patch-by: Shourya Shukla <periperidip@gmail.com>
Based-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>
---
 builtin/submodule--helper.c | 165 +++++++++++++++++++++++++++++++++++-
 git-submodule.sh            |  96 +--------------------
 2 files changed, 166 insertions(+), 95 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index da77248948..bbc5b4d9fd 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2748,7 +2748,7 @@ struct add_data {
 	const char *prefix;
 	const char *branch;
 	const char *reference_path;
-	const char *sm_path;
+	char *sm_path;
 	const char *sm_name;
 	const char *repo;
 	const char *realrepo;
@@ -3046,6 +3046,168 @@ static int add_config(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
+static void die_on_index_match(const char *path, int force)
+{
+	struct pathspec ps;
+	const char *args[] = { path, NULL };
+	parse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);
+
+	if (read_cache_preload(NULL) < 0)
+		die(_("index file corrupt"));
+
+	if (ps.nr) {
+		int i;
+		char *ps_matched = xcalloc(ps.nr, 1);
+
+		/* TODO: audit for interaction with sparse-index. */
+		ensure_full_index(&the_index);
+
+		/*
+		 * Since there is only one pathspec, we just need
+		 * need to check ps_matched[0] to know if a cache
+		 * entry matched.
+		 */
+		for (i = 0; i < active_nr; i++) {
+			ce_path_match(&the_index, active_cache[i], &ps,
+				      ps_matched);
+
+			if (ps_matched[0]) {
+				if (!force)
+					die(_("'%s' already exists in the index"),
+					    path);
+				if (!S_ISGITLINK(active_cache[i]->ce_mode))
+					die(_("'%s' already exists in the index "
+					      "and is not a submodule"), path);
+				break;
+			}
+		}
+		free(ps_matched);
+	}
+}
+
+static void die_on_repo_without_commits(const char *path)
+{
+	struct strbuf sb = STRBUF_INIT;
+	strbuf_addstr(&sb, path);
+	if (is_nonbare_repository_dir(&sb)) {
+		struct object_id oid;
+		if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
+			die(_("'%s' does not have a commit checked out"), path);
+	}
+}
+
+static int module_add(int argc, const char **argv, const char *prefix)
+{
+	int force = 0, quiet = 0, progress = 0, dissociate = 0;
+	struct add_data add_data = ADD_DATA_INIT;
+
+	struct option options[] = {
+		OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
+			   N_("branch of repository to add as submodule")),
+		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
+			   PARSE_OPT_NOCOMPLETE),
+		OPT__QUIET(&quiet, N_("print only error messages")),
+		OPT_BOOL(0, "progress", &progress, N_("force cloning progress")),
+		OPT_STRING(0, "reference", &add_data.reference_path, N_("repository"),
+			   N_("reference repository")),
+		OPT_BOOL(0, "dissociate", &dissociate, N_("borrow the objects from reference repositories")),
+		OPT_STRING(0, "name", &add_data.sm_name, N_("name"),
+			   N_("sets the submodule’s name to the given string "
+			      "instead of defaulting to its path")),
+		OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
+		OPT_END()
+	};
+
+	const char *const usage[] = {
+		N_("git submodule--helper add [<options>] [--] <repository> [<path>]"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, prefix, options, usage, 0);
+
+	if (!is_writing_gitmodules_ok())
+		die(_("please make sure that the .gitmodules file is in the working tree"));
+
+	if (prefix && *prefix &&
+	    add_data.reference_path && !is_absolute_path(add_data.reference_path))
+		add_data.reference_path = xstrfmt("%s%s", prefix, add_data.reference_path);
+
+	if (argc == 0 || argc > 2)
+		usage_with_options(usage, options);
+
+	add_data.repo = argv[0];
+	if (argc == 1)
+		add_data.sm_path = git_url_basename(add_data.repo, 0, 0);
+	else
+		add_data.sm_path = xstrdup(argv[1]);
+
+	if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
+		add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
+
+	if (starts_with_dot_dot_slash(add_data.repo) ||
+	    starts_with_dot_slash(add_data.repo)) {
+		if (prefix)
+			die(_("Relative path can only be used from the toplevel "
+			      "of the working tree"));
+
+		/* dereference source url relative to parent's url */
+		add_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);
+	} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {
+		add_data.realrepo = add_data.repo;
+	} else {
+		die(_("repo URL: '%s' must be absolute or begin with ./|../"),
+		    add_data.repo);
+	}
+
+	/*
+	 * normalize path:
+	 * multiple //; leading ./; /./; /../;
+	 */
+	normalize_path_copy(add_data.sm_path, add_data.sm_path);
+	strip_dir_trailing_slashes(add_data.sm_path);
+
+	die_on_index_match(add_data.sm_path, force);
+	die_on_repo_without_commits(add_data.sm_path);
+
+	if (!force) {
+		int exit_code = -1;
+		struct strbuf sb = STRBUF_INIT;
+		struct child_process cp = CHILD_PROCESS_INIT;
+		cp.git_cmd = 1;
+		cp.no_stdout = 1;
+		strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
+			     "--no-warn-embedded-repo", add_data.sm_path, NULL);
+		if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
+			strbuf_complete_line(&sb);
+			fputs(sb.buf, stderr);
+			free(add_data.sm_path);
+			return exit_code;
+		}
+		strbuf_release(&sb);
+	}
+
+	if(!add_data.sm_name)
+		add_data.sm_name = add_data.sm_path;
+
+	if (check_submodule_name(add_data.sm_name))
+		die(_("'%s' is not a valid submodule name"), add_data.sm_name);
+
+	add_data.prefix = prefix;
+	add_data.force = !!force;
+	add_data.quiet = !!quiet;
+	add_data.progress = !!progress;
+	add_data.dissociate = !!dissociate;
+
+	if (add_submodule(&add_data)) {
+		free(add_data.sm_path);
+		return 1;
+	}
+	configure_added_submodule(&add_data);
+	free(add_data.sm_path);
+
+	return 0;
+}
+
 #define SUPPORT_SUPER_PREFIX (1<<0)
 
 struct cmd_struct {
@@ -3060,6 +3222,7 @@ static struct cmd_struct commands[] = {
 	{"clone", module_clone, 0},
 	{"add-clone", add_clone, 0},
 	{"add-config", add_config, 0},
+	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
 	{"update-clone", update_clone, 0},
 	{"ensure-core-worktree", ensure_core_worktree, 0},
diff --git a/git-submodule.sh b/git-submodule.sh
index 8c219ef382..1070540525 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -145,104 +145,12 @@ cmd_add()
 		shift
 	done
 
-	if ! git submodule--helper config --check-writeable >/dev/null 2>&1
+	if test -z "$1"
 	then
-		 die "fatal: $(eval_gettext "please make sure that the .gitmodules file is in the working tree")"
-	fi
-
-	if test -n "$reference_path"
-	then
-		is_absolute_path "$reference_path" ||
-		reference_path="$wt_prefix$reference_path"
-
-		reference="--reference=$reference_path"
-	fi
-
-	repo=$1
-	sm_path=$2
-
-	if test -z "$sm_path"; then
-		sm_path=$(printf '%s\n' "$repo" |
-			sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
-	fi
-
-	if test -z "$repo" || test -z "$sm_path"; then
 		usage
 	fi
 
-	is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
-
-	# assure repo is absolute or relative to parent
-	case "$repo" in
-	./*|../*)
-		test -z "$wt_prefix" ||
-		die "fatal: $(gettext "Relative path can only be used from the toplevel of the working tree")"
-
-		# dereference source url relative to parent's url
-		realrepo=$(git submodule--helper resolve-relative-url "$repo") || exit
-		;;
-	*:*|/*)
-		# absolute url
-		realrepo=$repo
-		;;
-	*)
-		die "fatal: $(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
-	;;
-	esac
-
-	# normalize path:
-	# multiple //; leading ./; /./; /../; trailing /
-	sm_path=$(printf '%s/\n' "$sm_path" |
-		sed -e '
-			s|//*|/|g
-			s|^\(\./\)*||
-			s|/\(\./\)*|/|g
-			:start
-			s|\([^/]*\)/\.\./||
-			tstart
-			s|/*$||
-		')
-	if test -z "$force"
-	then
-		git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
-		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index")"
-	else
-		git ls-files -s "$sm_path" | sane_grep -v "^160000" > /dev/null 2>&1 &&
-		die "fatal: $(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
-	fi
-
-	if test -d "$sm_path" &&
-		test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null)
-	then
-	    git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null ||
-	    die "fatal: $(eval_gettext "'\$sm_path' does not have a commit checked out")"
-	fi
-
-	if test -z "$force"
-	then
-	    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" 2>&1 >/dev/null)
-	    res=$?
-	    if test $res -ne 0
-	    then
-		 echo >&2 "$dryerr"
-		 exit $res
-	    fi
-	fi
-
-	if test -n "$custom_name"
-	then
-		sm_name="$custom_name"
-	else
-		sm_name="$sm_path"
-	fi
-
-	if ! git submodule--helper check-name "$sm_name"
-	then
-		die "fatal: $(eval_gettext "'$sm_name' is not a valid submodule name")"
-	fi
-
-	git submodule--helper add-clone ${GIT_QUIET:+--quiet} ${force:+"--force"} ${progress:+"--progress"} ${branch:+--branch "$branch"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit
-	git submodule--helper add-config ${force:+--force} ${branch:+--branch "$branch"} --url "$repo" --resolved-url "$realrepo" --path "$sm_path" --name "$sm_name"
+	git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper add ${GIT_QUIET:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@"
 }
 
 #
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v5 6/9] submodule--helper: remove add-clone subcommand
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
                           ` (4 preceding siblings ...)
  2021-08-10 11:46         ` [GSoC] [PATCH v5 5/9] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
@ 2021-08-10 11:46         ` Atharva Raykar
  2021-08-10 11:46         ` [GSoC] [PATCH v5 7/9] submodule--helper: remove add-config subcommand Atharva Raykar
                           ` (3 subsequent siblings)
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-10 11:46 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

We no longer need this subcommand, as all of its functionality is being
called by the newly-introduced `module_add()` directly within C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 60 -------------------------------------
 1 file changed, 60 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index bbc5b4d9fd..6ab7de7741 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2860,65 +2860,6 @@ static int add_submodule(const struct add_data *add_data)
 	return 0;
 }
 
-static int add_clone(int argc, const char **argv, const char *prefix)
-{
-	int force = 0, quiet = 0, dissociate = 0, progress = 0;
-	struct add_data add_data = ADD_DATA_INIT;
-
-	struct option options[] = {
-		OPT_STRING('b', "branch", &add_data.branch,
-			   N_("branch"),
-			   N_("branch of repository to checkout on cloning")),
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("alternative anchor for relative paths")),
-		OPT_STRING(0, "path", &add_data.sm_path,
-			   N_("path"),
-			   N_("where the new submodule will be cloned to")),
-		OPT_STRING(0, "name", &add_data.sm_name,
-			   N_("string"),
-			   N_("name of the new submodule")),
-		OPT_STRING(0, "url", &add_data.realrepo,
-			   N_("string"),
-			   N_("url where to clone the submodule from")),
-		OPT_STRING(0, "reference", &add_data.reference_path,
-			   N_("repo"),
-			   N_("reference repository")),
-		OPT_BOOL(0, "dissociate", &dissociate,
-			 N_("use --reference only while cloning")),
-		OPT_INTEGER(0, "depth", &add_data.depth,
-			    N_("depth for shallow clones")),
-		OPT_BOOL(0, "progress", &progress,
-			 N_("force cloning progress")),
-		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT__QUIET(&quiet, "suppress output for cloning a submodule"),
-		OPT_END()
-	};
-
-	const char *const usage[] = {
-		N_("git submodule--helper add-clone [<options>...] "
-		   "--url <url> --path <path> --name <name>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (argc != 0)
-		usage_with_options(usage, options);
-
-	add_data.prefix = prefix;
-	add_data.progress = !!progress;
-	add_data.dissociate = !!dissociate;
-	add_data.force = !!force;
-	add_data.quiet = !!quiet;
-
-	if (add_submodule(&add_data))
-		return 1;
-
-	return 0;
-}
-
 static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)
 {
 	char *key;
@@ -3220,7 +3161,6 @@ static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
 	{"name", module_name, 0},
 	{"clone", module_clone, 0},
-	{"add-clone", add_clone, 0},
 	{"add-config", add_config, 0},
 	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v5 7/9] submodule--helper: remove add-config subcommand
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
                           ` (5 preceding siblings ...)
  2021-08-10 11:46         ` [GSoC] [PATCH v5 6/9] submodule--helper: remove add-clone subcommand Atharva Raykar
@ 2021-08-10 11:46         ` Atharva Raykar
  2021-08-10 11:46         ` [GSoC] [PATCH v5 8/9] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
                           ` (2 subsequent siblings)
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-10 11:46 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Also no longer needed is this subcommand, as all of its functionality is
being called by the newly-introduced `module_add()` directly within C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 49 -------------------------------------
 1 file changed, 49 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6ab7de7741..0baff16686 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2939,54 +2939,6 @@ static void configure_added_submodule(struct add_data *add_data)
 	}
 }
 
-static int add_config(int argc, const char **argv, const char *prefix)
-{
-	int force = 0;
-	struct add_data add_data = ADD_DATA_INIT;
-
-	struct option options[] = {
-		OPT_STRING('b', "branch", &add_data.branch,
-			   N_("branch"),
-			   N_("branch of repository to store in "
-			      "the submodule configuration")),
-		OPT_STRING(0, "url", &add_data.repo,
-			   N_("string"),
-			   N_("url to clone submodule from")),
-		OPT_STRING(0, "resolved-url", &add_data.realrepo,
-			   N_("string"),
-			   N_("url to clone the submodule from, after it has "
-			      "been dereferenced relative to parent's url, "
-			      "in the case where <url> is a relative url")),
-		OPT_STRING(0, "path", &add_data.sm_path,
-			   N_("path"),
-			   N_("where the new submodule will be cloned to")),
-		OPT_STRING(0, "name", &add_data.sm_name,
-			   N_("string"),
-			   N_("name of the new submodule")),
-		OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_END()
-	};
-
-	const char *const usage[] = {
-		N_("git submodule--helper add-config "
-		   "[--force|-f] [--branch|-b <branch>] "
-		   "--url <url> --resolved-url <resolved-url> "
-		   "--path <path> --name <name>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (argc)
-		usage_with_options(usage, options);
-
-	add_data.force = !!force;
-	configure_added_submodule(&add_data);
-
-	return 0;
-}
-
 static void die_on_index_match(const char *path, int force)
 {
 	struct pathspec ps;
@@ -3161,7 +3113,6 @@ static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
 	{"name", module_name, 0},
 	{"clone", module_clone, 0},
-	{"add-config", add_config, 0},
 	{"add", module_add, SUPPORT_SUPER_PREFIX},
 	{"update-module-mode", module_update_module_mode, 0},
 	{"update-clone", update_clone, 0},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v5 8/9] submodule--helper: remove resolve-relative-url subcommand
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
                           ` (6 preceding siblings ...)
  2021-08-10 11:46         ` [GSoC] [PATCH v5 7/9] submodule--helper: remove add-config subcommand Atharva Raykar
@ 2021-08-10 11:46         ` Atharva Raykar
  2021-08-10 11:46         ` [GSoC] [PATCH v5 9/9] submodule--helper: rename compute_submodule_clone_url() Atharva Raykar
  2021-09-08  0:31         ` [GSoC] [PATCH v5 0/9] submodule: convert the rest of 'add' to C Junio C Hamano
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-10 11:46 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

The shell subcommand `resolve-relative-url` is no longer required, as
its last caller has been removed when it was converted to C.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 20 --------------------
 1 file changed, 20 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 0baff16686..65591e47eb 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -223,25 +223,6 @@ static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat
 	return resolved_url;
 }
 
-static int resolve_relative_url(int argc, const char **argv, const char *prefix)
-{
-	const char *up_path = NULL;
-	char *res;
-	const char *url;
-
-	if (argc != 2 && argc != 3)
-		die("resolve-relative-url only accepts one or two arguments");
-
-	url = argv[1];
-	if (argc == 3)
-		up_path = argv[2];
-
-	res = compute_submodule_clone_url(url, up_path, 1);
-	puts(res);
-	free(res);
-	return 0;
-}
-
 static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)
 {
 	char *remoteurl, *res;
@@ -3118,7 +3099,6 @@ static struct cmd_struct commands[] = {
 	{"update-clone", update_clone, 0},
 	{"ensure-core-worktree", ensure_core_worktree, 0},
 	{"relative-path", resolve_relative_path, 0},
-	{"resolve-relative-url", resolve_relative_url, 0},
 	{"resolve-relative-url-test", resolve_relative_url_test, 0},
 	{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
 	{"init", module_init, SUPPORT_SUPER_PREFIX},
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* [GSoC] [PATCH v5 9/9] submodule--helper: rename compute_submodule_clone_url()
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
                           ` (7 preceding siblings ...)
  2021-08-10 11:46         ` [GSoC] [PATCH v5 8/9] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
@ 2021-08-10 11:46         ` Atharva Raykar
  2021-09-08  0:31         ` [GSoC] [PATCH v5 0/9] submodule: convert the rest of 'add' to C Junio C Hamano
  9 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-10 11:46 UTC (permalink / raw)
  To: raykar.ath
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Let's rename 'compute_submodule_clone_url()' to 'resolve_relative_url()'
to make it clear that this internal helper need not be used exclusively
for computing submodule clone URLs.

Since the original 'resolve-relative-url' subcommand and its C entry
point has been removed in c461095ae3 (submodule--helper: remove
resolve-relative-url subcommand, 2021-07-02), this rename can be done
without causing any confusion about which function it actually binds to.

Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Shourya Shukla <periperidip@gmail.com>
---
 builtin/submodule--helper.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 65591e47eb..5ab4e17e75 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -199,7 +199,7 @@ static char *relative_url(const char *remote_url,
 	return strbuf_detach(&sb, NULL);
 }
 
-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)
+static char *resolve_relative_url(const char *rel_url, const char *up_path, int quiet)
 {
 	char *remoteurl, *resolved_url;
 	char *remote = get_default_remote();
@@ -634,7 +634,7 @@ static void init_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(url) ||
 		    starts_with_dot_slash(url)) {
 			char *oldurl = url;
-			url = compute_submodule_clone_url(oldurl, NULL, 0);
+			url = resolve_relative_url(oldurl, NULL, 0);
 			free(oldurl);
 		}
 
@@ -1355,8 +1355,8 @@ static void sync_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(sub->url) ||
 		    starts_with_dot_slash(sub->url)) {
 			char *up_path = get_up_path(path);
-			sub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);
-			super_config_url = compute_submodule_clone_url(sub->url, NULL, 1);
+			sub_origin_url = resolve_relative_url(sub->url, up_path, 1);
+			super_config_url = resolve_relative_url(sub->url, NULL, 1);
 			free(up_path);
 		} else {
 			sub_origin_url = xstrdup(sub->url);
@@ -2098,7 +2098,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	if (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {
 		if (starts_with_dot_slash(sub->url) ||
 		    starts_with_dot_dot_slash(sub->url)) {
-			url = compute_submodule_clone_url(sub->url, NULL, 0);
+			url = resolve_relative_url(sub->url, NULL, 0);
 			need_free_url = 1;
 		} else
 			url = sub->url;
@@ -3025,7 +3025,7 @@ static int module_add(int argc, const char **argv, const char *prefix)
 			      "of the working tree"));
 
 		/* dereference source url relative to parent's url */
-		add_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);
+		add_data.realrepo = resolve_relative_url(add_data.repo, NULL, 1);
 	} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {
 		add_data.realrepo = add_data.repo;
 	} else {
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-09  8:47               ` Atharva Raykar
@ 2021-08-10 17:36                 ` Kaartic Sivaraam
  0 siblings, 0 replies; 78+ messages in thread
From: Kaartic Sivaraam @ 2021-08-10 17:36 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: Junio C Hamano, avarab, christian.couder, congdanhqx,
	emilyshaffer, git, jrnieder, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

On 09/08/21 2:17 pm, Atharva Raykar wrote:
> 
> Atharva Raykar <raykar.ath@gmail.com> writes:
> 
>> Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:
>>
>>> On 08/08/21 11:11 pm, Kaartic Sivaraam wrote:
>>>> On 07/08/21 12:46 pm, Atharva Raykar wrote:
>>>> [...]
>>>>   	char *remote = get_default_remote();
>>>> @@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)
>>>>    	strbuf_addf(&remotesb, "remote.%s.url", remote);
>>>>   	if (git_config_get_string(remotesb.buf, &remoteurl)) {
>>>> -		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
>>>> +		if (!quiet)
>>>> +			warning(_("could not look up configuration '%s'. "
>>>> +				  "Assuming this repository is its own "
>>>> +				  "authoritative upstream."),
>>>> +				remotesb.buf);
>>>>   		remoteurl = xgetcwd();
>>>>   	}
>>>> -	relurl = relative_url(remoteurl, rel_url, NULL);
>>>> +	relurl = relative_url(remoteurl, rel_url, up_path);
>>>
>>> After reading 2/8 of the series, I just noticed that 'remoteurl' is always
>>> initialized in 'resolve_realtive_url'. It is either initialized to the return
>>> value of 'xgetcwd' or retains its assigned value of 'NULL'. But it looks
>>> like that's not the case here. 'remoteurl' could be used uninitialized
>>> when the above if block does not get executed which in turn could result in
>>> weird behaviour in case 'remoteurl' gets a value of anything other than 'NULL'
>>> at runtime.
>>>
>>> This again has nothing to do with the change done in this patch. Regardless, it
>>> looks like something worth correcting. Thus, I thought of pointing it out.
>>>
>>
>> Right. I agree it should be corrected.
> 
> Actually on having another look, I'm not sure if we need to assign NULL
> to 'remoteurl' at all.
> 
> The 'if (git_config_get_string(...))' on success will allocate
> 'remoteurl'. If it fails, it will be given the return value of
> 'xgetcwd()'. There is nothing in the config API docs that suggest a
> success mode for the git_config_get_*() functions that will assign
> nothing to the buffer we give it. Therefore, by the time we get to the
> variable's first use in the 'relative_url()' function, we are guaranteed
> to have a well-defined value.
> 

Ah ha! That explains why we haven't got any reports about weird behaviours
when using the likes of `git submodule init` so far ;-)

Thanks for digging this and sorry about the false flag!

> It seems to me that the original 'resolve_relative_url()' had an
> unnecessary NULL initialization.
> 

Makes sense. I guess I feel into the trap of blindly trusting that the original
code was written correctly x-<

-- 
Sivaraam

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c
  2021-08-09  8:02           ` Atharva Raykar
@ 2021-08-10 17:53             ` Kaartic Sivaraam
  2021-08-10 21:27               ` Junio C Hamano
  2021-08-11 10:25               ` Atharva Raykar
  0 siblings, 2 replies; 78+ messages in thread
From: Kaartic Sivaraam @ 2021-08-10 17:53 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, pc44800, periperidip, rafaeloliveira.cs, sunshine

On 09/08/21 1:32 pm, Atharva Raykar wrote:
> 
> Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:
> 
>> On 07/08/21 12:46 pm, Atharva Raykar wrote:
>>>> [ ... ]
>>>
>>> diff --git a/dir.h b/dir.h
>>> index b3e1a54a97..a4a6fd7371 100644
>>> --- a/dir.h
>>> +++ b/dir.h
>>> @@ -453,6 +453,16 @@ static inline int is_dot_or_dotdot(const char *name)
>>>      int is_empty_dir(const char *dir);
>>>    +/*
>>> + * Retrieve the "humanish" basename of the given Git URL.
>>> + *
>>> + * For example:
>>> + * 	/path/to/repo.git => "repo"
>>> + * 	host.xz.foo/.git => "foo"
>>> + */
>>
>> Are you sure about the examples here? I just tried and ...
>>
>>    - '/path/to/repo.git' gave me 'repo' like you said
>>
>> .. but ..
>>
>>    - 'host.xz.foo/.git' gives me 'host.xz.foo' instead of 'foo'.
>>      I think you meant to have 'host.xz/foo.git' in the example.
> 
> Yikes! I meant 'host.xz:foo/.git'. That should give us 'foo'. Thanks for
> the correction.
> 

Interesting. I've usually seen host.xz:foo like syntax in HTTP URLs. For instance,

     http://host.xz:4000/bar.baz.git

`git_url_basename` returns `bar.baz` for the above.

I wonder what real-world URL has a syntax like 'host.xz:foo/.git' for which
'foo' would be an appropriate basename to return. Does a real-world URL of
this form exist? Or is this just cooked up to demonstrate the basename that
would be returned for a hypothetical URL like this?

-- 
Sivaraam

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c
  2021-08-10 17:53             ` Kaartic Sivaraam
@ 2021-08-10 21:27               ` Junio C Hamano
  2021-08-11 10:25               ` Atharva Raykar
  1 sibling, 0 replies; 78+ messages in thread
From: Junio C Hamano @ 2021-08-10 21:27 UTC (permalink / raw)
  To: Kaartic Sivaraam
  Cc: Atharva Raykar, avarab, christian.couder, congdanhqx,
	emilyshaffer, git, jrnieder, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:

> I wonder what real-world URL has a syntax like 'host.xz:foo/.git' for which
> 'foo' would be an appropriate basename to return. Does a real-world URL of
> this form exist? Or is this just cooked up to demonstrate the basename that
> would be returned for a hypothetical URL like this?

It is not really a URL, but historically we've called them
"scp-style URL".  scp of course copied the syntax from "rcp" where
<hostname> and <pathname> are separated by a colon ':' named a file
or a directory at the named path on the named host.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v5 1/9] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-10 11:46         ` [GSoC] [PATCH v5 1/9] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
@ 2021-08-11  6:44           ` Bagas Sanjaya
  2021-08-11 10:30             ` Atharva Raykar
  0 siblings, 1 reply; 78+ messages in thread
From: Bagas Sanjaya @ 2021-08-11  6:44 UTC (permalink / raw)
  To: Atharva Raykar
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine

On 10/08/21 18.46, Atharva Raykar wrote:
>   	if (git_config_get_string(remotesb.buf, &remoteurl)) {
> -		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
> +		if (!quiet)
> +			warning(_("could not look up configuration '%s'. "
> +				  "Assuming this repository is its own "
> +				  "authoritative upstream."),
> +				remotesb.buf);
>   		remoteurl = xgetcwd();
>   	}

Why did you split warning message? We could keep that in one line.

-- 
An old man doll... just what I always wanted! - Clara

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c
  2021-08-10 17:53             ` Kaartic Sivaraam
  2021-08-10 21:27               ` Junio C Hamano
@ 2021-08-11 10:25               ` Atharva Raykar
  1 sibling, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-11 10:25 UTC (permalink / raw)
  To: Kaartic Sivaraam
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, pc44800, periperidip, rafaeloliveira.cs, sunshine


Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:

> On 09/08/21 1:32 pm, Atharva Raykar wrote:
>> Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:
>>
>>> On 07/08/21 12:46 pm, Atharva Raykar wrote:
>>>>> [ ... ]
>> Yikes! I meant 'host.xz:foo/.git'. That should give us 'foo'. Thanks for
>> the correction.
>>
>
> Interesting. I've usually seen host.xz:foo like syntax in HTTP URLs. For instance,
>
>     http://host.xz:4000/bar.baz.git
>
> `git_url_basename` returns `bar.baz` for the above.
>
> I wonder what real-world URL has a syntax like 'host.xz:foo/.git' for which
> 'foo' would be an appropriate basename to return. Does a real-world URL of
> this form exist? Or is this just cooked up to demonstrate the basename that
> would be returned for a hypothetical URL like this?

Junio already answered all of your questions, I'll just add that I
lifted that example from the git-clone documentation [1] that uses the
exact same basename extraction function.

[1] https://git-scm.com/docs/git-clone#Documentation/git-clone.txt-ltdirectorygt

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v5 1/9] submodule--helper: add options for compute_submodule_clone_url()
  2021-08-11  6:44           ` Bagas Sanjaya
@ 2021-08-11 10:30             ` Atharva Raykar
  0 siblings, 0 replies; 78+ messages in thread
From: Atharva Raykar @ 2021-08-11 10:30 UTC (permalink / raw)
  To: Bagas Sanjaya
  Cc: avarab, christian.couder, congdanhqx, emilyshaffer, git, gitster,
	jrnieder, kaartic.sivaraam, pc44800, periperidip,
	rafaeloliveira.cs, sunshine


Bagas Sanjaya <bagasdotme@gmail.com> writes:

> On 10/08/21 18.46, Atharva Raykar wrote:
>>   	if (git_config_get_string(remotesb.buf, &remoteurl)) {
>> -		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
>> +		if (!quiet)
>> +			warning(_("could not look up configuration '%s'. "
>> +				  "Assuming this repository is its own "
>> +				  "authoritative upstream."),
>> +				remotesb.buf);
>>   		remoteurl = xgetcwd();
>>   	}
>
> Why did you split warning message? We could keep that in one line.

That line was too long, and given that I was moving the function and
changing it a little bit, I decided to make it adhere more closely to
the CodingGuidelines [1] and local convention.

[1] https://github.com/git/git/blob/6c85aac65fb455af85745130ce35ddae4678db84/Documentation/CodingGuidelines#L190

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [GSoC] [PATCH v5 0/9] submodule: convert the rest of 'add' to C
  2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
                           ` (8 preceding siblings ...)
  2021-08-10 11:46         ` [GSoC] [PATCH v5 9/9] submodule--helper: rename compute_submodule_clone_url() Atharva Raykar
@ 2021-09-08  0:31         ` Junio C Hamano
  9 siblings, 0 replies; 78+ messages in thread
From: Junio C Hamano @ 2021-09-08  0:31 UTC (permalink / raw)
  To: git
  Cc: Atharva Raykar, avarab, christian.couder, congdanhqx,
	emilyshaffer, git, jrnieder, kaartic.sivaraam, pc44800,
	periperidip, rafaeloliveira.cs, sunshine

Atharva Raykar <raykar.ath@gmail.com> writes:

> NOTE: This series uses (ar/submodule-add-config):
> https://lore.kernel.org/git/20210806140431.92018-1-raykar.ath@gmail.com/

I didn't see anybody comment on this round (and do not think I saw
anything glaringly wrong).

Is everybody happy with this version?  I am about to mark it for
'next' in the next issue of "What's cooking" report, so please
holler if I should wait.

Thanks.

^ permalink raw reply	[flat|nested] 78+ messages in thread

end of thread, other threads:[~2021-09-08  0:31 UTC | newest]

Thread overview: 78+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-05  7:19 [GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
2021-08-05  7:19 ` [GSoC] [PATCH 1/8] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
2021-08-05  7:19 ` [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
2021-08-06  0:53   ` Đoàn Trần Công Danh
2021-08-06  9:06     ` Christian Couder
2021-08-06 10:06       ` Atharva Raykar
2021-08-06 16:21       ` Junio C Hamano
2021-08-05  7:19 ` [GSoC] [PATCH 3/8] dir: libify and export helper functions from clone.c Atharva Raykar
2021-08-05  7:19 ` [GSoC] [PATCH 4/8] submodule--helper: remove constness of sm_path Atharva Raykar
2021-08-05  7:19 ` [GSoC] [PATCH 5/8] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
2021-08-05  7:19 ` [GSoC] [PATCH 6/8] submodule--helper: remove add-clone subcommand Atharva Raykar
2021-08-05  7:19 ` [GSoC] [PATCH 7/8] submodule--helper: remove add-config subcommand Atharva Raykar
2021-08-05  7:19 ` [GSoC] [PATCH 8/8] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
2021-08-05  7:40 ` [GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C Atharva Raykar
2021-08-05  7:40   ` [GSoC] [PATCH v2 1/9] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
2021-08-05 20:05     ` Junio C Hamano
2021-08-05  7:40   ` [GSoC] [PATCH v2 2/9] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
2021-08-05 20:13     ` Junio C Hamano
2021-08-05  7:40   ` [GSoC] [PATCH v2 3/9] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
2021-08-05 20:20     ` Junio C Hamano
2021-08-05  7:40   ` [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c Atharva Raykar
2021-08-05 20:37     ` Junio C Hamano
2021-08-06 11:12       ` Atharva Raykar
2021-08-06 16:36         ` Junio C Hamano
2021-08-07  7:15           ` Atharva Raykar
2021-08-05  7:40   ` [GSoC] [PATCH v2 5/9] submodule--helper: remove constness of sm_path Atharva Raykar
2021-08-05 20:40     ` Junio C Hamano
2021-08-06 11:16       ` Atharva Raykar
2021-08-05  7:40   ` [GSoC] [PATCH v2 6/9] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
2021-08-06  1:14     ` Đoàn Trần Công Danh
2021-08-06 11:33       ` Atharva Raykar
2021-08-05  7:40   ` [GSoC] [PATCH v2 7/9] submodule--helper: remove add-clone subcommand Atharva Raykar
2021-08-05  7:40   ` [GSoC] [PATCH v2 8/9] submodule--helper: remove add-config subcommand Atharva Raykar
2021-08-05  7:40   ` [GSoC] [PATCH v2 9/9] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
2021-08-06 12:01   ` [GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
2021-08-06 12:01     ` [GSoC] [PATCH v3 1/8] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
2021-08-06 12:01     ` [GSoC] [PATCH v3 2/8] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
2021-08-06 12:01     ` [GSoC] [PATCH v3 3/8] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
2021-08-06 12:01     ` [GSoC] [PATCH v3 4/8] dir: libify and export helper functions from clone.c Atharva Raykar
2021-08-06 12:01     ` [GSoC] [PATCH v3 5/8] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
2021-08-06 12:01     ` [GSoC] [PATCH v3 6/8] submodule--helper: remove add-clone subcommand Atharva Raykar
2021-08-06 12:01     ` [GSoC] [PATCH v3 7/8] submodule--helper: remove add-config subcommand Atharva Raykar
2021-08-06 12:01     ` [GSoC] [PATCH v3 8/8] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
2021-08-07  7:16     ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Atharva Raykar
2021-08-07  7:16       ` [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
2021-08-08 17:41         ` Kaartic Sivaraam
2021-08-08 18:26           ` Kaartic Sivaraam
2021-08-09  7:29             ` Atharva Raykar
2021-08-09  8:47               ` Atharva Raykar
2021-08-10 17:36                 ` Kaartic Sivaraam
2021-08-07  7:16       ` [GSoC] [PATCH v4 2/8] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
2021-08-07  7:16       ` [GSoC] [PATCH v4 3/8] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
2021-08-08 19:00         ` Kaartic Sivaraam
2021-08-09  7:36           ` Atharva Raykar
2021-08-07  7:16       ` [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c Atharva Raykar
2021-08-08 19:23         ` Kaartic Sivaraam
2021-08-09  8:02           ` Atharva Raykar
2021-08-10 17:53             ` Kaartic Sivaraam
2021-08-10 21:27               ` Junio C Hamano
2021-08-11 10:25               ` Atharva Raykar
2021-08-07  7:16       ` [GSoC] [PATCH v4 5/8] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
2021-08-07  7:16       ` [GSoC] [PATCH v4 6/8] submodule--helper: remove add-clone subcommand Atharva Raykar
2021-08-07  7:16       ` [GSoC] [PATCH v4 7/8] submodule--helper: remove add-config subcommand Atharva Raykar
2021-08-07  7:16       ` [GSoC] [PATCH v4 8/8] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
2021-08-08 18:01       ` [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C Kaartic Sivaraam
2021-08-10 11:46       ` [GSoC] [PATCH v5 0/9] " Atharva Raykar
2021-08-10 11:46         ` [GSoC] [PATCH v5 1/9] submodule--helper: add options for compute_submodule_clone_url() Atharva Raykar
2021-08-11  6:44           ` Bagas Sanjaya
2021-08-11 10:30             ` Atharva Raykar
2021-08-10 11:46         ` [GSoC] [PATCH v5 2/9] submodule--helper: refactor resolve_relative_url() helper Atharva Raykar
2021-08-10 11:46         ` [GSoC] [PATCH v5 3/9] submodule--helper: remove repeated code in sync_submodule() Atharva Raykar
2021-08-10 11:46         ` [GSoC] [PATCH v5 4/9] dir: libify and export helper functions from clone.c Atharva Raykar
2021-08-10 11:46         ` [GSoC] [PATCH v5 5/9] submodule--helper: convert the bulk of cmd_add() to C Atharva Raykar
2021-08-10 11:46         ` [GSoC] [PATCH v5 6/9] submodule--helper: remove add-clone subcommand Atharva Raykar
2021-08-10 11:46         ` [GSoC] [PATCH v5 7/9] submodule--helper: remove add-config subcommand Atharva Raykar
2021-08-10 11:46         ` [GSoC] [PATCH v5 8/9] submodule--helper: remove resolve-relative-url subcommand Atharva Raykar
2021-08-10 11:46         ` [GSoC] [PATCH v5 9/9] submodule--helper: rename compute_submodule_clone_url() Atharva Raykar
2021-09-08  0:31         ` [GSoC] [PATCH v5 0/9] submodule: convert the rest of 'add' to C Junio C Hamano

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.