{"thread":{"id":"56219","subject":"[GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C","startedAt":"2021-08-05T07:19:39Z","lastAt":"2021-09-08T00:31:16Z","messageCount":78,"participants":["Atharva Raykar","Junio C Hamano","Đoàn Trần Công Danh","Christian Couder","Kaartic Sivaraam","Bagas Sanjaya"],"isPatch":true,"patchVersion":1,"patchTotal":8},"messages":[{"id":"432055","messageId":"20210805071917.29500-1-raykar.ath@gmail.com","threadId":"56219","inReplyTo":null,"subject":"[GSoC] [PATCH 0/8] submodule: convert the rest of 'add' to C","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:19:09Z","receivedAt":"2021-08-05T07:19:39Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"NOTE: This series uses the change introduced by 'ar/submodule-add-config'[1]\n\nThis series completes the conversion of all the important shell logic in\n'submodule add' to C, by wrapping it in a submodule--helper builtin subcommand\ncalled 'add'.\n\nThe first 4 patches are preparatory patches. The refactors mostly involve\nexposing interfaces to C that were only previously usable as shell subcommands.\n\nThen we have a patch that translates the shell code to C, faithfully reproducing\nthe behaviour before the conversion.\n\nThe last 3 patches are cleanup patches. Our conversions have introduced a lot of\ndead code, all of them being 'submodule--helper' subcommands that have no\nfurther use, as we have C interfaces for these already. We remove these\nsubcommands.\n\nA question about the cache API used in [PATCH 5/8]:\n  What is the difference between 'read_cache()' and 'read_cache_preload()'? [2]\n  Which one is more appropriate for use in 'die_on_index_match()'?\n\nFetch-it-Via:\ngit fetch https://github.com/tfidfwastaken/git submodule-helper-add-list-1\n\nFootnotes\n=========\n\n[1] https://lore.kernel.org/git/20210801063352.50813-1-raykar.ath@gmail.com/\n[2] More about this question has been detailed in this section of my blog:\nhttp://atharvaraykar.me/gitnotes/week5#some-challenges-with-the-changes-that-are-cooking\n\nI'll quote it here for convenience:\n\n> Before iterating through the cache entries of the index, you need to populate\n> it.\n>\n> There’s two functions for this: read_cache() and read_cache_preload(). I have\n> used the latter in my code. The thing is, when I swap it with the former, I\n> could not find any change in the behaviour of my code. They appear to function\n> equivalently.\n>\n> I understand that the *_preload() variant takes a pathspec which preloads index\n> contents that match the pathspec in parallel. I don’t know what passing NULL to\n> it does. Moreover, does this imply that read_cache() loads the cache on-demand,\n> ie, it does no preloading?\n>\n> I am not sure about what exactly are their differences, and when is one variant\n> preferred over the other.\n\nAtharva Raykar (8):\n  submodule--helper: refactor resolve_relative_url() helper\n  submodule--helper: remove repeated code in sync_submodule()\n  dir: libify and export helper functions from clone.c\n  submodule--helper: remove constness of sm_path\n  submodule--helper: convert the bulk of cmd_add() to C\n  submodule--helper: remove add-clone subcommand\n  submodule--helper: remove add-config subcommand\n  submodule--helper: remove resolve-relative-url subcommand\n\n builtin/clone.c             | 118 +-------------\n builtin/submodule--helper.c | 304 +++++++++++++++++++-----------------\n dir.c                       | 114 ++++++++++++++\n dir.h                       |   3 +\n git-submodule.sh            |  96 +-----------\n 5 files changed, 278 insertions(+), 357 deletions(-)\n\n-- \n2.32.0\n\n"},{"id":"432056","messageId":"20210805071917.29500-2-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805071917.29500-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH 1/8] submodule--helper: refactor resolve_relative_url() helper","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:19:10Z","receivedAt":"2021-08-05T07:19:44Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Refactor the helper function to resolve a relative url, by reusing the\nexisting `compute_submodule_clone_url()` function.\n\n`compute_submodule_clone_url()` performs the same work that\n`resolve_relative_url()` is doing, so we eliminate this code repetition\nby moving the former function's definition up, and calling it inside\n`resolve_relative_url()`.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 61 +++++++++++++++----------------------\n 1 file changed, 25 insertions(+), 36 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 2d2d8ac637..f4b496bac6 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -199,33 +199,46 @@ static char *relative_url(const char *remote_url,\n \treturn strbuf_detach(&sb, NULL);\n }\n \n+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n+{\n+\tchar *remoteurl, *relurl;\n+\tchar *remote = get_default_remote();\n+\tstruct strbuf remotesb = STRBUF_INIT;\n+\n+\tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n+\tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n+\t\tif (!quiet)\n+\t\t\twarning(_(\"could not look up configuration '%s'. \"\n+\t\t\t\t  \"Assuming this repository is its own \"\n+\t\t\t\t  \"authoritative upstream.\"),\n+\t\t\t\tremotesb.buf);\n+\t\tremoteurl = xgetcwd();\n+\t}\n+\trelurl = relative_url(remoteurl, rel_url, up_path);\n+\n+\tfree(remote);\n+\tfree(remoteurl);\n+\tstrbuf_release(&remotesb);\n+\n+\treturn relurl;\n+}\n+\n static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n {\n-\tchar *remoteurl = NULL;\n-\tchar *remote = get_default_remote();\n \tconst char *up_path = NULL;\n \tchar *res;\n \tconst char *url;\n-\tstruct strbuf sb = STRBUF_INIT;\n \n \tif (argc != 2 && argc != 3)\n \t\tdie(\"resolve-relative-url only accepts one or two arguments\");\n \n \turl = argv[1];\n-\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n-\tfree(remote);\n-\n-\tif (git_config_get_string(sb.buf, &remoteurl))\n-\t\t/* the repository is its own authoritative upstream */\n-\t\tremoteurl = xgetcwd();\n-\n \tif (argc == 3)\n \t\tup_path = argv[2];\n \n-\tres = relative_url(remoteurl, url, up_path);\n+\tres = compute_submodule_clone_url(url, up_path, 1);\n \tputs(res);\n \tfree(res);\n-\tfree(remoteurl);\n \treturn 0;\n }\n \n@@ -590,30 +603,6 @@ static int module_foreach(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n-{\n-\tchar *remoteurl, *relurl;\n-\tchar *remote = get_default_remote();\n-\tstruct strbuf remotesb = STRBUF_INIT;\n-\n-\tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n-\tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n-\t\tif (!quiet)\n-\t\t\twarning(_(\"could not look up configuration '%s'. \"\n-\t\t\t\t  \"Assuming this repository is its own \"\n-\t\t\t\t  \"authoritative upstream.\"),\n-\t\t\t\tremotesb.buf);\n-\t\tremoteurl = xgetcwd();\n-\t}\n-\trelurl = relative_url(remoteurl, rel_url, up_path);\n-\n-\tfree(remote);\n-\tfree(remoteurl);\n-\tstrbuf_release(&remotesb);\n-\n-\treturn relurl;\n-}\n-\n struct init_cb {\n \tconst char *prefix;\n \tunsigned int flags;\n-- \n2.32.0\n\n"},{"id":"432057","messageId":"20210805071917.29500-3-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805071917.29500-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:19:11Z","receivedAt":"2021-08-05T07:19:50Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"This part of `sync_submodule()` is doing the same thing that\n`compute_submodule_clone_url()` is doing. Let's reuse that helper here.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 16 +++-------------\n 1 file changed, 3 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f4b496bac6..9b676c12f8 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,\n \tif (sub && sub->url) {\n \t\tif (starts_with_dot_dot_slash(sub->url) ||\n \t\t    starts_with_dot_slash(sub->url)) {\n-\t\t\tchar *remote_url, *up_path;\n-\t\t\tchar *remote = get_default_remote();\n-\t\t\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n-\n-\t\t\tif (git_config_get_string(sb.buf, &remote_url))\n-\t\t\t\tremote_url = xgetcwd();\n-\n-\t\t\tup_path = get_up_path(path);\n-\t\t\tsub_origin_url = relative_url(remote_url, sub->url, up_path);\n-\t\t\tsuper_config_url = relative_url(remote_url, sub->url, NULL);\n-\n-\t\t\tfree(remote);\n+\t\t\tchar *up_path = get_up_path(path);\n+\t\t\tsub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);\n+\t\t\tsuper_config_url = compute_submodule_clone_url(sub->url, NULL, 1);\n \t\t\tfree(up_path);\n-\t\t\tfree(remote_url);\n \t\t} else {\n \t\t\tsub_origin_url = xstrdup(sub->url);\n \t\t\tsuper_config_url = xstrdup(sub->url);\n-- \n2.32.0\n\n"},{"id":"432058","messageId":"20210805071917.29500-4-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805071917.29500-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH 3/8] dir: libify and export helper functions from clone.c","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:19:12Z","receivedAt":"2021-08-05T07:19:54Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"These functions can be useful to other parts of Git. Let's move them to\ndir.c, while renaming them to be make their functionality more explicit.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <shouryashukla.oo@gmail.com>\n---\n builtin/clone.c | 118 +-----------------------------------------------\n dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++\n dir.h           |   3 ++\n 3 files changed, 119 insertions(+), 116 deletions(-)\n\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 66fe66679c..b9b59a838f 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -217,120 +217,6 @@ static char *get_repo_path(const char *repo, int *is_bundle)\n \treturn canon;\n }\n \n-static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)\n-{\n-\tconst char *end = repo + strlen(repo), *start, *ptr;\n-\tsize_t len;\n-\tchar *dir;\n-\n-\t/*\n-\t * Skip scheme.\n-\t */\n-\tstart = strstr(repo, \"://\");\n-\tif (start == NULL)\n-\t\tstart = repo;\n-\telse\n-\t\tstart += 3;\n-\n-\t/*\n-\t * Skip authentication data. The stripping does happen\n-\t * greedily, such that we strip up to the last '@' inside\n-\t * the host part.\n-\t */\n-\tfor (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {\n-\t\tif (*ptr == '@')\n-\t\t\tstart = ptr + 1;\n-\t}\n-\n-\t/*\n-\t * Strip trailing spaces, slashes and /.git\n-\t */\n-\twhile (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))\n-\t\tend--;\n-\tif (end - start > 5 && is_dir_sep(end[-5]) &&\n-\t    !strncmp(end - 4, \".git\", 4)) {\n-\t\tend -= 5;\n-\t\twhile (start < end && is_dir_sep(end[-1]))\n-\t\t\tend--;\n-\t}\n-\n-\t/*\n-\t * Strip trailing port number if we've got only a\n-\t * hostname (that is, there is no dir separator but a\n-\t * colon). This check is required such that we do not\n-\t * strip URI's like '/foo/bar:2222.git', which should\n-\t * result in a dir '2222' being guessed due to backwards\n-\t * compatibility.\n-\t */\n-\tif (memchr(start, '/', end - start) == NULL\n-\t    && memchr(start, ':', end - start) != NULL) {\n-\t\tptr = end;\n-\t\twhile (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')\n-\t\t\tptr--;\n-\t\tif (start < ptr && ptr[-1] == ':')\n-\t\t\tend = ptr - 1;\n-\t}\n-\n-\t/*\n-\t * Find last component. To remain backwards compatible we\n-\t * also regard colons as path separators, such that\n-\t * cloning a repository 'foo:bar.git' would result in a\n-\t * directory 'bar' being guessed.\n-\t */\n-\tptr = end;\n-\twhile (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')\n-\t\tptr--;\n-\tstart = ptr;\n-\n-\t/*\n-\t * Strip .{bundle,git}.\n-\t */\n-\tlen = end - start;\n-\tstrip_suffix_mem(start, &len, is_bundle ? \".bundle\" : \".git\");\n-\n-\tif (!len || (len == 1 && *start == '/'))\n-\t\tdie(_(\"No directory name could be guessed.\\n\"\n-\t\t      \"Please specify a directory on the command line\"));\n-\n-\tif (is_bare)\n-\t\tdir = xstrfmt(\"%.*s.git\", (int)len, start);\n-\telse\n-\t\tdir = xstrndup(start, len);\n-\t/*\n-\t * Replace sequences of 'control' characters and whitespace\n-\t * with one ascii space, remove leading and trailing spaces.\n-\t */\n-\tif (*dir) {\n-\t\tchar *out = dir;\n-\t\tint prev_space = 1 /* strip leading whitespace */;\n-\t\tfor (end = dir; *end; ++end) {\n-\t\t\tchar ch = *end;\n-\t\t\tif ((unsigned char)ch < '\\x20')\n-\t\t\t\tch = '\\x20';\n-\t\t\tif (isspace(ch)) {\n-\t\t\t\tif (prev_space)\n-\t\t\t\t\tcontinue;\n-\t\t\t\tprev_space = 1;\n-\t\t\t} else\n-\t\t\t\tprev_space = 0;\n-\t\t\t*out++ = ch;\n-\t\t}\n-\t\t*out = '\\0';\n-\t\tif (out > dir && prev_space)\n-\t\t\tout[-1] = '\\0';\n-\t}\n-\treturn dir;\n-}\n-\n-static void strip_trailing_slashes(char *dir)\n-{\n-\tchar *end = dir + strlen(dir);\n-\n-\twhile (dir < end - 1 && is_dir_sep(end[-1]))\n-\t\tend--;\n-\t*end = '\\0';\n-}\n-\n static int add_one_reference(struct string_list_item *item, void *cb_data)\n {\n \tstruct strbuf err = STRBUF_INIT;\n@@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \tif (argc == 2)\n \t\tdir = xstrdup(argv[1]);\n \telse\n-\t\tdir = guess_dir_name(repo_name, is_bundle, option_bare);\n-\tstrip_trailing_slashes(dir);\n+\t\tdir = guess_dir_name_from_git_url(repo_name, is_bundle, option_bare);\n+\tstrip_dir_trailing_slashes(dir);\n \n \tdest_exists = path_exists(dir);\n \tif (dest_exists && !is_empty_dir(dir))\ndiff --git a/dir.c b/dir.c\nindex 03c4d21267..84b47c4dbc 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -2970,6 +2970,120 @@ int is_empty_dir(const char *path)\n \treturn ret;\n }\n \n+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare)\n+{\n+\tconst char *end = repo + strlen(repo), *start, *ptr;\n+\tsize_t len;\n+\tchar *dir;\n+\n+\t/*\n+\t * Skip scheme.\n+\t */\n+\tstart = strstr(repo, \"://\");\n+\tif (start == NULL)\n+\t\tstart = repo;\n+\telse\n+\t\tstart += 3;\n+\n+\t/*\n+\t * Skip authentication data. The stripping does happen\n+\t * greedily, such that we strip up to the last '@' inside\n+\t * the host part.\n+\t */\n+\tfor (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {\n+\t\tif (*ptr == '@')\n+\t\t\tstart = ptr + 1;\n+\t}\n+\n+\t/*\n+\t * Strip trailing spaces, slashes and /.git\n+\t */\n+\twhile (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))\n+\t\tend--;\n+\tif (end - start > 5 && is_dir_sep(end[-5]) &&\n+\t    !strncmp(end - 4, \".git\", 4)) {\n+\t\tend -= 5;\n+\t\twhile (start < end && is_dir_sep(end[-1]))\n+\t\t\tend--;\n+\t}\n+\n+\t/*\n+\t * Strip trailing port number if we've got only a\n+\t * hostname (that is, there is no dir separator but a\n+\t * colon). This check is required such that we do not\n+\t * strip URI's like '/foo/bar:2222.git', which should\n+\t * result in a dir '2222' being guessed due to backwards\n+\t * compatibility.\n+\t */\n+\tif (memchr(start, '/', end - start) == NULL\n+\t    && memchr(start, ':', end - start) != NULL) {\n+\t\tptr = end;\n+\t\twhile (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')\n+\t\t\tptr--;\n+\t\tif (start < ptr && ptr[-1] == ':')\n+\t\t\tend = ptr - 1;\n+\t}\n+\n+\t/*\n+\t * Find last component. To remain backwards compatible we\n+\t * also regard colons as path separators, such that\n+\t * cloning a repository 'foo:bar.git' would result in a\n+\t * directory 'bar' being guessed.\n+\t */\n+\tptr = end;\n+\twhile (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')\n+\t\tptr--;\n+\tstart = ptr;\n+\n+\t/*\n+\t * Strip .{bundle,git}.\n+\t */\n+\tlen = end - start;\n+\tstrip_suffix_mem(start, &len, is_bundle ? \".bundle\" : \".git\");\n+\n+\tif (!len || (len == 1 && *start == '/'))\n+\t\tdie(_(\"No directory name could be guessed.\\n\"\n+\t\t      \"Please specify a directory on the command line\"));\n+\n+\tif (is_bare)\n+\t\tdir = xstrfmt(\"%.*s.git\", (int)len, start);\n+\telse\n+\t\tdir = xstrndup(start, len);\n+\t/*\n+\t * Replace sequences of 'control' characters and whitespace\n+\t * with one ascii space, remove leading and trailing spaces.\n+\t */\n+\tif (*dir) {\n+\t\tchar *out = dir;\n+\t\tint prev_space = 1 /* strip leading whitespace */;\n+\t\tfor (end = dir; *end; ++end) {\n+\t\t\tchar ch = *end;\n+\t\t\tif ((unsigned char)ch < '\\x20')\n+\t\t\t\tch = '\\x20';\n+\t\t\tif (isspace(ch)) {\n+\t\t\t\tif (prev_space)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tprev_space = 1;\n+\t\t\t} else\n+\t\t\t\tprev_space = 0;\n+\t\t\t*out++ = ch;\n+\t\t}\n+\t\t*out = '\\0';\n+\t\tif (out > dir && prev_space)\n+\t\t\tout[-1] = '\\0';\n+\t}\n+\treturn dir;\n+}\n+\n+void strip_dir_trailing_slashes(char *dir)\n+{\n+\tchar *end = dir + strlen(dir);\n+\n+\twhile (dir < end - 1 && is_dir_sep(end[-1]))\n+\t\tend--;\n+\t*end = '\\0';\n+}\n+\n static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)\n {\n \tDIR *dir;\ndiff --git a/dir.h b/dir.h\nindex b3e1a54a97..76441dde2d 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -453,6 +453,9 @@ static inline int is_dot_or_dotdot(const char *name)\n \n int is_empty_dir(const char *dir);\n \n+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare);\n+void strip_dir_trailing_slashes(char *dir);\n+\n void setup_standard_excludes(struct dir_struct *dir);\n \n char *get_sparse_checkout_filename(void);\n-- \n2.32.0\n\n"},{"id":"432059","messageId":"20210805071917.29500-5-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805071917.29500-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH 4/8] submodule--helper: remove constness of sm_path","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:19:13Z","receivedAt":"2021-08-05T07:20:00Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"This is needed so that it can be modified by normalize_path_copy() in\nthe next patch.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 9b676c12f8..99aabf1078 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2748,7 +2748,7 @@ struct add_data {\n \tconst char *prefix;\n \tconst char *branch;\n \tconst char *reference_path;\n-\tconst char *sm_path;\n+\tchar *sm_path;\n \tconst char *sm_name;\n \tconst char *repo;\n \tconst char *realrepo;\n-- \n2.32.0\n\n"},{"id":"432060","messageId":"20210805071917.29500-6-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805071917.29500-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH 5/8] submodule--helper: convert the bulk of cmd_add() to C","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:19:14Z","receivedAt":"2021-08-05T07:20:05Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Introduce the 'add' subcommand to `submodule--helper.c` that does all\nthe work 'submodule add' past the parsing of flags.\n\nAs with the previous conversions, this is meant to be a faithful\nconversion with no modification to the behaviour of `submodule add`.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nHelped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\nBased-on-patch-by: Shourya Shukla <periperidip@gmail.com>\nBased-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>\n---\n builtin/submodule--helper.c | 160 ++++++++++++++++++++++++++++++++++++\n git-submodule.sh            |  96 +---------------------\n 2 files changed, 162 insertions(+), 94 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 99aabf1078..05ae9ebe50 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -3046,6 +3046,165 @@ static int add_config(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static void die_on_index_match(const char *path, int force)\n+{\n+\tstruct pathspec ps;\n+\tconst char *args[] = { path, NULL };\n+\tparse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);\n+\n+\tif (read_cache_preload(NULL) < 0)\n+\t\tdie(_(\"index file corrupt\"));\n+\n+\tif (ps.nr) {\n+\t\tint i;\n+\t\tchar *ps_matched = xcalloc(ps.nr, 1);\n+\n+\t\t/* TODO: audit for interaction with sparse-index. */\n+\t\tensure_full_index(&the_index);\n+\n+\t\t/*\n+\t\t * Since there is only one pathspec, we just need\n+\t\t * need to check ps_matched[0] to know if a cache\n+\t\t * entry matched.\n+\t\t */\n+\t\tfor (i = 0; i < active_nr; i++) {\n+\t\t\tce_path_match(&the_index, active_cache[i], &ps,\n+\t\t\t\t      ps_matched);\n+\n+\t\t\tif (ps_matched[0]) {\n+\t\t\t\tif (!force)\n+\t\t\t\t\tdie(_(\"'%s' already exists in the index\"),\n+\t\t\t\t\t    path);\n+\t\t\t\tif (!S_ISGITLINK(active_cache[i]->ce_mode))\n+\t\t\t\t\tdie(_(\"'%s' already exists in the index \"\n+\t\t\t\t\t      \"and is not a submodule\"), path);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tfree(ps_matched);\n+\t}\n+}\n+\n+static void die_on_repo_without_commits(const char *path)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstrbuf_addstr(&sb, path);\n+\tif (is_nonbare_repository_dir(&sb)) {\n+\t\tstruct object_id oid;\n+\t\tif (resolve_gitlink_ref(path, \"HEAD\", &oid) < 0)\n+\t\t\tdie(_(\"'%s' does not have a commit checked out\"), path);\n+\t}\n+}\n+\n+static int module_add(int argc, const char **argv, const char *prefix)\n+{\n+\tint force = 0, quiet = 0, progress = 0, dissociate = 0;\n+\tstruct add_data add_data = ADD_DATA_INIT;\n+\n+\tstruct option options[] = {\n+\t\tOPT_STRING('b', \"branch\", &add_data.branch, N_(\"branch\"),\n+\t\t\t   N_(\"branch of repository to add as submodule\")),\n+\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n+\t\t\t   PARSE_OPT_NOCOMPLETE),\n+\t\tOPT__QUIET(&quiet, N_(\"print only error messages\")),\n+\t\tOPT_BOOL(0, \"progress\", &progress, N_(\"force cloning progress\")),\n+\t\tOPT_STRING(0, \"reference\", &add_data.reference_path, N_(\"repository\"),\n+\t\t\t   N_(\"reference repository\")),\n+\t\tOPT_BOOL(0, \"dissociate\", &dissociate, N_(\"borrow the objects from reference repositories\")),\n+\t\tOPT_STRING(0, \"name\", &add_data.sm_name, N_(\"name\"),\n+\t\t\t   N_(\"sets the submodule’s name to the given string \"\n+\t\t\t      \"instead of defaulting to its path\")),\n+\t\tOPT_INTEGER(0, \"depth\", &add_data.depth, N_(\"depth for shallow clones\")),\n+\t\tOPT_END()\n+\t};\n+\n+\tconst char *const usage[] = {\n+\t\tN_(\"git submodule--helper add [<options>] [--] <repository> [<path>]\"),\n+\t\tNULL\n+\t};\n+\n+\targc = parse_options(argc, argv, prefix, options, usage, 0);\n+\n+\tif (!is_writing_gitmodules_ok())\n+\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n+\n+\tif (prefix && *prefix &&\n+\t    add_data.reference_path && !is_absolute_path(add_data.reference_path))\n+\t\tadd_data.reference_path = xstrfmt(\"%s%s\", prefix, add_data.reference_path);\n+\n+\tif (argc == 0 || argc > 2)\n+\t\tusage_with_options(usage, options);\n+\n+\tadd_data.repo = argv[0];\n+\tif (argc == 1)\n+\t\tadd_data.sm_path = guess_dir_name_from_git_url(add_data.repo, 0, 0);\n+\telse\n+\t\tadd_data.sm_path = xstrdup(argv[1]);\n+\n+\tif (prefix && *prefix && !is_absolute_path(add_data.sm_path))\n+\t\tadd_data.sm_path = xstrfmt(\"%s%s\", prefix, add_data.sm_path);\n+\n+\tif (starts_with_dot_dot_slash(add_data.repo) ||\n+\t    starts_with_dot_slash(add_data.repo)) {\n+\t\tif (prefix)\n+\t\t\tdie(_(\"Relative path can only be used from the toplevel \"\n+\t\t\t      \"of the working tree\"));\n+\n+\t\t/* dereference source url relative to parent's url */\n+\t\tadd_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);\n+\t} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {\n+\t\tadd_data.realrepo = add_data.repo;\n+\t} else {\n+\t\tdie(_(\"repo URL: '%s' must be absolute or begin with ./|../\"),\n+\t\t    add_data.repo);\n+\t}\n+\n+\t/*\n+\t * normalize path:\n+\t * multiple //; leading ./; /./; /../;\n+\t */\n+\tnormalize_path_copy(add_data.sm_path, add_data.sm_path);\n+\tstrip_dir_trailing_slashes(add_data.sm_path);\n+\n+\tdie_on_index_match(add_data.sm_path, force);\n+\tdie_on_repo_without_commits(add_data.sm_path);\n+\n+\tif (!force) {\n+\t\tint exit_code = -1;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\t\tcp.git_cmd = 1;\n+\t\tcp.no_stdout = 1;\n+\t\tstrvec_pushl(&cp.args, \"add\", \"--dry-run\", \"--ignore-missing\",\n+\t\t\t     \"--no-warn-embedded-repo\", add_data.sm_path, NULL);\n+\t\tif ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {\n+\t\t\tstrbuf_complete_line(&sb);\n+\t\t\tfputs(sb.buf, stderr);\n+\t\t\treturn exit_code;\n+\t\t}\n+\t\tstrbuf_release(&sb);\n+\t}\n+\n+\tif(!add_data.sm_name)\n+\t\tadd_data.sm_name = add_data.sm_path;\n+\n+\tif (check_submodule_name(add_data.sm_name))\n+\t\tdie(_(\"'%s' is not a valid submodule name\"), add_data.sm_name);\n+\n+\tadd_data.prefix = prefix;\n+\tadd_data.force = !!force;\n+\tadd_data.quiet = !!quiet;\n+\tadd_data.progress = !!progress;\n+\tadd_data.dissociate = !!dissociate;\n+\n+\tif (add_submodule(&add_data))\n+\t\treturn 1;\n+\tconfigure_added_submodule(&add_data);\n+\tfree(add_data.sm_path);\n+\n+\treturn 0;\n+}\n+\n #define SUPPORT_SUPER_PREFIX (1<<0)\n \n struct cmd_struct {\n@@ -3060,6 +3219,7 @@ static struct cmd_struct commands[] = {\n \t{\"clone\", module_clone, 0},\n \t{\"add-clone\", add_clone, 0},\n \t{\"add-config\", add_config, 0},\n+\t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n \t{\"update-clone\", update_clone, 0},\n \t{\"ensure-core-worktree\", ensure_core_worktree, 0},\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 8c219ef382..1070540525 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -145,104 +145,12 @@ cmd_add()\n \t\tshift\n \tdone\n \n-\tif ! git submodule--helper config --check-writeable >/dev/null 2>&1\n+\tif test -z \"$1\"\n \tthen\n-\t\t die \"fatal: $(eval_gettext \"please make sure that the .gitmodules file is in the working tree\")\"\n-\tfi\n-\n-\tif test -n \"$reference_path\"\n-\tthen\n-\t\tis_absolute_path \"$reference_path\" ||\n-\t\treference_path=\"$wt_prefix$reference_path\"\n-\n-\t\treference=\"--reference=$reference_path\"\n-\tfi\n-\n-\trepo=$1\n-\tsm_path=$2\n-\n-\tif test -z \"$sm_path\"; then\n-\t\tsm_path=$(printf '%s\\n' \"$repo\" |\n-\t\t\tsed -e 's|/$||' -e 's|:*/*\\.git$||' -e 's|.*[/:]||g')\n-\tfi\n-\n-\tif test -z \"$repo\" || test -z \"$sm_path\"; then\n \t\tusage\n \tfi\n \n-\tis_absolute_path \"$sm_path\" || sm_path=\"$wt_prefix$sm_path\"\n-\n-\t# assure repo is absolute or relative to parent\n-\tcase \"$repo\" in\n-\t./*|../*)\n-\t\ttest -z \"$wt_prefix\" ||\n-\t\tdie \"fatal: $(gettext \"Relative path can only be used from the toplevel of the working tree\")\"\n-\n-\t\t# dereference source url relative to parent's url\n-\t\trealrepo=$(git submodule--helper resolve-relative-url \"$repo\") || exit\n-\t\t;;\n-\t*:*|/*)\n-\t\t# absolute url\n-\t\trealrepo=$repo\n-\t\t;;\n-\t*)\n-\t\tdie \"fatal: $(eval_gettext \"repo URL: '\\$repo' must be absolute or begin with ./|../\")\"\n-\t;;\n-\tesac\n-\n-\t# normalize path:\n-\t# multiple //; leading ./; /./; /../; trailing /\n-\tsm_path=$(printf '%s/\\n' \"$sm_path\" |\n-\t\tsed -e '\n-\t\t\ts|//*|/|g\n-\t\t\ts|^\\(\\./\\)*||\n-\t\t\ts|/\\(\\./\\)*|/|g\n-\t\t\t:start\n-\t\t\ts|\\([^/]*\\)/\\.\\./||\n-\t\t\ttstart\n-\t\t\ts|/*$||\n-\t\t')\n-\tif test -z \"$force\"\n-\tthen\n-\t\tgit ls-files --error-unmatch \"$sm_path\" > /dev/null 2>&1 &&\n-\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index\")\"\n-\telse\n-\t\tgit ls-files -s \"$sm_path\" | sane_grep -v \"^160000\" > /dev/null 2>&1 &&\n-\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index and is not a submodule\")\"\n-\tfi\n-\n-\tif test -d \"$sm_path\" &&\n-\t\ttest -z $(git -C \"$sm_path\" rev-parse --show-cdup 2>/dev/null)\n-\tthen\n-\t    git -C \"$sm_path\" rev-parse --verify -q HEAD >/dev/null ||\n-\t    die \"fatal: $(eval_gettext \"'\\$sm_path' does not have a commit checked out\")\"\n-\tfi\n-\n-\tif test -z \"$force\"\n-\tthen\n-\t    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo \"$sm_path\" 2>&1 >/dev/null)\n-\t    res=$?\n-\t    if test $res -ne 0\n-\t    then\n-\t\t echo >&2 \"$dryerr\"\n-\t\t exit $res\n-\t    fi\n-\tfi\n-\n-\tif test -n \"$custom_name\"\n-\tthen\n-\t\tsm_name=\"$custom_name\"\n-\telse\n-\t\tsm_name=\"$sm_path\"\n-\tfi\n-\n-\tif ! git submodule--helper check-name \"$sm_name\"\n-\tthen\n-\t\tdie \"fatal: $(eval_gettext \"'$sm_name' is not a valid submodule name\")\"\n-\tfi\n-\n-\tgit 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\n-\tgit submodule--helper add-config ${force:+--force} ${branch:+--branch \"$branch\"} --url \"$repo\" --resolved-url \"$realrepo\" --path \"$sm_path\" --name \"$sm_name\"\n+\tgit ${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\"} -- \"$@\"\n }\n \n #\n-- \n2.32.0\n\n"},{"id":"432061","messageId":"20210805071917.29500-7-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805071917.29500-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH 6/8] submodule--helper: remove add-clone subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:19:15Z","receivedAt":"2021-08-05T07:20:07Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"We no longer need this subcommand, as all of its functionality is being\ncalled by the newly-introduced `module_add()` directly within C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 60 -------------------------------------\n 1 file changed, 60 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 05ae9ebe50..700cc8bbeb 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2860,65 +2860,6 @@ static int add_submodule(const struct add_data *add_data)\n \treturn 0;\n }\n \n-static int add_clone(int argc, const char **argv, const char *prefix)\n-{\n-\tint force = 0, quiet = 0, dissociate = 0, progress = 0;\n-\tstruct add_data add_data = ADD_DATA_INIT;\n-\n-\tstruct option options[] = {\n-\t\tOPT_STRING('b', \"branch\", &add_data.branch,\n-\t\t\t   N_(\"branch\"),\n-\t\t\t   N_(\"branch of repository to checkout on cloning\")),\n-\t\tOPT_STRING(0, \"prefix\", &prefix,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"alternative anchor for relative paths\")),\n-\t\tOPT_STRING(0, \"path\", &add_data.sm_path,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"where the new submodule will be cloned to\")),\n-\t\tOPT_STRING(0, \"name\", &add_data.sm_name,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"name of the new submodule\")),\n-\t\tOPT_STRING(0, \"url\", &add_data.realrepo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url where to clone the submodule from\")),\n-\t\tOPT_STRING(0, \"reference\", &add_data.reference_path,\n-\t\t\t   N_(\"repo\"),\n-\t\t\t   N_(\"reference repository\")),\n-\t\tOPT_BOOL(0, \"dissociate\", &dissociate,\n-\t\t\t N_(\"use --reference only while cloning\")),\n-\t\tOPT_INTEGER(0, \"depth\", &add_data.depth,\n-\t\t\t    N_(\"depth for shallow clones\")),\n-\t\tOPT_BOOL(0, \"progress\", &progress,\n-\t\t\t N_(\"force cloning progress\")),\n-\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n-\t\t\t   PARSE_OPT_NOCOMPLETE),\n-\t\tOPT__QUIET(&quiet, \"suppress output for cloning a submodule\"),\n-\t\tOPT_END()\n-\t};\n-\n-\tconst char *const usage[] = {\n-\t\tN_(\"git submodule--helper add-clone [<options>...] \"\n-\t\t   \"--url <url> --path <path> --name <name>\"),\n-\t\tNULL\n-\t};\n-\n-\targc = parse_options(argc, argv, prefix, options, usage, 0);\n-\n-\tif (argc != 0)\n-\t\tusage_with_options(usage, options);\n-\n-\tadd_data.prefix = prefix;\n-\tadd_data.progress = !!progress;\n-\tadd_data.dissociate = !!dissociate;\n-\tadd_data.force = !!force;\n-\tadd_data.quiet = !!quiet;\n-\n-\tif (add_submodule(&add_data))\n-\t\treturn 1;\n-\n-\treturn 0;\n-}\n-\n static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)\n {\n \tchar *key;\n@@ -3217,7 +3158,6 @@ static struct cmd_struct commands[] = {\n \t{\"list\", module_list, 0},\n \t{\"name\", module_name, 0},\n \t{\"clone\", module_clone, 0},\n-\t{\"add-clone\", add_clone, 0},\n \t{\"add-config\", add_config, 0},\n \t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n-- \n2.32.0\n\n"},{"id":"432062","messageId":"20210805071917.29500-9-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805071917.29500-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH 8/8] submodule--helper: remove resolve-relative-url subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:19:17Z","receivedAt":"2021-08-05T07:20:19Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"The shell subcommand `resolve-relative-url` is no longer required, as\nits last caller has been removed when it was converted to C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 20 --------------------\n 1 file changed, 20 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex da83e8e2a5..514891a22f 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -223,25 +223,6 @@ static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat\n \treturn relurl;\n }\n \n-static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n-{\n-\tconst char *up_path = NULL;\n-\tchar *res;\n-\tconst char *url;\n-\n-\tif (argc != 2 && argc != 3)\n-\t\tdie(\"resolve-relative-url only accepts one or two arguments\");\n-\n-\turl = argv[1];\n-\tif (argc == 3)\n-\t\tup_path = argv[2];\n-\n-\tres = compute_submodule_clone_url(url, up_path, 1);\n-\tputs(res);\n-\tfree(res);\n-\treturn 0;\n-}\n-\n static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)\n {\n \tchar *remoteurl, *res;\n@@ -3115,7 +3096,6 @@ static struct cmd_struct commands[] = {\n \t{\"update-clone\", update_clone, 0},\n \t{\"ensure-core-worktree\", ensure_core_worktree, 0},\n \t{\"relative-path\", resolve_relative_path, 0},\n-\t{\"resolve-relative-url\", resolve_relative_url, 0},\n \t{\"resolve-relative-url-test\", resolve_relative_url_test, 0},\n \t{\"foreach\", module_foreach, SUPPORT_SUPER_PREFIX},\n \t{\"init\", module_init, SUPPORT_SUPER_PREFIX},\n-- \n2.32.0\n\n"},{"id":"432063","messageId":"20210805071917.29500-8-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805071917.29500-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH 7/8] submodule--helper: remove add-config subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:19:16Z","receivedAt":"2021-08-05T07:20:19Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Also no longer needed is this subcommand, as all of its functionality is\nbeing called by the newly-introduced `module_add()` directly within C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 49 -------------------------------------\n 1 file changed, 49 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 700cc8bbeb..da83e8e2a5 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2939,54 +2939,6 @@ static void configure_added_submodule(struct add_data *add_data)\n \t}\n }\n \n-static int add_config(int argc, const char **argv, const char *prefix)\n-{\n-\tint force = 0;\n-\tstruct add_data add_data = ADD_DATA_INIT;\n-\n-\tstruct option options[] = {\n-\t\tOPT_STRING('b', \"branch\", &add_data.branch,\n-\t\t\t   N_(\"branch\"),\n-\t\t\t   N_(\"branch of repository to store in \"\n-\t\t\t      \"the submodule configuration\")),\n-\t\tOPT_STRING(0, \"url\", &add_data.repo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url to clone submodule from\")),\n-\t\tOPT_STRING(0, \"resolved-url\", &add_data.realrepo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url to clone the submodule from, after it has \"\n-\t\t\t      \"been dereferenced relative to parent's url, \"\n-\t\t\t      \"in the case where <url> is a relative url\")),\n-\t\tOPT_STRING(0, \"path\", &add_data.sm_path,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"where the new submodule will be cloned to\")),\n-\t\tOPT_STRING(0, \"name\", &add_data.sm_name,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"name of the new submodule\")),\n-\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n-\t\t\t   PARSE_OPT_NOCOMPLETE),\n-\t\tOPT_END()\n-\t};\n-\n-\tconst char *const usage[] = {\n-\t\tN_(\"git submodule--helper add-config \"\n-\t\t   \"[--force|-f] [--branch|-b <branch>] \"\n-\t\t   \"--url <url> --resolved-url <resolved-url> \"\n-\t\t   \"--path <path> --name <name>\"),\n-\t\tNULL\n-\t};\n-\n-\targc = parse_options(argc, argv, prefix, options, usage, 0);\n-\n-\tif (argc)\n-\t\tusage_with_options(usage, options);\n-\n-\tadd_data.force = !!force;\n-\tconfigure_added_submodule(&add_data);\n-\n-\treturn 0;\n-}\n-\n static void die_on_index_match(const char *path, int force)\n {\n \tstruct pathspec ps;\n@@ -3158,7 +3110,6 @@ static struct cmd_struct commands[] = {\n \t{\"list\", module_list, 0},\n \t{\"name\", module_name, 0},\n \t{\"clone\", module_clone, 0},\n-\t{\"add-config\", add_config, 0},\n \t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n \t{\"update-clone\", update_clone, 0},\n-- \n2.32.0\n\n"},{"id":"432064","messageId":"20210805074054.29916-1-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805071917.29500-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v2 0/9] submodule: convert the rest of 'add' to C","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:40:45Z","receivedAt":"2021-08-05T07:41:30Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"I missed the adding the first patch of this series, so I am re-sending with the\nmissing commit included.\n\nNo change since v1, except for the inclusion of 75edf24186 (submodule--helper:\nadd options for compute_submodule_clone_url(), 2021-07-06) at the beginning.\n\nI am including the cover letter of v1 as-is, so the discussion can start from\nhere, with minor edits to reflect the accurate counts of the patches:\n\n---8<------8<------8<------8<------8<---\n\nNOTE: This series uses the change introduced by 'ar/submodule-add-config'[1]\n\nThis series completes the conversion of all the important shell logic in\n'submodule add' to C, by wrapping it in a submodule--helper builtin subcommand\ncalled 'add'.\n\nThe first 5 patches are preparatory patches. The refactors mostly involve\nexposing interfaces to C that were only previously usable as shell subcommands.\n\nThen we have a patch that translates the shell code to C, faithfully reproducing\nthe behaviour before the conversion.\n\nThe last 3 patches are cleanup patches. Our conversions have introduced a lot of\ndead code, all of them being 'submodule--helper' subcommands that have no\nfurther use, as we have C interfaces for these already. We remove these\nsubcommands.\n\nA question about the cache API used in [PATCH 5/9]:\n  What is the difference between 'read_cache()' and 'read_cache_preload()'? [2]\n  Which one is more appropriate for use in 'die_on_index_match()'?\n\nFetch-it-Via:\ngit fetch https://github.com/tfidfwastaken/git submodule-helper-add-list-1\n\nFootnotes\n=========\n\n[1] https://lore.kernel.org/git/20210801063352.50813-1-raykar.ath@gmail.com/\n[2] More about this question has been detailed in this section of my blog:\nhttp://atharvaraykar.me/gitnotes/week5#some-challenges-with-the-changes-that-are-cooking\n\nI'll quote it here for convenience:\n\n> Before iterating through the cache entries of the index, you need to populate\n> it.\n>\n> There’s two functions for this: read_cache() and read_cache_preload(). I have\n> used the latter in my code. The thing is, when I swap it with the former, I\n> could not find any change in the behaviour of my code. They appear to function\n> equivalently.\n>\n> I understand that the *_preload() variant takes a pathspec which preloads index\n> contents that match the pathspec in parallel. I don’t know what passing NULL to\n> it does. Moreover, does this imply that read_cache() loads the cache on-demand,\n> ie, it does no preloading?\n>\n> I am not sure about what exactly are their differences, and when is one variant\n> preferred over the other.\n\n--->8------>8------>8------>8------>8---\n\nAtharva Raykar (9):\n  submodule--helper: add options for compute_submodule_clone_url()\n  submodule--helper: refactor resolve_relative_url() helper\n  submodule--helper: remove repeated code in sync_submodule()\n  dir: libify and export helper functions from clone.c\n  submodule--helper: remove constness of sm_path\n  submodule--helper: convert the bulk of cmd_add() to C\n  submodule--helper: remove add-clone subcommand\n  submodule--helper: remove add-config subcommand\n  submodule--helper: remove resolve-relative-url subcommand\n\n builtin/clone.c             | 118 +-------------\n builtin/submodule--helper.c | 304 +++++++++++++++++++-----------------\n dir.c                       | 114 ++++++++++++++\n dir.h                       |   3 +\n git-submodule.sh            |  96 +-----------\n 5 files changed, 280 insertions(+), 355 deletions(-)\n\n-- \n2.32.0\n\n"},{"id":"432065","messageId":"20210805074054.29916-2-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805074054.29916-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v2 1/9] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:40:46Z","receivedAt":"2021-08-05T07:41:34Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Let's modify the interface to `compute_submodule_clone_url()` function\nby adding two more arguments, so that we can reuse this in various parts\nof `submodule--helper.c` that follow a common pattern, which is--read\nthe remote url configuration of the superproject and then call\n`relative_url()`.\n\nThis function is nearly identical to `resolve_relative_url()`, the only\ndifference being the extra warning message. We can add a quiet flag to\nit, to suppress that warning when not needed, and then refactor\n`resolve_relative_url()` by using this function, something we will do in\nthe next patch.\n\nHaving this functionality factored out will be useful for converting the\nrest of `submodule add` in subsequent patches.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 14 +++++++++-----\n 1 file changed, 9 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 6891480013..2d2d8ac637 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -590,7 +590,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n-static char *compute_submodule_clone_url(const char *rel_url)\n+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n {\n \tchar *remoteurl, *relurl;\n \tchar *remote = get_default_remote();\n@@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)\n \n \tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n-\t\twarning(_(\"could not look up configuration '%s'. Assuming this repository is its own authoritative upstream.\"), remotesb.buf);\n+\t\tif (!quiet)\n+\t\t\twarning(_(\"could not look up configuration '%s'. \"\n+\t\t\t\t  \"Assuming this repository is its own \"\n+\t\t\t\t  \"authoritative upstream.\"),\n+\t\t\t\tremotesb.buf);\n \t\tremoteurl = xgetcwd();\n \t}\n-\trelurl = relative_url(remoteurl, rel_url, NULL);\n+\trelurl = relative_url(remoteurl, rel_url, up_path);\n \n \tfree(remote);\n \tfree(remoteurl);\n@@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,\n \t\tif (starts_with_dot_dot_slash(url) ||\n \t\t    starts_with_dot_slash(url)) {\n \t\t\tchar *oldurl = url;\n-\t\t\turl = compute_submodule_clone_url(oldurl);\n+\t\t\turl = compute_submodule_clone_url(oldurl, NULL, 0);\n \t\t\tfree(oldurl);\n \t\t}\n \n@@ -2134,7 +2138,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \tif (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {\n \t\tif (starts_with_dot_slash(sub->url) ||\n \t\t    starts_with_dot_dot_slash(sub->url)) {\n-\t\t\turl = compute_submodule_clone_url(sub->url);\n+\t\t\turl = compute_submodule_clone_url(sub->url, NULL, 0);\n \t\t\tneed_free_url = 1;\n \t\t} else\n \t\t\turl = sub->url;\n-- \n2.32.0\n\n"},{"id":"432066","messageId":"20210805074054.29916-3-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805074054.29916-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v2 2/9] submodule--helper: refactor resolve_relative_url() helper","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:40:47Z","receivedAt":"2021-08-05T07:41:40Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Refactor the helper function to resolve a relative url, by reusing the\nexisting `compute_submodule_clone_url()` function.\n\n`compute_submodule_clone_url()` performs the same work that\n`resolve_relative_url()` is doing, so we eliminate this code repetition\nby moving the former function's definition up, and calling it inside\n`resolve_relative_url()`.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 61 +++++++++++++++----------------------\n 1 file changed, 25 insertions(+), 36 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 2d2d8ac637..f4b496bac6 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -199,33 +199,46 @@ static char *relative_url(const char *remote_url,\n \treturn strbuf_detach(&sb, NULL);\n }\n \n+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n+{\n+\tchar *remoteurl, *relurl;\n+\tchar *remote = get_default_remote();\n+\tstruct strbuf remotesb = STRBUF_INIT;\n+\n+\tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n+\tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n+\t\tif (!quiet)\n+\t\t\twarning(_(\"could not look up configuration '%s'. \"\n+\t\t\t\t  \"Assuming this repository is its own \"\n+\t\t\t\t  \"authoritative upstream.\"),\n+\t\t\t\tremotesb.buf);\n+\t\tremoteurl = xgetcwd();\n+\t}\n+\trelurl = relative_url(remoteurl, rel_url, up_path);\n+\n+\tfree(remote);\n+\tfree(remoteurl);\n+\tstrbuf_release(&remotesb);\n+\n+\treturn relurl;\n+}\n+\n static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n {\n-\tchar *remoteurl = NULL;\n-\tchar *remote = get_default_remote();\n \tconst char *up_path = NULL;\n \tchar *res;\n \tconst char *url;\n-\tstruct strbuf sb = STRBUF_INIT;\n \n \tif (argc != 2 && argc != 3)\n \t\tdie(\"resolve-relative-url only accepts one or two arguments\");\n \n \turl = argv[1];\n-\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n-\tfree(remote);\n-\n-\tif (git_config_get_string(sb.buf, &remoteurl))\n-\t\t/* the repository is its own authoritative upstream */\n-\t\tremoteurl = xgetcwd();\n-\n \tif (argc == 3)\n \t\tup_path = argv[2];\n \n-\tres = relative_url(remoteurl, url, up_path);\n+\tres = compute_submodule_clone_url(url, up_path, 1);\n \tputs(res);\n \tfree(res);\n-\tfree(remoteurl);\n \treturn 0;\n }\n \n@@ -590,30 +603,6 @@ static int module_foreach(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n-{\n-\tchar *remoteurl, *relurl;\n-\tchar *remote = get_default_remote();\n-\tstruct strbuf remotesb = STRBUF_INIT;\n-\n-\tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n-\tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n-\t\tif (!quiet)\n-\t\t\twarning(_(\"could not look up configuration '%s'. \"\n-\t\t\t\t  \"Assuming this repository is its own \"\n-\t\t\t\t  \"authoritative upstream.\"),\n-\t\t\t\tremotesb.buf);\n-\t\tremoteurl = xgetcwd();\n-\t}\n-\trelurl = relative_url(remoteurl, rel_url, up_path);\n-\n-\tfree(remote);\n-\tfree(remoteurl);\n-\tstrbuf_release(&remotesb);\n-\n-\treturn relurl;\n-}\n-\n struct init_cb {\n \tconst char *prefix;\n \tunsigned int flags;\n-- \n2.32.0\n\n"},{"id":"432067","messageId":"20210805074054.29916-4-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805074054.29916-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v2 3/9] submodule--helper: remove repeated code in sync_submodule()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:40:48Z","receivedAt":"2021-08-05T07:41:43Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"This part of `sync_submodule()` is doing the same thing that\n`compute_submodule_clone_url()` is doing. Let's reuse that helper here.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 16 +++-------------\n 1 file changed, 3 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f4b496bac6..9b676c12f8 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,\n \tif (sub && sub->url) {\n \t\tif (starts_with_dot_dot_slash(sub->url) ||\n \t\t    starts_with_dot_slash(sub->url)) {\n-\t\t\tchar *remote_url, *up_path;\n-\t\t\tchar *remote = get_default_remote();\n-\t\t\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n-\n-\t\t\tif (git_config_get_string(sb.buf, &remote_url))\n-\t\t\t\tremote_url = xgetcwd();\n-\n-\t\t\tup_path = get_up_path(path);\n-\t\t\tsub_origin_url = relative_url(remote_url, sub->url, up_path);\n-\t\t\tsuper_config_url = relative_url(remote_url, sub->url, NULL);\n-\n-\t\t\tfree(remote);\n+\t\t\tchar *up_path = get_up_path(path);\n+\t\t\tsub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);\n+\t\t\tsuper_config_url = compute_submodule_clone_url(sub->url, NULL, 1);\n \t\t\tfree(up_path);\n-\t\t\tfree(remote_url);\n \t\t} else {\n \t\t\tsub_origin_url = xstrdup(sub->url);\n \t\t\tsuper_config_url = xstrdup(sub->url);\n-- \n2.32.0\n\n"},{"id":"432068","messageId":"20210805074054.29916-5-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805074054.29916-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:40:49Z","receivedAt":"2021-08-05T07:41:51Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"These functions can be useful to other parts of Git. Let's move them to\ndir.c, while renaming them to be make their functionality more explicit.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <shouryashukla.oo@gmail.com>\n---\n builtin/clone.c | 118 +-----------------------------------------------\n dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++\n dir.h           |   3 ++\n 3 files changed, 119 insertions(+), 116 deletions(-)\n\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 66fe66679c..b9b59a838f 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -217,120 +217,6 @@ static char *get_repo_path(const char *repo, int *is_bundle)\n \treturn canon;\n }\n \n-static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)\n-{\n-\tconst char *end = repo + strlen(repo), *start, *ptr;\n-\tsize_t len;\n-\tchar *dir;\n-\n-\t/*\n-\t * Skip scheme.\n-\t */\n-\tstart = strstr(repo, \"://\");\n-\tif (start == NULL)\n-\t\tstart = repo;\n-\telse\n-\t\tstart += 3;\n-\n-\t/*\n-\t * Skip authentication data. The stripping does happen\n-\t * greedily, such that we strip up to the last '@' inside\n-\t * the host part.\n-\t */\n-\tfor (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {\n-\t\tif (*ptr == '@')\n-\t\t\tstart = ptr + 1;\n-\t}\n-\n-\t/*\n-\t * Strip trailing spaces, slashes and /.git\n-\t */\n-\twhile (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))\n-\t\tend--;\n-\tif (end - start > 5 && is_dir_sep(end[-5]) &&\n-\t    !strncmp(end - 4, \".git\", 4)) {\n-\t\tend -= 5;\n-\t\twhile (start < end && is_dir_sep(end[-1]))\n-\t\t\tend--;\n-\t}\n-\n-\t/*\n-\t * Strip trailing port number if we've got only a\n-\t * hostname (that is, there is no dir separator but a\n-\t * colon). This check is required such that we do not\n-\t * strip URI's like '/foo/bar:2222.git', which should\n-\t * result in a dir '2222' being guessed due to backwards\n-\t * compatibility.\n-\t */\n-\tif (memchr(start, '/', end - start) == NULL\n-\t    && memchr(start, ':', end - start) != NULL) {\n-\t\tptr = end;\n-\t\twhile (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')\n-\t\t\tptr--;\n-\t\tif (start < ptr && ptr[-1] == ':')\n-\t\t\tend = ptr - 1;\n-\t}\n-\n-\t/*\n-\t * Find last component. To remain backwards compatible we\n-\t * also regard colons as path separators, such that\n-\t * cloning a repository 'foo:bar.git' would result in a\n-\t * directory 'bar' being guessed.\n-\t */\n-\tptr = end;\n-\twhile (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')\n-\t\tptr--;\n-\tstart = ptr;\n-\n-\t/*\n-\t * Strip .{bundle,git}.\n-\t */\n-\tlen = end - start;\n-\tstrip_suffix_mem(start, &len, is_bundle ? \".bundle\" : \".git\");\n-\n-\tif (!len || (len == 1 && *start == '/'))\n-\t\tdie(_(\"No directory name could be guessed.\\n\"\n-\t\t      \"Please specify a directory on the command line\"));\n-\n-\tif (is_bare)\n-\t\tdir = xstrfmt(\"%.*s.git\", (int)len, start);\n-\telse\n-\t\tdir = xstrndup(start, len);\n-\t/*\n-\t * Replace sequences of 'control' characters and whitespace\n-\t * with one ascii space, remove leading and trailing spaces.\n-\t */\n-\tif (*dir) {\n-\t\tchar *out = dir;\n-\t\tint prev_space = 1 /* strip leading whitespace */;\n-\t\tfor (end = dir; *end; ++end) {\n-\t\t\tchar ch = *end;\n-\t\t\tif ((unsigned char)ch < '\\x20')\n-\t\t\t\tch = '\\x20';\n-\t\t\tif (isspace(ch)) {\n-\t\t\t\tif (prev_space)\n-\t\t\t\t\tcontinue;\n-\t\t\t\tprev_space = 1;\n-\t\t\t} else\n-\t\t\t\tprev_space = 0;\n-\t\t\t*out++ = ch;\n-\t\t}\n-\t\t*out = '\\0';\n-\t\tif (out > dir && prev_space)\n-\t\t\tout[-1] = '\\0';\n-\t}\n-\treturn dir;\n-}\n-\n-static void strip_trailing_slashes(char *dir)\n-{\n-\tchar *end = dir + strlen(dir);\n-\n-\twhile (dir < end - 1 && is_dir_sep(end[-1]))\n-\t\tend--;\n-\t*end = '\\0';\n-}\n-\n static int add_one_reference(struct string_list_item *item, void *cb_data)\n {\n \tstruct strbuf err = STRBUF_INIT;\n@@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \tif (argc == 2)\n \t\tdir = xstrdup(argv[1]);\n \telse\n-\t\tdir = guess_dir_name(repo_name, is_bundle, option_bare);\n-\tstrip_trailing_slashes(dir);\n+\t\tdir = guess_dir_name_from_git_url(repo_name, is_bundle, option_bare);\n+\tstrip_dir_trailing_slashes(dir);\n \n \tdest_exists = path_exists(dir);\n \tif (dest_exists && !is_empty_dir(dir))\ndiff --git a/dir.c b/dir.c\nindex 03c4d21267..84b47c4dbc 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -2970,6 +2970,120 @@ int is_empty_dir(const char *path)\n \treturn ret;\n }\n \n+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare)\n+{\n+\tconst char *end = repo + strlen(repo), *start, *ptr;\n+\tsize_t len;\n+\tchar *dir;\n+\n+\t/*\n+\t * Skip scheme.\n+\t */\n+\tstart = strstr(repo, \"://\");\n+\tif (start == NULL)\n+\t\tstart = repo;\n+\telse\n+\t\tstart += 3;\n+\n+\t/*\n+\t * Skip authentication data. The stripping does happen\n+\t * greedily, such that we strip up to the last '@' inside\n+\t * the host part.\n+\t */\n+\tfor (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {\n+\t\tif (*ptr == '@')\n+\t\t\tstart = ptr + 1;\n+\t}\n+\n+\t/*\n+\t * Strip trailing spaces, slashes and /.git\n+\t */\n+\twhile (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))\n+\t\tend--;\n+\tif (end - start > 5 && is_dir_sep(end[-5]) &&\n+\t    !strncmp(end - 4, \".git\", 4)) {\n+\t\tend -= 5;\n+\t\twhile (start < end && is_dir_sep(end[-1]))\n+\t\t\tend--;\n+\t}\n+\n+\t/*\n+\t * Strip trailing port number if we've got only a\n+\t * hostname (that is, there is no dir separator but a\n+\t * colon). This check is required such that we do not\n+\t * strip URI's like '/foo/bar:2222.git', which should\n+\t * result in a dir '2222' being guessed due to backwards\n+\t * compatibility.\n+\t */\n+\tif (memchr(start, '/', end - start) == NULL\n+\t    && memchr(start, ':', end - start) != NULL) {\n+\t\tptr = end;\n+\t\twhile (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')\n+\t\t\tptr--;\n+\t\tif (start < ptr && ptr[-1] == ':')\n+\t\t\tend = ptr - 1;\n+\t}\n+\n+\t/*\n+\t * Find last component. To remain backwards compatible we\n+\t * also regard colons as path separators, such that\n+\t * cloning a repository 'foo:bar.git' would result in a\n+\t * directory 'bar' being guessed.\n+\t */\n+\tptr = end;\n+\twhile (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')\n+\t\tptr--;\n+\tstart = ptr;\n+\n+\t/*\n+\t * Strip .{bundle,git}.\n+\t */\n+\tlen = end - start;\n+\tstrip_suffix_mem(start, &len, is_bundle ? \".bundle\" : \".git\");\n+\n+\tif (!len || (len == 1 && *start == '/'))\n+\t\tdie(_(\"No directory name could be guessed.\\n\"\n+\t\t      \"Please specify a directory on the command line\"));\n+\n+\tif (is_bare)\n+\t\tdir = xstrfmt(\"%.*s.git\", (int)len, start);\n+\telse\n+\t\tdir = xstrndup(start, len);\n+\t/*\n+\t * Replace sequences of 'control' characters and whitespace\n+\t * with one ascii space, remove leading and trailing spaces.\n+\t */\n+\tif (*dir) {\n+\t\tchar *out = dir;\n+\t\tint prev_space = 1 /* strip leading whitespace */;\n+\t\tfor (end = dir; *end; ++end) {\n+\t\t\tchar ch = *end;\n+\t\t\tif ((unsigned char)ch < '\\x20')\n+\t\t\t\tch = '\\x20';\n+\t\t\tif (isspace(ch)) {\n+\t\t\t\tif (prev_space)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tprev_space = 1;\n+\t\t\t} else\n+\t\t\t\tprev_space = 0;\n+\t\t\t*out++ = ch;\n+\t\t}\n+\t\t*out = '\\0';\n+\t\tif (out > dir && prev_space)\n+\t\t\tout[-1] = '\\0';\n+\t}\n+\treturn dir;\n+}\n+\n+void strip_dir_trailing_slashes(char *dir)\n+{\n+\tchar *end = dir + strlen(dir);\n+\n+\twhile (dir < end - 1 && is_dir_sep(end[-1]))\n+\t\tend--;\n+\t*end = '\\0';\n+}\n+\n static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)\n {\n \tDIR *dir;\ndiff --git a/dir.h b/dir.h\nindex b3e1a54a97..76441dde2d 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -453,6 +453,9 @@ static inline int is_dot_or_dotdot(const char *name)\n \n int is_empty_dir(const char *dir);\n \n+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare);\n+void strip_dir_trailing_slashes(char *dir);\n+\n void setup_standard_excludes(struct dir_struct *dir);\n \n char *get_sparse_checkout_filename(void);\n-- \n2.32.0\n\n"},{"id":"432069","messageId":"20210805074054.29916-6-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805074054.29916-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v2 5/9] submodule--helper: remove constness of sm_path","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:40:50Z","receivedAt":"2021-08-05T07:41:52Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"This is needed so that it can be modified by normalize_path_copy() in\nthe next patch.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 9b676c12f8..99aabf1078 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2748,7 +2748,7 @@ struct add_data {\n \tconst char *prefix;\n \tconst char *branch;\n \tconst char *reference_path;\n-\tconst char *sm_path;\n+\tchar *sm_path;\n \tconst char *sm_name;\n \tconst char *repo;\n \tconst char *realrepo;\n-- \n2.32.0\n\n"},{"id":"432070","messageId":"20210805074054.29916-7-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805074054.29916-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v2 6/9] submodule--helper: convert the bulk of cmd_add() to C","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:40:51Z","receivedAt":"2021-08-05T07:41:59Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Introduce the 'add' subcommand to `submodule--helper.c` that does all\nthe work 'submodule add' past the parsing of flags.\n\nAs with the previous conversions, this is meant to be a faithful\nconversion with no modification to the behaviour of `submodule add`.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nHelped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\nBased-on-patch-by: Shourya Shukla <periperidip@gmail.com>\nBased-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>\n---\n builtin/submodule--helper.c | 160 ++++++++++++++++++++++++++++++++++++\n git-submodule.sh            |  96 +---------------------\n 2 files changed, 162 insertions(+), 94 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 99aabf1078..05ae9ebe50 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -3046,6 +3046,165 @@ static int add_config(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static void die_on_index_match(const char *path, int force)\n+{\n+\tstruct pathspec ps;\n+\tconst char *args[] = { path, NULL };\n+\tparse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);\n+\n+\tif (read_cache_preload(NULL) < 0)\n+\t\tdie(_(\"index file corrupt\"));\n+\n+\tif (ps.nr) {\n+\t\tint i;\n+\t\tchar *ps_matched = xcalloc(ps.nr, 1);\n+\n+\t\t/* TODO: audit for interaction with sparse-index. */\n+\t\tensure_full_index(&the_index);\n+\n+\t\t/*\n+\t\t * Since there is only one pathspec, we just need\n+\t\t * need to check ps_matched[0] to know if a cache\n+\t\t * entry matched.\n+\t\t */\n+\t\tfor (i = 0; i < active_nr; i++) {\n+\t\t\tce_path_match(&the_index, active_cache[i], &ps,\n+\t\t\t\t      ps_matched);\n+\n+\t\t\tif (ps_matched[0]) {\n+\t\t\t\tif (!force)\n+\t\t\t\t\tdie(_(\"'%s' already exists in the index\"),\n+\t\t\t\t\t    path);\n+\t\t\t\tif (!S_ISGITLINK(active_cache[i]->ce_mode))\n+\t\t\t\t\tdie(_(\"'%s' already exists in the index \"\n+\t\t\t\t\t      \"and is not a submodule\"), path);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tfree(ps_matched);\n+\t}\n+}\n+\n+static void die_on_repo_without_commits(const char *path)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstrbuf_addstr(&sb, path);\n+\tif (is_nonbare_repository_dir(&sb)) {\n+\t\tstruct object_id oid;\n+\t\tif (resolve_gitlink_ref(path, \"HEAD\", &oid) < 0)\n+\t\t\tdie(_(\"'%s' does not have a commit checked out\"), path);\n+\t}\n+}\n+\n+static int module_add(int argc, const char **argv, const char *prefix)\n+{\n+\tint force = 0, quiet = 0, progress = 0, dissociate = 0;\n+\tstruct add_data add_data = ADD_DATA_INIT;\n+\n+\tstruct option options[] = {\n+\t\tOPT_STRING('b', \"branch\", &add_data.branch, N_(\"branch\"),\n+\t\t\t   N_(\"branch of repository to add as submodule\")),\n+\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n+\t\t\t   PARSE_OPT_NOCOMPLETE),\n+\t\tOPT__QUIET(&quiet, N_(\"print only error messages\")),\n+\t\tOPT_BOOL(0, \"progress\", &progress, N_(\"force cloning progress\")),\n+\t\tOPT_STRING(0, \"reference\", &add_data.reference_path, N_(\"repository\"),\n+\t\t\t   N_(\"reference repository\")),\n+\t\tOPT_BOOL(0, \"dissociate\", &dissociate, N_(\"borrow the objects from reference repositories\")),\n+\t\tOPT_STRING(0, \"name\", &add_data.sm_name, N_(\"name\"),\n+\t\t\t   N_(\"sets the submodule’s name to the given string \"\n+\t\t\t      \"instead of defaulting to its path\")),\n+\t\tOPT_INTEGER(0, \"depth\", &add_data.depth, N_(\"depth for shallow clones\")),\n+\t\tOPT_END()\n+\t};\n+\n+\tconst char *const usage[] = {\n+\t\tN_(\"git submodule--helper add [<options>] [--] <repository> [<path>]\"),\n+\t\tNULL\n+\t};\n+\n+\targc = parse_options(argc, argv, prefix, options, usage, 0);\n+\n+\tif (!is_writing_gitmodules_ok())\n+\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n+\n+\tif (prefix && *prefix &&\n+\t    add_data.reference_path && !is_absolute_path(add_data.reference_path))\n+\t\tadd_data.reference_path = xstrfmt(\"%s%s\", prefix, add_data.reference_path);\n+\n+\tif (argc == 0 || argc > 2)\n+\t\tusage_with_options(usage, options);\n+\n+\tadd_data.repo = argv[0];\n+\tif (argc == 1)\n+\t\tadd_data.sm_path = guess_dir_name_from_git_url(add_data.repo, 0, 0);\n+\telse\n+\t\tadd_data.sm_path = xstrdup(argv[1]);\n+\n+\tif (prefix && *prefix && !is_absolute_path(add_data.sm_path))\n+\t\tadd_data.sm_path = xstrfmt(\"%s%s\", prefix, add_data.sm_path);\n+\n+\tif (starts_with_dot_dot_slash(add_data.repo) ||\n+\t    starts_with_dot_slash(add_data.repo)) {\n+\t\tif (prefix)\n+\t\t\tdie(_(\"Relative path can only be used from the toplevel \"\n+\t\t\t      \"of the working tree\"));\n+\n+\t\t/* dereference source url relative to parent's url */\n+\t\tadd_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);\n+\t} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {\n+\t\tadd_data.realrepo = add_data.repo;\n+\t} else {\n+\t\tdie(_(\"repo URL: '%s' must be absolute or begin with ./|../\"),\n+\t\t    add_data.repo);\n+\t}\n+\n+\t/*\n+\t * normalize path:\n+\t * multiple //; leading ./; /./; /../;\n+\t */\n+\tnormalize_path_copy(add_data.sm_path, add_data.sm_path);\n+\tstrip_dir_trailing_slashes(add_data.sm_path);\n+\n+\tdie_on_index_match(add_data.sm_path, force);\n+\tdie_on_repo_without_commits(add_data.sm_path);\n+\n+\tif (!force) {\n+\t\tint exit_code = -1;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\t\tcp.git_cmd = 1;\n+\t\tcp.no_stdout = 1;\n+\t\tstrvec_pushl(&cp.args, \"add\", \"--dry-run\", \"--ignore-missing\",\n+\t\t\t     \"--no-warn-embedded-repo\", add_data.sm_path, NULL);\n+\t\tif ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {\n+\t\t\tstrbuf_complete_line(&sb);\n+\t\t\tfputs(sb.buf, stderr);\n+\t\t\treturn exit_code;\n+\t\t}\n+\t\tstrbuf_release(&sb);\n+\t}\n+\n+\tif(!add_data.sm_name)\n+\t\tadd_data.sm_name = add_data.sm_path;\n+\n+\tif (check_submodule_name(add_data.sm_name))\n+\t\tdie(_(\"'%s' is not a valid submodule name\"), add_data.sm_name);\n+\n+\tadd_data.prefix = prefix;\n+\tadd_data.force = !!force;\n+\tadd_data.quiet = !!quiet;\n+\tadd_data.progress = !!progress;\n+\tadd_data.dissociate = !!dissociate;\n+\n+\tif (add_submodule(&add_data))\n+\t\treturn 1;\n+\tconfigure_added_submodule(&add_data);\n+\tfree(add_data.sm_path);\n+\n+\treturn 0;\n+}\n+\n #define SUPPORT_SUPER_PREFIX (1<<0)\n \n struct cmd_struct {\n@@ -3060,6 +3219,7 @@ static struct cmd_struct commands[] = {\n \t{\"clone\", module_clone, 0},\n \t{\"add-clone\", add_clone, 0},\n \t{\"add-config\", add_config, 0},\n+\t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n \t{\"update-clone\", update_clone, 0},\n \t{\"ensure-core-worktree\", ensure_core_worktree, 0},\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 8c219ef382..1070540525 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -145,104 +145,12 @@ cmd_add()\n \t\tshift\n \tdone\n \n-\tif ! git submodule--helper config --check-writeable >/dev/null 2>&1\n+\tif test -z \"$1\"\n \tthen\n-\t\t die \"fatal: $(eval_gettext \"please make sure that the .gitmodules file is in the working tree\")\"\n-\tfi\n-\n-\tif test -n \"$reference_path\"\n-\tthen\n-\t\tis_absolute_path \"$reference_path\" ||\n-\t\treference_path=\"$wt_prefix$reference_path\"\n-\n-\t\treference=\"--reference=$reference_path\"\n-\tfi\n-\n-\trepo=$1\n-\tsm_path=$2\n-\n-\tif test -z \"$sm_path\"; then\n-\t\tsm_path=$(printf '%s\\n' \"$repo\" |\n-\t\t\tsed -e 's|/$||' -e 's|:*/*\\.git$||' -e 's|.*[/:]||g')\n-\tfi\n-\n-\tif test -z \"$repo\" || test -z \"$sm_path\"; then\n \t\tusage\n \tfi\n \n-\tis_absolute_path \"$sm_path\" || sm_path=\"$wt_prefix$sm_path\"\n-\n-\t# assure repo is absolute or relative to parent\n-\tcase \"$repo\" in\n-\t./*|../*)\n-\t\ttest -z \"$wt_prefix\" ||\n-\t\tdie \"fatal: $(gettext \"Relative path can only be used from the toplevel of the working tree\")\"\n-\n-\t\t# dereference source url relative to parent's url\n-\t\trealrepo=$(git submodule--helper resolve-relative-url \"$repo\") || exit\n-\t\t;;\n-\t*:*|/*)\n-\t\t# absolute url\n-\t\trealrepo=$repo\n-\t\t;;\n-\t*)\n-\t\tdie \"fatal: $(eval_gettext \"repo URL: '\\$repo' must be absolute or begin with ./|../\")\"\n-\t;;\n-\tesac\n-\n-\t# normalize path:\n-\t# multiple //; leading ./; /./; /../; trailing /\n-\tsm_path=$(printf '%s/\\n' \"$sm_path\" |\n-\t\tsed -e '\n-\t\t\ts|//*|/|g\n-\t\t\ts|^\\(\\./\\)*||\n-\t\t\ts|/\\(\\./\\)*|/|g\n-\t\t\t:start\n-\t\t\ts|\\([^/]*\\)/\\.\\./||\n-\t\t\ttstart\n-\t\t\ts|/*$||\n-\t\t')\n-\tif test -z \"$force\"\n-\tthen\n-\t\tgit ls-files --error-unmatch \"$sm_path\" > /dev/null 2>&1 &&\n-\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index\")\"\n-\telse\n-\t\tgit ls-files -s \"$sm_path\" | sane_grep -v \"^160000\" > /dev/null 2>&1 &&\n-\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index and is not a submodule\")\"\n-\tfi\n-\n-\tif test -d \"$sm_path\" &&\n-\t\ttest -z $(git -C \"$sm_path\" rev-parse --show-cdup 2>/dev/null)\n-\tthen\n-\t    git -C \"$sm_path\" rev-parse --verify -q HEAD >/dev/null ||\n-\t    die \"fatal: $(eval_gettext \"'\\$sm_path' does not have a commit checked out\")\"\n-\tfi\n-\n-\tif test -z \"$force\"\n-\tthen\n-\t    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo \"$sm_path\" 2>&1 >/dev/null)\n-\t    res=$?\n-\t    if test $res -ne 0\n-\t    then\n-\t\t echo >&2 \"$dryerr\"\n-\t\t exit $res\n-\t    fi\n-\tfi\n-\n-\tif test -n \"$custom_name\"\n-\tthen\n-\t\tsm_name=\"$custom_name\"\n-\telse\n-\t\tsm_name=\"$sm_path\"\n-\tfi\n-\n-\tif ! git submodule--helper check-name \"$sm_name\"\n-\tthen\n-\t\tdie \"fatal: $(eval_gettext \"'$sm_name' is not a valid submodule name\")\"\n-\tfi\n-\n-\tgit 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\n-\tgit submodule--helper add-config ${force:+--force} ${branch:+--branch \"$branch\"} --url \"$repo\" --resolved-url \"$realrepo\" --path \"$sm_path\" --name \"$sm_name\"\n+\tgit ${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\"} -- \"$@\"\n }\n \n #\n-- \n2.32.0\n\n"},{"id":"432071","messageId":"20210805074054.29916-8-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805074054.29916-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v2 7/9] submodule--helper: remove add-clone subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:40:52Z","receivedAt":"2021-08-05T07:41:59Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"We no longer need this subcommand, as all of its functionality is being\ncalled by the newly-introduced `module_add()` directly within C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 60 -------------------------------------\n 1 file changed, 60 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 05ae9ebe50..700cc8bbeb 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2860,65 +2860,6 @@ static int add_submodule(const struct add_data *add_data)\n \treturn 0;\n }\n \n-static int add_clone(int argc, const char **argv, const char *prefix)\n-{\n-\tint force = 0, quiet = 0, dissociate = 0, progress = 0;\n-\tstruct add_data add_data = ADD_DATA_INIT;\n-\n-\tstruct option options[] = {\n-\t\tOPT_STRING('b', \"branch\", &add_data.branch,\n-\t\t\t   N_(\"branch\"),\n-\t\t\t   N_(\"branch of repository to checkout on cloning\")),\n-\t\tOPT_STRING(0, \"prefix\", &prefix,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"alternative anchor for relative paths\")),\n-\t\tOPT_STRING(0, \"path\", &add_data.sm_path,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"where the new submodule will be cloned to\")),\n-\t\tOPT_STRING(0, \"name\", &add_data.sm_name,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"name of the new submodule\")),\n-\t\tOPT_STRING(0, \"url\", &add_data.realrepo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url where to clone the submodule from\")),\n-\t\tOPT_STRING(0, \"reference\", &add_data.reference_path,\n-\t\t\t   N_(\"repo\"),\n-\t\t\t   N_(\"reference repository\")),\n-\t\tOPT_BOOL(0, \"dissociate\", &dissociate,\n-\t\t\t N_(\"use --reference only while cloning\")),\n-\t\tOPT_INTEGER(0, \"depth\", &add_data.depth,\n-\t\t\t    N_(\"depth for shallow clones\")),\n-\t\tOPT_BOOL(0, \"progress\", &progress,\n-\t\t\t N_(\"force cloning progress\")),\n-\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n-\t\t\t   PARSE_OPT_NOCOMPLETE),\n-\t\tOPT__QUIET(&quiet, \"suppress output for cloning a submodule\"),\n-\t\tOPT_END()\n-\t};\n-\n-\tconst char *const usage[] = {\n-\t\tN_(\"git submodule--helper add-clone [<options>...] \"\n-\t\t   \"--url <url> --path <path> --name <name>\"),\n-\t\tNULL\n-\t};\n-\n-\targc = parse_options(argc, argv, prefix, options, usage, 0);\n-\n-\tif (argc != 0)\n-\t\tusage_with_options(usage, options);\n-\n-\tadd_data.prefix = prefix;\n-\tadd_data.progress = !!progress;\n-\tadd_data.dissociate = !!dissociate;\n-\tadd_data.force = !!force;\n-\tadd_data.quiet = !!quiet;\n-\n-\tif (add_submodule(&add_data))\n-\t\treturn 1;\n-\n-\treturn 0;\n-}\n-\n static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)\n {\n \tchar *key;\n@@ -3217,7 +3158,6 @@ static struct cmd_struct commands[] = {\n \t{\"list\", module_list, 0},\n \t{\"name\", module_name, 0},\n \t{\"clone\", module_clone, 0},\n-\t{\"add-clone\", add_clone, 0},\n \t{\"add-config\", add_config, 0},\n \t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n-- \n2.32.0\n\n"},{"id":"432072","messageId":"20210805074054.29916-9-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805074054.29916-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v2 8/9] submodule--helper: remove add-config subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:40:53Z","receivedAt":"2021-08-05T07:42:08Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Also no longer needed is this subcommand, as all of its functionality is\nbeing called by the newly-introduced `module_add()` directly within C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 49 -------------------------------------\n 1 file changed, 49 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 700cc8bbeb..da83e8e2a5 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2939,54 +2939,6 @@ static void configure_added_submodule(struct add_data *add_data)\n \t}\n }\n \n-static int add_config(int argc, const char **argv, const char *prefix)\n-{\n-\tint force = 0;\n-\tstruct add_data add_data = ADD_DATA_INIT;\n-\n-\tstruct option options[] = {\n-\t\tOPT_STRING('b', \"branch\", &add_data.branch,\n-\t\t\t   N_(\"branch\"),\n-\t\t\t   N_(\"branch of repository to store in \"\n-\t\t\t      \"the submodule configuration\")),\n-\t\tOPT_STRING(0, \"url\", &add_data.repo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url to clone submodule from\")),\n-\t\tOPT_STRING(0, \"resolved-url\", &add_data.realrepo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url to clone the submodule from, after it has \"\n-\t\t\t      \"been dereferenced relative to parent's url, \"\n-\t\t\t      \"in the case where <url> is a relative url\")),\n-\t\tOPT_STRING(0, \"path\", &add_data.sm_path,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"where the new submodule will be cloned to\")),\n-\t\tOPT_STRING(0, \"name\", &add_data.sm_name,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"name of the new submodule\")),\n-\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n-\t\t\t   PARSE_OPT_NOCOMPLETE),\n-\t\tOPT_END()\n-\t};\n-\n-\tconst char *const usage[] = {\n-\t\tN_(\"git submodule--helper add-config \"\n-\t\t   \"[--force|-f] [--branch|-b <branch>] \"\n-\t\t   \"--url <url> --resolved-url <resolved-url> \"\n-\t\t   \"--path <path> --name <name>\"),\n-\t\tNULL\n-\t};\n-\n-\targc = parse_options(argc, argv, prefix, options, usage, 0);\n-\n-\tif (argc)\n-\t\tusage_with_options(usage, options);\n-\n-\tadd_data.force = !!force;\n-\tconfigure_added_submodule(&add_data);\n-\n-\treturn 0;\n-}\n-\n static void die_on_index_match(const char *path, int force)\n {\n \tstruct pathspec ps;\n@@ -3158,7 +3110,6 @@ static struct cmd_struct commands[] = {\n \t{\"list\", module_list, 0},\n \t{\"name\", module_name, 0},\n \t{\"clone\", module_clone, 0},\n-\t{\"add-config\", add_config, 0},\n \t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n \t{\"update-clone\", update_clone, 0},\n-- \n2.32.0\n\n"},{"id":"432073","messageId":"20210805074054.29916-10-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805074054.29916-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v2 9/9] submodule--helper: remove resolve-relative-url subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-05T07:40:54Z","receivedAt":"2021-08-05T07:42:09Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"The shell subcommand `resolve-relative-url` is no longer required, as\nits last caller has been removed when it was converted to C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 20 --------------------\n 1 file changed, 20 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex da83e8e2a5..514891a22f 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -223,25 +223,6 @@ static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat\n \treturn relurl;\n }\n \n-static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n-{\n-\tconst char *up_path = NULL;\n-\tchar *res;\n-\tconst char *url;\n-\n-\tif (argc != 2 && argc != 3)\n-\t\tdie(\"resolve-relative-url only accepts one or two arguments\");\n-\n-\turl = argv[1];\n-\tif (argc == 3)\n-\t\tup_path = argv[2];\n-\n-\tres = compute_submodule_clone_url(url, up_path, 1);\n-\tputs(res);\n-\tfree(res);\n-\treturn 0;\n-}\n-\n static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)\n {\n \tchar *remoteurl, *res;\n@@ -3115,7 +3096,6 @@ static struct cmd_struct commands[] = {\n \t{\"update-clone\", update_clone, 0},\n \t{\"ensure-core-worktree\", ensure_core_worktree, 0},\n \t{\"relative-path\", resolve_relative_path, 0},\n-\t{\"resolve-relative-url\", resolve_relative_url, 0},\n \t{\"resolve-relative-url-test\", resolve_relative_url_test, 0},\n \t{\"foreach\", module_foreach, SUPPORT_SUPER_PREFIX},\n \t{\"init\", module_init, SUPPORT_SUPER_PREFIX},\n-- \n2.32.0\n\n"},{"id":"432129","messageId":"xmqqzgtvk676.fsf@gitster.g","threadId":"56219","inReplyTo":"20210805074054.29916-2-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v2 1/9] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-08-05T20:05:49Z","receivedAt":"2021-08-05T20:05:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Atharva Raykar <raykar.ath@gmail.com> writes:\n\n> -static char *compute_submodule_clone_url(const char *rel_url)\n> +static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n>  {\n>  \tchar *remoteurl, *relurl;\n>  \tchar *remote = get_default_remote();\n> @@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)\n>  \n>  \tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n>  \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n> -\t\twarning(_(\"could not look up configuration '%s'. Assuming this repository is its own authoritative upstream.\"), remotesb.buf);\n> +\t\tif (!quiet)\n> +\t\t\twarning(_(\"could not look up configuration '%s'. \"\n> +\t\t\t\t  \"Assuming this repository is its own \"\n> +\t\t\t\t  \"authoritative upstream.\"),\n> +\t\t\t\tremotesb.buf);\n>  \t\tremoteurl = xgetcwd();\n>  \t}\n> -\trelurl = relative_url(remoteurl, rel_url, NULL);\n> +\trelurl = relative_url(remoteurl, rel_url, up_path);\n\nOK, so we can optionally operate silently, and also tell\nrelative_url the path the URL should be made relative to.\n\nExisting callers, of course, should pass NULL and 0 as these\noptional features are new, as we can see below.\n\n>  \tfree(remote);\n>  \tfree(remoteurl);\n> @@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,\n>  \t\tif (starts_with_dot_dot_slash(url) ||\n>  \t\t    starts_with_dot_slash(url)) {\n>  \t\t\tchar *oldurl = url;\n> -\t\t\turl = compute_submodule_clone_url(oldurl);\n> +\t\t\turl = compute_submodule_clone_url(oldurl, NULL, 0);\n>  \t\t\tfree(oldurl);\n>  \t\t}\n>  \n> @@ -2134,7 +2138,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n>  \tif (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {\n>  \t\tif (starts_with_dot_slash(sub->url) ||\n>  \t\t    starts_with_dot_dot_slash(sub->url)) {\n> -\t\t\turl = compute_submodule_clone_url(sub->url);\n> +\t\t\turl = compute_submodule_clone_url(sub->url, NULL, 0);\n>  \t\t\tneed_free_url = 1;\n>  \t\t} else\n>  \t\t\turl = sub->url;\n\nAll makes sense.\n"},{"id":"432130","messageId":"xmqqv94jk5to.fsf@gitster.g","threadId":"56219","inReplyTo":"20210805074054.29916-3-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v2 2/9] submodule--helper: refactor resolve_relative_url() helper","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-08-05T20:13:55Z","receivedAt":"2021-08-05T20:13:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Atharva Raykar <raykar.ath@gmail.com> writes:\n\n> Refactor the helper function to resolve a relative url, by reusing the\n> existing `compute_submodule_clone_url()` function.\n>\n> `compute_submodule_clone_url()` performs the same work that\n> `resolve_relative_url()` is doing, so we eliminate this code repetition\n> by moving the former function's definition up, and calling it inside\n> `resolve_relative_url()`.\n\nLooking good.\n\n> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Shourya Shukla <periperidip@gmail.com>\n> ---\n>  builtin/submodule--helper.c | 61 +++++++++++++++----------------------\n>  1 file changed, 25 insertions(+), 36 deletions(-)\n\nThis step is easier to see with \"show --patience --color-moved\" to\nsee that compute_submodule_clone_url() has only been moved without\nany change.  And the actual change is much smaller than what the\ndiffstat suggests above (11 lines lost, 1 line updated, if I counted\ncorrectly).\n\nNicely done.\n\n"},{"id":"432131","messageId":"xmqqr1f7k5iv.fsf@gitster.g","threadId":"56219","inReplyTo":"20210805074054.29916-4-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v2 3/9] submodule--helper: remove repeated code in sync_submodule()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-08-05T20:20:24Z","receivedAt":"2021-08-05T20:20:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Atharva Raykar <raykar.ath@gmail.com> writes:\n\n> This part of `sync_submodule()` is doing the same thing that\n> `compute_submodule_clone_url()` is doing. Let's reuse that helper here.\n>\n> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Shourya Shukla <periperidip@gmail.com>\n> ---\n>  builtin/submodule--helper.c | 16 +++-------------\n>  1 file changed, 3 insertions(+), 13 deletions(-)\n\nThe original used the result of get_default_remote() twice before\nfreeing it, but now all that code to allocate and free remote is\ncontained in compute_submodule_clone_url(), which mean swe allocate,\nuse, and free twice.  In exchange, our logic here works at a higher\nlevel of abstraction, which is a big plus.\n\nNice.\n\n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index f4b496bac6..9b676c12f8 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,\n>  \tif (sub && sub->url) {\n>  \t\tif (starts_with_dot_dot_slash(sub->url) ||\n>  \t\t    starts_with_dot_slash(sub->url)) {\n> -\t\t\tchar *remote_url, *up_path;\n> -\t\t\tchar *remote = get_default_remote();\n> -\t\t\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n> -\n> -\t\t\tif (git_config_get_string(sb.buf, &remote_url))\n> -\t\t\t\tremote_url = xgetcwd();\n> -\n> -\t\t\tup_path = get_up_path(path);\n> -\t\t\tsub_origin_url = relative_url(remote_url, sub->url, up_path);\n> -\t\t\tsuper_config_url = relative_url(remote_url, sub->url, NULL);\n> -\n> -\t\t\tfree(remote);\n> +\t\t\tchar *up_path = get_up_path(path);\n> +\t\t\tsub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);\n> +\t\t\tsuper_config_url = compute_submodule_clone_url(sub->url, NULL, 1);\n>  \t\t\tfree(up_path);\n> -\t\t\tfree(remote_url);\n>  \t\t} else {\n>  \t\t\tsub_origin_url = xstrdup(sub->url);\n>  \t\t\tsuper_config_url = xstrdup(sub->url);\n"},{"id":"432133","messageId":"xmqqim0jk4qx.fsf@gitster.g","threadId":"56219","inReplyTo":"20210805074054.29916-5-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-08-05T20:37:10Z","receivedAt":"2021-08-05T20:37:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Atharva Raykar <raykar.ath@gmail.com> writes:\n\n> These functions can be useful to other parts of Git. Let's move them to\n> dir.c, while renaming them to be make their functionality more explicit.\n\nHmph, guess_dir_name_from_git_url() is not all that more clarifying\nthan the original, at least to me.  For a file-scope static helper,\nit probably was good enough with a short name with no function doc,\nbut we should describe what it does in comments in dir.h and come up\nwith a suitable name, taking input from that description.\n\n> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Shourya Shukla <shouryashukla.oo@gmail.com>\n> ---\n>  builtin/clone.c | 118 +-----------------------------------------------\n>  dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++\n>  dir.h           |   3 ++\n>  3 files changed, 119 insertions(+), 116 deletions(-)\n\nAgain \"show --color-moved\" helps to see that these two helper\nfunctions are moved across files without any change other than the\nnames, which is good.\n\n> @@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n>  \tif (argc == 2)\n>  \t\tdir = xstrdup(argv[1]);\n>  \telse\n> -\t\tdir = guess_dir_name(repo_name, is_bundle, option_bare);\n> -\tstrip_trailing_slashes(dir);\n> +\t\tdir = guess_dir_name_from_git_url(repo_name, is_bundle, option_bare);\n> +\tstrip_dir_trailing_slashes(dir);\n\nSo, what does this new public helper function guess?  The name of\nthe function says it guesses a directory name, but it is not just\nany directory name, but a directory with some specific meaning.\n\nHere repo_name has the URL the user gave \"git clone\", and even\nthough there are some code before this part that computed on the\nvariable, it hasn't been modified.  And \"from_git_url\" is a good way\nto indicate that that is one of the input the function uses to guess\nthe name of \"the directory with some unknown specific meaning\".\n\nI think this codepath wants the new directory to create as the\nresult of \"git clone\" operation in \"dir\".  So, even though I still\ndo not have a good answer to the earlier \"this is not just any\ndirectory but with some specific meaning---what is it?\" question,\nadjectives that are appropriate for the \"directory\" to answer it\nmay be along the lines of \"new\", \"resulting\", \"cloned\", etc.\n\n> diff --git a/dir.h b/dir.h\n> index b3e1a54a97..76441dde2d 100644\n> --- a/dir.h\n> +++ b/dir.h\n> @@ -453,6 +453,9 @@ static inline int is_dot_or_dotdot(const char *name)\n>  \n>  int is_empty_dir(const char *dir);\n>  \n\nWe would want docstring here for the function (and possibly rename\nthe function to clarify what kind of \"dir\" we are talking about).\n\n\n> +char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare);\n> +void strip_dir_trailing_slashes(char *dir);\n> +\n>  void setup_standard_excludes(struct dir_struct *dir);\n>  \n>  char *get_sparse_checkout_filename(void);\n\nThanks.\n"},{"id":"432135","messageId":"xmqqeeb7k4kl.fsf@gitster.g","threadId":"56219","inReplyTo":"20210805074054.29916-6-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v2 5/9] submodule--helper: remove constness of sm_path","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-08-05T20:40:58Z","receivedAt":"2021-08-05T20:41:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Atharva Raykar <raykar.ath@gmail.com> writes:\n\n> This is needed so that it can be modified by normalize_path_copy() in\n> the next patch.\n\nThis is a hard-to-judge change.  With this alone, we cannot tell if\nsomebody has already looked at the member (and possibly saved the\npointer elsewhere) before \"the next patch\" starts modifying the\nmember in the struct.  It probably should be done in a single patch\nto demonstrate why it is needed and how existing users of the field\nare OK with this change.\n\n>\n> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Shourya Shukla <periperidip@gmail.com>\n> ---\n>  builtin/submodule--helper.c | 2 +-\n>  1 file changed, 1 insertion(+), 1 deletion(-)\n>\n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index 9b676c12f8..99aabf1078 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -2748,7 +2748,7 @@ struct add_data {\n>  \tconst char *prefix;\n>  \tconst char *branch;\n>  \tconst char *reference_path;\n> -\tconst char *sm_path;\n> +\tchar *sm_path;\n>  \tconst char *sm_name;\n>  \tconst char *repo;\n>  \tconst char *realrepo;\n"},{"id":"432148","messageId":"YQyIJpq/r0O7zhb1@danh.dev","threadId":"56219","inReplyTo":"20210805071917.29500-3-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule()","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2021-08-06T00:53:58Z","receivedAt":"2021-08-06T00:54:19Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"On 2021-08-05 12:49:11+0530, Atharva Raykar <raykar.ath@gmail.com> wrote:\n> This part of `sync_submodule()` is doing the same thing that\n> `compute_submodule_clone_url()` is doing. Let's reuse that helper here.\n> \n> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Shourya Shukla <periperidip@gmail.com>\n> ---\n>  builtin/submodule--helper.c | 16 +++-------------\n>  1 file changed, 3 insertions(+), 13 deletions(-)\n> \n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index f4b496bac6..9b676c12f8 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,\n>  \tif (sub && sub->url) {\n>  \t\tif (starts_with_dot_dot_slash(sub->url) ||\n>  \t\t    starts_with_dot_slash(sub->url)) {\n> -\t\t\tchar *remote_url, *up_path;\n> -\t\t\tchar *remote = get_default_remote();\n> -\t\t\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n> -\n> -\t\t\tif (git_config_get_string(sb.buf, &remote_url))\n> -\t\t\t\tremote_url = xgetcwd();\n> -\n> -\t\t\tup_path = get_up_path(path);\n> -\t\t\tsub_origin_url = relative_url(remote_url, sub->url, up_path);\n> -\t\t\tsuper_config_url = relative_url(remote_url, sub->url, NULL);\n> -\n> -\t\t\tfree(remote);\n> +\t\t\tchar *up_path = get_up_path(path);\n> +\t\t\tsub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);\n> +\t\t\tsuper_config_url = compute_submodule_clone_url(sub->url, NULL, 1);\n\nWhile previous patch is definitely a refactoring, this patch add small\noverhead to the system, the new code will query (then free())\ngit_config_get_string() and/or xgetcwd() one more time in the second\ncompute_submodule_clone_url()\n\nI think the abstraction overhead is not that big, though.\n\n>  \t\t\tfree(up_path);\n> -\t\t\tfree(remote_url);\n>  \t\t} else {\n>  \t\t\tsub_origin_url = xstrdup(sub->url);\n>  \t\t\tsuper_config_url = xstrdup(sub->url);\n> -- \n> 2.32.0\n> \n\n-- \nDanh\n"},{"id":"432149","messageId":"YQyNDv3bzVZwpAVl@danh.dev","threadId":"56219","inReplyTo":"20210805074054.29916-7-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v2 6/9] submodule--helper: convert the bulk of cmd_add() to C","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2021-08-06T01:14:54Z","receivedAt":"2021-08-06T01:15:00Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"On 2021-08-05 13:10:51+0530, Atharva Raykar <raykar.ath@gmail.com> wrote:\n> Introduce the 'add' subcommand to `submodule--helper.c` that does all\n> the work 'submodule add' past the parsing of flags.\n> \n> As with the previous conversions, this is meant to be a faithful\n> conversion with no modification to the behaviour of `submodule add`.\n> \n> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Helped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>\n> Mentored-by: Shourya Shukla <periperidip@gmail.com>\n> Based-on-patch-by: Shourya Shukla <periperidip@gmail.com>\n> Based-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>\n> ---\n>  builtin/submodule--helper.c | 160 ++++++++++++++++++++++++++++++++++++\n>  git-submodule.sh            |  96 +---------------------\n>  2 files changed, 162 insertions(+), 94 deletions(-)\n> \n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index 99aabf1078..05ae9ebe50 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -3046,6 +3046,165 @@ static int add_config(int argc, const char **argv, const char *prefix)\n>  \treturn 0;\n>  }\n>  \n> +static void die_on_index_match(const char *path, int force)\n> +{\n> +\tstruct pathspec ps;\n> +\tconst char *args[] = { path, NULL };\n> +\tparse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);\n> +\n> +\tif (read_cache_preload(NULL) < 0)\n> +\t\tdie(_(\"index file corrupt\"));\n> +\n> +\tif (ps.nr) {\n> +\t\tint i;\n> +\t\tchar *ps_matched = xcalloc(ps.nr, 1);\n> +\n> +\t\t/* TODO: audit for interaction with sparse-index. */\n> +\t\tensure_full_index(&the_index);\n> +\n> +\t\t/*\n> +\t\t * Since there is only one pathspec, we just need\n> +\t\t * need to check ps_matched[0] to know if a cache\n> +\t\t * entry matched.\n> +\t\t */\n> +\t\tfor (i = 0; i < active_nr; i++) {\n> +\t\t\tce_path_match(&the_index, active_cache[i], &ps,\n> +\t\t\t\t      ps_matched);\n> +\n> +\t\t\tif (ps_matched[0]) {\n> +\t\t\t\tif (!force)\n> +\t\t\t\t\tdie(_(\"'%s' already exists in the index\"),\n> +\t\t\t\t\t    path);\n> +\t\t\t\tif (!S_ISGITLINK(active_cache[i]->ce_mode))\n> +\t\t\t\t\tdie(_(\"'%s' already exists in the index \"\n> +\t\t\t\t\t      \"and is not a submodule\"), path);\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\t\t}\n> +\t\tfree(ps_matched);\n> +\t}\n> +}\n> +\n> +static void die_on_repo_without_commits(const char *path)\n> +{\n> +\tstruct strbuf sb = STRBUF_INIT;\n> +\tstrbuf_addstr(&sb, path);\n> +\tif (is_nonbare_repository_dir(&sb)) {\n> +\t\tstruct object_id oid;\n> +\t\tif (resolve_gitlink_ref(path, \"HEAD\", &oid) < 0)\n> +\t\t\tdie(_(\"'%s' does not have a commit checked out\"), path);\n> +\t}\n> +}\n> +\n> +static int module_add(int argc, const char **argv, const char *prefix)\n> +{\n> +\tint force = 0, quiet = 0, progress = 0, dissociate = 0;\n> +\tstruct add_data add_data = ADD_DATA_INIT;\n> +\n> +\tstruct option options[] = {\n> +\t\tOPT_STRING('b', \"branch\", &add_data.branch, N_(\"branch\"),\n> +\t\t\t   N_(\"branch of repository to add as submodule\")),\n> +\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n> +\t\t\t   PARSE_OPT_NOCOMPLETE),\n> +\t\tOPT__QUIET(&quiet, N_(\"print only error messages\")),\n> +\t\tOPT_BOOL(0, \"progress\", &progress, N_(\"force cloning progress\")),\n> +\t\tOPT_STRING(0, \"reference\", &add_data.reference_path, N_(\"repository\"),\n> +\t\t\t   N_(\"reference repository\")),\n> +\t\tOPT_BOOL(0, \"dissociate\", &dissociate, N_(\"borrow the objects from reference repositories\")),\n> +\t\tOPT_STRING(0, \"name\", &add_data.sm_name, N_(\"name\"),\n> +\t\t\t   N_(\"sets the submodule’s name to the given string \"\n> +\t\t\t      \"instead of defaulting to its path\")),\n> +\t\tOPT_INTEGER(0, \"depth\", &add_data.depth, N_(\"depth for shallow clones\")),\n> +\t\tOPT_END()\n> +\t};\n> +\n> +\tconst char *const usage[] = {\n> +\t\tN_(\"git submodule--helper add [<options>] [--] <repository> [<path>]\"),\n> +\t\tNULL\n> +\t};\n> +\n> +\targc = parse_options(argc, argv, prefix, options, usage, 0);\n> +\n> +\tif (!is_writing_gitmodules_ok())\n> +\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n> +\n> +\tif (prefix && *prefix &&\n> +\t    add_data.reference_path && !is_absolute_path(add_data.reference_path))\n> +\t\tadd_data.reference_path = xstrfmt(\"%s%s\", prefix, add_data.reference_path);\n> +\n> +\tif (argc == 0 || argc > 2)\n> +\t\tusage_with_options(usage, options);\n> +\n> +\tadd_data.repo = argv[0];\n> +\tif (argc == 1)\n> +\t\tadd_data.sm_path = guess_dir_name_from_git_url(add_data.repo, 0, 0);\n> +\telse\n> +\t\tadd_data.sm_path = xstrdup(argv[1]);\n\nadd_data.sm_path is allocated in this block (regardless of legs).\n\n> +\tif (prefix && *prefix && !is_absolute_path(add_data.sm_path))\n> +\t\tadd_data.sm_path = xstrfmt(\"%s%s\", prefix, add_data.sm_path);\n> +\n> +\tif (starts_with_dot_dot_slash(add_data.repo) ||\n> +\t    starts_with_dot_slash(add_data.repo)) {\n> +\t\tif (prefix)\n> +\t\t\tdie(_(\"Relative path can only be used from the toplevel \"\n> +\t\t\t      \"of the working tree\"));\n> +\n> +\t\t/* dereference source url relative to parent's url */\n> +\t\tadd_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);\n> +\t} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {\n> +\t\tadd_data.realrepo = add_data.repo;\n> +\t} else {\n> +\t\tdie(_(\"repo URL: '%s' must be absolute or begin with ./|../\"),\n> +\t\t    add_data.repo);\n> +\t}\n> +\n> +\t/*\n> +\t * normalize path:\n> +\t * multiple //; leading ./; /./; /../;\n> +\t */\n> +\tnormalize_path_copy(add_data.sm_path, add_data.sm_path);\n> +\tstrip_dir_trailing_slashes(add_data.sm_path);\n> +\n> +\tdie_on_index_match(add_data.sm_path, force);\n> +\tdie_on_repo_without_commits(add_data.sm_path);\n> +\n> +\tif (!force) {\n> +\t\tint exit_code = -1;\n> +\t\tstruct strbuf sb = STRBUF_INIT;\n> +\t\tstruct child_process cp = CHILD_PROCESS_INIT;\n> +\t\tcp.git_cmd = 1;\n> +\t\tcp.no_stdout = 1;\n> +\t\tstrvec_pushl(&cp.args, \"add\", \"--dry-run\", \"--ignore-missing\",\n> +\t\t\t     \"--no-warn-embedded-repo\", add_data.sm_path, NULL);\n> +\t\tif ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {\n> +\t\t\tstrbuf_complete_line(&sb);\n> +\t\t\tfputs(sb.buf, stderr);\n> +\t\t\treturn exit_code;\n\nBut, we don't free it when return from here.\n\n> +\t\t}\n> +\t\tstrbuf_release(&sb);\n> +\t}\n> +\n> +\tif(!add_data.sm_name)\n> +\t\tadd_data.sm_name = add_data.sm_path;\n> +\n> +\tif (check_submodule_name(add_data.sm_name))\n> +\t\tdie(_(\"'%s' is not a valid submodule name\"), add_data.sm_name);\n> +\n> +\tadd_data.prefix = prefix;\n> +\tadd_data.force = !!force;\n> +\tadd_data.quiet = !!quiet;\n> +\tadd_data.progress = !!progress;\n> +\tadd_data.dissociate = !!dissociate;\n> +\n> +\tif (add_submodule(&add_data))\n> +\t\treturn 1;\n\nAnd here.\n\n> +\tconfigure_added_submodule(&add_data);\n> +\tfree(add_data.sm_path);\n\nHowever, it will be free()-d here, is it intended?\n\nI think we may use UNLEAK above (for now) because we will exit process\nafter this function.\n\nHowever, I anticipated we may need to do more stuffs after this\nfunction in the future.\n\n> +\n> +\treturn 0;\n> +}\n> +\n>  #define SUPPORT_SUPER_PREFIX (1<<0)\n>  \n>  struct cmd_struct {\n> @@ -3060,6 +3219,7 @@ static struct cmd_struct commands[] = {\n>  \t{\"clone\", module_clone, 0},\n>  \t{\"add-clone\", add_clone, 0},\n>  \t{\"add-config\", add_config, 0},\n> +\t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n>  \t{\"update-module-mode\", module_update_module_mode, 0},\n>  \t{\"update-clone\", update_clone, 0},\n>  \t{\"ensure-core-worktree\", ensure_core_worktree, 0},\n> diff --git a/git-submodule.sh b/git-submodule.sh\n> index 8c219ef382..1070540525 100755\n> --- a/git-submodule.sh\n> +++ b/git-submodule.sh\n> @@ -145,104 +145,12 @@ cmd_add()\n>  \t\tshift\n>  \tdone\n>  \n> -\tif ! git submodule--helper config --check-writeable >/dev/null 2>&1\n> +\tif test -z \"$1\"\n>  \tthen\n> -\t\t die \"fatal: $(eval_gettext \"please make sure that the .gitmodules file is in the working tree\")\"\n> -\tfi\n> -\n> -\tif test -n \"$reference_path\"\n> -\tthen\n> -\t\tis_absolute_path \"$reference_path\" ||\n> -\t\treference_path=\"$wt_prefix$reference_path\"\n> -\n> -\t\treference=\"--reference=$reference_path\"\n> -\tfi\n> -\n> -\trepo=$1\n> -\tsm_path=$2\n> -\n> -\tif test -z \"$sm_path\"; then\n> -\t\tsm_path=$(printf '%s\\n' \"$repo\" |\n> -\t\t\tsed -e 's|/$||' -e 's|:*/*\\.git$||' -e 's|.*[/:]||g')\n> -\tfi\n> -\n> -\tif test -z \"$repo\" || test -z \"$sm_path\"; then\n>  \t\tusage\n>  \tfi\n>  \n> -\tis_absolute_path \"$sm_path\" || sm_path=\"$wt_prefix$sm_path\"\n> -\n> -\t# assure repo is absolute or relative to parent\n> -\tcase \"$repo\" in\n> -\t./*|../*)\n> -\t\ttest -z \"$wt_prefix\" ||\n> -\t\tdie \"fatal: $(gettext \"Relative path can only be used from the toplevel of the working tree\")\"\n> -\n> -\t\t# dereference source url relative to parent's url\n> -\t\trealrepo=$(git submodule--helper resolve-relative-url \"$repo\") || exit\n> -\t\t;;\n> -\t*:*|/*)\n> -\t\t# absolute url\n> -\t\trealrepo=$repo\n> -\t\t;;\n> -\t*)\n> -\t\tdie \"fatal: $(eval_gettext \"repo URL: '\\$repo' must be absolute or begin with ./|../\")\"\n> -\t;;\n> -\tesac\n> -\n> -\t# normalize path:\n> -\t# multiple //; leading ./; /./; /../; trailing /\n> -\tsm_path=$(printf '%s/\\n' \"$sm_path\" |\n> -\t\tsed -e '\n> -\t\t\ts|//*|/|g\n> -\t\t\ts|^\\(\\./\\)*||\n> -\t\t\ts|/\\(\\./\\)*|/|g\n> -\t\t\t:start\n> -\t\t\ts|\\([^/]*\\)/\\.\\./||\n> -\t\t\ttstart\n> -\t\t\ts|/*$||\n> -\t\t')\n> -\tif test -z \"$force\"\n> -\tthen\n> -\t\tgit ls-files --error-unmatch \"$sm_path\" > /dev/null 2>&1 &&\n> -\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index\")\"\n> -\telse\n> -\t\tgit ls-files -s \"$sm_path\" | sane_grep -v \"^160000\" > /dev/null 2>&1 &&\n> -\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index and is not a submodule\")\"\n> -\tfi\n> -\n> -\tif test -d \"$sm_path\" &&\n> -\t\ttest -z $(git -C \"$sm_path\" rev-parse --show-cdup 2>/dev/null)\n> -\tthen\n> -\t    git -C \"$sm_path\" rev-parse --verify -q HEAD >/dev/null ||\n> -\t    die \"fatal: $(eval_gettext \"'\\$sm_path' does not have a commit checked out\")\"\n> -\tfi\n> -\n> -\tif test -z \"$force\"\n> -\tthen\n> -\t    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo \"$sm_path\" 2>&1 >/dev/null)\n> -\t    res=$?\n> -\t    if test $res -ne 0\n> -\t    then\n> -\t\t echo >&2 \"$dryerr\"\n> -\t\t exit $res\n> -\t    fi\n> -\tfi\n> -\n> -\tif test -n \"$custom_name\"\n> -\tthen\n> -\t\tsm_name=\"$custom_name\"\n> -\telse\n> -\t\tsm_name=\"$sm_path\"\n> -\tfi\n> -\n> -\tif ! git submodule--helper check-name \"$sm_name\"\n> -\tthen\n> -\t\tdie \"fatal: $(eval_gettext \"'$sm_name' is not a valid submodule name\")\"\n> -\tfi\n> -\n> -\tgit 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\n> -\tgit submodule--helper add-config ${force:+--force} ${branch:+--branch \"$branch\"} --url \"$repo\" --resolved-url \"$realrepo\" --path \"$sm_path\" --name \"$sm_name\"\n> +\tgit ${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\"} -- \"$@\"\n>  }\n>  \n>  #\n> -- \n> 2.32.0\n> \n\n-- \nDanh\n"},{"id":"432156","messageId":"CAP8UFD0hnkO+LMo2OTAiqPoi20V25806-zL97DA5qPz+3tgKnA@mail.gmail.com","threadId":"56219","inReplyTo":"YQyIJpq/r0O7zhb1@danh.dev","subject":"Re: [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule()","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2021-08-06T09:06:03Z","receivedAt":"2021-08-06T09:06:17Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Fri, Aug 6, 2021 at 2:54 AM Đoàn Trần Công Danh <congdanhqx@gmail.com> wrote:\n\n> While previous patch is definitely a refactoring, this patch add small\n> overhead to the system, the new code will query (then free())\n> git_config_get_string() and/or xgetcwd() one more time in the second\n> compute_submodule_clone_url()\n>\n> I think the abstraction overhead is not that big, though.\n\nYeah, Junio made basically the same comment. So it would be nice if\nthe commit message could mention we are adding a very small overhead\nin exchange for code simplification (10 lines removed).\n"},{"id":"432157","messageId":"m25ywivqdg.fsf@gmail.com","threadId":"56219","inReplyTo":"CAP8UFD0hnkO+LMo2OTAiqPoi20V25806-zL97DA5qPz+3tgKnA@mail.gmail.com","subject":"Re: [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T10:06:51Z","receivedAt":"2021-08-06T10:07:00Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"\nChristian Couder <christian.couder@gmail.com> writes:\n\n> On Fri, Aug 6, 2021 at 2:54 AM Đoàn Trần Công Danh <congdanhqx@gmail.com> wrote:\n>\n>> While previous patch is definitely a refactoring, this patch add small\n>> overhead to the system, the new code will query (then free())\n>> git_config_get_string() and/or xgetcwd() one more time in the second\n>> compute_submodule_clone_url()\n>>\n>> I think the abstraction overhead is not that big, though.\n>\n> Yeah, Junio made basically the same comment. So it would be nice if\n> the commit message could mention we are adding a very small overhead\n> in exchange for code simplification (10 lines removed).\n\nOkay, that makes sense.\n"},{"id":"432158","messageId":"m235rmvnc1.fsf@gmail.com","threadId":"56219","inReplyTo":"xmqqim0jk4qx.fsf@gitster.g","subject":"Re: [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T11:12:30Z","receivedAt":"2021-08-06T11:12:39Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"\nJunio C Hamano <gitster@pobox.com> writes:\n\n> Atharva Raykar <raykar.ath@gmail.com> writes:\n>\n>> These functions can be useful to other parts of Git. Let's move them to\n>> dir.c, while renaming them to be make their functionality more explicit.\n>\n> Hmph, guess_dir_name_from_git_url() is not all that more clarifying\n> than the original, at least to me.  For a file-scope static helper,\n> it probably was good enough with a short name with no function doc,\n> but we should describe what it does in comments in dir.h and come up\n> with a suitable name, taking input from that description.\n>\n> [...]\n>\n>> @@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n>>  \tif (argc == 2)\n>>  \t\tdir = xstrdup(argv[1]);\n>>  \telse\n>> -\t\tdir = guess_dir_name(repo_name, is_bundle, option_bare);\n>> -\tstrip_trailing_slashes(dir);\n>> +\t\tdir = guess_dir_name_from_git_url(repo_name, is_bundle, option_bare);\n>> +\tstrip_dir_trailing_slashes(dir);\n>\n> So, what does this new public helper function guess?  The name of\n> the function says it guesses a directory name, but it is not just\n> any directory name, but a directory with some specific meaning.\n>\n> Here repo_name has the URL the user gave \"git clone\", and even\n> though there are some code before this part that computed on the\n> variable, it hasn't been modified.  And \"from_git_url\" is a good way\n> to indicate that that is one of the input the function uses to guess\n> the name of \"the directory with some unknown specific meaning\".\n>\n> I think this codepath wants the new directory to create as the\n> result of \"git clone\" operation in \"dir\".  So, even though I still\n> do not have a good answer to the earlier \"this is not just any\n> directory but with some specific meaning---what is it?\" question,\n> adjectives that are appropriate for the \"directory\" to answer it\n> may be along the lines of \"new\", \"resulting\", \"cloned\", etc.\n\nNaming things is hard...\n\nMaybe the right phrase would be 'target directory'? We are creating a\ntarget directory name by looking at the \"humanish\" part of the Git URL.\n\nI think the intention of all callers of this function is to get a\n\"default\" directory name which will be used as the target of some\noperation in the absence of the user providing one.\n\nSo maybe the name could be: 'guess_target_dir_from_git_url()'\n\nThis would make sense for any operation now or in the future that wants\nto reuse this functionality.\n\n>> diff --git a/dir.h b/dir.h\n>> index b3e1a54a97..76441dde2d 100644\n>> --- a/dir.h\n>> +++ b/dir.h\n>> @@ -453,6 +453,9 @@ static inline int is_dot_or_dotdot(const char *name)\n>>\n>>  int is_empty_dir(const char *dir);\n>>\n>\n> We would want docstring here for the function (and possibly rename\n> the function to clarify what kind of \"dir\" we are talking about).\n\nOkay, I will add it.\n\n>> +char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare);\n>> +void strip_dir_trailing_slashes(char *dir);\n>> +\n>>  void setup_standard_excludes(struct dir_struct *dir);\n>>\n>>  char *get_sparse_checkout_filename(void);\n>\n> Thanks.\n"},{"id":"432159","messageId":"m2zgtuu8kq.fsf@gmail.com","threadId":"56219","inReplyTo":"xmqqeeb7k4kl.fsf@gitster.g","subject":"Re: [GSoC] [PATCH v2 5/9] submodule--helper: remove constness of sm_path","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T11:16:37Z","receivedAt":"2021-08-06T11:16:45Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"\nJunio C Hamano <gitster@pobox.com> writes:\n\n> Atharva Raykar <raykar.ath@gmail.com> writes:\n>\n>> This is needed so that it can be modified by normalize_path_copy() in\n>> the next patch.\n>\n> This is a hard-to-judge change.  With this alone, we cannot tell if\n> somebody has already looked at the member (and possibly saved the\n> pointer elsewhere) before \"the next patch\" starts modifying the\n> member in the struct.  It probably should be done in a single patch\n> to demonstrate why it is needed and how existing users of the field\n> are OK with this change.\n\nOkay, I will move this to the next patch.\n"},{"id":"432160","messageId":"m2wnoyu7sf.fsf@gmail.com","threadId":"56219","inReplyTo":"YQyNDv3bzVZwpAVl@danh.dev","subject":"Re: [GSoC] [PATCH v2 6/9] submodule--helper: convert the bulk of cmd_add() to C","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T11:33:36Z","receivedAt":"2021-08-06T11:33:45Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"\nĐoàn Trần Công Danh <congdanhqx@gmail.com> writes:\n\n> On 2021-08-05 13:10:51+0530, Atharva Raykar <raykar.ath@gmail.com> wrote:\n>> [...]\n>> +\t\tadd_data.sm_path = xstrdup(argv[1]);\n>\n> add_data.sm_path is allocated in this block (regardless of legs).\n>\n>> [...]\n>> +\t\tif ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {\n>> +\t\t\tstrbuf_complete_line(&sb);\n>> +\t\t\tfputs(sb.buf, stderr);\n>> +\t\t\treturn exit_code;\n>\n> But, we don't free it when return from here.\n>\n>> [...]\n>> +\n>> +\tif (add_submodule(&add_data))\n>> +\t\treturn 1;\n>\n> And here.\n>\n>> +\tconfigure_added_submodule(&add_data);\n>> +\tfree(add_data.sm_path);\n>\n> However, it will be free()-d here, is it intended?\n\nYeah I meant to have it free()'d wherever possible, although I suppose\nit isn't strictly necessary since we exit.\n\n> I think we may use UNLEAK above (for now) because we will exit process\n> after this function.\n>\n> However, I anticipated we may need to do more stuffs after this\n> function in the future.\n\nRight. So it's better I ensure that it's freed properly everywhere.\n\n>> [...]\n>> --\n>> 2.32.0\n>>\n"},{"id":"432162","messageId":"20210806120147.73349-1-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210805074054.29916-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v3 0/8] submodule: convert the rest of 'add' to C","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T12:01:39Z","receivedAt":"2021-08-06T12:02:10Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Changes since v2:\n\n* Mention the small overhead introduced in [2/8] in the commit message.\n* Attempt a more descriptive name for the libified dir helper. Add a docstring\n  to explain it as well.\n* Combine the \"unconstification of sm_path\" patch into the next one.\n\nAtharva Raykar (8):\n  submodule--helper: add options for compute_submodule_clone_url()\n  submodule--helper: refactor resolve_relative_url() helper\n  submodule--helper: remove repeated code in sync_submodule()\n  dir: libify and export helper functions from clone.c\n  submodule--helper: convert the bulk of cmd_add() to C\n  submodule--helper: remove add-clone subcommand\n  submodule--helper: remove add-config subcommand\n  submodule--helper: remove resolve-relative-url subcommand\n\n builtin/clone.c             | 118 +-------------\n builtin/submodule--helper.c | 307 +++++++++++++++++++-----------------\n dir.c                       | 114 +++++++++++++\n dir.h                       |  11 ++\n git-submodule.sh            |  96 +----------\n 5 files changed, 291 insertions(+), 355 deletions(-)\n\nRange-diff against v2:\n-:  ---------- > 1:  75edf24186 submodule--helper: add options for compute_submodule_clone_url()\n-:  ---------- > 2:  8e7a3e727a submodule--helper: refactor resolve_relative_url() helper\n1:  d8ee0bc450 ! 3:  82961ddd02 submodule--helper: remove repeated code in sync_submodule()\n    @@ Commit message\n         This part of `sync_submodule()` is doing the same thing that\n         `compute_submodule_clone_url()` is doing. Let's reuse that helper here.\n     \n    +    Note that this change adds a small overhead where we allocate and free\n    +    the 'remote' twice, but that is a small price to pay for the higher\n    +    level of abstraction we get.\n    +\n         Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>\n         Mentored-by: Christian Couder <christian.couder@gmail.com>\n         Mentored-by: Shourya Shukla <periperidip@gmail.com>\n2:  6ac470d86f ! 4:  99d139375d dir: libify and export helper functions from clone.c\n    @@ Commit message\n     \n         Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>\n         Mentored-by: Christian Couder <christian.couder@gmail.com>\n    -    Mentored-by: Shourya Shukla <shouryashukla.oo@gmail.com>\n    +    Mentored-by: Shourya Shukla <periperidip@gmail.com>\n     \n      ## builtin/clone.c ##\n     @@ builtin/clone.c: static char *get_repo_path(const char *repo, int *is_bundle)\n    @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)\n      \telse\n     -\t\tdir = guess_dir_name(repo_name, is_bundle, option_bare);\n     -\tstrip_trailing_slashes(dir);\n    -+\t\tdir = guess_dir_name_from_git_url(repo_name, is_bundle, option_bare);\n    ++\t\tdir = guess_target_dir_from_git_url(repo_name, is_bundle, option_bare);\n     +\tstrip_dir_trailing_slashes(dir);\n      \n      \tdest_exists = path_exists(dir);\n    @@ dir.c: int is_empty_dir(const char *path)\n      \treturn ret;\n      }\n      \n    -+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare)\n    ++char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare)\n     +{\n     +\tconst char *end = repo + strlen(repo), *start, *ptr;\n     +\tsize_t len;\n    @@ dir.h: static inline int is_dot_or_dotdot(const char *name)\n      \n      int is_empty_dir(const char *dir);\n      \n    -+char *guess_dir_name_from_git_url(const char *repo, int is_bundle, int is_bare);\n    ++/*\n    ++ * Retrieve a target directory name by reading \"humanish\" part of the\n    ++ * given Git URL.\n    ++ *\n    ++ * For example:\n    ++ * \t/path/to/repo.git => \"repo\"\n    ++ * \thost.xz.foo/.git => \"foo\"\n    ++ */\n    ++char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare);\n     +void strip_dir_trailing_slashes(char *dir);\n     +\n      void setup_standard_excludes(struct dir_struct *dir);\n3:  c0b264a4e8 < -:  ---------- submodule--helper: remove constness of sm_path\n4:  f61124327f ! 5:  11eea777ba submodule--helper: convert the bulk of cmd_add() to C\n    @@ Commit message\n         Introduce the 'add' subcommand to `submodule--helper.c` that does all\n         the work 'submodule add' past the parsing of flags.\n     \n    +    We also remove the constness of the sm_path field of the `add_data`\n    +    struct. This is needed so that it can be modified by\n    +    normalize_path_copy().\n    +\n         As with the previous conversions, this is meant to be a faithful\n         conversion with no modification to the behaviour of `submodule add`.\n     \n    @@ Commit message\n         Based-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>\n     \n      ## builtin/submodule--helper.c ##\n    +@@ builtin/submodule--helper.c: struct add_data {\n    + \tconst char *prefix;\n    + \tconst char *branch;\n    + \tconst char *reference_path;\n    +-\tconst char *sm_path;\n    ++\tchar *sm_path;\n    + \tconst char *sm_name;\n    + \tconst char *repo;\n    + \tconst char *realrepo;\n     @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv, const char *prefix)\n      \treturn 0;\n      }\n    @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv,\n     +\n     +\tadd_data.repo = argv[0];\n     +\tif (argc == 1)\n    -+\t\tadd_data.sm_path = guess_dir_name_from_git_url(add_data.repo, 0, 0);\n    ++\t\tadd_data.sm_path = guess_target_dir_from_git_url(add_data.repo, 0, 0);\n     +\telse\n     +\t\tadd_data.sm_path = xstrdup(argv[1]);\n     +\n    @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv,\n     +\t\tif ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {\n     +\t\t\tstrbuf_complete_line(&sb);\n     +\t\t\tfputs(sb.buf, stderr);\n    ++\t\t\tfree(add_data.sm_path);\n     +\t\t\treturn exit_code;\n     +\t\t}\n     +\t\tstrbuf_release(&sb);\n    @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv,\n     +\tadd_data.progress = !!progress;\n     +\tadd_data.dissociate = !!dissociate;\n     +\n    -+\tif (add_submodule(&add_data))\n    ++\tif (add_submodule(&add_data)) {\n    ++\t\tfree(add_data.sm_path);\n     +\t\treturn 1;\n    ++\t}\n     +\tconfigure_added_submodule(&add_data);\n     +\tfree(add_data.sm_path);\n     +\n5:  0c37bf84c3 = 6:  51393cd99b submodule--helper: remove add-clone subcommand\n6:  d7e0db2565 = 7:  50cedcd8a8 submodule--helper: remove add-config subcommand\n7:  6dd7cb1e18 = 8:  02558da532 submodule--helper: remove resolve-relative-url subcommand\n-- \n2.32.0\n\n"},{"id":"432163","messageId":"20210806120147.73349-2-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210806120147.73349-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v3 1/8] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T12:01:40Z","receivedAt":"2021-08-06T12:02:14Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Let's modify the interface to `compute_submodule_clone_url()` function\nby adding two more arguments, so that we can reuse this in various parts\nof `submodule--helper.c` that follow a common pattern, which is--read\nthe remote url configuration of the superproject and then call\n`relative_url()`.\n\nThis function is nearly identical to `resolve_relative_url()`, the only\ndifference being the extra warning message. We can add a quiet flag to\nit, to suppress that warning when not needed, and then refactor\n`resolve_relative_url()` by using this function, something we will do in\nthe next patch.\n\nHaving this functionality factored out will be useful for converting the\nrest of `submodule add` in subsequent patches.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 14 +++++++++-----\n 1 file changed, 9 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 6891480013..2d2d8ac637 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -590,7 +590,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n-static char *compute_submodule_clone_url(const char *rel_url)\n+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n {\n \tchar *remoteurl, *relurl;\n \tchar *remote = get_default_remote();\n@@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)\n \n \tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n-\t\twarning(_(\"could not look up configuration '%s'. Assuming this repository is its own authoritative upstream.\"), remotesb.buf);\n+\t\tif (!quiet)\n+\t\t\twarning(_(\"could not look up configuration '%s'. \"\n+\t\t\t\t  \"Assuming this repository is its own \"\n+\t\t\t\t  \"authoritative upstream.\"),\n+\t\t\t\tremotesb.buf);\n \t\tremoteurl = xgetcwd();\n \t}\n-\trelurl = relative_url(remoteurl, rel_url, NULL);\n+\trelurl = relative_url(remoteurl, rel_url, up_path);\n \n \tfree(remote);\n \tfree(remoteurl);\n@@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,\n \t\tif (starts_with_dot_dot_slash(url) ||\n \t\t    starts_with_dot_slash(url)) {\n \t\t\tchar *oldurl = url;\n-\t\t\turl = compute_submodule_clone_url(oldurl);\n+\t\t\turl = compute_submodule_clone_url(oldurl, NULL, 0);\n \t\t\tfree(oldurl);\n \t\t}\n \n@@ -2134,7 +2138,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \tif (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {\n \t\tif (starts_with_dot_slash(sub->url) ||\n \t\t    starts_with_dot_dot_slash(sub->url)) {\n-\t\t\turl = compute_submodule_clone_url(sub->url);\n+\t\t\turl = compute_submodule_clone_url(sub->url, NULL, 0);\n \t\t\tneed_free_url = 1;\n \t\t} else\n \t\t\turl = sub->url;\n-- \n2.32.0\n\n"},{"id":"432164","messageId":"20210806120147.73349-3-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210806120147.73349-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v3 2/8] submodule--helper: refactor resolve_relative_url() helper","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T12:01:41Z","receivedAt":"2021-08-06T12:02:22Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Refactor the helper function to resolve a relative url, by reusing the\nexisting `compute_submodule_clone_url()` function.\n\n`compute_submodule_clone_url()` performs the same work that\n`resolve_relative_url()` is doing, so we eliminate this code repetition\nby moving the former function's definition up, and calling it inside\n`resolve_relative_url()`.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 61 +++++++++++++++----------------------\n 1 file changed, 25 insertions(+), 36 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 2d2d8ac637..f4b496bac6 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -199,33 +199,46 @@ static char *relative_url(const char *remote_url,\n \treturn strbuf_detach(&sb, NULL);\n }\n \n+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n+{\n+\tchar *remoteurl, *relurl;\n+\tchar *remote = get_default_remote();\n+\tstruct strbuf remotesb = STRBUF_INIT;\n+\n+\tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n+\tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n+\t\tif (!quiet)\n+\t\t\twarning(_(\"could not look up configuration '%s'. \"\n+\t\t\t\t  \"Assuming this repository is its own \"\n+\t\t\t\t  \"authoritative upstream.\"),\n+\t\t\t\tremotesb.buf);\n+\t\tremoteurl = xgetcwd();\n+\t}\n+\trelurl = relative_url(remoteurl, rel_url, up_path);\n+\n+\tfree(remote);\n+\tfree(remoteurl);\n+\tstrbuf_release(&remotesb);\n+\n+\treturn relurl;\n+}\n+\n static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n {\n-\tchar *remoteurl = NULL;\n-\tchar *remote = get_default_remote();\n \tconst char *up_path = NULL;\n \tchar *res;\n \tconst char *url;\n-\tstruct strbuf sb = STRBUF_INIT;\n \n \tif (argc != 2 && argc != 3)\n \t\tdie(\"resolve-relative-url only accepts one or two arguments\");\n \n \turl = argv[1];\n-\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n-\tfree(remote);\n-\n-\tif (git_config_get_string(sb.buf, &remoteurl))\n-\t\t/* the repository is its own authoritative upstream */\n-\t\tremoteurl = xgetcwd();\n-\n \tif (argc == 3)\n \t\tup_path = argv[2];\n \n-\tres = relative_url(remoteurl, url, up_path);\n+\tres = compute_submodule_clone_url(url, up_path, 1);\n \tputs(res);\n \tfree(res);\n-\tfree(remoteurl);\n \treturn 0;\n }\n \n@@ -590,30 +603,6 @@ static int module_foreach(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n-{\n-\tchar *remoteurl, *relurl;\n-\tchar *remote = get_default_remote();\n-\tstruct strbuf remotesb = STRBUF_INIT;\n-\n-\tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n-\tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n-\t\tif (!quiet)\n-\t\t\twarning(_(\"could not look up configuration '%s'. \"\n-\t\t\t\t  \"Assuming this repository is its own \"\n-\t\t\t\t  \"authoritative upstream.\"),\n-\t\t\t\tremotesb.buf);\n-\t\tremoteurl = xgetcwd();\n-\t}\n-\trelurl = relative_url(remoteurl, rel_url, up_path);\n-\n-\tfree(remote);\n-\tfree(remoteurl);\n-\tstrbuf_release(&remotesb);\n-\n-\treturn relurl;\n-}\n-\n struct init_cb {\n \tconst char *prefix;\n \tunsigned int flags;\n-- \n2.32.0\n\n"},{"id":"432165","messageId":"20210806120147.73349-4-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210806120147.73349-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v3 3/8] submodule--helper: remove repeated code in sync_submodule()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T12:01:42Z","receivedAt":"2021-08-06T12:02:23Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"This part of `sync_submodule()` is doing the same thing that\n`compute_submodule_clone_url()` is doing. Let's reuse that helper here.\n\nNote that this change adds a small overhead where we allocate and free\nthe 'remote' twice, but that is a small price to pay for the higher\nlevel of abstraction we get.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 16 +++-------------\n 1 file changed, 3 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f4b496bac6..9b676c12f8 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,\n \tif (sub && sub->url) {\n \t\tif (starts_with_dot_dot_slash(sub->url) ||\n \t\t    starts_with_dot_slash(sub->url)) {\n-\t\t\tchar *remote_url, *up_path;\n-\t\t\tchar *remote = get_default_remote();\n-\t\t\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n-\n-\t\t\tif (git_config_get_string(sb.buf, &remote_url))\n-\t\t\t\tremote_url = xgetcwd();\n-\n-\t\t\tup_path = get_up_path(path);\n-\t\t\tsub_origin_url = relative_url(remote_url, sub->url, up_path);\n-\t\t\tsuper_config_url = relative_url(remote_url, sub->url, NULL);\n-\n-\t\t\tfree(remote);\n+\t\t\tchar *up_path = get_up_path(path);\n+\t\t\tsub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);\n+\t\t\tsuper_config_url = compute_submodule_clone_url(sub->url, NULL, 1);\n \t\t\tfree(up_path);\n-\t\t\tfree(remote_url);\n \t\t} else {\n \t\t\tsub_origin_url = xstrdup(sub->url);\n \t\t\tsuper_config_url = xstrdup(sub->url);\n-- \n2.32.0\n\n"},{"id":"432166","messageId":"20210806120147.73349-5-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210806120147.73349-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v3 4/8] dir: libify and export helper functions from clone.c","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T12:01:43Z","receivedAt":"2021-08-06T12:02:27Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"These functions can be useful to other parts of Git. Let's move them to\ndir.c, while renaming them to be make their functionality more explicit.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/clone.c | 118 +-----------------------------------------------\n dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++\n dir.h           |  11 +++++\n 3 files changed, 127 insertions(+), 116 deletions(-)\n\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 66fe66679c..fab0a3cef6 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -217,120 +217,6 @@ static char *get_repo_path(const char *repo, int *is_bundle)\n \treturn canon;\n }\n \n-static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)\n-{\n-\tconst char *end = repo + strlen(repo), *start, *ptr;\n-\tsize_t len;\n-\tchar *dir;\n-\n-\t/*\n-\t * Skip scheme.\n-\t */\n-\tstart = strstr(repo, \"://\");\n-\tif (start == NULL)\n-\t\tstart = repo;\n-\telse\n-\t\tstart += 3;\n-\n-\t/*\n-\t * Skip authentication data. The stripping does happen\n-\t * greedily, such that we strip up to the last '@' inside\n-\t * the host part.\n-\t */\n-\tfor (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {\n-\t\tif (*ptr == '@')\n-\t\t\tstart = ptr + 1;\n-\t}\n-\n-\t/*\n-\t * Strip trailing spaces, slashes and /.git\n-\t */\n-\twhile (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))\n-\t\tend--;\n-\tif (end - start > 5 && is_dir_sep(end[-5]) &&\n-\t    !strncmp(end - 4, \".git\", 4)) {\n-\t\tend -= 5;\n-\t\twhile (start < end && is_dir_sep(end[-1]))\n-\t\t\tend--;\n-\t}\n-\n-\t/*\n-\t * Strip trailing port number if we've got only a\n-\t * hostname (that is, there is no dir separator but a\n-\t * colon). This check is required such that we do not\n-\t * strip URI's like '/foo/bar:2222.git', which should\n-\t * result in a dir '2222' being guessed due to backwards\n-\t * compatibility.\n-\t */\n-\tif (memchr(start, '/', end - start) == NULL\n-\t    && memchr(start, ':', end - start) != NULL) {\n-\t\tptr = end;\n-\t\twhile (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')\n-\t\t\tptr--;\n-\t\tif (start < ptr && ptr[-1] == ':')\n-\t\t\tend = ptr - 1;\n-\t}\n-\n-\t/*\n-\t * Find last component. To remain backwards compatible we\n-\t * also regard colons as path separators, such that\n-\t * cloning a repository 'foo:bar.git' would result in a\n-\t * directory 'bar' being guessed.\n-\t */\n-\tptr = end;\n-\twhile (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')\n-\t\tptr--;\n-\tstart = ptr;\n-\n-\t/*\n-\t * Strip .{bundle,git}.\n-\t */\n-\tlen = end - start;\n-\tstrip_suffix_mem(start, &len, is_bundle ? \".bundle\" : \".git\");\n-\n-\tif (!len || (len == 1 && *start == '/'))\n-\t\tdie(_(\"No directory name could be guessed.\\n\"\n-\t\t      \"Please specify a directory on the command line\"));\n-\n-\tif (is_bare)\n-\t\tdir = xstrfmt(\"%.*s.git\", (int)len, start);\n-\telse\n-\t\tdir = xstrndup(start, len);\n-\t/*\n-\t * Replace sequences of 'control' characters and whitespace\n-\t * with one ascii space, remove leading and trailing spaces.\n-\t */\n-\tif (*dir) {\n-\t\tchar *out = dir;\n-\t\tint prev_space = 1 /* strip leading whitespace */;\n-\t\tfor (end = dir; *end; ++end) {\n-\t\t\tchar ch = *end;\n-\t\t\tif ((unsigned char)ch < '\\x20')\n-\t\t\t\tch = '\\x20';\n-\t\t\tif (isspace(ch)) {\n-\t\t\t\tif (prev_space)\n-\t\t\t\t\tcontinue;\n-\t\t\t\tprev_space = 1;\n-\t\t\t} else\n-\t\t\t\tprev_space = 0;\n-\t\t\t*out++ = ch;\n-\t\t}\n-\t\t*out = '\\0';\n-\t\tif (out > dir && prev_space)\n-\t\t\tout[-1] = '\\0';\n-\t}\n-\treturn dir;\n-}\n-\n-static void strip_trailing_slashes(char *dir)\n-{\n-\tchar *end = dir + strlen(dir);\n-\n-\twhile (dir < end - 1 && is_dir_sep(end[-1]))\n-\t\tend--;\n-\t*end = '\\0';\n-}\n-\n static int add_one_reference(struct string_list_item *item, void *cb_data)\n {\n \tstruct strbuf err = STRBUF_INIT;\n@@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \tif (argc == 2)\n \t\tdir = xstrdup(argv[1]);\n \telse\n-\t\tdir = guess_dir_name(repo_name, is_bundle, option_bare);\n-\tstrip_trailing_slashes(dir);\n+\t\tdir = guess_target_dir_from_git_url(repo_name, is_bundle, option_bare);\n+\tstrip_dir_trailing_slashes(dir);\n \n \tdest_exists = path_exists(dir);\n \tif (dest_exists && !is_empty_dir(dir))\ndiff --git a/dir.c b/dir.c\nindex 03c4d21267..9a9ab135c4 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -2970,6 +2970,120 @@ int is_empty_dir(const char *path)\n \treturn ret;\n }\n \n+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare)\n+{\n+\tconst char *end = repo + strlen(repo), *start, *ptr;\n+\tsize_t len;\n+\tchar *dir;\n+\n+\t/*\n+\t * Skip scheme.\n+\t */\n+\tstart = strstr(repo, \"://\");\n+\tif (start == NULL)\n+\t\tstart = repo;\n+\telse\n+\t\tstart += 3;\n+\n+\t/*\n+\t * Skip authentication data. The stripping does happen\n+\t * greedily, such that we strip up to the last '@' inside\n+\t * the host part.\n+\t */\n+\tfor (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {\n+\t\tif (*ptr == '@')\n+\t\t\tstart = ptr + 1;\n+\t}\n+\n+\t/*\n+\t * Strip trailing spaces, slashes and /.git\n+\t */\n+\twhile (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))\n+\t\tend--;\n+\tif (end - start > 5 && is_dir_sep(end[-5]) &&\n+\t    !strncmp(end - 4, \".git\", 4)) {\n+\t\tend -= 5;\n+\t\twhile (start < end && is_dir_sep(end[-1]))\n+\t\t\tend--;\n+\t}\n+\n+\t/*\n+\t * Strip trailing port number if we've got only a\n+\t * hostname (that is, there is no dir separator but a\n+\t * colon). This check is required such that we do not\n+\t * strip URI's like '/foo/bar:2222.git', which should\n+\t * result in a dir '2222' being guessed due to backwards\n+\t * compatibility.\n+\t */\n+\tif (memchr(start, '/', end - start) == NULL\n+\t    && memchr(start, ':', end - start) != NULL) {\n+\t\tptr = end;\n+\t\twhile (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')\n+\t\t\tptr--;\n+\t\tif (start < ptr && ptr[-1] == ':')\n+\t\t\tend = ptr - 1;\n+\t}\n+\n+\t/*\n+\t * Find last component. To remain backwards compatible we\n+\t * also regard colons as path separators, such that\n+\t * cloning a repository 'foo:bar.git' would result in a\n+\t * directory 'bar' being guessed.\n+\t */\n+\tptr = end;\n+\twhile (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')\n+\t\tptr--;\n+\tstart = ptr;\n+\n+\t/*\n+\t * Strip .{bundle,git}.\n+\t */\n+\tlen = end - start;\n+\tstrip_suffix_mem(start, &len, is_bundle ? \".bundle\" : \".git\");\n+\n+\tif (!len || (len == 1 && *start == '/'))\n+\t\tdie(_(\"No directory name could be guessed.\\n\"\n+\t\t      \"Please specify a directory on the command line\"));\n+\n+\tif (is_bare)\n+\t\tdir = xstrfmt(\"%.*s.git\", (int)len, start);\n+\telse\n+\t\tdir = xstrndup(start, len);\n+\t/*\n+\t * Replace sequences of 'control' characters and whitespace\n+\t * with one ascii space, remove leading and trailing spaces.\n+\t */\n+\tif (*dir) {\n+\t\tchar *out = dir;\n+\t\tint prev_space = 1 /* strip leading whitespace */;\n+\t\tfor (end = dir; *end; ++end) {\n+\t\t\tchar ch = *end;\n+\t\t\tif ((unsigned char)ch < '\\x20')\n+\t\t\t\tch = '\\x20';\n+\t\t\tif (isspace(ch)) {\n+\t\t\t\tif (prev_space)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tprev_space = 1;\n+\t\t\t} else\n+\t\t\t\tprev_space = 0;\n+\t\t\t*out++ = ch;\n+\t\t}\n+\t\t*out = '\\0';\n+\t\tif (out > dir && prev_space)\n+\t\t\tout[-1] = '\\0';\n+\t}\n+\treturn dir;\n+}\n+\n+void strip_dir_trailing_slashes(char *dir)\n+{\n+\tchar *end = dir + strlen(dir);\n+\n+\twhile (dir < end - 1 && is_dir_sep(end[-1]))\n+\t\tend--;\n+\t*end = '\\0';\n+}\n+\n static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)\n {\n \tDIR *dir;\ndiff --git a/dir.h b/dir.h\nindex b3e1a54a97..6f0abdfe04 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -453,6 +453,17 @@ static inline int is_dot_or_dotdot(const char *name)\n \n int is_empty_dir(const char *dir);\n \n+/*\n+ * Retrieve a target directory name by reading \"humanish\" part of the\n+ * given Git URL.\n+ *\n+ * For example:\n+ * \t/path/to/repo.git => \"repo\"\n+ * \thost.xz.foo/.git => \"foo\"\n+ */\n+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare);\n+void strip_dir_trailing_slashes(char *dir);\n+\n void setup_standard_excludes(struct dir_struct *dir);\n \n char *get_sparse_checkout_filename(void);\n-- \n2.32.0\n\n"},{"id":"432167","messageId":"20210806120147.73349-6-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210806120147.73349-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v3 5/8] submodule--helper: convert the bulk of cmd_add() to C","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T12:01:44Z","receivedAt":"2021-08-06T12:02:32Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Introduce the 'add' subcommand to `submodule--helper.c` that does all\nthe work 'submodule add' past the parsing of flags.\n\nWe also remove the constness of the sm_path field of the `add_data`\nstruct. This is needed so that it can be modified by\nnormalize_path_copy().\n\nAs with the previous conversions, this is meant to be a faithful\nconversion with no modification to the behaviour of `submodule add`.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nHelped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\nBased-on-patch-by: Shourya Shukla <periperidip@gmail.com>\nBased-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>\n---\n builtin/submodule--helper.c | 165 +++++++++++++++++++++++++++++++++++-\n git-submodule.sh            |  96 +--------------------\n 2 files changed, 166 insertions(+), 95 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 9b676c12f8..f31e5a9bde 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2748,7 +2748,7 @@ struct add_data {\n \tconst char *prefix;\n \tconst char *branch;\n \tconst char *reference_path;\n-\tconst char *sm_path;\n+\tchar *sm_path;\n \tconst char *sm_name;\n \tconst char *repo;\n \tconst char *realrepo;\n@@ -3046,6 +3046,168 @@ static int add_config(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static void die_on_index_match(const char *path, int force)\n+{\n+\tstruct pathspec ps;\n+\tconst char *args[] = { path, NULL };\n+\tparse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);\n+\n+\tif (read_cache_preload(NULL) < 0)\n+\t\tdie(_(\"index file corrupt\"));\n+\n+\tif (ps.nr) {\n+\t\tint i;\n+\t\tchar *ps_matched = xcalloc(ps.nr, 1);\n+\n+\t\t/* TODO: audit for interaction with sparse-index. */\n+\t\tensure_full_index(&the_index);\n+\n+\t\t/*\n+\t\t * Since there is only one pathspec, we just need\n+\t\t * need to check ps_matched[0] to know if a cache\n+\t\t * entry matched.\n+\t\t */\n+\t\tfor (i = 0; i < active_nr; i++) {\n+\t\t\tce_path_match(&the_index, active_cache[i], &ps,\n+\t\t\t\t      ps_matched);\n+\n+\t\t\tif (ps_matched[0]) {\n+\t\t\t\tif (!force)\n+\t\t\t\t\tdie(_(\"'%s' already exists in the index\"),\n+\t\t\t\t\t    path);\n+\t\t\t\tif (!S_ISGITLINK(active_cache[i]->ce_mode))\n+\t\t\t\t\tdie(_(\"'%s' already exists in the index \"\n+\t\t\t\t\t      \"and is not a submodule\"), path);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tfree(ps_matched);\n+\t}\n+}\n+\n+static void die_on_repo_without_commits(const char *path)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstrbuf_addstr(&sb, path);\n+\tif (is_nonbare_repository_dir(&sb)) {\n+\t\tstruct object_id oid;\n+\t\tif (resolve_gitlink_ref(path, \"HEAD\", &oid) < 0)\n+\t\t\tdie(_(\"'%s' does not have a commit checked out\"), path);\n+\t}\n+}\n+\n+static int module_add(int argc, const char **argv, const char *prefix)\n+{\n+\tint force = 0, quiet = 0, progress = 0, dissociate = 0;\n+\tstruct add_data add_data = ADD_DATA_INIT;\n+\n+\tstruct option options[] = {\n+\t\tOPT_STRING('b', \"branch\", &add_data.branch, N_(\"branch\"),\n+\t\t\t   N_(\"branch of repository to add as submodule\")),\n+\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n+\t\t\t   PARSE_OPT_NOCOMPLETE),\n+\t\tOPT__QUIET(&quiet, N_(\"print only error messages\")),\n+\t\tOPT_BOOL(0, \"progress\", &progress, N_(\"force cloning progress\")),\n+\t\tOPT_STRING(0, \"reference\", &add_data.reference_path, N_(\"repository\"),\n+\t\t\t   N_(\"reference repository\")),\n+\t\tOPT_BOOL(0, \"dissociate\", &dissociate, N_(\"borrow the objects from reference repositories\")),\n+\t\tOPT_STRING(0, \"name\", &add_data.sm_name, N_(\"name\"),\n+\t\t\t   N_(\"sets the submodule’s name to the given string \"\n+\t\t\t      \"instead of defaulting to its path\")),\n+\t\tOPT_INTEGER(0, \"depth\", &add_data.depth, N_(\"depth for shallow clones\")),\n+\t\tOPT_END()\n+\t};\n+\n+\tconst char *const usage[] = {\n+\t\tN_(\"git submodule--helper add [<options>] [--] <repository> [<path>]\"),\n+\t\tNULL\n+\t};\n+\n+\targc = parse_options(argc, argv, prefix, options, usage, 0);\n+\n+\tif (!is_writing_gitmodules_ok())\n+\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n+\n+\tif (prefix && *prefix &&\n+\t    add_data.reference_path && !is_absolute_path(add_data.reference_path))\n+\t\tadd_data.reference_path = xstrfmt(\"%s%s\", prefix, add_data.reference_path);\n+\n+\tif (argc == 0 || argc > 2)\n+\t\tusage_with_options(usage, options);\n+\n+\tadd_data.repo = argv[0];\n+\tif (argc == 1)\n+\t\tadd_data.sm_path = guess_target_dir_from_git_url(add_data.repo, 0, 0);\n+\telse\n+\t\tadd_data.sm_path = xstrdup(argv[1]);\n+\n+\tif (prefix && *prefix && !is_absolute_path(add_data.sm_path))\n+\t\tadd_data.sm_path = xstrfmt(\"%s%s\", prefix, add_data.sm_path);\n+\n+\tif (starts_with_dot_dot_slash(add_data.repo) ||\n+\t    starts_with_dot_slash(add_data.repo)) {\n+\t\tif (prefix)\n+\t\t\tdie(_(\"Relative path can only be used from the toplevel \"\n+\t\t\t      \"of the working tree\"));\n+\n+\t\t/* dereference source url relative to parent's url */\n+\t\tadd_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);\n+\t} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {\n+\t\tadd_data.realrepo = add_data.repo;\n+\t} else {\n+\t\tdie(_(\"repo URL: '%s' must be absolute or begin with ./|../\"),\n+\t\t    add_data.repo);\n+\t}\n+\n+\t/*\n+\t * normalize path:\n+\t * multiple //; leading ./; /./; /../;\n+\t */\n+\tnormalize_path_copy(add_data.sm_path, add_data.sm_path);\n+\tstrip_dir_trailing_slashes(add_data.sm_path);\n+\n+\tdie_on_index_match(add_data.sm_path, force);\n+\tdie_on_repo_without_commits(add_data.sm_path);\n+\n+\tif (!force) {\n+\t\tint exit_code = -1;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\t\tcp.git_cmd = 1;\n+\t\tcp.no_stdout = 1;\n+\t\tstrvec_pushl(&cp.args, \"add\", \"--dry-run\", \"--ignore-missing\",\n+\t\t\t     \"--no-warn-embedded-repo\", add_data.sm_path, NULL);\n+\t\tif ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {\n+\t\t\tstrbuf_complete_line(&sb);\n+\t\t\tfputs(sb.buf, stderr);\n+\t\t\tfree(add_data.sm_path);\n+\t\t\treturn exit_code;\n+\t\t}\n+\t\tstrbuf_release(&sb);\n+\t}\n+\n+\tif(!add_data.sm_name)\n+\t\tadd_data.sm_name = add_data.sm_path;\n+\n+\tif (check_submodule_name(add_data.sm_name))\n+\t\tdie(_(\"'%s' is not a valid submodule name\"), add_data.sm_name);\n+\n+\tadd_data.prefix = prefix;\n+\tadd_data.force = !!force;\n+\tadd_data.quiet = !!quiet;\n+\tadd_data.progress = !!progress;\n+\tadd_data.dissociate = !!dissociate;\n+\n+\tif (add_submodule(&add_data)) {\n+\t\tfree(add_data.sm_path);\n+\t\treturn 1;\n+\t}\n+\tconfigure_added_submodule(&add_data);\n+\tfree(add_data.sm_path);\n+\n+\treturn 0;\n+}\n+\n #define SUPPORT_SUPER_PREFIX (1<<0)\n \n struct cmd_struct {\n@@ -3060,6 +3222,7 @@ static struct cmd_struct commands[] = {\n \t{\"clone\", module_clone, 0},\n \t{\"add-clone\", add_clone, 0},\n \t{\"add-config\", add_config, 0},\n+\t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n \t{\"update-clone\", update_clone, 0},\n \t{\"ensure-core-worktree\", ensure_core_worktree, 0},\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 8c219ef382..1070540525 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -145,104 +145,12 @@ cmd_add()\n \t\tshift\n \tdone\n \n-\tif ! git submodule--helper config --check-writeable >/dev/null 2>&1\n+\tif test -z \"$1\"\n \tthen\n-\t\t die \"fatal: $(eval_gettext \"please make sure that the .gitmodules file is in the working tree\")\"\n-\tfi\n-\n-\tif test -n \"$reference_path\"\n-\tthen\n-\t\tis_absolute_path \"$reference_path\" ||\n-\t\treference_path=\"$wt_prefix$reference_path\"\n-\n-\t\treference=\"--reference=$reference_path\"\n-\tfi\n-\n-\trepo=$1\n-\tsm_path=$2\n-\n-\tif test -z \"$sm_path\"; then\n-\t\tsm_path=$(printf '%s\\n' \"$repo\" |\n-\t\t\tsed -e 's|/$||' -e 's|:*/*\\.git$||' -e 's|.*[/:]||g')\n-\tfi\n-\n-\tif test -z \"$repo\" || test -z \"$sm_path\"; then\n \t\tusage\n \tfi\n \n-\tis_absolute_path \"$sm_path\" || sm_path=\"$wt_prefix$sm_path\"\n-\n-\t# assure repo is absolute or relative to parent\n-\tcase \"$repo\" in\n-\t./*|../*)\n-\t\ttest -z \"$wt_prefix\" ||\n-\t\tdie \"fatal: $(gettext \"Relative path can only be used from the toplevel of the working tree\")\"\n-\n-\t\t# dereference source url relative to parent's url\n-\t\trealrepo=$(git submodule--helper resolve-relative-url \"$repo\") || exit\n-\t\t;;\n-\t*:*|/*)\n-\t\t# absolute url\n-\t\trealrepo=$repo\n-\t\t;;\n-\t*)\n-\t\tdie \"fatal: $(eval_gettext \"repo URL: '\\$repo' must be absolute or begin with ./|../\")\"\n-\t;;\n-\tesac\n-\n-\t# normalize path:\n-\t# multiple //; leading ./; /./; /../; trailing /\n-\tsm_path=$(printf '%s/\\n' \"$sm_path\" |\n-\t\tsed -e '\n-\t\t\ts|//*|/|g\n-\t\t\ts|^\\(\\./\\)*||\n-\t\t\ts|/\\(\\./\\)*|/|g\n-\t\t\t:start\n-\t\t\ts|\\([^/]*\\)/\\.\\./||\n-\t\t\ttstart\n-\t\t\ts|/*$||\n-\t\t')\n-\tif test -z \"$force\"\n-\tthen\n-\t\tgit ls-files --error-unmatch \"$sm_path\" > /dev/null 2>&1 &&\n-\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index\")\"\n-\telse\n-\t\tgit ls-files -s \"$sm_path\" | sane_grep -v \"^160000\" > /dev/null 2>&1 &&\n-\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index and is not a submodule\")\"\n-\tfi\n-\n-\tif test -d \"$sm_path\" &&\n-\t\ttest -z $(git -C \"$sm_path\" rev-parse --show-cdup 2>/dev/null)\n-\tthen\n-\t    git -C \"$sm_path\" rev-parse --verify -q HEAD >/dev/null ||\n-\t    die \"fatal: $(eval_gettext \"'\\$sm_path' does not have a commit checked out\")\"\n-\tfi\n-\n-\tif test -z \"$force\"\n-\tthen\n-\t    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo \"$sm_path\" 2>&1 >/dev/null)\n-\t    res=$?\n-\t    if test $res -ne 0\n-\t    then\n-\t\t echo >&2 \"$dryerr\"\n-\t\t exit $res\n-\t    fi\n-\tfi\n-\n-\tif test -n \"$custom_name\"\n-\tthen\n-\t\tsm_name=\"$custom_name\"\n-\telse\n-\t\tsm_name=\"$sm_path\"\n-\tfi\n-\n-\tif ! git submodule--helper check-name \"$sm_name\"\n-\tthen\n-\t\tdie \"fatal: $(eval_gettext \"'$sm_name' is not a valid submodule name\")\"\n-\tfi\n-\n-\tgit 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\n-\tgit submodule--helper add-config ${force:+--force} ${branch:+--branch \"$branch\"} --url \"$repo\" --resolved-url \"$realrepo\" --path \"$sm_path\" --name \"$sm_name\"\n+\tgit ${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\"} -- \"$@\"\n }\n \n #\n-- \n2.32.0\n\n"},{"id":"432168","messageId":"20210806120147.73349-7-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210806120147.73349-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v3 6/8] submodule--helper: remove add-clone subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T12:01:45Z","receivedAt":"2021-08-06T12:02:35Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"We no longer need this subcommand, as all of its functionality is being\ncalled by the newly-introduced `module_add()` directly within C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 60 -------------------------------------\n 1 file changed, 60 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f31e5a9bde..1257066a0f 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2860,65 +2860,6 @@ static int add_submodule(const struct add_data *add_data)\n \treturn 0;\n }\n \n-static int add_clone(int argc, const char **argv, const char *prefix)\n-{\n-\tint force = 0, quiet = 0, dissociate = 0, progress = 0;\n-\tstruct add_data add_data = ADD_DATA_INIT;\n-\n-\tstruct option options[] = {\n-\t\tOPT_STRING('b', \"branch\", &add_data.branch,\n-\t\t\t   N_(\"branch\"),\n-\t\t\t   N_(\"branch of repository to checkout on cloning\")),\n-\t\tOPT_STRING(0, \"prefix\", &prefix,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"alternative anchor for relative paths\")),\n-\t\tOPT_STRING(0, \"path\", &add_data.sm_path,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"where the new submodule will be cloned to\")),\n-\t\tOPT_STRING(0, \"name\", &add_data.sm_name,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"name of the new submodule\")),\n-\t\tOPT_STRING(0, \"url\", &add_data.realrepo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url where to clone the submodule from\")),\n-\t\tOPT_STRING(0, \"reference\", &add_data.reference_path,\n-\t\t\t   N_(\"repo\"),\n-\t\t\t   N_(\"reference repository\")),\n-\t\tOPT_BOOL(0, \"dissociate\", &dissociate,\n-\t\t\t N_(\"use --reference only while cloning\")),\n-\t\tOPT_INTEGER(0, \"depth\", &add_data.depth,\n-\t\t\t    N_(\"depth for shallow clones\")),\n-\t\tOPT_BOOL(0, \"progress\", &progress,\n-\t\t\t N_(\"force cloning progress\")),\n-\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n-\t\t\t   PARSE_OPT_NOCOMPLETE),\n-\t\tOPT__QUIET(&quiet, \"suppress output for cloning a submodule\"),\n-\t\tOPT_END()\n-\t};\n-\n-\tconst char *const usage[] = {\n-\t\tN_(\"git submodule--helper add-clone [<options>...] \"\n-\t\t   \"--url <url> --path <path> --name <name>\"),\n-\t\tNULL\n-\t};\n-\n-\targc = parse_options(argc, argv, prefix, options, usage, 0);\n-\n-\tif (argc != 0)\n-\t\tusage_with_options(usage, options);\n-\n-\tadd_data.prefix = prefix;\n-\tadd_data.progress = !!progress;\n-\tadd_data.dissociate = !!dissociate;\n-\tadd_data.force = !!force;\n-\tadd_data.quiet = !!quiet;\n-\n-\tif (add_submodule(&add_data))\n-\t\treturn 1;\n-\n-\treturn 0;\n-}\n-\n static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)\n {\n \tchar *key;\n@@ -3220,7 +3161,6 @@ static struct cmd_struct commands[] = {\n \t{\"list\", module_list, 0},\n \t{\"name\", module_name, 0},\n \t{\"clone\", module_clone, 0},\n-\t{\"add-clone\", add_clone, 0},\n \t{\"add-config\", add_config, 0},\n \t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n-- \n2.32.0\n\n"},{"id":"432169","messageId":"20210806120147.73349-8-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210806120147.73349-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v3 7/8] submodule--helper: remove add-config subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T12:01:46Z","receivedAt":"2021-08-06T12:02:40Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Also no longer needed is this subcommand, as all of its functionality is\nbeing called by the newly-introduced `module_add()` directly within C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 49 -------------------------------------\n 1 file changed, 49 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 1257066a0f..a858c2be29 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2939,54 +2939,6 @@ static void configure_added_submodule(struct add_data *add_data)\n \t}\n }\n \n-static int add_config(int argc, const char **argv, const char *prefix)\n-{\n-\tint force = 0;\n-\tstruct add_data add_data = ADD_DATA_INIT;\n-\n-\tstruct option options[] = {\n-\t\tOPT_STRING('b', \"branch\", &add_data.branch,\n-\t\t\t   N_(\"branch\"),\n-\t\t\t   N_(\"branch of repository to store in \"\n-\t\t\t      \"the submodule configuration\")),\n-\t\tOPT_STRING(0, \"url\", &add_data.repo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url to clone submodule from\")),\n-\t\tOPT_STRING(0, \"resolved-url\", &add_data.realrepo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url to clone the submodule from, after it has \"\n-\t\t\t      \"been dereferenced relative to parent's url, \"\n-\t\t\t      \"in the case where <url> is a relative url\")),\n-\t\tOPT_STRING(0, \"path\", &add_data.sm_path,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"where the new submodule will be cloned to\")),\n-\t\tOPT_STRING(0, \"name\", &add_data.sm_name,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"name of the new submodule\")),\n-\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n-\t\t\t   PARSE_OPT_NOCOMPLETE),\n-\t\tOPT_END()\n-\t};\n-\n-\tconst char *const usage[] = {\n-\t\tN_(\"git submodule--helper add-config \"\n-\t\t   \"[--force|-f] [--branch|-b <branch>] \"\n-\t\t   \"--url <url> --resolved-url <resolved-url> \"\n-\t\t   \"--path <path> --name <name>\"),\n-\t\tNULL\n-\t};\n-\n-\targc = parse_options(argc, argv, prefix, options, usage, 0);\n-\n-\tif (argc)\n-\t\tusage_with_options(usage, options);\n-\n-\tadd_data.force = !!force;\n-\tconfigure_added_submodule(&add_data);\n-\n-\treturn 0;\n-}\n-\n static void die_on_index_match(const char *path, int force)\n {\n \tstruct pathspec ps;\n@@ -3161,7 +3113,6 @@ static struct cmd_struct commands[] = {\n \t{\"list\", module_list, 0},\n \t{\"name\", module_name, 0},\n \t{\"clone\", module_clone, 0},\n-\t{\"add-config\", add_config, 0},\n \t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n \t{\"update-clone\", update_clone, 0},\n-- \n2.32.0\n\n"},{"id":"432170","messageId":"20210806120147.73349-9-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210806120147.73349-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v3 8/8] submodule--helper: remove resolve-relative-url subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-06T12:01:47Z","receivedAt":"2021-08-06T12:02:50Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"The shell subcommand `resolve-relative-url` is no longer required, as\nits last caller has been removed when it was converted to C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 20 --------------------\n 1 file changed, 20 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex a858c2be29..9772435959 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -223,25 +223,6 @@ static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat\n \treturn relurl;\n }\n \n-static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n-{\n-\tconst char *up_path = NULL;\n-\tchar *res;\n-\tconst char *url;\n-\n-\tif (argc != 2 && argc != 3)\n-\t\tdie(\"resolve-relative-url only accepts one or two arguments\");\n-\n-\turl = argv[1];\n-\tif (argc == 3)\n-\t\tup_path = argv[2];\n-\n-\tres = compute_submodule_clone_url(url, up_path, 1);\n-\tputs(res);\n-\tfree(res);\n-\treturn 0;\n-}\n-\n static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)\n {\n \tchar *remoteurl, *res;\n@@ -3118,7 +3099,6 @@ static struct cmd_struct commands[] = {\n \t{\"update-clone\", update_clone, 0},\n \t{\"ensure-core-worktree\", ensure_core_worktree, 0},\n \t{\"relative-path\", resolve_relative_path, 0},\n-\t{\"resolve-relative-url\", resolve_relative_url, 0},\n \t{\"resolve-relative-url-test\", resolve_relative_url_test, 0},\n \t{\"foreach\", module_foreach, SUPPORT_SUPER_PREFIX},\n \t{\"init\", module_init, SUPPORT_SUPER_PREFIX},\n-- \n2.32.0\n\n"},{"id":"432182","messageId":"xmqq5ywik0gw.fsf@gitster.g","threadId":"56219","inReplyTo":"CAP8UFD0hnkO+LMo2OTAiqPoi20V25806-zL97DA5qPz+3tgKnA@mail.gmail.com","subject":"Re: [GSoC] [PATCH 2/8] submodule--helper: remove repeated code in sync_submodule()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-08-06T16:21:51Z","receivedAt":"2021-08-06T16:21:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Christian Couder <christian.couder@gmail.com> writes:\n\n> On Fri, Aug 6, 2021 at 2:54 AM Đoàn Trần Công Danh <congdanhqx@gmail.com> wrote:\n>\n>> While previous patch is definitely a refactoring, this patch add small\n>> overhead to the system, the new code will query (then free())\n>> git_config_get_string() and/or xgetcwd() one more time in the second\n>> compute_submodule_clone_url()\n>>\n>> I think the abstraction overhead is not that big, though.\n>\n> Yeah, Junio made basically the same comment. So it would be nice if\n> the commit message could mention we are adding a very small overhead\n> in exchange for code simplification (10 lines removed).\n\nIf you guys want to, I wouldn't stop, but my comment was just a\nthinking-aloud observation, not a suggestion to add to the proposed\nlog message.\n\nThanks.\n"},{"id":"432183","messageId":"xmqq1r76jzsk.fsf@gitster.g","threadId":"56219","inReplyTo":"m235rmvnc1.fsf@gmail.com","subject":"Re: [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-08-06T16:36:27Z","receivedAt":"2021-08-06T16:36:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Atharva Raykar <raykar.ath@gmail.com> writes:\n\n> Naming things is hard...\n\nAbsolutely.\n\n> Maybe the right phrase would be 'target directory'? We are creating a\n> target directory name by looking at the \"humanish\" part of the Git URL.\n>\n> I think the intention of all callers of this function is to get a\n> \"default\" directory name which will be used as the target of some\n> operation in the absence of the user providing one.\n>\n> So maybe the name could be: 'guess_target_dir_from_git_url()'\n\nI have no immediate objection to the name.  \n\nJust to see how people (including you) may react to a name from a\ncompletely different line of thinking, let me throw this, though.\n\nHow does git_url_basename() sound?  \n\nInstead of saying what we'd use it for (i.e. as the name for the\ndirectory getting created), we say what we compute.  We take a\nURL-looking thing that is used by Git, and we compute something like\nbasename() but that is tailored for Git (e.g. unlike \"basename\na/b/c.git\" that yields \"c.git\", we give \"c\" for \"a/b/c.git\".\nLikewise \"<scheme>://a/b/c/.git\" won't yield \".git\", we compute\n\"c\").\n\nHaving said that, I think guess_target_dir_from_git_url() is clear\nenough.\n\n> This would make sense for any operation now or in the future that wants\n> to reuse this functionality.\n\nThat is mostly for you to decide.   I can help you sanity check the\nproposed name(s) with existing callers, but you'd be a better judge\nfor callers you'll be adding ;-)\n"},{"id":"432232","messageId":"m2lf5dbu92.fsf@gmail.com","threadId":"56219","inReplyTo":"xmqq1r76jzsk.fsf@gitster.g","subject":"Re: [GSoC] [PATCH v2 4/9] dir: libify and export helper functions from clone.c","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-07T07:15:37Z","receivedAt":"2021-08-07T07:16:40Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"\nJunio C Hamano <gitster@pobox.com> writes:\n\n> Atharva Raykar <raykar.ath@gmail.com> writes:\n>\n>> Naming things is hard...\n>\n> Absolutely.\n>\n>> Maybe the right phrase would be 'target directory'? We are creating a\n>> target directory name by looking at the \"humanish\" part of the Git URL.\n>>\n>> I think the intention of all callers of this function is to get a\n>> \"default\" directory name which will be used as the target of some\n>> operation in the absence of the user providing one.\n>>\n>> So maybe the name could be: 'guess_target_dir_from_git_url()'\n>\n> I have no immediate objection to the name.\n>\n> Just to see how people (including you) may react to a name from a\n> completely different line of thinking, let me throw this, though.\n>\n> How does git_url_basename() sound?\n>\n> Instead of saying what we'd use it for (i.e. as the name for the\n> directory getting created), we say what we compute.  We take a\n> URL-looking thing that is used by Git, and we compute something like\n> basename() but that is tailored for Git (e.g. unlike \"basename\n> a/b/c.git\" that yields \"c.git\", we give \"c\" for \"a/b/c.git\".\n> Likewise \"<scheme>://a/b/c/.git\" won't yield \".git\", we compute\n> \"c\").\n>\n> Having said that, I think guess_target_dir_from_git_url() is clear\n> enough.\n\nEven though the name I suggested is clear enough, I liked your\nsuggestion a lot more. Not only is it more succinct, but it also opens\nup the future possibility that the basename of a Git URL might be used\nfor purposes other than finding a directory name.\n\n>> This would make sense for any operation now or in the future that wants\n>> to reuse this functionality.\n>\n> That is mostly for you to decide.   I can help you sanity check the\n> proposed name(s) with existing callers, but you'd be a better judge\n> for callers you'll be adding ;-)\n"},{"id":"432233","messageId":"20210807071613.99610-1-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210806120147.73349-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-07T07:16:05Z","receivedAt":"2021-08-07T07:16:54Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Changes since v3:\n\n* Rename the libified dir helper and update the docstring.\n\nAtharva Raykar (8):\n  submodule--helper: add options for compute_submodule_clone_url()\n  submodule--helper: refactor resolve_relative_url() helper\n  submodule--helper: remove repeated code in sync_submodule()\n  dir: libify and export helper functions from clone.c\n  submodule--helper: convert the bulk of cmd_add() to C\n  submodule--helper: remove add-clone subcommand\n  submodule--helper: remove add-config subcommand\n  submodule--helper: remove resolve-relative-url subcommand\n\n builtin/clone.c             | 118 +-------------\n builtin/submodule--helper.c | 307 +++++++++++++++++++-----------------\n dir.c                       | 114 +++++++++++++\n dir.h                       |  10 ++\n git-submodule.sh            |  96 +----------\n 5 files changed, 290 insertions(+), 355 deletions(-)\n\nRange-diff against v3:\n-:  ---------- > 1:  75edf24186 submodule--helper: add options for compute_submodule_clone_url()\n-:  ---------- > 2:  8e7a3e727a submodule--helper: refactor resolve_relative_url() helper\n-:  ---------- > 3:  82961ddd02 submodule--helper: remove repeated code in sync_submodule()\n1:  99d139375d ! 4:  fa97d6801e dir: libify and export helper functions from clone.c\n    @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)\n      \telse\n     -\t\tdir = guess_dir_name(repo_name, is_bundle, option_bare);\n     -\tstrip_trailing_slashes(dir);\n    -+\t\tdir = guess_target_dir_from_git_url(repo_name, is_bundle, option_bare);\n    ++\t\tdir = git_url_basename(repo_name, is_bundle, option_bare);\n     +\tstrip_dir_trailing_slashes(dir);\n      \n      \tdest_exists = path_exists(dir);\n    @@ dir.c: int is_empty_dir(const char *path)\n      \treturn ret;\n      }\n      \n    -+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare)\n    ++char *git_url_basename(const char *repo, int is_bundle, int is_bare)\n     +{\n     +\tconst char *end = repo + strlen(repo), *start, *ptr;\n     +\tsize_t len;\n    @@ dir.h: static inline int is_dot_or_dotdot(const char *name)\n      int is_empty_dir(const char *dir);\n      \n     +/*\n    -+ * Retrieve a target directory name by reading \"humanish\" part of the\n    -+ * given Git URL.\n    ++ * Retrieve the \"humanish\" basename of the given Git URL.\n     + *\n     + * For example:\n     + * \t/path/to/repo.git => \"repo\"\n     + * \thost.xz.foo/.git => \"foo\"\n     + */\n    -+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare);\n    ++char *git_url_basename(const char *repo, int is_bundle, int is_bare);\n     +void strip_dir_trailing_slashes(char *dir);\n     +\n      void setup_standard_excludes(struct dir_struct *dir);\n2:  11eea777ba ! 5:  a3aa25518d submodule--helper: convert the bulk of cmd_add() to C\n    @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv,\n     +\n     +\tadd_data.repo = argv[0];\n     +\tif (argc == 1)\n    -+\t\tadd_data.sm_path = guess_target_dir_from_git_url(add_data.repo, 0, 0);\n    ++\t\tadd_data.sm_path = git_url_basename(add_data.repo, 0, 0);\n     +\telse\n     +\t\tadd_data.sm_path = xstrdup(argv[1]);\n     +\n3:  51393cd99b = 6:  9667159d4b submodule--helper: remove add-clone subcommand\n4:  50cedcd8a8 = 7:  dc87b5627a submodule--helper: remove add-config subcommand\n5:  02558da532 = 8:  ea08e4fbad submodule--helper: remove resolve-relative-url subcommand\n-- \n2.32.0\n\n"},{"id":"432234","messageId":"20210807071613.99610-2-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-07T07:16:06Z","receivedAt":"2021-08-07T07:16:59Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Let's modify the interface to `compute_submodule_clone_url()` function\nby adding two more arguments, so that we can reuse this in various parts\nof `submodule--helper.c` that follow a common pattern, which is--read\nthe remote url configuration of the superproject and then call\n`relative_url()`.\n\nThis function is nearly identical to `resolve_relative_url()`, the only\ndifference being the extra warning message. We can add a quiet flag to\nit, to suppress that warning when not needed, and then refactor\n`resolve_relative_url()` by using this function, something we will do in\nthe next patch.\n\nHaving this functionality factored out will be useful for converting the\nrest of `submodule add` in subsequent patches.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 14 +++++++++-----\n 1 file changed, 9 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 6891480013..2d2d8ac637 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -590,7 +590,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n-static char *compute_submodule_clone_url(const char *rel_url)\n+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n {\n \tchar *remoteurl, *relurl;\n \tchar *remote = get_default_remote();\n@@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)\n \n \tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n-\t\twarning(_(\"could not look up configuration '%s'. Assuming this repository is its own authoritative upstream.\"), remotesb.buf);\n+\t\tif (!quiet)\n+\t\t\twarning(_(\"could not look up configuration '%s'. \"\n+\t\t\t\t  \"Assuming this repository is its own \"\n+\t\t\t\t  \"authoritative upstream.\"),\n+\t\t\t\tremotesb.buf);\n \t\tremoteurl = xgetcwd();\n \t}\n-\trelurl = relative_url(remoteurl, rel_url, NULL);\n+\trelurl = relative_url(remoteurl, rel_url, up_path);\n \n \tfree(remote);\n \tfree(remoteurl);\n@@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,\n \t\tif (starts_with_dot_dot_slash(url) ||\n \t\t    starts_with_dot_slash(url)) {\n \t\t\tchar *oldurl = url;\n-\t\t\turl = compute_submodule_clone_url(oldurl);\n+\t\t\turl = compute_submodule_clone_url(oldurl, NULL, 0);\n \t\t\tfree(oldurl);\n \t\t}\n \n@@ -2134,7 +2138,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \tif (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {\n \t\tif (starts_with_dot_slash(sub->url) ||\n \t\t    starts_with_dot_dot_slash(sub->url)) {\n-\t\t\turl = compute_submodule_clone_url(sub->url);\n+\t\t\turl = compute_submodule_clone_url(sub->url, NULL, 0);\n \t\t\tneed_free_url = 1;\n \t\t} else\n \t\t\turl = sub->url;\n-- \n2.32.0\n\n"},{"id":"432235","messageId":"20210807071613.99610-3-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v4 2/8] submodule--helper: refactor resolve_relative_url() helper","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-07T07:16:07Z","receivedAt":"2021-08-07T07:17:03Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Refactor the helper function to resolve a relative url, by reusing the\nexisting `compute_submodule_clone_url()` function.\n\n`compute_submodule_clone_url()` performs the same work that\n`resolve_relative_url()` is doing, so we eliminate this code repetition\nby moving the former function's definition up, and calling it inside\n`resolve_relative_url()`.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 61 +++++++++++++++----------------------\n 1 file changed, 25 insertions(+), 36 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 2d2d8ac637..f4b496bac6 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -199,33 +199,46 @@ static char *relative_url(const char *remote_url,\n \treturn strbuf_detach(&sb, NULL);\n }\n \n+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n+{\n+\tchar *remoteurl, *relurl;\n+\tchar *remote = get_default_remote();\n+\tstruct strbuf remotesb = STRBUF_INIT;\n+\n+\tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n+\tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n+\t\tif (!quiet)\n+\t\t\twarning(_(\"could not look up configuration '%s'. \"\n+\t\t\t\t  \"Assuming this repository is its own \"\n+\t\t\t\t  \"authoritative upstream.\"),\n+\t\t\t\tremotesb.buf);\n+\t\tremoteurl = xgetcwd();\n+\t}\n+\trelurl = relative_url(remoteurl, rel_url, up_path);\n+\n+\tfree(remote);\n+\tfree(remoteurl);\n+\tstrbuf_release(&remotesb);\n+\n+\treturn relurl;\n+}\n+\n static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n {\n-\tchar *remoteurl = NULL;\n-\tchar *remote = get_default_remote();\n \tconst char *up_path = NULL;\n \tchar *res;\n \tconst char *url;\n-\tstruct strbuf sb = STRBUF_INIT;\n \n \tif (argc != 2 && argc != 3)\n \t\tdie(\"resolve-relative-url only accepts one or two arguments\");\n \n \turl = argv[1];\n-\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n-\tfree(remote);\n-\n-\tif (git_config_get_string(sb.buf, &remoteurl))\n-\t\t/* the repository is its own authoritative upstream */\n-\t\tremoteurl = xgetcwd();\n-\n \tif (argc == 3)\n \t\tup_path = argv[2];\n \n-\tres = relative_url(remoteurl, url, up_path);\n+\tres = compute_submodule_clone_url(url, up_path, 1);\n \tputs(res);\n \tfree(res);\n-\tfree(remoteurl);\n \treturn 0;\n }\n \n@@ -590,30 +603,6 @@ static int module_foreach(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n-{\n-\tchar *remoteurl, *relurl;\n-\tchar *remote = get_default_remote();\n-\tstruct strbuf remotesb = STRBUF_INIT;\n-\n-\tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n-\tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n-\t\tif (!quiet)\n-\t\t\twarning(_(\"could not look up configuration '%s'. \"\n-\t\t\t\t  \"Assuming this repository is its own \"\n-\t\t\t\t  \"authoritative upstream.\"),\n-\t\t\t\tremotesb.buf);\n-\t\tremoteurl = xgetcwd();\n-\t}\n-\trelurl = relative_url(remoteurl, rel_url, up_path);\n-\n-\tfree(remote);\n-\tfree(remoteurl);\n-\tstrbuf_release(&remotesb);\n-\n-\treturn relurl;\n-}\n-\n struct init_cb {\n \tconst char *prefix;\n \tunsigned int flags;\n-- \n2.32.0\n\n"},{"id":"432236","messageId":"20210807071613.99610-4-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v4 3/8] submodule--helper: remove repeated code in sync_submodule()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-07T07:16:08Z","receivedAt":"2021-08-07T07:17:10Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"This part of `sync_submodule()` is doing the same thing that\n`compute_submodule_clone_url()` is doing. Let's reuse that helper here.\n\nNote that this change adds a small overhead where we allocate and free\nthe 'remote' twice, but that is a small price to pay for the higher\nlevel of abstraction we get.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 16 +++-------------\n 1 file changed, 3 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f4b496bac6..9b676c12f8 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,\n \tif (sub && sub->url) {\n \t\tif (starts_with_dot_dot_slash(sub->url) ||\n \t\t    starts_with_dot_slash(sub->url)) {\n-\t\t\tchar *remote_url, *up_path;\n-\t\t\tchar *remote = get_default_remote();\n-\t\t\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n-\n-\t\t\tif (git_config_get_string(sb.buf, &remote_url))\n-\t\t\t\tremote_url = xgetcwd();\n-\n-\t\t\tup_path = get_up_path(path);\n-\t\t\tsub_origin_url = relative_url(remote_url, sub->url, up_path);\n-\t\t\tsuper_config_url = relative_url(remote_url, sub->url, NULL);\n-\n-\t\t\tfree(remote);\n+\t\t\tchar *up_path = get_up_path(path);\n+\t\t\tsub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);\n+\t\t\tsuper_config_url = compute_submodule_clone_url(sub->url, NULL, 1);\n \t\t\tfree(up_path);\n-\t\t\tfree(remote_url);\n \t\t} else {\n \t\t\tsub_origin_url = xstrdup(sub->url);\n \t\t\tsuper_config_url = xstrdup(sub->url);\n-- \n2.32.0\n\n"},{"id":"432237","messageId":"20210807071613.99610-5-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-07T07:16:09Z","receivedAt":"2021-08-07T07:17:16Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"These functions can be useful to other parts of Git. Let's move them to\ndir.c, while renaming them to be make their functionality more explicit.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/clone.c | 118 +-----------------------------------------------\n dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++\n dir.h           |  10 ++++\n 3 files changed, 126 insertions(+), 116 deletions(-)\n\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 66fe66679c..5ba24b7ae7 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -217,120 +217,6 @@ static char *get_repo_path(const char *repo, int *is_bundle)\n \treturn canon;\n }\n \n-static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)\n-{\n-\tconst char *end = repo + strlen(repo), *start, *ptr;\n-\tsize_t len;\n-\tchar *dir;\n-\n-\t/*\n-\t * Skip scheme.\n-\t */\n-\tstart = strstr(repo, \"://\");\n-\tif (start == NULL)\n-\t\tstart = repo;\n-\telse\n-\t\tstart += 3;\n-\n-\t/*\n-\t * Skip authentication data. The stripping does happen\n-\t * greedily, such that we strip up to the last '@' inside\n-\t * the host part.\n-\t */\n-\tfor (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {\n-\t\tif (*ptr == '@')\n-\t\t\tstart = ptr + 1;\n-\t}\n-\n-\t/*\n-\t * Strip trailing spaces, slashes and /.git\n-\t */\n-\twhile (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))\n-\t\tend--;\n-\tif (end - start > 5 && is_dir_sep(end[-5]) &&\n-\t    !strncmp(end - 4, \".git\", 4)) {\n-\t\tend -= 5;\n-\t\twhile (start < end && is_dir_sep(end[-1]))\n-\t\t\tend--;\n-\t}\n-\n-\t/*\n-\t * Strip trailing port number if we've got only a\n-\t * hostname (that is, there is no dir separator but a\n-\t * colon). This check is required such that we do not\n-\t * strip URI's like '/foo/bar:2222.git', which should\n-\t * result in a dir '2222' being guessed due to backwards\n-\t * compatibility.\n-\t */\n-\tif (memchr(start, '/', end - start) == NULL\n-\t    && memchr(start, ':', end - start) != NULL) {\n-\t\tptr = end;\n-\t\twhile (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')\n-\t\t\tptr--;\n-\t\tif (start < ptr && ptr[-1] == ':')\n-\t\t\tend = ptr - 1;\n-\t}\n-\n-\t/*\n-\t * Find last component. To remain backwards compatible we\n-\t * also regard colons as path separators, such that\n-\t * cloning a repository 'foo:bar.git' would result in a\n-\t * directory 'bar' being guessed.\n-\t */\n-\tptr = end;\n-\twhile (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')\n-\t\tptr--;\n-\tstart = ptr;\n-\n-\t/*\n-\t * Strip .{bundle,git}.\n-\t */\n-\tlen = end - start;\n-\tstrip_suffix_mem(start, &len, is_bundle ? \".bundle\" : \".git\");\n-\n-\tif (!len || (len == 1 && *start == '/'))\n-\t\tdie(_(\"No directory name could be guessed.\\n\"\n-\t\t      \"Please specify a directory on the command line\"));\n-\n-\tif (is_bare)\n-\t\tdir = xstrfmt(\"%.*s.git\", (int)len, start);\n-\telse\n-\t\tdir = xstrndup(start, len);\n-\t/*\n-\t * Replace sequences of 'control' characters and whitespace\n-\t * with one ascii space, remove leading and trailing spaces.\n-\t */\n-\tif (*dir) {\n-\t\tchar *out = dir;\n-\t\tint prev_space = 1 /* strip leading whitespace */;\n-\t\tfor (end = dir; *end; ++end) {\n-\t\t\tchar ch = *end;\n-\t\t\tif ((unsigned char)ch < '\\x20')\n-\t\t\t\tch = '\\x20';\n-\t\t\tif (isspace(ch)) {\n-\t\t\t\tif (prev_space)\n-\t\t\t\t\tcontinue;\n-\t\t\t\tprev_space = 1;\n-\t\t\t} else\n-\t\t\t\tprev_space = 0;\n-\t\t\t*out++ = ch;\n-\t\t}\n-\t\t*out = '\\0';\n-\t\tif (out > dir && prev_space)\n-\t\t\tout[-1] = '\\0';\n-\t}\n-\treturn dir;\n-}\n-\n-static void strip_trailing_slashes(char *dir)\n-{\n-\tchar *end = dir + strlen(dir);\n-\n-\twhile (dir < end - 1 && is_dir_sep(end[-1]))\n-\t\tend--;\n-\t*end = '\\0';\n-}\n-\n static int add_one_reference(struct string_list_item *item, void *cb_data)\n {\n \tstruct strbuf err = STRBUF_INIT;\n@@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \tif (argc == 2)\n \t\tdir = xstrdup(argv[1]);\n \telse\n-\t\tdir = guess_dir_name(repo_name, is_bundle, option_bare);\n-\tstrip_trailing_slashes(dir);\n+\t\tdir = git_url_basename(repo_name, is_bundle, option_bare);\n+\tstrip_dir_trailing_slashes(dir);\n \n \tdest_exists = path_exists(dir);\n \tif (dest_exists && !is_empty_dir(dir))\ndiff --git a/dir.c b/dir.c\nindex 03c4d21267..6d26db3189 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -2970,6 +2970,120 @@ int is_empty_dir(const char *path)\n \treturn ret;\n }\n \n+char *git_url_basename(const char *repo, int is_bundle, int is_bare)\n+{\n+\tconst char *end = repo + strlen(repo), *start, *ptr;\n+\tsize_t len;\n+\tchar *dir;\n+\n+\t/*\n+\t * Skip scheme.\n+\t */\n+\tstart = strstr(repo, \"://\");\n+\tif (start == NULL)\n+\t\tstart = repo;\n+\telse\n+\t\tstart += 3;\n+\n+\t/*\n+\t * Skip authentication data. The stripping does happen\n+\t * greedily, such that we strip up to the last '@' inside\n+\t * the host part.\n+\t */\n+\tfor (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {\n+\t\tif (*ptr == '@')\n+\t\t\tstart = ptr + 1;\n+\t}\n+\n+\t/*\n+\t * Strip trailing spaces, slashes and /.git\n+\t */\n+\twhile (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))\n+\t\tend--;\n+\tif (end - start > 5 && is_dir_sep(end[-5]) &&\n+\t    !strncmp(end - 4, \".git\", 4)) {\n+\t\tend -= 5;\n+\t\twhile (start < end && is_dir_sep(end[-1]))\n+\t\t\tend--;\n+\t}\n+\n+\t/*\n+\t * Strip trailing port number if we've got only a\n+\t * hostname (that is, there is no dir separator but a\n+\t * colon). This check is required such that we do not\n+\t * strip URI's like '/foo/bar:2222.git', which should\n+\t * result in a dir '2222' being guessed due to backwards\n+\t * compatibility.\n+\t */\n+\tif (memchr(start, '/', end - start) == NULL\n+\t    && memchr(start, ':', end - start) != NULL) {\n+\t\tptr = end;\n+\t\twhile (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')\n+\t\t\tptr--;\n+\t\tif (start < ptr && ptr[-1] == ':')\n+\t\t\tend = ptr - 1;\n+\t}\n+\n+\t/*\n+\t * Find last component. To remain backwards compatible we\n+\t * also regard colons as path separators, such that\n+\t * cloning a repository 'foo:bar.git' would result in a\n+\t * directory 'bar' being guessed.\n+\t */\n+\tptr = end;\n+\twhile (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')\n+\t\tptr--;\n+\tstart = ptr;\n+\n+\t/*\n+\t * Strip .{bundle,git}.\n+\t */\n+\tlen = end - start;\n+\tstrip_suffix_mem(start, &len, is_bundle ? \".bundle\" : \".git\");\n+\n+\tif (!len || (len == 1 && *start == '/'))\n+\t\tdie(_(\"No directory name could be guessed.\\n\"\n+\t\t      \"Please specify a directory on the command line\"));\n+\n+\tif (is_bare)\n+\t\tdir = xstrfmt(\"%.*s.git\", (int)len, start);\n+\telse\n+\t\tdir = xstrndup(start, len);\n+\t/*\n+\t * Replace sequences of 'control' characters and whitespace\n+\t * with one ascii space, remove leading and trailing spaces.\n+\t */\n+\tif (*dir) {\n+\t\tchar *out = dir;\n+\t\tint prev_space = 1 /* strip leading whitespace */;\n+\t\tfor (end = dir; *end; ++end) {\n+\t\t\tchar ch = *end;\n+\t\t\tif ((unsigned char)ch < '\\x20')\n+\t\t\t\tch = '\\x20';\n+\t\t\tif (isspace(ch)) {\n+\t\t\t\tif (prev_space)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tprev_space = 1;\n+\t\t\t} else\n+\t\t\t\tprev_space = 0;\n+\t\t\t*out++ = ch;\n+\t\t}\n+\t\t*out = '\\0';\n+\t\tif (out > dir && prev_space)\n+\t\t\tout[-1] = '\\0';\n+\t}\n+\treturn dir;\n+}\n+\n+void strip_dir_trailing_slashes(char *dir)\n+{\n+\tchar *end = dir + strlen(dir);\n+\n+\twhile (dir < end - 1 && is_dir_sep(end[-1]))\n+\t\tend--;\n+\t*end = '\\0';\n+}\n+\n static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)\n {\n \tDIR *dir;\ndiff --git a/dir.h b/dir.h\nindex b3e1a54a97..a4a6fd7371 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -453,6 +453,16 @@ static inline int is_dot_or_dotdot(const char *name)\n \n int is_empty_dir(const char *dir);\n \n+/*\n+ * Retrieve the \"humanish\" basename of the given Git URL.\n+ *\n+ * For example:\n+ * \t/path/to/repo.git => \"repo\"\n+ * \thost.xz.foo/.git => \"foo\"\n+ */\n+char *git_url_basename(const char *repo, int is_bundle, int is_bare);\n+void strip_dir_trailing_slashes(char *dir);\n+\n void setup_standard_excludes(struct dir_struct *dir);\n \n char *get_sparse_checkout_filename(void);\n-- \n2.32.0\n\n"},{"id":"432238","messageId":"20210807071613.99610-6-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v4 5/8] submodule--helper: convert the bulk of cmd_add() to C","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-07T07:16:10Z","receivedAt":"2021-08-07T07:17:19Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Introduce the 'add' subcommand to `submodule--helper.c` that does all\nthe work 'submodule add' past the parsing of flags.\n\nWe also remove the constness of the sm_path field of the `add_data`\nstruct. This is needed so that it can be modified by\nnormalize_path_copy().\n\nAs with the previous conversions, this is meant to be a faithful\nconversion with no modification to the behaviour of `submodule add`.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nHelped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\nBased-on-patch-by: Shourya Shukla <periperidip@gmail.com>\nBased-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>\n---\n builtin/submodule--helper.c | 165 +++++++++++++++++++++++++++++++++++-\n git-submodule.sh            |  96 +--------------------\n 2 files changed, 166 insertions(+), 95 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 9b676c12f8..3aa3ae8b61 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2748,7 +2748,7 @@ struct add_data {\n \tconst char *prefix;\n \tconst char *branch;\n \tconst char *reference_path;\n-\tconst char *sm_path;\n+\tchar *sm_path;\n \tconst char *sm_name;\n \tconst char *repo;\n \tconst char *realrepo;\n@@ -3046,6 +3046,168 @@ static int add_config(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static void die_on_index_match(const char *path, int force)\n+{\n+\tstruct pathspec ps;\n+\tconst char *args[] = { path, NULL };\n+\tparse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);\n+\n+\tif (read_cache_preload(NULL) < 0)\n+\t\tdie(_(\"index file corrupt\"));\n+\n+\tif (ps.nr) {\n+\t\tint i;\n+\t\tchar *ps_matched = xcalloc(ps.nr, 1);\n+\n+\t\t/* TODO: audit for interaction with sparse-index. */\n+\t\tensure_full_index(&the_index);\n+\n+\t\t/*\n+\t\t * Since there is only one pathspec, we just need\n+\t\t * need to check ps_matched[0] to know if a cache\n+\t\t * entry matched.\n+\t\t */\n+\t\tfor (i = 0; i < active_nr; i++) {\n+\t\t\tce_path_match(&the_index, active_cache[i], &ps,\n+\t\t\t\t      ps_matched);\n+\n+\t\t\tif (ps_matched[0]) {\n+\t\t\t\tif (!force)\n+\t\t\t\t\tdie(_(\"'%s' already exists in the index\"),\n+\t\t\t\t\t    path);\n+\t\t\t\tif (!S_ISGITLINK(active_cache[i]->ce_mode))\n+\t\t\t\t\tdie(_(\"'%s' already exists in the index \"\n+\t\t\t\t\t      \"and is not a submodule\"), path);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tfree(ps_matched);\n+\t}\n+}\n+\n+static void die_on_repo_without_commits(const char *path)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstrbuf_addstr(&sb, path);\n+\tif (is_nonbare_repository_dir(&sb)) {\n+\t\tstruct object_id oid;\n+\t\tif (resolve_gitlink_ref(path, \"HEAD\", &oid) < 0)\n+\t\t\tdie(_(\"'%s' does not have a commit checked out\"), path);\n+\t}\n+}\n+\n+static int module_add(int argc, const char **argv, const char *prefix)\n+{\n+\tint force = 0, quiet = 0, progress = 0, dissociate = 0;\n+\tstruct add_data add_data = ADD_DATA_INIT;\n+\n+\tstruct option options[] = {\n+\t\tOPT_STRING('b', \"branch\", &add_data.branch, N_(\"branch\"),\n+\t\t\t   N_(\"branch of repository to add as submodule\")),\n+\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n+\t\t\t   PARSE_OPT_NOCOMPLETE),\n+\t\tOPT__QUIET(&quiet, N_(\"print only error messages\")),\n+\t\tOPT_BOOL(0, \"progress\", &progress, N_(\"force cloning progress\")),\n+\t\tOPT_STRING(0, \"reference\", &add_data.reference_path, N_(\"repository\"),\n+\t\t\t   N_(\"reference repository\")),\n+\t\tOPT_BOOL(0, \"dissociate\", &dissociate, N_(\"borrow the objects from reference repositories\")),\n+\t\tOPT_STRING(0, \"name\", &add_data.sm_name, N_(\"name\"),\n+\t\t\t   N_(\"sets the submodule’s name to the given string \"\n+\t\t\t      \"instead of defaulting to its path\")),\n+\t\tOPT_INTEGER(0, \"depth\", &add_data.depth, N_(\"depth for shallow clones\")),\n+\t\tOPT_END()\n+\t};\n+\n+\tconst char *const usage[] = {\n+\t\tN_(\"git submodule--helper add [<options>] [--] <repository> [<path>]\"),\n+\t\tNULL\n+\t};\n+\n+\targc = parse_options(argc, argv, prefix, options, usage, 0);\n+\n+\tif (!is_writing_gitmodules_ok())\n+\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n+\n+\tif (prefix && *prefix &&\n+\t    add_data.reference_path && !is_absolute_path(add_data.reference_path))\n+\t\tadd_data.reference_path = xstrfmt(\"%s%s\", prefix, add_data.reference_path);\n+\n+\tif (argc == 0 || argc > 2)\n+\t\tusage_with_options(usage, options);\n+\n+\tadd_data.repo = argv[0];\n+\tif (argc == 1)\n+\t\tadd_data.sm_path = git_url_basename(add_data.repo, 0, 0);\n+\telse\n+\t\tadd_data.sm_path = xstrdup(argv[1]);\n+\n+\tif (prefix && *prefix && !is_absolute_path(add_data.sm_path))\n+\t\tadd_data.sm_path = xstrfmt(\"%s%s\", prefix, add_data.sm_path);\n+\n+\tif (starts_with_dot_dot_slash(add_data.repo) ||\n+\t    starts_with_dot_slash(add_data.repo)) {\n+\t\tif (prefix)\n+\t\t\tdie(_(\"Relative path can only be used from the toplevel \"\n+\t\t\t      \"of the working tree\"));\n+\n+\t\t/* dereference source url relative to parent's url */\n+\t\tadd_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);\n+\t} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {\n+\t\tadd_data.realrepo = add_data.repo;\n+\t} else {\n+\t\tdie(_(\"repo URL: '%s' must be absolute or begin with ./|../\"),\n+\t\t    add_data.repo);\n+\t}\n+\n+\t/*\n+\t * normalize path:\n+\t * multiple //; leading ./; /./; /../;\n+\t */\n+\tnormalize_path_copy(add_data.sm_path, add_data.sm_path);\n+\tstrip_dir_trailing_slashes(add_data.sm_path);\n+\n+\tdie_on_index_match(add_data.sm_path, force);\n+\tdie_on_repo_without_commits(add_data.sm_path);\n+\n+\tif (!force) {\n+\t\tint exit_code = -1;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\t\tcp.git_cmd = 1;\n+\t\tcp.no_stdout = 1;\n+\t\tstrvec_pushl(&cp.args, \"add\", \"--dry-run\", \"--ignore-missing\",\n+\t\t\t     \"--no-warn-embedded-repo\", add_data.sm_path, NULL);\n+\t\tif ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {\n+\t\t\tstrbuf_complete_line(&sb);\n+\t\t\tfputs(sb.buf, stderr);\n+\t\t\tfree(add_data.sm_path);\n+\t\t\treturn exit_code;\n+\t\t}\n+\t\tstrbuf_release(&sb);\n+\t}\n+\n+\tif(!add_data.sm_name)\n+\t\tadd_data.sm_name = add_data.sm_path;\n+\n+\tif (check_submodule_name(add_data.sm_name))\n+\t\tdie(_(\"'%s' is not a valid submodule name\"), add_data.sm_name);\n+\n+\tadd_data.prefix = prefix;\n+\tadd_data.force = !!force;\n+\tadd_data.quiet = !!quiet;\n+\tadd_data.progress = !!progress;\n+\tadd_data.dissociate = !!dissociate;\n+\n+\tif (add_submodule(&add_data)) {\n+\t\tfree(add_data.sm_path);\n+\t\treturn 1;\n+\t}\n+\tconfigure_added_submodule(&add_data);\n+\tfree(add_data.sm_path);\n+\n+\treturn 0;\n+}\n+\n #define SUPPORT_SUPER_PREFIX (1<<0)\n \n struct cmd_struct {\n@@ -3060,6 +3222,7 @@ static struct cmd_struct commands[] = {\n \t{\"clone\", module_clone, 0},\n \t{\"add-clone\", add_clone, 0},\n \t{\"add-config\", add_config, 0},\n+\t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n \t{\"update-clone\", update_clone, 0},\n \t{\"ensure-core-worktree\", ensure_core_worktree, 0},\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 8c219ef382..1070540525 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -145,104 +145,12 @@ cmd_add()\n \t\tshift\n \tdone\n \n-\tif ! git submodule--helper config --check-writeable >/dev/null 2>&1\n+\tif test -z \"$1\"\n \tthen\n-\t\t die \"fatal: $(eval_gettext \"please make sure that the .gitmodules file is in the working tree\")\"\n-\tfi\n-\n-\tif test -n \"$reference_path\"\n-\tthen\n-\t\tis_absolute_path \"$reference_path\" ||\n-\t\treference_path=\"$wt_prefix$reference_path\"\n-\n-\t\treference=\"--reference=$reference_path\"\n-\tfi\n-\n-\trepo=$1\n-\tsm_path=$2\n-\n-\tif test -z \"$sm_path\"; then\n-\t\tsm_path=$(printf '%s\\n' \"$repo\" |\n-\t\t\tsed -e 's|/$||' -e 's|:*/*\\.git$||' -e 's|.*[/:]||g')\n-\tfi\n-\n-\tif test -z \"$repo\" || test -z \"$sm_path\"; then\n \t\tusage\n \tfi\n \n-\tis_absolute_path \"$sm_path\" || sm_path=\"$wt_prefix$sm_path\"\n-\n-\t# assure repo is absolute or relative to parent\n-\tcase \"$repo\" in\n-\t./*|../*)\n-\t\ttest -z \"$wt_prefix\" ||\n-\t\tdie \"fatal: $(gettext \"Relative path can only be used from the toplevel of the working tree\")\"\n-\n-\t\t# dereference source url relative to parent's url\n-\t\trealrepo=$(git submodule--helper resolve-relative-url \"$repo\") || exit\n-\t\t;;\n-\t*:*|/*)\n-\t\t# absolute url\n-\t\trealrepo=$repo\n-\t\t;;\n-\t*)\n-\t\tdie \"fatal: $(eval_gettext \"repo URL: '\\$repo' must be absolute or begin with ./|../\")\"\n-\t;;\n-\tesac\n-\n-\t# normalize path:\n-\t# multiple //; leading ./; /./; /../; trailing /\n-\tsm_path=$(printf '%s/\\n' \"$sm_path\" |\n-\t\tsed -e '\n-\t\t\ts|//*|/|g\n-\t\t\ts|^\\(\\./\\)*||\n-\t\t\ts|/\\(\\./\\)*|/|g\n-\t\t\t:start\n-\t\t\ts|\\([^/]*\\)/\\.\\./||\n-\t\t\ttstart\n-\t\t\ts|/*$||\n-\t\t')\n-\tif test -z \"$force\"\n-\tthen\n-\t\tgit ls-files --error-unmatch \"$sm_path\" > /dev/null 2>&1 &&\n-\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index\")\"\n-\telse\n-\t\tgit ls-files -s \"$sm_path\" | sane_grep -v \"^160000\" > /dev/null 2>&1 &&\n-\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index and is not a submodule\")\"\n-\tfi\n-\n-\tif test -d \"$sm_path\" &&\n-\t\ttest -z $(git -C \"$sm_path\" rev-parse --show-cdup 2>/dev/null)\n-\tthen\n-\t    git -C \"$sm_path\" rev-parse --verify -q HEAD >/dev/null ||\n-\t    die \"fatal: $(eval_gettext \"'\\$sm_path' does not have a commit checked out\")\"\n-\tfi\n-\n-\tif test -z \"$force\"\n-\tthen\n-\t    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo \"$sm_path\" 2>&1 >/dev/null)\n-\t    res=$?\n-\t    if test $res -ne 0\n-\t    then\n-\t\t echo >&2 \"$dryerr\"\n-\t\t exit $res\n-\t    fi\n-\tfi\n-\n-\tif test -n \"$custom_name\"\n-\tthen\n-\t\tsm_name=\"$custom_name\"\n-\telse\n-\t\tsm_name=\"$sm_path\"\n-\tfi\n-\n-\tif ! git submodule--helper check-name \"$sm_name\"\n-\tthen\n-\t\tdie \"fatal: $(eval_gettext \"'$sm_name' is not a valid submodule name\")\"\n-\tfi\n-\n-\tgit 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\n-\tgit submodule--helper add-config ${force:+--force} ${branch:+--branch \"$branch\"} --url \"$repo\" --resolved-url \"$realrepo\" --path \"$sm_path\" --name \"$sm_name\"\n+\tgit ${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\"} -- \"$@\"\n }\n \n #\n-- \n2.32.0\n\n"},{"id":"432239","messageId":"20210807071613.99610-7-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v4 6/8] submodule--helper: remove add-clone subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-07T07:16:11Z","receivedAt":"2021-08-07T07:17:26Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"We no longer need this subcommand, as all of its functionality is being\ncalled by the newly-introduced `module_add()` directly within C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 60 -------------------------------------\n 1 file changed, 60 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 3aa3ae8b61..5932438d65 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2860,65 +2860,6 @@ static int add_submodule(const struct add_data *add_data)\n \treturn 0;\n }\n \n-static int add_clone(int argc, const char **argv, const char *prefix)\n-{\n-\tint force = 0, quiet = 0, dissociate = 0, progress = 0;\n-\tstruct add_data add_data = ADD_DATA_INIT;\n-\n-\tstruct option options[] = {\n-\t\tOPT_STRING('b', \"branch\", &add_data.branch,\n-\t\t\t   N_(\"branch\"),\n-\t\t\t   N_(\"branch of repository to checkout on cloning\")),\n-\t\tOPT_STRING(0, \"prefix\", &prefix,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"alternative anchor for relative paths\")),\n-\t\tOPT_STRING(0, \"path\", &add_data.sm_path,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"where the new submodule will be cloned to\")),\n-\t\tOPT_STRING(0, \"name\", &add_data.sm_name,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"name of the new submodule\")),\n-\t\tOPT_STRING(0, \"url\", &add_data.realrepo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url where to clone the submodule from\")),\n-\t\tOPT_STRING(0, \"reference\", &add_data.reference_path,\n-\t\t\t   N_(\"repo\"),\n-\t\t\t   N_(\"reference repository\")),\n-\t\tOPT_BOOL(0, \"dissociate\", &dissociate,\n-\t\t\t N_(\"use --reference only while cloning\")),\n-\t\tOPT_INTEGER(0, \"depth\", &add_data.depth,\n-\t\t\t    N_(\"depth for shallow clones\")),\n-\t\tOPT_BOOL(0, \"progress\", &progress,\n-\t\t\t N_(\"force cloning progress\")),\n-\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n-\t\t\t   PARSE_OPT_NOCOMPLETE),\n-\t\tOPT__QUIET(&quiet, \"suppress output for cloning a submodule\"),\n-\t\tOPT_END()\n-\t};\n-\n-\tconst char *const usage[] = {\n-\t\tN_(\"git submodule--helper add-clone [<options>...] \"\n-\t\t   \"--url <url> --path <path> --name <name>\"),\n-\t\tNULL\n-\t};\n-\n-\targc = parse_options(argc, argv, prefix, options, usage, 0);\n-\n-\tif (argc != 0)\n-\t\tusage_with_options(usage, options);\n-\n-\tadd_data.prefix = prefix;\n-\tadd_data.progress = !!progress;\n-\tadd_data.dissociate = !!dissociate;\n-\tadd_data.force = !!force;\n-\tadd_data.quiet = !!quiet;\n-\n-\tif (add_submodule(&add_data))\n-\t\treturn 1;\n-\n-\treturn 0;\n-}\n-\n static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)\n {\n \tchar *key;\n@@ -3220,7 +3161,6 @@ static struct cmd_struct commands[] = {\n \t{\"list\", module_list, 0},\n \t{\"name\", module_name, 0},\n \t{\"clone\", module_clone, 0},\n-\t{\"add-clone\", add_clone, 0},\n \t{\"add-config\", add_config, 0},\n \t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n-- \n2.32.0\n\n"},{"id":"432240","messageId":"20210807071613.99610-8-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v4 7/8] submodule--helper: remove add-config subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-07T07:16:12Z","receivedAt":"2021-08-07T07:17:32Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Also no longer needed is this subcommand, as all of its functionality is\nbeing called by the newly-introduced `module_add()` directly within C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 49 -------------------------------------\n 1 file changed, 49 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 5932438d65..d526423a0c 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2939,54 +2939,6 @@ static void configure_added_submodule(struct add_data *add_data)\n \t}\n }\n \n-static int add_config(int argc, const char **argv, const char *prefix)\n-{\n-\tint force = 0;\n-\tstruct add_data add_data = ADD_DATA_INIT;\n-\n-\tstruct option options[] = {\n-\t\tOPT_STRING('b', \"branch\", &add_data.branch,\n-\t\t\t   N_(\"branch\"),\n-\t\t\t   N_(\"branch of repository to store in \"\n-\t\t\t      \"the submodule configuration\")),\n-\t\tOPT_STRING(0, \"url\", &add_data.repo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url to clone submodule from\")),\n-\t\tOPT_STRING(0, \"resolved-url\", &add_data.realrepo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url to clone the submodule from, after it has \"\n-\t\t\t      \"been dereferenced relative to parent's url, \"\n-\t\t\t      \"in the case where <url> is a relative url\")),\n-\t\tOPT_STRING(0, \"path\", &add_data.sm_path,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"where the new submodule will be cloned to\")),\n-\t\tOPT_STRING(0, \"name\", &add_data.sm_name,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"name of the new submodule\")),\n-\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n-\t\t\t   PARSE_OPT_NOCOMPLETE),\n-\t\tOPT_END()\n-\t};\n-\n-\tconst char *const usage[] = {\n-\t\tN_(\"git submodule--helper add-config \"\n-\t\t   \"[--force|-f] [--branch|-b <branch>] \"\n-\t\t   \"--url <url> --resolved-url <resolved-url> \"\n-\t\t   \"--path <path> --name <name>\"),\n-\t\tNULL\n-\t};\n-\n-\targc = parse_options(argc, argv, prefix, options, usage, 0);\n-\n-\tif (argc)\n-\t\tusage_with_options(usage, options);\n-\n-\tadd_data.force = !!force;\n-\tconfigure_added_submodule(&add_data);\n-\n-\treturn 0;\n-}\n-\n static void die_on_index_match(const char *path, int force)\n {\n \tstruct pathspec ps;\n@@ -3161,7 +3113,6 @@ static struct cmd_struct commands[] = {\n \t{\"list\", module_list, 0},\n \t{\"name\", module_name, 0},\n \t{\"clone\", module_clone, 0},\n-\t{\"add-config\", add_config, 0},\n \t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n \t{\"update-clone\", update_clone, 0},\n-- \n2.32.0\n\n"},{"id":"432241","messageId":"20210807071613.99610-9-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v4 8/8] submodule--helper: remove resolve-relative-url subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-07T07:16:13Z","receivedAt":"2021-08-07T07:17:33Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"The shell subcommand `resolve-relative-url` is no longer required, as\nits last caller has been removed when it was converted to C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 20 --------------------\n 1 file changed, 20 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex d526423a0c..bc123d7aaf 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -223,25 +223,6 @@ static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat\n \treturn relurl;\n }\n \n-static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n-{\n-\tconst char *up_path = NULL;\n-\tchar *res;\n-\tconst char *url;\n-\n-\tif (argc != 2 && argc != 3)\n-\t\tdie(\"resolve-relative-url only accepts one or two arguments\");\n-\n-\turl = argv[1];\n-\tif (argc == 3)\n-\t\tup_path = argv[2];\n-\n-\tres = compute_submodule_clone_url(url, up_path, 1);\n-\tputs(res);\n-\tfree(res);\n-\treturn 0;\n-}\n-\n static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)\n {\n \tchar *remoteurl, *res;\n@@ -3118,7 +3099,6 @@ static struct cmd_struct commands[] = {\n \t{\"update-clone\", update_clone, 0},\n \t{\"ensure-core-worktree\", ensure_core_worktree, 0},\n \t{\"relative-path\", resolve_relative_path, 0},\n-\t{\"resolve-relative-url\", resolve_relative_url, 0},\n \t{\"resolve-relative-url-test\", resolve_relative_url_test, 0},\n \t{\"foreach\", module_foreach, SUPPORT_SUPER_PREFIX},\n \t{\"init\", module_init, SUPPORT_SUPER_PREFIX},\n-- \n2.32.0\n\n"},{"id":"432269","messageId":"0752736f-11d5-103b-653f-a4bbe6436304@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-2-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Kaartic Sivaraam","fromEmail":"kaartic.sivaraam@gmail.com","sentAt":"2021-08-08T17:41:29Z","receivedAt":"2021-08-08T17:41:48Z","isPatch":true,"sender":{"key":"kaartic.sivaraam@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12448084?v=4"},"body":"On 07/08/21 12:46 pm, Atharva Raykar wrote:\n> Let's modify the interface to `compute_submodule_clone_url()` function\n> by adding two more arguments, so that we can reuse this in various parts\n> of `submodule--helper.c` that follow a common pattern, which is--read\n> the remote url configuration of the superproject and then call\n> `relative_url()`.\n> \n> This function is nearly identical to `resolve_relative_url()`, the only\n> difference being the extra warning message. We can add a quiet flag to\n> it, ...\n\nIt took me a while to figure what \"it\" meant in the above sentence. Does it\nrefer to `compute_submodule_clone_url` or `resolve_relative_url`. After one\nsees the patch and takes a look at `resolve_relative_url`, it's clear the \"it\"\nindeed does refer to `resolve_relative_url`. But it might worth clarifying this\nin the commit message itself.\n\nCertainly not worth a re-roll on its own. May be Junio could amend this while queing ?\n\n\n> ...  to suppress that warning when not needed, and then refactor\n> `resolve_relative_url()` by using this function, something we will do in\n> the next patch.\n> \n> Having this functionality factored out will be useful for converting the\n> rest of `submodule add` in subsequent patches.\n> \n> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Shourya Shukla <periperidip@gmail.com>\n\nOtherwise, this looks good.\n\n-- \nSivaraam\n"},{"id":"432273","messageId":"1131ec9a-d836-b45a-63c8-6f1d39dd3399@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-1-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v4 0/8] submodule: convert the rest of 'add' to C","fromName":"Kaartic Sivaraam","fromEmail":"kaartic.sivaraam@gmail.com","sentAt":"2021-08-08T18:01:00Z","receivedAt":"2021-08-08T18:01:08Z","isPatch":true,"sender":{"key":"kaartic.sivaraam@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12448084?v=4"},"body":"On 07/08/21 12:46 pm, Atharva Raykar wrote:\n> Changes since v3:\n> \n> * Rename the libified dir helper and update the docstring.\n>\n\nJust a note. I'm not really sure about this yet, the fact\nthat this series depends on the change introduced by\n'ar/submodule-add-config'[1] might be worth mentioning in\nre-rolls too. This could help the maintainer to easily identify\nthe topic dependency :-)\n\n[1]: https://lore.kernel.org/git/20210801063352.50813-1-raykar.ath@gmail.com/\n\nAnd ...\n\n> Atharva Raykar (8):\n>    submodule--helper: add options for compute_submodule_clone_url()\n>    submodule--helper: refactor resolve_relative_url() helper\n>    submodule--helper: remove repeated code in sync_submodule()\n>    dir: libify and export helper functions from clone.c\n>    submodule--helper: convert the bulk of cmd_add() to C\n>    submodule--helper: remove add-clone subcommand\n>    submodule--helper: remove add-config subcommand\n>    submodule--helper: remove resolve-relative-url subcommand\n> \n>   builtin/clone.c             | 118 +-------------\n>   builtin/submodule--helper.c | 307 +++++++++++++++++++-----------------\n>   dir.c                       | 114 +++++++++++++\n>   dir.h                       |  10 ++\n>   git-submodule.sh            |  96 +----------\n>   5 files changed, 290 insertions(+), 355 deletions(-)\n> \n> Range-diff against v3:\n\nThanks for consistently including a useful range-diff!\n\n-- \nSivaraam\n\n> -:  ---------- > 1:  75edf24186 submodule--helper: add options for compute_submodule_clone_url()\n> -:  ---------- > 2:  8e7a3e727a submodule--helper: refactor resolve_relative_url() helper\n> -:  ---------- > 3:  82961ddd02 submodule--helper: remove repeated code in sync_submodule()\n> 1:  99d139375d ! 4:  fa97d6801e dir: libify and export helper functions from clone.c\n>      @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)\n>        \telse\n>       -\t\tdir = guess_dir_name(repo_name, is_bundle, option_bare);\n>       -\tstrip_trailing_slashes(dir);\n>      -+\t\tdir = guess_target_dir_from_git_url(repo_name, is_bundle, option_bare);\n>      ++\t\tdir = git_url_basename(repo_name, is_bundle, option_bare);\n>       +\tstrip_dir_trailing_slashes(dir);\n>        \n>        \tdest_exists = path_exists(dir);\n>      @@ dir.c: int is_empty_dir(const char *path)\n>        \treturn ret;\n>        }\n>        \n>      -+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare)\n>      ++char *git_url_basename(const char *repo, int is_bundle, int is_bare)\n>       +{\n>       +\tconst char *end = repo + strlen(repo), *start, *ptr;\n>       +\tsize_t len;\n>      @@ dir.h: static inline int is_dot_or_dotdot(const char *name)\n>        int is_empty_dir(const char *dir);\n>        \n>       +/*\n>      -+ * Retrieve a target directory name by reading \"humanish\" part of the\n>      -+ * given Git URL.\n>      ++ * Retrieve the \"humanish\" basename of the given Git URL.\n>       + *\n>       + * For example:\n>       + * \t/path/to/repo.git => \"repo\"\n>       + * \thost.xz.foo/.git => \"foo\"\n>       + */\n>      -+char *guess_target_dir_from_git_url(const char *repo, int is_bundle, int is_bare);\n>      ++char *git_url_basename(const char *repo, int is_bundle, int is_bare);\n>       +void strip_dir_trailing_slashes(char *dir);\n>       +\n>        void setup_standard_excludes(struct dir_struct *dir);\n> 2:  11eea777ba ! 5:  a3aa25518d submodule--helper: convert the bulk of cmd_add() to C\n>      @@ builtin/submodule--helper.c: static int add_config(int argc, const char **argv,\n>       +\n>       +\tadd_data.repo = argv[0];\n>       +\tif (argc == 1)\n>      -+\t\tadd_data.sm_path = guess_target_dir_from_git_url(add_data.repo, 0, 0);\n>      ++\t\tadd_data.sm_path = git_url_basename(add_data.repo, 0, 0);\n>       +\telse\n>       +\t\tadd_data.sm_path = xstrdup(argv[1]);\n>       +\n> 3:  51393cd99b = 6:  9667159d4b submodule--helper: remove add-clone subcommand\n> 4:  50cedcd8a8 = 7:  dc87b5627a submodule--helper: remove add-config subcommand\n> 5:  02558da532 = 8:  ea08e4fbad submodule--helper: remove resolve-relative-url subcommand\n> \n"},{"id":"432275","messageId":"187083ab-a2e3-0933-5bff-9b409b2946ea@gmail.com","threadId":"56219","inReplyTo":"0752736f-11d5-103b-653f-a4bbe6436304@gmail.com","subject":"Re: [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Kaartic Sivaraam","fromEmail":"kaartic.sivaraam@gmail.com","sentAt":"2021-08-08T18:26:48Z","receivedAt":"2021-08-08T18:26:55Z","isPatch":true,"sender":{"key":"kaartic.sivaraam@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12448084?v=4"},"body":"On 08/08/21 11:11 pm, Kaartic Sivaraam wrote:\n> On 07/08/21 12:46 pm, Atharva Raykar wrote:\n>> Let's modify the interface to `compute_submodule_clone_url()` function\n>> by adding two more arguments, so that we can reuse this in various parts\n>> of `submodule--helper.c` that follow a common pattern, which is--read\n>> the remote url configuration of the superproject and then call\n>> `relative_url()`.\n>>\n>> This function is nearly identical to `resolve_relative_url()`, the only\n>> difference being the extra warning message. We can add a quiet flag to\n>> it, ...\n> \n> It took me a while to figure what \"it\" meant in the above sentence. Does it\n> refer to `compute_submodule_clone_url` or `resolve_relative_url`. After one\n> sees the patch and takes a look at `resolve_relative_url`, it's clear the \"it\"\n> indeed does refer to `resolve_relative_url`. But it might worth clarifying this\n> in the commit message itself.\n> \n> Certainly not worth a re-roll on its own. May be Junio could amend this while queing ?\n> \nActually, I just noticed two other things which might be re-roll worthy. Read on ...\n\n> -static char *compute_submodule_clone_url(const char *rel_url)\n> +static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n>  {\n>  \tchar *remoteurl, *relurl;\n\nI know this isn't new code. But there's already an argument names\n'rel_url'. So, a variable named 'relurl' in the same scope is making it\nhard to distinguish between these two. Could you also try distinguishing\nthese better by renaming 'relurl' to 'res' or something else?\n\n>  \tchar *remote = get_default_remote();\n> @@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)\n>  \n>  \tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n>  \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n> -\t\twarning(_(\"could not look up configuration '%s'. Assuming this repository is its own authoritative upstream.\"), remotesb.buf);\n> +\t\tif (!quiet)\n> +\t\t\twarning(_(\"could not look up configuration '%s'. \"\n> +\t\t\t\t  \"Assuming this repository is its own \"\n> +\t\t\t\t  \"authoritative upstream.\"),\n> +\t\t\t\tremotesb.buf);\n>  \t\tremoteurl = xgetcwd();\n>  \t}\n> -\trelurl = relative_url(remoteurl, rel_url, NULL);\n> +\trelurl = relative_url(remoteurl, rel_url, up_path);\n\nAfter reading 2/8 of the series, I just noticed that 'remoteurl' is always\ninitialized in 'resolve_realtive_url'. It is either initialized to the return\nvalue of 'xgetcwd' or retains its assigned value of 'NULL'. But it looks\nlike that's not the case here. 'remoteurl' could be used uninitialized\nwhen the above if block does not get executed which in turn could result in\nweird behaviour in case 'remoteurl' gets a value of anything other than 'NULL'\nat runtime.\n\nThis again has nothing to do with the change done in this patch. Regardless, it\nlooks like something worth correcting. Thus, I thought of pointing it out.\n\n>  \n>  \tfree(remote);\n>  \tfree(remoteurl);\n> @@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,\n>  \t\tif (starts_with_dot_dot_slash(url) ||\n>  \t\t    starts_with_dot_slash(url)) {\n>  \t\t\tchar *oldurl = url;\n> -\t\t\turl = compute_submodule_clone_url(oldurl);\n> +\t\t\turl = compute_submodule_clone_url(oldurl, NULL, 0);\n>  \t\t\tfree(oldurl);\n>  \t\t}\n>\n\n\n-- \nSivaraam\n"},{"id":"432276","messageId":"d37adee0-8636-548b-c581-16eaa417a05c@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-4-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v4 3/8] submodule--helper: remove repeated code in sync_submodule()","fromName":"Kaartic Sivaraam","fromEmail":"kaartic.sivaraam@gmail.com","sentAt":"2021-08-08T19:00:07Z","receivedAt":"2021-08-08T19:00:15Z","isPatch":true,"sender":{"key":"kaartic.sivaraam@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12448084?v=4"},"body":"On 07/08/21 12:46 pm, Atharva Raykar wrote:\n> This part of `sync_submodule()` is doing the same thing that\n> `compute_submodule_clone_url()` is doing. Let's reuse that helper here.\n> \n\nNice to see more code redundancy being removed. Now that we're using\n'compute_submodule_clone_url' in multiple places, I'm starting to\nwonder if the name still suits the helper. Yeah, I just started yet\nanother naming discussion ;-) I guess this one wouldn't be tough though.\nIt feels to me like 'resolve_relative_url' is a good enough name that\ndoesn't mislead readers by having 'clone_url' in its name. In case anyone\nelse has better name suggestions, they are indeed very welcome to suggest\nthose :-)\n\nOnce there's agreement on a particular name, I think the helper function\ncould be renamed. Possibly in a new patch next to this one.\n\n> Note that this change adds a small overhead where we allocate and free\n> the 'remote' twice, but that is a small price to pay for the higher\n> level of abstraction we get.\n> \n> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Shourya Shukla <periperidip@gmail.com>\n> ---\n>   builtin/submodule--helper.c | 16 +++-------------\n>   1 file changed, 3 insertions(+), 13 deletions(-)\n> \n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index f4b496bac6..9b676c12f8 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,\n>   \tif (sub && sub->url) {\n>   \t\tif (starts_with_dot_dot_slash(sub->url) ||\n>   \t\t    starts_with_dot_slash(sub->url)) {\n> -\t\t\tchar *remote_url, *up_path;\n> -\t\t\tchar *remote = get_default_remote();\n> -\t\t\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n> -\n> -\t\t\tif (git_config_get_string(sb.buf, &remote_url))\n> -\t\t\t\tremote_url = xgetcwd();\n> -\n> -\t\t\tup_path = get_up_path(path);\n> -\t\t\tsub_origin_url = relative_url(remote_url, sub->url, up_path);\n> -\t\t\tsuper_config_url = relative_url(remote_url, sub->url, NULL);\n> -\n> -\t\t\tfree(remote);\n> +\t\t\tchar *up_path = get_up_path(path);\n> +\t\t\tsub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);\n> +\t\t\tsuper_config_url = compute_submodule_clone_url(sub->url, NULL, 1);\n>   \t\t\tfree(up_path);\n> -\t\t\tfree(remote_url);\n>   \t\t} else {\n>   \t\t\tsub_origin_url = xstrdup(sub->url);\n>   \t\t\tsuper_config_url = xstrdup(sub->url);\n> \n\n\n-- \nSivaraam\n"},{"id":"432277","messageId":"1b731c17-7284-746d-331b-d0edd5823318@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-5-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c","fromName":"Kaartic Sivaraam","fromEmail":"kaartic.sivaraam@gmail.com","sentAt":"2021-08-08T19:23:31Z","receivedAt":"2021-08-08T19:23:44Z","isPatch":true,"sender":{"key":"kaartic.sivaraam@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12448084?v=4"},"body":"On 07/08/21 12:46 pm, Atharva Raykar wrote:\n>> [ ... ]\n>\n> diff --git a/dir.h b/dir.h\n> index b3e1a54a97..a4a6fd7371 100644\n> --- a/dir.h\n> +++ b/dir.h\n> @@ -453,6 +453,16 @@ static inline int is_dot_or_dotdot(const char *name)\n>   \n>   int is_empty_dir(const char *dir);\n>   \n> +/*\n> + * Retrieve the \"humanish\" basename of the given Git URL.\n> + *\n> + * For example:\n> + * \t/path/to/repo.git => \"repo\"\n> + * \thost.xz.foo/.git => \"foo\"\n> + */\n\nAre you sure about the examples here? I just tried and ...\n\n   - '/path/to/repo.git' gave me 'repo' like you said\n\n.. but ..\n\n   - 'host.xz.foo/.git' gives me 'host.xz.foo' instead of 'foo'.\n     I think you meant to have 'host.xz/foo.git' in the example.\n\nAlso, here's another example that might be useful to mention in the docstring:\n\n   - 'http://example.com/user/bar.baz' => 'bar.baz'\n\n> +char *git_url_basename(const char *repo, int is_bundle, int is_bare);\n> +void strip_dir_trailing_slashes(char *dir);\n> +\n>   void setup_standard_excludes(struct dir_struct *dir);\n>   \n>   char *get_sparse_checkout_filename(void);\n> \n\n-- \nSivaraam\n"},{"id":"432290","messageId":"m27dgvaxfj.fsf@gmail.com","threadId":"56219","inReplyTo":"187083ab-a2e3-0933-5bff-9b409b2946ea@gmail.com","subject":"Re: [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-09T07:29:04Z","receivedAt":"2021-08-09T07:29:15Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"\nKaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:\n\n> On 08/08/21 11:11 pm, Kaartic Sivaraam wrote:\n>> On 07/08/21 12:46 pm, Atharva Raykar wrote:\n>>> [...]\n>> It took me a while to figure what \"it\" meant in the above sentence. Does it\n>> refer to `compute_submodule_clone_url` or `resolve_relative_url`. After one\n>> sees the patch and takes a look at `resolve_relative_url`, it's clear the \"it\"\n>> indeed does refer to `resolve_relative_url`. But it might worth clarifying this\n>> in the commit message itself.\n>> Certainly not worth a re-roll on its own. May be Junio could amend this while\n>> queing ?\n>>\n> Actually, I just noticed two other things which might be re-roll worthy. Read on ...\n\nI'll keep re-rolling till the code is good, it's never a problem ;-)\n\n>> -static char *compute_submodule_clone_url(const char *rel_url)\n>> +static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n>>  {\n>>  \tchar *remoteurl, *relurl;\n>\n> I know this isn't new code. But there's already an argument names\n> 'rel_url'. So, a variable named 'relurl' in the same scope is making it\n> hard to distinguish between these two. Could you also try distinguishing\n> these better by renaming 'relurl' to 'res' or something else?\n\nOkay.\n\n>>  \tchar *remote = get_default_remote();\n>> @@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)\n>>   \tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n>>  \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n>> -\t\twarning(_(\"could not look up configuration '%s'. Assuming this repository is its own authoritative upstream.\"), remotesb.buf);\n>> +\t\tif (!quiet)\n>> +\t\t\twarning(_(\"could not look up configuration '%s'. \"\n>> +\t\t\t\t  \"Assuming this repository is its own \"\n>> +\t\t\t\t  \"authoritative upstream.\"),\n>> +\t\t\t\tremotesb.buf);\n>>  \t\tremoteurl = xgetcwd();\n>>  \t}\n>> -\trelurl = relative_url(remoteurl, rel_url, NULL);\n>> +\trelurl = relative_url(remoteurl, rel_url, up_path);\n>\n> After reading 2/8 of the series, I just noticed that 'remoteurl' is always\n> initialized in 'resolve_realtive_url'. It is either initialized to the return\n> value of 'xgetcwd' or retains its assigned value of 'NULL'. But it looks\n> like that's not the case here. 'remoteurl' could be used uninitialized\n> when the above if block does not get executed which in turn could result in\n> weird behaviour in case 'remoteurl' gets a value of anything other than 'NULL'\n> at runtime.\n>\n> This again has nothing to do with the change done in this patch. Regardless, it\n> looks like something worth correcting. Thus, I thought of pointing it out.\n>\n\nRight. I agree it should be corrected.\n\n>>   \tfree(remote);\n>>  \tfree(remoteurl);\n>> @@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,\n>>  \t\tif (starts_with_dot_dot_slash(url) ||\n>>  \t\t    starts_with_dot_slash(url)) {\n>>  \t\t\tchar *oldurl = url;\n>> -\t\t\turl = compute_submodule_clone_url(oldurl);\n>> +\t\t\turl = compute_submodule_clone_url(oldurl, NULL, 0);\n>>  \t\t\tfree(oldurl);\n>>  \t\t}\n>>\n"},{"id":"432291","messageId":"m24kbzax2o.fsf@gmail.com","threadId":"56219","inReplyTo":"d37adee0-8636-548b-c581-16eaa417a05c@gmail.com","subject":"Re: [GSoC] [PATCH v4 3/8] submodule--helper: remove repeated code in sync_submodule()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-09T07:36:47Z","receivedAt":"2021-08-09T07:36:55Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"\nKaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:\n\n> On 07/08/21 12:46 pm, Atharva Raykar wrote:\n>> This part of `sync_submodule()` is doing the same thing that\n>> `compute_submodule_clone_url()` is doing. Let's reuse that helper here.\n>>\n>\n> Nice to see more code redundancy being removed. Now that we're using\n> 'compute_submodule_clone_url' in multiple places, I'm starting to\n> wonder if the name still suits the helper. Yeah, I just started yet\n> another naming discussion ;-) I guess this one wouldn't be tough though.\n> It feels to me like 'resolve_relative_url' is a good enough name that\n> doesn't mislead readers by having 'clone_url' in its name. In case anyone\n> else has better name suggestions, they are indeed very welcome to suggest\n> those :-)\n>\n> Once there's agreement on a particular name, I think the helper function\n> could be renamed. Possibly in a new patch next to this one.\n\nI don't mind the rename back to resolve_relative_url(), although it\ndefinitely has to come in a separate patch. I didn't want to create a\nsituation where readers will be confused about what actually happened\nwith that function. I felt a thing might happen if I repurpose it from\nsubcommand to internal helper in the same patch.\n\n>> Note that this change adds a small overhead where we allocate and free\n>> the 'remote' twice, but that is a small price to pay for the higher\n>> level of abstraction we get.\n>> Signed-off-by: Atharva Raykar <raykar.ath@gmail.com>\n>> Mentored-by: Christian Couder <christian.couder@gmail.com>\n>> Mentored-by: Shourya Shukla <periperidip@gmail.com>\n>> ---\n>>   builtin/submodule--helper.c | 16 +++-------------\n>>   1 file changed, 3 insertions(+), 13 deletions(-)\n>> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n>> index f4b496bac6..9b676c12f8 100644\n>> --- a/builtin/submodule--helper.c\n>> +++ b/builtin/submodule--helper.c\n>> @@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,\n>>   \tif (sub && sub->url) {\n>>   \t\tif (starts_with_dot_dot_slash(sub->url) ||\n>>   \t\t    starts_with_dot_slash(sub->url)) {\n>> -\t\t\tchar *remote_url, *up_path;\n>> -\t\t\tchar *remote = get_default_remote();\n>> -\t\t\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n>> -\n>> -\t\t\tif (git_config_get_string(sb.buf, &remote_url))\n>> -\t\t\t\tremote_url = xgetcwd();\n>> -\n>> -\t\t\tup_path = get_up_path(path);\n>> -\t\t\tsub_origin_url = relative_url(remote_url, sub->url, up_path);\n>> -\t\t\tsuper_config_url = relative_url(remote_url, sub->url, NULL);\n>> -\n>> -\t\t\tfree(remote);\n>> +\t\t\tchar *up_path = get_up_path(path);\n>> +\t\t\tsub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);\n>> +\t\t\tsuper_config_url = compute_submodule_clone_url(sub->url, NULL, 1);\n>>   \t\t\tfree(up_path);\n>> -\t\t\tfree(remote_url);\n>>   \t\t} else {\n>>   \t\t\tsub_origin_url = xstrdup(sub->url);\n>>   \t\t\tsuper_config_url = xstrdup(sub->url);\n>>\n"},{"id":"432294","messageId":"m21r73avvx.fsf@gmail.com","threadId":"56219","inReplyTo":"1b731c17-7284-746d-331b-d0edd5823318@gmail.com","subject":"Re: [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-09T08:02:26Z","receivedAt":"2021-08-09T08:02:41Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"\nKaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:\n\n> On 07/08/21 12:46 pm, Atharva Raykar wrote:\n>>> [ ... ]\n>>\n>> diff --git a/dir.h b/dir.h\n>> index b3e1a54a97..a4a6fd7371 100644\n>> --- a/dir.h\n>> +++ b/dir.h\n>> @@ -453,6 +453,16 @@ static inline int is_dot_or_dotdot(const char *name)\n>>     int is_empty_dir(const char *dir);\n>>   +/*\n>> + * Retrieve the \"humanish\" basename of the given Git URL.\n>> + *\n>> + * For example:\n>> + * \t/path/to/repo.git => \"repo\"\n>> + * \thost.xz.foo/.git => \"foo\"\n>> + */\n>\n> Are you sure about the examples here? I just tried and ...\n>\n>   - '/path/to/repo.git' gave me 'repo' like you said\n>\n> .. but ..\n>\n>   - 'host.xz.foo/.git' gives me 'host.xz.foo' instead of 'foo'.\n>     I think you meant to have 'host.xz/foo.git' in the example.\n\nYikes! I meant 'host.xz:foo/.git'. That should give us 'foo'. Thanks for\nthe correction.\n\n> Also, here's another example that might be useful to mention in the docstring:\n>\n>   - 'http://example.com/user/bar.baz' => 'bar.baz'\n\nYeah, especially since that's probably the most familiar example for\nmost end users.\n\n>> +char *git_url_basename(const char *repo, int is_bundle, int is_bare);\n>> +void strip_dir_trailing_slashes(char *dir);\n>> +\n>>   void setup_standard_excludes(struct dir_struct *dir);\n>>     char *get_sparse_checkout_filename(void);\n>>\n"},{"id":"432301","messageId":"m2wnov9f8s.fsf@gmail.com","threadId":"56219","inReplyTo":"m27dgvaxfj.fsf@gmail.com","subject":"Re: [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-09T08:47:15Z","receivedAt":"2021-08-09T08:47:25Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"\nAtharva Raykar <raykar.ath@gmail.com> writes:\n\n> Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:\n>\n>> On 08/08/21 11:11 pm, Kaartic Sivaraam wrote:\n>>> On 07/08/21 12:46 pm, Atharva Raykar wrote:\n>>> [...]\n>>>  \tchar *remote = get_default_remote();\n>>> @@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)\n>>>   \tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n>>>  \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n>>> -\t\twarning(_(\"could not look up configuration '%s'. Assuming this repository is its own authoritative upstream.\"), remotesb.buf);\n>>> +\t\tif (!quiet)\n>>> +\t\t\twarning(_(\"could not look up configuration '%s'. \"\n>>> +\t\t\t\t  \"Assuming this repository is its own \"\n>>> +\t\t\t\t  \"authoritative upstream.\"),\n>>> +\t\t\t\tremotesb.buf);\n>>>  \t\tremoteurl = xgetcwd();\n>>>  \t}\n>>> -\trelurl = relative_url(remoteurl, rel_url, NULL);\n>>> +\trelurl = relative_url(remoteurl, rel_url, up_path);\n>>\n>> After reading 2/8 of the series, I just noticed that 'remoteurl' is always\n>> initialized in 'resolve_realtive_url'. It is either initialized to the return\n>> value of 'xgetcwd' or retains its assigned value of 'NULL'. But it looks\n>> like that's not the case here. 'remoteurl' could be used uninitialized\n>> when the above if block does not get executed which in turn could result in\n>> weird behaviour in case 'remoteurl' gets a value of anything other than 'NULL'\n>> at runtime.\n>>\n>> This again has nothing to do with the change done in this patch. Regardless, it\n>> looks like something worth correcting. Thus, I thought of pointing it out.\n>>\n>\n> Right. I agree it should be corrected.\n\nActually on having another look, I'm not sure if we need to assign NULL\nto 'remoteurl' at all.\n\nThe 'if (git_config_get_string(...))' on success will allocate\n'remoteurl'. If it fails, it will be given the return value of\n'xgetcwd()'. There is nothing in the config API docs that suggest a\nsuccess mode for the git_config_get_*() functions that will assign\nnothing to the buffer we give it. Therefore, by the time we get to the\nvariable's first use in the 'relative_url()' function, we are guaranteed\nto have a well-defined value.\n\nIt seems to me that the original 'resolve_relative_url()' had an\nunnecessary NULL initialization.\n"},{"id":"432362","messageId":"20210810114641.27188-1-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210807071613.99610-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v5 0/9] submodule: convert the rest of 'add' to C","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-10T11:46:32Z","receivedAt":"2021-08-10T11:47:36Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"NOTE: This series uses (ar/submodule-add-config):\nhttps://lore.kernel.org/git/20210806140431.92018-1-raykar.ath@gmail.com/\n\nSince v4:\n* Rename a local variable in 'compute_submodule_clone_url()' to reduce ambiguity.\n* Add a new patch that renames 'compute_submodule_clone_url()' to\n  'resolve_relative_url()' to better convey its use. We add it at the end after\n  the 'resolve-relative-url' subcommand is removed so that there is no confusion\n  as to what that function name binds to.\n* Fix incorrect example in the docstring for 'git_url_basename()'. Also add\n  another example for more clarity.\n\nAlso since this query of mine got buried in the revisions, I shall include it\nhere again:\n\nQuestions about the cache API used in [PATCH 5/9]:\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  1. What is the difference between 'read_cache()' and 'read_cache_preload()'?\n     From what I can tell, the latter optimistically preloads the index stat\n     data. Is there any reason to use 'read_cache()' over\n     'read_cache_preload()'?\n  2. Which one is more appropriate for use in 'die_on_index_match()'?\n\nFetch-it-Via:\ngit fetch https://github.com/tfidfwastaken/git submodule-helper-add-list-5\n\nAtharva Raykar (9):\n  submodule--helper: add options for compute_submodule_clone_url()\n  submodule--helper: refactor resolve_relative_url() helper\n  submodule--helper: remove repeated code in sync_submodule()\n  dir: libify and export helper functions from clone.c\n  submodule--helper: convert the bulk of cmd_add() to C\n  submodule--helper: remove add-clone subcommand\n  submodule--helper: remove add-config subcommand\n  submodule--helper: remove resolve-relative-url subcommand\n  submodule--helper: rename compute_submodule_clone_url()\n\n builtin/clone.c             | 118 +-------------\n builtin/submodule--helper.c | 307 +++++++++++++++++++-----------------\n dir.c                       | 114 +++++++++++++\n dir.h                       |  11 ++\n git-submodule.sh            |  96 +----------\n 5 files changed, 291 insertions(+), 355 deletions(-)\n\nRange-diff against v4:\n 1:  75edf24186 !  1:  78e19c4b01 submodule--helper: add options for compute_submodule_clone_url()\n    @@ Commit message\n         `resolve_relative_url()` by using this function, something we will do in\n         the next patch.\n     \n    +    We also rename the local variable 'relurl' to avoid potential confusion\n    +    with the 'rel_url' parameter while we are at it.\n    +\n         Having this functionality factored out will be useful for converting the\n         rest of `submodule add` in subsequent patches.\n     \n    @@ builtin/submodule--helper.c: static int module_foreach(int argc, const char **ar\n     -static char *compute_submodule_clone_url(const char *rel_url)\n     +static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n      {\n    - \tchar *remoteurl, *relurl;\n    +-\tchar *remoteurl, *relurl;\n    ++\tchar *remoteurl, *resolved_url;\n      \tchar *remote = get_default_remote();\n    -@@ builtin/submodule--helper.c: static char *compute_submodule_clone_url(const char *rel_url)\n    + \tstruct strbuf remotesb = STRBUF_INIT;\n      \n      \tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n      \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n    @@ builtin/submodule--helper.c: static char *compute_submodule_clone_url(const char\n      \t\tremoteurl = xgetcwd();\n      \t}\n     -\trelurl = relative_url(remoteurl, rel_url, NULL);\n    -+\trelurl = relative_url(remoteurl, rel_url, up_path);\n    ++\tresolved_url = relative_url(remoteurl, rel_url, up_path);\n      \n      \tfree(remote);\n      \tfree(remoteurl);\n    + \tstrbuf_release(&remotesb);\n    + \n    +-\treturn relurl;\n    ++\treturn resolved_url;\n    + }\n    + \n    + struct init_cb {\n     @@ builtin/submodule--helper.c: static void init_submodule(const char *path, const char *prefix,\n      \t\tif (starts_with_dot_dot_slash(url) ||\n      \t\t    starts_with_dot_slash(url)) {\n 2:  8e7a3e727a !  2:  faadf74ec1 submodule--helper: refactor resolve_relative_url() helper\n    @@ builtin/submodule--helper.c: static char *relative_url(const char *remote_url,\n     +static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n      {\n     -\tchar *remoteurl = NULL;\n    -+\tchar *remoteurl, *relurl;\n    ++\tchar *remoteurl, *resolved_url;\n      \tchar *remote = get_default_remote();\n     +\tstruct strbuf remotesb = STRBUF_INIT;\n     +\n    @@ builtin/submodule--helper.c: static char *relative_url(const char *remote_url,\n     +\t\t\t\tremotesb.buf);\n     +\t\tremoteurl = xgetcwd();\n     +\t}\n    -+\trelurl = relative_url(remoteurl, rel_url, up_path);\n    ++\tresolved_url = relative_url(remoteurl, rel_url, up_path);\n     +\n     +\tfree(remote);\n     +\tfree(remoteurl);\n     +\tstrbuf_release(&remotesb);\n     +\n    -+\treturn relurl;\n    ++\treturn resolved_url;\n     +}\n     +\n     +static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n    @@ builtin/submodule--helper.c: static int module_foreach(int argc, const char **ar\n      \n     -static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n     -{\n    --\tchar *remoteurl, *relurl;\n    +-\tchar *remoteurl, *resolved_url;\n     -\tchar *remote = get_default_remote();\n     -\tstruct strbuf remotesb = STRBUF_INIT;\n     -\n    @@ builtin/submodule--helper.c: static int module_foreach(int argc, const char **ar\n     -\t\t\t\tremotesb.buf);\n     -\t\tremoteurl = xgetcwd();\n     -\t}\n    --\trelurl = relative_url(remoteurl, rel_url, up_path);\n    +-\tresolved_url = relative_url(remoteurl, rel_url, up_path);\n     -\n     -\tfree(remote);\n     -\tfree(remoteurl);\n     -\tstrbuf_release(&remotesb);\n     -\n    --\treturn relurl;\n    +-\treturn resolved_url;\n     -}\n     -\n      struct init_cb {\n 3:  82961ddd02 =  3:  d2127bd09a submodule--helper: remove repeated code in sync_submodule()\n 4:  fa97d6801e !  4:  4b05f93def dir: libify and export helper functions from clone.c\n    @@ dir.h: static inline int is_dot_or_dotdot(const char *name)\n     + *\n     + * For example:\n     + * \t/path/to/repo.git => \"repo\"\n    -+ * \thost.xz.foo/.git => \"foo\"\n    ++ * \thost.xz:foo/.git => \"foo\"\n    ++ * \thttp://example.com/user/bar.baz => \"bar.baz\"\n     + */\n     +char *git_url_basename(const char *repo, int is_bundle, int is_bare);\n     +void strip_dir_trailing_slashes(char *dir);\n 5:  a3aa25518d =  5:  1491a011b0 submodule--helper: convert the bulk of cmd_add() to C\n 6:  9667159d4b =  6:  5d5d07a6ba submodule--helper: remove add-clone subcommand\n 7:  dc87b5627a =  7:  0ea27c2a15 submodule--helper: remove add-config subcommand\n 8:  ea08e4fbad !  8:  6bd2571f73 submodule--helper: remove resolve-relative-url subcommand\n    @@ Commit message\n     \n      ## builtin/submodule--helper.c ##\n     @@ builtin/submodule--helper.c: static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat\n    - \treturn relurl;\n    + \treturn resolved_url;\n      }\n      \n     -static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n -:  ---------- >  9:  14a05a0c1d submodule--helper: rename compute_submodule_clone_url()\n-- \n2.32.0\n\n"},{"id":"432363","messageId":"20210810114641.27188-2-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210810114641.27188-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v5 1/9] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-10T11:46:33Z","receivedAt":"2021-08-10T11:47:42Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Let's modify the interface to `compute_submodule_clone_url()` function\nby adding two more arguments, so that we can reuse this in various parts\nof `submodule--helper.c` that follow a common pattern, which is--read\nthe remote url configuration of the superproject and then call\n`relative_url()`.\n\nThis function is nearly identical to `resolve_relative_url()`, the only\ndifference being the extra warning message. We can add a quiet flag to\nit, to suppress that warning when not needed, and then refactor\n`resolve_relative_url()` by using this function, something we will do in\nthe next patch.\n\nWe also rename the local variable 'relurl' to avoid potential confusion\nwith the 'rel_url' parameter while we are at it.\n\nHaving this functionality factored out will be useful for converting the\nrest of `submodule add` in subsequent patches.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 18 +++++++++++-------\n 1 file changed, 11 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 6891480013..d850b30fce 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -590,24 +590,28 @@ static int module_foreach(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n-static char *compute_submodule_clone_url(const char *rel_url)\n+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n {\n-\tchar *remoteurl, *relurl;\n+\tchar *remoteurl, *resolved_url;\n \tchar *remote = get_default_remote();\n \tstruct strbuf remotesb = STRBUF_INIT;\n \n \tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n-\t\twarning(_(\"could not look up configuration '%s'. Assuming this repository is its own authoritative upstream.\"), remotesb.buf);\n+\t\tif (!quiet)\n+\t\t\twarning(_(\"could not look up configuration '%s'. \"\n+\t\t\t\t  \"Assuming this repository is its own \"\n+\t\t\t\t  \"authoritative upstream.\"),\n+\t\t\t\tremotesb.buf);\n \t\tremoteurl = xgetcwd();\n \t}\n-\trelurl = relative_url(remoteurl, rel_url, NULL);\n+\tresolved_url = relative_url(remoteurl, rel_url, up_path);\n \n \tfree(remote);\n \tfree(remoteurl);\n \tstrbuf_release(&remotesb);\n \n-\treturn relurl;\n+\treturn resolved_url;\n }\n \n struct init_cb {\n@@ -660,7 +664,7 @@ static void init_submodule(const char *path, const char *prefix,\n \t\tif (starts_with_dot_dot_slash(url) ||\n \t\t    starts_with_dot_slash(url)) {\n \t\t\tchar *oldurl = url;\n-\t\t\turl = compute_submodule_clone_url(oldurl);\n+\t\t\turl = compute_submodule_clone_url(oldurl, NULL, 0);\n \t\t\tfree(oldurl);\n \t\t}\n \n@@ -2134,7 +2138,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \tif (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {\n \t\tif (starts_with_dot_slash(sub->url) ||\n \t\t    starts_with_dot_dot_slash(sub->url)) {\n-\t\t\turl = compute_submodule_clone_url(sub->url);\n+\t\t\turl = compute_submodule_clone_url(sub->url, NULL, 0);\n \t\t\tneed_free_url = 1;\n \t\t} else\n \t\t\turl = sub->url;\n-- \n2.32.0\n\n"},{"id":"432364","messageId":"20210810114641.27188-4-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210810114641.27188-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v5 3/9] submodule--helper: remove repeated code in sync_submodule()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-10T11:46:35Z","receivedAt":"2021-08-10T11:48:04Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"This part of `sync_submodule()` is doing the same thing that\n`compute_submodule_clone_url()` is doing. Let's reuse that helper here.\n\nNote that this change adds a small overhead where we allocate and free\nthe 'remote' twice, but that is a small price to pay for the higher\nlevel of abstraction we get.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 16 +++-------------\n 1 file changed, 3 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex fe126cdee9..da77248948 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1373,20 +1373,10 @@ static void sync_submodule(const char *path, const char *prefix,\n \tif (sub && sub->url) {\n \t\tif (starts_with_dot_dot_slash(sub->url) ||\n \t\t    starts_with_dot_slash(sub->url)) {\n-\t\t\tchar *remote_url, *up_path;\n-\t\t\tchar *remote = get_default_remote();\n-\t\t\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n-\n-\t\t\tif (git_config_get_string(sb.buf, &remote_url))\n-\t\t\t\tremote_url = xgetcwd();\n-\n-\t\t\tup_path = get_up_path(path);\n-\t\t\tsub_origin_url = relative_url(remote_url, sub->url, up_path);\n-\t\t\tsuper_config_url = relative_url(remote_url, sub->url, NULL);\n-\n-\t\t\tfree(remote);\n+\t\t\tchar *up_path = get_up_path(path);\n+\t\t\tsub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);\n+\t\t\tsuper_config_url = compute_submodule_clone_url(sub->url, NULL, 1);\n \t\t\tfree(up_path);\n-\t\t\tfree(remote_url);\n \t\t} else {\n \t\t\tsub_origin_url = xstrdup(sub->url);\n \t\t\tsuper_config_url = xstrdup(sub->url);\n-- \n2.32.0\n\n"},{"id":"432365","messageId":"20210810114641.27188-3-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210810114641.27188-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v5 2/9] submodule--helper: refactor resolve_relative_url() helper","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-10T11:46:34Z","receivedAt":"2021-08-10T11:48:06Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Refactor the helper function to resolve a relative url, by reusing the\nexisting `compute_submodule_clone_url()` function.\n\n`compute_submodule_clone_url()` performs the same work that\n`resolve_relative_url()` is doing, so we eliminate this code repetition\nby moving the former function's definition up, and calling it inside\n`resolve_relative_url()`.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 61 +++++++++++++++----------------------\n 1 file changed, 25 insertions(+), 36 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex d850b30fce..fe126cdee9 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -199,33 +199,46 @@ static char *relative_url(const char *remote_url,\n \treturn strbuf_detach(&sb, NULL);\n }\n \n+static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n+{\n+\tchar *remoteurl, *resolved_url;\n+\tchar *remote = get_default_remote();\n+\tstruct strbuf remotesb = STRBUF_INIT;\n+\n+\tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n+\tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n+\t\tif (!quiet)\n+\t\t\twarning(_(\"could not look up configuration '%s'. \"\n+\t\t\t\t  \"Assuming this repository is its own \"\n+\t\t\t\t  \"authoritative upstream.\"),\n+\t\t\t\tremotesb.buf);\n+\t\tremoteurl = xgetcwd();\n+\t}\n+\tresolved_url = relative_url(remoteurl, rel_url, up_path);\n+\n+\tfree(remote);\n+\tfree(remoteurl);\n+\tstrbuf_release(&remotesb);\n+\n+\treturn resolved_url;\n+}\n+\n static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n {\n-\tchar *remoteurl = NULL;\n-\tchar *remote = get_default_remote();\n \tconst char *up_path = NULL;\n \tchar *res;\n \tconst char *url;\n-\tstruct strbuf sb = STRBUF_INIT;\n \n \tif (argc != 2 && argc != 3)\n \t\tdie(\"resolve-relative-url only accepts one or two arguments\");\n \n \turl = argv[1];\n-\tstrbuf_addf(&sb, \"remote.%s.url\", remote);\n-\tfree(remote);\n-\n-\tif (git_config_get_string(sb.buf, &remoteurl))\n-\t\t/* the repository is its own authoritative upstream */\n-\t\tremoteurl = xgetcwd();\n-\n \tif (argc == 3)\n \t\tup_path = argv[2];\n \n-\tres = relative_url(remoteurl, url, up_path);\n+\tres = compute_submodule_clone_url(url, up_path, 1);\n \tputs(res);\n \tfree(res);\n-\tfree(remoteurl);\n \treturn 0;\n }\n \n@@ -590,30 +603,6 @@ static int module_foreach(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n-{\n-\tchar *remoteurl, *resolved_url;\n-\tchar *remote = get_default_remote();\n-\tstruct strbuf remotesb = STRBUF_INIT;\n-\n-\tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n-\tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n-\t\tif (!quiet)\n-\t\t\twarning(_(\"could not look up configuration '%s'. \"\n-\t\t\t\t  \"Assuming this repository is its own \"\n-\t\t\t\t  \"authoritative upstream.\"),\n-\t\t\t\tremotesb.buf);\n-\t\tremoteurl = xgetcwd();\n-\t}\n-\tresolved_url = relative_url(remoteurl, rel_url, up_path);\n-\n-\tfree(remote);\n-\tfree(remoteurl);\n-\tstrbuf_release(&remotesb);\n-\n-\treturn resolved_url;\n-}\n-\n struct init_cb {\n \tconst char *prefix;\n \tunsigned int flags;\n-- \n2.32.0\n\n"},{"id":"432366","messageId":"20210810114641.27188-5-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210810114641.27188-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v5 4/9] dir: libify and export helper functions from clone.c","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-10T11:46:36Z","receivedAt":"2021-08-10T11:48:07Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"These functions can be useful to other parts of Git. Let's move them to\ndir.c, while renaming them to be make their functionality more explicit.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/clone.c | 118 +-----------------------------------------------\n dir.c           | 114 ++++++++++++++++++++++++++++++++++++++++++++++\n dir.h           |  11 +++++\n 3 files changed, 127 insertions(+), 116 deletions(-)\n\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 66fe66679c..5ba24b7ae7 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -217,120 +217,6 @@ static char *get_repo_path(const char *repo, int *is_bundle)\n \treturn canon;\n }\n \n-static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)\n-{\n-\tconst char *end = repo + strlen(repo), *start, *ptr;\n-\tsize_t len;\n-\tchar *dir;\n-\n-\t/*\n-\t * Skip scheme.\n-\t */\n-\tstart = strstr(repo, \"://\");\n-\tif (start == NULL)\n-\t\tstart = repo;\n-\telse\n-\t\tstart += 3;\n-\n-\t/*\n-\t * Skip authentication data. The stripping does happen\n-\t * greedily, such that we strip up to the last '@' inside\n-\t * the host part.\n-\t */\n-\tfor (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {\n-\t\tif (*ptr == '@')\n-\t\t\tstart = ptr + 1;\n-\t}\n-\n-\t/*\n-\t * Strip trailing spaces, slashes and /.git\n-\t */\n-\twhile (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))\n-\t\tend--;\n-\tif (end - start > 5 && is_dir_sep(end[-5]) &&\n-\t    !strncmp(end - 4, \".git\", 4)) {\n-\t\tend -= 5;\n-\t\twhile (start < end && is_dir_sep(end[-1]))\n-\t\t\tend--;\n-\t}\n-\n-\t/*\n-\t * Strip trailing port number if we've got only a\n-\t * hostname (that is, there is no dir separator but a\n-\t * colon). This check is required such that we do not\n-\t * strip URI's like '/foo/bar:2222.git', which should\n-\t * result in a dir '2222' being guessed due to backwards\n-\t * compatibility.\n-\t */\n-\tif (memchr(start, '/', end - start) == NULL\n-\t    && memchr(start, ':', end - start) != NULL) {\n-\t\tptr = end;\n-\t\twhile (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')\n-\t\t\tptr--;\n-\t\tif (start < ptr && ptr[-1] == ':')\n-\t\t\tend = ptr - 1;\n-\t}\n-\n-\t/*\n-\t * Find last component. To remain backwards compatible we\n-\t * also regard colons as path separators, such that\n-\t * cloning a repository 'foo:bar.git' would result in a\n-\t * directory 'bar' being guessed.\n-\t */\n-\tptr = end;\n-\twhile (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')\n-\t\tptr--;\n-\tstart = ptr;\n-\n-\t/*\n-\t * Strip .{bundle,git}.\n-\t */\n-\tlen = end - start;\n-\tstrip_suffix_mem(start, &len, is_bundle ? \".bundle\" : \".git\");\n-\n-\tif (!len || (len == 1 && *start == '/'))\n-\t\tdie(_(\"No directory name could be guessed.\\n\"\n-\t\t      \"Please specify a directory on the command line\"));\n-\n-\tif (is_bare)\n-\t\tdir = xstrfmt(\"%.*s.git\", (int)len, start);\n-\telse\n-\t\tdir = xstrndup(start, len);\n-\t/*\n-\t * Replace sequences of 'control' characters and whitespace\n-\t * with one ascii space, remove leading and trailing spaces.\n-\t */\n-\tif (*dir) {\n-\t\tchar *out = dir;\n-\t\tint prev_space = 1 /* strip leading whitespace */;\n-\t\tfor (end = dir; *end; ++end) {\n-\t\t\tchar ch = *end;\n-\t\t\tif ((unsigned char)ch < '\\x20')\n-\t\t\t\tch = '\\x20';\n-\t\t\tif (isspace(ch)) {\n-\t\t\t\tif (prev_space)\n-\t\t\t\t\tcontinue;\n-\t\t\t\tprev_space = 1;\n-\t\t\t} else\n-\t\t\t\tprev_space = 0;\n-\t\t\t*out++ = ch;\n-\t\t}\n-\t\t*out = '\\0';\n-\t\tif (out > dir && prev_space)\n-\t\t\tout[-1] = '\\0';\n-\t}\n-\treturn dir;\n-}\n-\n-static void strip_trailing_slashes(char *dir)\n-{\n-\tchar *end = dir + strlen(dir);\n-\n-\twhile (dir < end - 1 && is_dir_sep(end[-1]))\n-\t\tend--;\n-\t*end = '\\0';\n-}\n-\n static int add_one_reference(struct string_list_item *item, void *cb_data)\n {\n \tstruct strbuf err = STRBUF_INIT;\n@@ -1041,8 +927,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \tif (argc == 2)\n \t\tdir = xstrdup(argv[1]);\n \telse\n-\t\tdir = guess_dir_name(repo_name, is_bundle, option_bare);\n-\tstrip_trailing_slashes(dir);\n+\t\tdir = git_url_basename(repo_name, is_bundle, option_bare);\n+\tstrip_dir_trailing_slashes(dir);\n \n \tdest_exists = path_exists(dir);\n \tif (dest_exists && !is_empty_dir(dir))\ndiff --git a/dir.c b/dir.c\nindex 03c4d21267..6d26db3189 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -2970,6 +2970,120 @@ int is_empty_dir(const char *path)\n \treturn ret;\n }\n \n+char *git_url_basename(const char *repo, int is_bundle, int is_bare)\n+{\n+\tconst char *end = repo + strlen(repo), *start, *ptr;\n+\tsize_t len;\n+\tchar *dir;\n+\n+\t/*\n+\t * Skip scheme.\n+\t */\n+\tstart = strstr(repo, \"://\");\n+\tif (start == NULL)\n+\t\tstart = repo;\n+\telse\n+\t\tstart += 3;\n+\n+\t/*\n+\t * Skip authentication data. The stripping does happen\n+\t * greedily, such that we strip up to the last '@' inside\n+\t * the host part.\n+\t */\n+\tfor (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {\n+\t\tif (*ptr == '@')\n+\t\t\tstart = ptr + 1;\n+\t}\n+\n+\t/*\n+\t * Strip trailing spaces, slashes and /.git\n+\t */\n+\twhile (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))\n+\t\tend--;\n+\tif (end - start > 5 && is_dir_sep(end[-5]) &&\n+\t    !strncmp(end - 4, \".git\", 4)) {\n+\t\tend -= 5;\n+\t\twhile (start < end && is_dir_sep(end[-1]))\n+\t\t\tend--;\n+\t}\n+\n+\t/*\n+\t * Strip trailing port number if we've got only a\n+\t * hostname (that is, there is no dir separator but a\n+\t * colon). This check is required such that we do not\n+\t * strip URI's like '/foo/bar:2222.git', which should\n+\t * result in a dir '2222' being guessed due to backwards\n+\t * compatibility.\n+\t */\n+\tif (memchr(start, '/', end - start) == NULL\n+\t    && memchr(start, ':', end - start) != NULL) {\n+\t\tptr = end;\n+\t\twhile (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')\n+\t\t\tptr--;\n+\t\tif (start < ptr && ptr[-1] == ':')\n+\t\t\tend = ptr - 1;\n+\t}\n+\n+\t/*\n+\t * Find last component. To remain backwards compatible we\n+\t * also regard colons as path separators, such that\n+\t * cloning a repository 'foo:bar.git' would result in a\n+\t * directory 'bar' being guessed.\n+\t */\n+\tptr = end;\n+\twhile (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')\n+\t\tptr--;\n+\tstart = ptr;\n+\n+\t/*\n+\t * Strip .{bundle,git}.\n+\t */\n+\tlen = end - start;\n+\tstrip_suffix_mem(start, &len, is_bundle ? \".bundle\" : \".git\");\n+\n+\tif (!len || (len == 1 && *start == '/'))\n+\t\tdie(_(\"No directory name could be guessed.\\n\"\n+\t\t      \"Please specify a directory on the command line\"));\n+\n+\tif (is_bare)\n+\t\tdir = xstrfmt(\"%.*s.git\", (int)len, start);\n+\telse\n+\t\tdir = xstrndup(start, len);\n+\t/*\n+\t * Replace sequences of 'control' characters and whitespace\n+\t * with one ascii space, remove leading and trailing spaces.\n+\t */\n+\tif (*dir) {\n+\t\tchar *out = dir;\n+\t\tint prev_space = 1 /* strip leading whitespace */;\n+\t\tfor (end = dir; *end; ++end) {\n+\t\t\tchar ch = *end;\n+\t\t\tif ((unsigned char)ch < '\\x20')\n+\t\t\t\tch = '\\x20';\n+\t\t\tif (isspace(ch)) {\n+\t\t\t\tif (prev_space)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tprev_space = 1;\n+\t\t\t} else\n+\t\t\t\tprev_space = 0;\n+\t\t\t*out++ = ch;\n+\t\t}\n+\t\t*out = '\\0';\n+\t\tif (out > dir && prev_space)\n+\t\t\tout[-1] = '\\0';\n+\t}\n+\treturn dir;\n+}\n+\n+void strip_dir_trailing_slashes(char *dir)\n+{\n+\tchar *end = dir + strlen(dir);\n+\n+\twhile (dir < end - 1 && is_dir_sep(end[-1]))\n+\t\tend--;\n+\t*end = '\\0';\n+}\n+\n static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)\n {\n \tDIR *dir;\ndiff --git a/dir.h b/dir.h\nindex b3e1a54a97..63ff04f5ac 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -453,6 +453,17 @@ static inline int is_dot_or_dotdot(const char *name)\n \n int is_empty_dir(const char *dir);\n \n+/*\n+ * Retrieve the \"humanish\" basename of the given Git URL.\n+ *\n+ * For example:\n+ * \t/path/to/repo.git => \"repo\"\n+ * \thost.xz:foo/.git => \"foo\"\n+ * \thttp://example.com/user/bar.baz => \"bar.baz\"\n+ */\n+char *git_url_basename(const char *repo, int is_bundle, int is_bare);\n+void strip_dir_trailing_slashes(char *dir);\n+\n void setup_standard_excludes(struct dir_struct *dir);\n \n char *get_sparse_checkout_filename(void);\n-- \n2.32.0\n\n"},{"id":"432367","messageId":"20210810114641.27188-6-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210810114641.27188-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v5 5/9] submodule--helper: convert the bulk of cmd_add() to C","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-10T11:46:37Z","receivedAt":"2021-08-10T11:48:09Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Introduce the 'add' subcommand to `submodule--helper.c` that does all\nthe work 'submodule add' past the parsing of flags.\n\nWe also remove the constness of the sm_path field of the `add_data`\nstruct. This is needed so that it can be modified by\nnormalize_path_copy().\n\nAs with the previous conversions, this is meant to be a faithful\nconversion with no modification to the behaviour of `submodule add`.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nHelped-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\nBased-on-patch-by: Shourya Shukla <periperidip@gmail.com>\nBased-on-patch-by: Prathamesh Chavan <pc44800@gmail.com>\n---\n builtin/submodule--helper.c | 165 +++++++++++++++++++++++++++++++++++-\n git-submodule.sh            |  96 +--------------------\n 2 files changed, 166 insertions(+), 95 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex da77248948..bbc5b4d9fd 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2748,7 +2748,7 @@ struct add_data {\n \tconst char *prefix;\n \tconst char *branch;\n \tconst char *reference_path;\n-\tconst char *sm_path;\n+\tchar *sm_path;\n \tconst char *sm_name;\n \tconst char *repo;\n \tconst char *realrepo;\n@@ -3046,6 +3046,168 @@ static int add_config(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static void die_on_index_match(const char *path, int force)\n+{\n+\tstruct pathspec ps;\n+\tconst char *args[] = { path, NULL };\n+\tparse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);\n+\n+\tif (read_cache_preload(NULL) < 0)\n+\t\tdie(_(\"index file corrupt\"));\n+\n+\tif (ps.nr) {\n+\t\tint i;\n+\t\tchar *ps_matched = xcalloc(ps.nr, 1);\n+\n+\t\t/* TODO: audit for interaction with sparse-index. */\n+\t\tensure_full_index(&the_index);\n+\n+\t\t/*\n+\t\t * Since there is only one pathspec, we just need\n+\t\t * need to check ps_matched[0] to know if a cache\n+\t\t * entry matched.\n+\t\t */\n+\t\tfor (i = 0; i < active_nr; i++) {\n+\t\t\tce_path_match(&the_index, active_cache[i], &ps,\n+\t\t\t\t      ps_matched);\n+\n+\t\t\tif (ps_matched[0]) {\n+\t\t\t\tif (!force)\n+\t\t\t\t\tdie(_(\"'%s' already exists in the index\"),\n+\t\t\t\t\t    path);\n+\t\t\t\tif (!S_ISGITLINK(active_cache[i]->ce_mode))\n+\t\t\t\t\tdie(_(\"'%s' already exists in the index \"\n+\t\t\t\t\t      \"and is not a submodule\"), path);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tfree(ps_matched);\n+\t}\n+}\n+\n+static void die_on_repo_without_commits(const char *path)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstrbuf_addstr(&sb, path);\n+\tif (is_nonbare_repository_dir(&sb)) {\n+\t\tstruct object_id oid;\n+\t\tif (resolve_gitlink_ref(path, \"HEAD\", &oid) < 0)\n+\t\t\tdie(_(\"'%s' does not have a commit checked out\"), path);\n+\t}\n+}\n+\n+static int module_add(int argc, const char **argv, const char *prefix)\n+{\n+\tint force = 0, quiet = 0, progress = 0, dissociate = 0;\n+\tstruct add_data add_data = ADD_DATA_INIT;\n+\n+\tstruct option options[] = {\n+\t\tOPT_STRING('b', \"branch\", &add_data.branch, N_(\"branch\"),\n+\t\t\t   N_(\"branch of repository to add as submodule\")),\n+\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n+\t\t\t   PARSE_OPT_NOCOMPLETE),\n+\t\tOPT__QUIET(&quiet, N_(\"print only error messages\")),\n+\t\tOPT_BOOL(0, \"progress\", &progress, N_(\"force cloning progress\")),\n+\t\tOPT_STRING(0, \"reference\", &add_data.reference_path, N_(\"repository\"),\n+\t\t\t   N_(\"reference repository\")),\n+\t\tOPT_BOOL(0, \"dissociate\", &dissociate, N_(\"borrow the objects from reference repositories\")),\n+\t\tOPT_STRING(0, \"name\", &add_data.sm_name, N_(\"name\"),\n+\t\t\t   N_(\"sets the submodule’s name to the given string \"\n+\t\t\t      \"instead of defaulting to its path\")),\n+\t\tOPT_INTEGER(0, \"depth\", &add_data.depth, N_(\"depth for shallow clones\")),\n+\t\tOPT_END()\n+\t};\n+\n+\tconst char *const usage[] = {\n+\t\tN_(\"git submodule--helper add [<options>] [--] <repository> [<path>]\"),\n+\t\tNULL\n+\t};\n+\n+\targc = parse_options(argc, argv, prefix, options, usage, 0);\n+\n+\tif (!is_writing_gitmodules_ok())\n+\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n+\n+\tif (prefix && *prefix &&\n+\t    add_data.reference_path && !is_absolute_path(add_data.reference_path))\n+\t\tadd_data.reference_path = xstrfmt(\"%s%s\", prefix, add_data.reference_path);\n+\n+\tif (argc == 0 || argc > 2)\n+\t\tusage_with_options(usage, options);\n+\n+\tadd_data.repo = argv[0];\n+\tif (argc == 1)\n+\t\tadd_data.sm_path = git_url_basename(add_data.repo, 0, 0);\n+\telse\n+\t\tadd_data.sm_path = xstrdup(argv[1]);\n+\n+\tif (prefix && *prefix && !is_absolute_path(add_data.sm_path))\n+\t\tadd_data.sm_path = xstrfmt(\"%s%s\", prefix, add_data.sm_path);\n+\n+\tif (starts_with_dot_dot_slash(add_data.repo) ||\n+\t    starts_with_dot_slash(add_data.repo)) {\n+\t\tif (prefix)\n+\t\t\tdie(_(\"Relative path can only be used from the toplevel \"\n+\t\t\t      \"of the working tree\"));\n+\n+\t\t/* dereference source url relative to parent's url */\n+\t\tadd_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);\n+\t} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {\n+\t\tadd_data.realrepo = add_data.repo;\n+\t} else {\n+\t\tdie(_(\"repo URL: '%s' must be absolute or begin with ./|../\"),\n+\t\t    add_data.repo);\n+\t}\n+\n+\t/*\n+\t * normalize path:\n+\t * multiple //; leading ./; /./; /../;\n+\t */\n+\tnormalize_path_copy(add_data.sm_path, add_data.sm_path);\n+\tstrip_dir_trailing_slashes(add_data.sm_path);\n+\n+\tdie_on_index_match(add_data.sm_path, force);\n+\tdie_on_repo_without_commits(add_data.sm_path);\n+\n+\tif (!force) {\n+\t\tint exit_code = -1;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\t\tcp.git_cmd = 1;\n+\t\tcp.no_stdout = 1;\n+\t\tstrvec_pushl(&cp.args, \"add\", \"--dry-run\", \"--ignore-missing\",\n+\t\t\t     \"--no-warn-embedded-repo\", add_data.sm_path, NULL);\n+\t\tif ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {\n+\t\t\tstrbuf_complete_line(&sb);\n+\t\t\tfputs(sb.buf, stderr);\n+\t\t\tfree(add_data.sm_path);\n+\t\t\treturn exit_code;\n+\t\t}\n+\t\tstrbuf_release(&sb);\n+\t}\n+\n+\tif(!add_data.sm_name)\n+\t\tadd_data.sm_name = add_data.sm_path;\n+\n+\tif (check_submodule_name(add_data.sm_name))\n+\t\tdie(_(\"'%s' is not a valid submodule name\"), add_data.sm_name);\n+\n+\tadd_data.prefix = prefix;\n+\tadd_data.force = !!force;\n+\tadd_data.quiet = !!quiet;\n+\tadd_data.progress = !!progress;\n+\tadd_data.dissociate = !!dissociate;\n+\n+\tif (add_submodule(&add_data)) {\n+\t\tfree(add_data.sm_path);\n+\t\treturn 1;\n+\t}\n+\tconfigure_added_submodule(&add_data);\n+\tfree(add_data.sm_path);\n+\n+\treturn 0;\n+}\n+\n #define SUPPORT_SUPER_PREFIX (1<<0)\n \n struct cmd_struct {\n@@ -3060,6 +3222,7 @@ static struct cmd_struct commands[] = {\n \t{\"clone\", module_clone, 0},\n \t{\"add-clone\", add_clone, 0},\n \t{\"add-config\", add_config, 0},\n+\t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n \t{\"update-clone\", update_clone, 0},\n \t{\"ensure-core-worktree\", ensure_core_worktree, 0},\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 8c219ef382..1070540525 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -145,104 +145,12 @@ cmd_add()\n \t\tshift\n \tdone\n \n-\tif ! git submodule--helper config --check-writeable >/dev/null 2>&1\n+\tif test -z \"$1\"\n \tthen\n-\t\t die \"fatal: $(eval_gettext \"please make sure that the .gitmodules file is in the working tree\")\"\n-\tfi\n-\n-\tif test -n \"$reference_path\"\n-\tthen\n-\t\tis_absolute_path \"$reference_path\" ||\n-\t\treference_path=\"$wt_prefix$reference_path\"\n-\n-\t\treference=\"--reference=$reference_path\"\n-\tfi\n-\n-\trepo=$1\n-\tsm_path=$2\n-\n-\tif test -z \"$sm_path\"; then\n-\t\tsm_path=$(printf '%s\\n' \"$repo\" |\n-\t\t\tsed -e 's|/$||' -e 's|:*/*\\.git$||' -e 's|.*[/:]||g')\n-\tfi\n-\n-\tif test -z \"$repo\" || test -z \"$sm_path\"; then\n \t\tusage\n \tfi\n \n-\tis_absolute_path \"$sm_path\" || sm_path=\"$wt_prefix$sm_path\"\n-\n-\t# assure repo is absolute or relative to parent\n-\tcase \"$repo\" in\n-\t./*|../*)\n-\t\ttest -z \"$wt_prefix\" ||\n-\t\tdie \"fatal: $(gettext \"Relative path can only be used from the toplevel of the working tree\")\"\n-\n-\t\t# dereference source url relative to parent's url\n-\t\trealrepo=$(git submodule--helper resolve-relative-url \"$repo\") || exit\n-\t\t;;\n-\t*:*|/*)\n-\t\t# absolute url\n-\t\trealrepo=$repo\n-\t\t;;\n-\t*)\n-\t\tdie \"fatal: $(eval_gettext \"repo URL: '\\$repo' must be absolute or begin with ./|../\")\"\n-\t;;\n-\tesac\n-\n-\t# normalize path:\n-\t# multiple //; leading ./; /./; /../; trailing /\n-\tsm_path=$(printf '%s/\\n' \"$sm_path\" |\n-\t\tsed -e '\n-\t\t\ts|//*|/|g\n-\t\t\ts|^\\(\\./\\)*||\n-\t\t\ts|/\\(\\./\\)*|/|g\n-\t\t\t:start\n-\t\t\ts|\\([^/]*\\)/\\.\\./||\n-\t\t\ttstart\n-\t\t\ts|/*$||\n-\t\t')\n-\tif test -z \"$force\"\n-\tthen\n-\t\tgit ls-files --error-unmatch \"$sm_path\" > /dev/null 2>&1 &&\n-\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index\")\"\n-\telse\n-\t\tgit ls-files -s \"$sm_path\" | sane_grep -v \"^160000\" > /dev/null 2>&1 &&\n-\t\tdie \"fatal: $(eval_gettext \"'\\$sm_path' already exists in the index and is not a submodule\")\"\n-\tfi\n-\n-\tif test -d \"$sm_path\" &&\n-\t\ttest -z $(git -C \"$sm_path\" rev-parse --show-cdup 2>/dev/null)\n-\tthen\n-\t    git -C \"$sm_path\" rev-parse --verify -q HEAD >/dev/null ||\n-\t    die \"fatal: $(eval_gettext \"'\\$sm_path' does not have a commit checked out\")\"\n-\tfi\n-\n-\tif test -z \"$force\"\n-\tthen\n-\t    dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo \"$sm_path\" 2>&1 >/dev/null)\n-\t    res=$?\n-\t    if test $res -ne 0\n-\t    then\n-\t\t echo >&2 \"$dryerr\"\n-\t\t exit $res\n-\t    fi\n-\tfi\n-\n-\tif test -n \"$custom_name\"\n-\tthen\n-\t\tsm_name=\"$custom_name\"\n-\telse\n-\t\tsm_name=\"$sm_path\"\n-\tfi\n-\n-\tif ! git submodule--helper check-name \"$sm_name\"\n-\tthen\n-\t\tdie \"fatal: $(eval_gettext \"'$sm_name' is not a valid submodule name\")\"\n-\tfi\n-\n-\tgit 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\n-\tgit submodule--helper add-config ${force:+--force} ${branch:+--branch \"$branch\"} --url \"$repo\" --resolved-url \"$realrepo\" --path \"$sm_path\" --name \"$sm_name\"\n+\tgit ${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\"} -- \"$@\"\n }\n \n #\n-- \n2.32.0\n\n"},{"id":"432368","messageId":"20210810114641.27188-7-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210810114641.27188-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v5 6/9] submodule--helper: remove add-clone subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-10T11:46:38Z","receivedAt":"2021-08-10T11:48:14Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"We no longer need this subcommand, as all of its functionality is being\ncalled by the newly-introduced `module_add()` directly within C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 60 -------------------------------------\n 1 file changed, 60 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex bbc5b4d9fd..6ab7de7741 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2860,65 +2860,6 @@ static int add_submodule(const struct add_data *add_data)\n \treturn 0;\n }\n \n-static int add_clone(int argc, const char **argv, const char *prefix)\n-{\n-\tint force = 0, quiet = 0, dissociate = 0, progress = 0;\n-\tstruct add_data add_data = ADD_DATA_INIT;\n-\n-\tstruct option options[] = {\n-\t\tOPT_STRING('b', \"branch\", &add_data.branch,\n-\t\t\t   N_(\"branch\"),\n-\t\t\t   N_(\"branch of repository to checkout on cloning\")),\n-\t\tOPT_STRING(0, \"prefix\", &prefix,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"alternative anchor for relative paths\")),\n-\t\tOPT_STRING(0, \"path\", &add_data.sm_path,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"where the new submodule will be cloned to\")),\n-\t\tOPT_STRING(0, \"name\", &add_data.sm_name,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"name of the new submodule\")),\n-\t\tOPT_STRING(0, \"url\", &add_data.realrepo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url where to clone the submodule from\")),\n-\t\tOPT_STRING(0, \"reference\", &add_data.reference_path,\n-\t\t\t   N_(\"repo\"),\n-\t\t\t   N_(\"reference repository\")),\n-\t\tOPT_BOOL(0, \"dissociate\", &dissociate,\n-\t\t\t N_(\"use --reference only while cloning\")),\n-\t\tOPT_INTEGER(0, \"depth\", &add_data.depth,\n-\t\t\t    N_(\"depth for shallow clones\")),\n-\t\tOPT_BOOL(0, \"progress\", &progress,\n-\t\t\t N_(\"force cloning progress\")),\n-\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n-\t\t\t   PARSE_OPT_NOCOMPLETE),\n-\t\tOPT__QUIET(&quiet, \"suppress output for cloning a submodule\"),\n-\t\tOPT_END()\n-\t};\n-\n-\tconst char *const usage[] = {\n-\t\tN_(\"git submodule--helper add-clone [<options>...] \"\n-\t\t   \"--url <url> --path <path> --name <name>\"),\n-\t\tNULL\n-\t};\n-\n-\targc = parse_options(argc, argv, prefix, options, usage, 0);\n-\n-\tif (argc != 0)\n-\t\tusage_with_options(usage, options);\n-\n-\tadd_data.prefix = prefix;\n-\tadd_data.progress = !!progress;\n-\tadd_data.dissociate = !!dissociate;\n-\tadd_data.force = !!force;\n-\tadd_data.quiet = !!quiet;\n-\n-\tif (add_submodule(&add_data))\n-\t\treturn 1;\n-\n-\treturn 0;\n-}\n-\n static int config_submodule_in_gitmodules(const char *name, const char *var, const char *value)\n {\n \tchar *key;\n@@ -3220,7 +3161,6 @@ static struct cmd_struct commands[] = {\n \t{\"list\", module_list, 0},\n \t{\"name\", module_name, 0},\n \t{\"clone\", module_clone, 0},\n-\t{\"add-clone\", add_clone, 0},\n \t{\"add-config\", add_config, 0},\n \t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n-- \n2.32.0\n\n"},{"id":"432369","messageId":"20210810114641.27188-10-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210810114641.27188-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v5 9/9] submodule--helper: rename compute_submodule_clone_url()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-10T11:46:41Z","receivedAt":"2021-08-10T11:48:17Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Let's rename 'compute_submodule_clone_url()' to 'resolve_relative_url()'\nto make it clear that this internal helper need not be used exclusively\nfor computing submodule clone URLs.\n\nSince the original 'resolve-relative-url' subcommand and its C entry\npoint has been removed in c461095ae3 (submodule--helper: remove\nresolve-relative-url subcommand, 2021-07-02), this rename can be done\nwithout causing any confusion about which function it actually binds to.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 65591e47eb..5ab4e17e75 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -199,7 +199,7 @@ static char *relative_url(const char *remote_url,\n \treturn strbuf_detach(&sb, NULL);\n }\n \n-static char *compute_submodule_clone_url(const char *rel_url, const char *up_path, int quiet)\n+static char *resolve_relative_url(const char *rel_url, const char *up_path, int quiet)\n {\n \tchar *remoteurl, *resolved_url;\n \tchar *remote = get_default_remote();\n@@ -634,7 +634,7 @@ static void init_submodule(const char *path, const char *prefix,\n \t\tif (starts_with_dot_dot_slash(url) ||\n \t\t    starts_with_dot_slash(url)) {\n \t\t\tchar *oldurl = url;\n-\t\t\turl = compute_submodule_clone_url(oldurl, NULL, 0);\n+\t\t\turl = resolve_relative_url(oldurl, NULL, 0);\n \t\t\tfree(oldurl);\n \t\t}\n \n@@ -1355,8 +1355,8 @@ static void sync_submodule(const char *path, const char *prefix,\n \t\tif (starts_with_dot_dot_slash(sub->url) ||\n \t\t    starts_with_dot_slash(sub->url)) {\n \t\t\tchar *up_path = get_up_path(path);\n-\t\t\tsub_origin_url = compute_submodule_clone_url(sub->url, up_path, 1);\n-\t\t\tsuper_config_url = compute_submodule_clone_url(sub->url, NULL, 1);\n+\t\t\tsub_origin_url = resolve_relative_url(sub->url, up_path, 1);\n+\t\t\tsuper_config_url = resolve_relative_url(sub->url, NULL, 1);\n \t\t\tfree(up_path);\n \t\t} else {\n \t\t\tsub_origin_url = xstrdup(sub->url);\n@@ -2098,7 +2098,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \tif (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {\n \t\tif (starts_with_dot_slash(sub->url) ||\n \t\t    starts_with_dot_dot_slash(sub->url)) {\n-\t\t\turl = compute_submodule_clone_url(sub->url, NULL, 0);\n+\t\t\turl = resolve_relative_url(sub->url, NULL, 0);\n \t\t\tneed_free_url = 1;\n \t\t} else\n \t\t\turl = sub->url;\n@@ -3025,7 +3025,7 @@ static int module_add(int argc, const char **argv, const char *prefix)\n \t\t\t      \"of the working tree\"));\n \n \t\t/* dereference source url relative to parent's url */\n-\t\tadd_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);\n+\t\tadd_data.realrepo = resolve_relative_url(add_data.repo, NULL, 1);\n \t} else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {\n \t\tadd_data.realrepo = add_data.repo;\n \t} else {\n-- \n2.32.0\n\n"},{"id":"432370","messageId":"20210810114641.27188-9-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210810114641.27188-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v5 8/9] submodule--helper: remove resolve-relative-url subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-10T11:46:40Z","receivedAt":"2021-08-10T11:48:24Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"The shell subcommand `resolve-relative-url` is no longer required, as\nits last caller has been removed when it was converted to C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 20 --------------------\n 1 file changed, 20 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 0baff16686..65591e47eb 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -223,25 +223,6 @@ static char *compute_submodule_clone_url(const char *rel_url, const char *up_pat\n \treturn resolved_url;\n }\n \n-static int resolve_relative_url(int argc, const char **argv, const char *prefix)\n-{\n-\tconst char *up_path = NULL;\n-\tchar *res;\n-\tconst char *url;\n-\n-\tif (argc != 2 && argc != 3)\n-\t\tdie(\"resolve-relative-url only accepts one or two arguments\");\n-\n-\turl = argv[1];\n-\tif (argc == 3)\n-\t\tup_path = argv[2];\n-\n-\tres = compute_submodule_clone_url(url, up_path, 1);\n-\tputs(res);\n-\tfree(res);\n-\treturn 0;\n-}\n-\n static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)\n {\n \tchar *remoteurl, *res;\n@@ -3118,7 +3099,6 @@ static struct cmd_struct commands[] = {\n \t{\"update-clone\", update_clone, 0},\n \t{\"ensure-core-worktree\", ensure_core_worktree, 0},\n \t{\"relative-path\", resolve_relative_path, 0},\n-\t{\"resolve-relative-url\", resolve_relative_url, 0},\n \t{\"resolve-relative-url-test\", resolve_relative_url_test, 0},\n \t{\"foreach\", module_foreach, SUPPORT_SUPER_PREFIX},\n \t{\"init\", module_init, SUPPORT_SUPER_PREFIX},\n-- \n2.32.0\n\n"},{"id":"432371","messageId":"20210810114641.27188-8-raykar.ath@gmail.com","threadId":"56219","inReplyTo":"20210810114641.27188-1-raykar.ath@gmail.com","subject":"[GSoC] [PATCH v5 7/9] submodule--helper: remove add-config subcommand","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-10T11:46:39Z","receivedAt":"2021-08-10T11:48:25Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"Also no longer needed is this subcommand, as all of its functionality is\nbeing called by the newly-introduced `module_add()` directly within C.\n\nSigned-off-by: Atharva Raykar <raykar.ath@gmail.com>\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Shourya Shukla <periperidip@gmail.com>\n---\n builtin/submodule--helper.c | 49 -------------------------------------\n 1 file changed, 49 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 6ab7de7741..0baff16686 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2939,54 +2939,6 @@ static void configure_added_submodule(struct add_data *add_data)\n \t}\n }\n \n-static int add_config(int argc, const char **argv, const char *prefix)\n-{\n-\tint force = 0;\n-\tstruct add_data add_data = ADD_DATA_INIT;\n-\n-\tstruct option options[] = {\n-\t\tOPT_STRING('b', \"branch\", &add_data.branch,\n-\t\t\t   N_(\"branch\"),\n-\t\t\t   N_(\"branch of repository to store in \"\n-\t\t\t      \"the submodule configuration\")),\n-\t\tOPT_STRING(0, \"url\", &add_data.repo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url to clone submodule from\")),\n-\t\tOPT_STRING(0, \"resolved-url\", &add_data.realrepo,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"url to clone the submodule from, after it has \"\n-\t\t\t      \"been dereferenced relative to parent's url, \"\n-\t\t\t      \"in the case where <url> is a relative url\")),\n-\t\tOPT_STRING(0, \"path\", &add_data.sm_path,\n-\t\t\t   N_(\"path\"),\n-\t\t\t   N_(\"where the new submodule will be cloned to\")),\n-\t\tOPT_STRING(0, \"name\", &add_data.sm_name,\n-\t\t\t   N_(\"string\"),\n-\t\t\t   N_(\"name of the new submodule\")),\n-\t\tOPT__FORCE(&force, N_(\"allow adding an otherwise ignored submodule path\"),\n-\t\t\t   PARSE_OPT_NOCOMPLETE),\n-\t\tOPT_END()\n-\t};\n-\n-\tconst char *const usage[] = {\n-\t\tN_(\"git submodule--helper add-config \"\n-\t\t   \"[--force|-f] [--branch|-b <branch>] \"\n-\t\t   \"--url <url> --resolved-url <resolved-url> \"\n-\t\t   \"--path <path> --name <name>\"),\n-\t\tNULL\n-\t};\n-\n-\targc = parse_options(argc, argv, prefix, options, usage, 0);\n-\n-\tif (argc)\n-\t\tusage_with_options(usage, options);\n-\n-\tadd_data.force = !!force;\n-\tconfigure_added_submodule(&add_data);\n-\n-\treturn 0;\n-}\n-\n static void die_on_index_match(const char *path, int force)\n {\n \tstruct pathspec ps;\n@@ -3161,7 +3113,6 @@ static struct cmd_struct commands[] = {\n \t{\"list\", module_list, 0},\n \t{\"name\", module_name, 0},\n \t{\"clone\", module_clone, 0},\n-\t{\"add-config\", add_config, 0},\n \t{\"add\", module_add, SUPPORT_SUPER_PREFIX},\n \t{\"update-module-mode\", module_update_module_mode, 0},\n \t{\"update-clone\", update_clone, 0},\n-- \n2.32.0\n\n"},{"id":"432388","messageId":"7b19892d-9171-bc72-1f96-8df88f8d57a5@gmail.com","threadId":"56219","inReplyTo":"m2wnov9f8s.fsf@gmail.com","subject":"Re: [GSoC] [PATCH v4 1/8] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Kaartic Sivaraam","fromEmail":"kaartic.sivaraam@gmail.com","sentAt":"2021-08-10T17:36:03Z","receivedAt":"2021-08-10T17:58:27Z","isPatch":true,"sender":{"key":"kaartic.sivaraam@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12448084?v=4"},"body":"On 09/08/21 2:17 pm, Atharva Raykar wrote:\n> \n> Atharva Raykar <raykar.ath@gmail.com> writes:\n> \n>> Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:\n>>\n>>> On 08/08/21 11:11 pm, Kaartic Sivaraam wrote:\n>>>> On 07/08/21 12:46 pm, Atharva Raykar wrote:\n>>>> [...]\n>>>>   \tchar *remote = get_default_remote();\n>>>> @@ -598,10 +598,14 @@ static char *compute_submodule_clone_url(const char *rel_url)\n>>>>    \tstrbuf_addf(&remotesb, \"remote.%s.url\", remote);\n>>>>   \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n>>>> -\t\twarning(_(\"could not look up configuration '%s'. Assuming this repository is its own authoritative upstream.\"), remotesb.buf);\n>>>> +\t\tif (!quiet)\n>>>> +\t\t\twarning(_(\"could not look up configuration '%s'. \"\n>>>> +\t\t\t\t  \"Assuming this repository is its own \"\n>>>> +\t\t\t\t  \"authoritative upstream.\"),\n>>>> +\t\t\t\tremotesb.buf);\n>>>>   \t\tremoteurl = xgetcwd();\n>>>>   \t}\n>>>> -\trelurl = relative_url(remoteurl, rel_url, NULL);\n>>>> +\trelurl = relative_url(remoteurl, rel_url, up_path);\n>>>\n>>> After reading 2/8 of the series, I just noticed that 'remoteurl' is always\n>>> initialized in 'resolve_realtive_url'. It is either initialized to the return\n>>> value of 'xgetcwd' or retains its assigned value of 'NULL'. But it looks\n>>> like that's not the case here. 'remoteurl' could be used uninitialized\n>>> when the above if block does not get executed which in turn could result in\n>>> weird behaviour in case 'remoteurl' gets a value of anything other than 'NULL'\n>>> at runtime.\n>>>\n>>> This again has nothing to do with the change done in this patch. Regardless, it\n>>> looks like something worth correcting. Thus, I thought of pointing it out.\n>>>\n>>\n>> Right. I agree it should be corrected.\n> \n> Actually on having another look, I'm not sure if we need to assign NULL\n> to 'remoteurl' at all.\n> \n> The 'if (git_config_get_string(...))' on success will allocate\n> 'remoteurl'. If it fails, it will be given the return value of\n> 'xgetcwd()'. There is nothing in the config API docs that suggest a\n> success mode for the git_config_get_*() functions that will assign\n> nothing to the buffer we give it. Therefore, by the time we get to the\n> variable's first use in the 'relative_url()' function, we are guaranteed\n> to have a well-defined value.\n> \n\nAh ha! That explains why we haven't got any reports about weird behaviours\nwhen using the likes of `git submodule init` so far ;-)\n\nThanks for digging this and sorry about the false flag!\n\n> It seems to me that the original 'resolve_relative_url()' had an\n> unnecessary NULL initialization.\n> \n\nMakes sense. I guess I feel into the trap of blindly trusting that the original\ncode was written correctly x-<\n\n-- \nSivaraam\n"},{"id":"432389","messageId":"68bb457b-9575-c2a1-6d51-fc7cd85a50b7@gmail.com","threadId":"56219","inReplyTo":"m21r73avvx.fsf@gmail.com","subject":"Re: [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c","fromName":"Kaartic Sivaraam","fromEmail":"kaartic.sivaraam@gmail.com","sentAt":"2021-08-10T17:53:13Z","receivedAt":"2021-08-10T18:17:30Z","isPatch":true,"sender":{"key":"kaartic.sivaraam@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12448084?v=4"},"body":"On 09/08/21 1:32 pm, Atharva Raykar wrote:\n> \n> Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:\n> \n>> On 07/08/21 12:46 pm, Atharva Raykar wrote:\n>>>> [ ... ]\n>>>\n>>> diff --git a/dir.h b/dir.h\n>>> index b3e1a54a97..a4a6fd7371 100644\n>>> --- a/dir.h\n>>> +++ b/dir.h\n>>> @@ -453,6 +453,16 @@ static inline int is_dot_or_dotdot(const char *name)\n>>>      int is_empty_dir(const char *dir);\n>>>    +/*\n>>> + * Retrieve the \"humanish\" basename of the given Git URL.\n>>> + *\n>>> + * For example:\n>>> + * \t/path/to/repo.git => \"repo\"\n>>> + * \thost.xz.foo/.git => \"foo\"\n>>> + */\n>>\n>> Are you sure about the examples here? I just tried and ...\n>>\n>>    - '/path/to/repo.git' gave me 'repo' like you said\n>>\n>> .. but ..\n>>\n>>    - 'host.xz.foo/.git' gives me 'host.xz.foo' instead of 'foo'.\n>>      I think you meant to have 'host.xz/foo.git' in the example.\n> \n> Yikes! I meant 'host.xz:foo/.git'. That should give us 'foo'. Thanks for\n> the correction.\n> \n\nInteresting. I've usually seen host.xz:foo like syntax in HTTP URLs. For instance,\n\n     http://host.xz:4000/bar.baz.git\n\n`git_url_basename` returns `bar.baz` for the above.\n\nI wonder what real-world URL has a syntax like 'host.xz:foo/.git' for which\n'foo' would be an appropriate basename to return. Does a real-world URL of\nthis form exist? Or is this just cooked up to demonstrate the basename that\nwould be returned for a hypothetical URL like this?\n\n-- \nSivaraam\n"},{"id":"432419","messageId":"xmqqpmulc7o7.fsf@gitster.g","threadId":"56219","inReplyTo":"68bb457b-9575-c2a1-6d51-fc7cd85a50b7@gmail.com","subject":"Re: [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-08-10T21:27:04Z","receivedAt":"2021-08-10T21:27:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:\n\n> I wonder what real-world URL has a syntax like 'host.xz:foo/.git' for which\n> 'foo' would be an appropriate basename to return. Does a real-world URL of\n> this form exist? Or is this just cooked up to demonstrate the basename that\n> would be returned for a hypothetical URL like this?\n\nIt is not really a URL, but historically we've called them\n\"scp-style URL\".  scp of course copied the syntax from \"rcp\" where\n<hostname> and <pathname> are separated by a colon ':' named a file\nor a directory at the named path on the named host.\n"},{"id":"432451","messageId":"21917b01-94f7-2698-b904-2d75f37af447@gmail.com","threadId":"56219","inReplyTo":"20210810114641.27188-2-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v5 1/9] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Bagas Sanjaya","fromEmail":"bagasdotme@gmail.com","sentAt":"2021-08-11T06:44:59Z","receivedAt":"2021-08-11T06:45:06Z","isPatch":true,"sender":{"key":"bagasdotme@gmail.com","avatar":"https://avatars.githubusercontent.com/u/40219486?v=4"},"body":"On 10/08/21 18.46, Atharva Raykar wrote:\n>   \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n> -\t\twarning(_(\"could not look up configuration '%s'. Assuming this repository is its own authoritative upstream.\"), remotesb.buf);\n> +\t\tif (!quiet)\n> +\t\t\twarning(_(\"could not look up configuration '%s'. \"\n> +\t\t\t\t  \"Assuming this repository is its own \"\n> +\t\t\t\t  \"authoritative upstream.\"),\n> +\t\t\t\tremotesb.buf);\n>   \t\tremoteurl = xgetcwd();\n>   \t}\n\nWhy did you split warning message? We could keep that in one line.\n\n-- \nAn old man doll... just what I always wanted! - Clara\n"},{"id":"432473","messageId":"m2sfzg9t22.fsf@gmail.com","threadId":"56219","inReplyTo":"68bb457b-9575-c2a1-6d51-fc7cd85a50b7@gmail.com","subject":"Re: [GSoC] [PATCH v4 4/8] dir: libify and export helper functions from clone.c","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-11T10:25:41Z","receivedAt":"2021-08-11T10:26:03Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"\nKaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:\n\n> On 09/08/21 1:32 pm, Atharva Raykar wrote:\n>> Kaartic Sivaraam <kaartic.sivaraam@gmail.com> writes:\n>>\n>>> On 07/08/21 12:46 pm, Atharva Raykar wrote:\n>>>>> [ ... ]\n>> Yikes! I meant 'host.xz:foo/.git'. That should give us 'foo'. Thanks for\n>> the correction.\n>>\n>\n> Interesting. I've usually seen host.xz:foo like syntax in HTTP URLs. For instance,\n>\n>     http://host.xz:4000/bar.baz.git\n>\n> `git_url_basename` returns `bar.baz` for the above.\n>\n> I wonder what real-world URL has a syntax like 'host.xz:foo/.git' for which\n> 'foo' would be an appropriate basename to return. Does a real-world URL of\n> this form exist? Or is this just cooked up to demonstrate the basename that\n> would be returned for a hypothetical URL like this?\n\nJunio already answered all of your questions, I'll just add that I\nlifted that example from the git-clone documentation [1] that uses the\nexact same basename extraction function.\n\n[1] https://git-scm.com/docs/git-clone#Documentation/git-clone.txt-ltdirectorygt\n"},{"id":"432474","messageId":"m2pmuk9stu.fsf@gmail.com","threadId":"56219","inReplyTo":"21917b01-94f7-2698-b904-2d75f37af447@gmail.com","subject":"Re: [GSoC] [PATCH v5 1/9] submodule--helper: add options for compute_submodule_clone_url()","fromName":"Atharva Raykar","fromEmail":"raykar.ath@gmail.com","sentAt":"2021-08-11T10:30:37Z","receivedAt":"2021-08-11T10:31:01Z","isPatch":true,"sender":{"key":"raykar.ath@gmail.com","avatar":"https://avatars.githubusercontent.com/u/24277692?v=4"},"body":"\nBagas Sanjaya <bagasdotme@gmail.com> writes:\n\n> On 10/08/21 18.46, Atharva Raykar wrote:\n>>   \tif (git_config_get_string(remotesb.buf, &remoteurl)) {\n>> -\t\twarning(_(\"could not look up configuration '%s'. Assuming this repository is its own authoritative upstream.\"), remotesb.buf);\n>> +\t\tif (!quiet)\n>> +\t\t\twarning(_(\"could not look up configuration '%s'. \"\n>> +\t\t\t\t  \"Assuming this repository is its own \"\n>> +\t\t\t\t  \"authoritative upstream.\"),\n>> +\t\t\t\tremotesb.buf);\n>>   \t\tremoteurl = xgetcwd();\n>>   \t}\n>\n> Why did you split warning message? We could keep that in one line.\n\nThat line was too long, and given that I was moving the function and\nchanging it a little bit, I decided to make it adhere more closely to\nthe CodingGuidelines [1] and local convention.\n\n[1] https://github.com/git/git/blob/6c85aac65fb455af85745130ce35ddae4678db84/Documentation/CodingGuidelines#L190\n"},{"id":"434973","messageId":"xmqq1r5z9acx.fsf@gitster.g","threadId":"56219","inReplyTo":"20210810114641.27188-1-raykar.ath@gmail.com","subject":"Re: [GSoC] [PATCH v5 0/9] submodule: convert the rest of 'add' to C","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-09-08T00:31:10Z","receivedAt":"2021-09-08T00:31:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Atharva Raykar <raykar.ath@gmail.com> writes:\n\n> NOTE: This series uses (ar/submodule-add-config):\n> https://lore.kernel.org/git/20210806140431.92018-1-raykar.ath@gmail.com/\n\nI didn't see anybody comment on this round (and do not think I saw\nanything glaringly wrong).\n\nIs everybody happy with this version?  I am about to mark it for\n'next' in the next issue of \"What's cooking\" report, so please\nholler if I should wait.\n\nThanks.\n"}]}