{"thread":{"id":"46213","subject":"[GSoC] Update: Week 5","startedAt":"2017-06-19T21:41:13Z","lastAt":"2017-06-26T23:24:28Z","messageCount":16,"participants":["Prathamesh Chavan","Andrew Ardill","Brandon Williams","Stefan Beller","Christian Couder"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"322615","messageId":"CAME+mvUQJFneV7b1G7zmAidP-5L=nimvY43V0ug-Gtesr83tzg@mail.gmail.com","threadId":"46213","inReplyTo":null,"subject":"[GSoC] Update: Week 5","fromName":"Prathamesh Chavan","fromEmail":"pc44800@gmail.com","sentAt":"2017-06-19T21:41:06Z","receivedAt":"2017-06-19T21:41:13Z","isPatch":false,"sender":{"key":"pc44800@gmail.com","avatar":"https://avatars.githubusercontent.com/u/17272661?v=4"},"body":"SUMMARY OF MY PROJECT:\n\nGit submodule subcommands are currently implemented by using shell script\n'git-submodule.sh'. There are several reasons why we'll prefer not to\nuse the shell script. My project intends to convert the subcommands into\nC code, thus making them builtins. This will increase Git's portability\nand hence the efficiency of working with the git-submodule commands.\nLink to the complete proposal: [1]\n\nMentors:\nStefan Beller <sbeller@google.com>\nChristian Couder <christian.couder@gmail.com>\n\nUPDATES:\n\nFollowing are the updates about my ongoing project:\n\n1. sync and status: The patches were discussed with the mentors\n   and after that, are being posted with this patch.\n\n2. deinit: The patch is finally debugged, and is ready to be\n   discussed. It is also attached with this update.\n\n3. summary: While porting the subcommand, I underwent certain\n   issues. After getting them clarified from my mentors, I\n   have resumed working on it. I'm aware of the time I have\n   taken for porting this subcommand is more than the previous\n   ones. Hence will try my best to finish this in this week.\n\n4. foreach: As stated in the previous update, the subcommand was\n   ported without resolving the bug, and simply translating the\n   present code, and adding a NEEDSWORK tag to the comment for\n   mentioning the reported bug as well.\n   But as communicating between child_process is still an issue\n   and so there was no simple was to current carry out the\n   porting. And hence, a hack was used instead. But after\n   discussing it, instead using the repository-object patch\n   series will help to resolve these issues in this situation.\n\nPLAN FOR WEEK-6 (20 June 2017 to 26 June 2017):\n\n1. summary: Mostly I'll be working on this and post the patch\n   for discussion as soon as possible.\n\n2. foreach: As it was decided that unblock the conversion of\n   this submodule subcommand, the original cmd_foreach was\n   ported without including the BUG-FIX patch here.\n   Hence, for this week I will try to utilize the\n   'repository-object' series by Brandon Williams.\n\n3. deinit: I will be working on improvising this patch as it was\n   recently debugged and posted for discussion.\n\n[1]: https://docs.google.com/document/d/1krxVLooWl--75Pot3dazhfygR3wCUUWZWzTXtK1L-xU/\n\nThanks,\nPrathamesh Chavan\n"},{"id":"322616","messageId":"20170619215025.10086-1-pc44800@gmail.com","threadId":"46213","inReplyTo":"CAME+mvUQJFneV7b1G7zmAidP-5L=nimvY43V0ug-Gtesr83tzg@mail.gmail.com","subject":"[GSoC][PATCH 1/6] dir: create function count_slashes","fromName":"Prathamesh Chavan","fromEmail":"pc44800@gmail.com","sentAt":"2017-06-19T21:50:20Z","receivedAt":"2017-06-19T21:50:54Z","isPatch":true,"sender":{"key":"pc44800@gmail.com","avatar":"https://avatars.githubusercontent.com/u/17272661?v=4"},"body":"Similar functions exist in apply.c and builtin/show-branch.c for\ncounting the number of slashes in a string. Also in the later\npatches, we introduce a third caller for the same. Hence, we unify\nit now by cleaning the existing functions and declaring a common\nfunction count_slashes in dir.h and implementing it in dir.c to\nremove this code duplication.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Stefan Beller <sbeller@google.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Prathamesh Chavan <pc44800@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\nThe complete build report of this is available at:\nhttps://travis-ci.org/pratham-pc/git/builds/\nBranch: All-patch-series\nBuild #111\n\n apply.c               | 11 -----------\n builtin/show-branch.c | 13 +++----------\n dir.c                 |  9 +++++++++\n dir.h                 |  3 +++\n 4 files changed, 15 insertions(+), 21 deletions(-)\n\ndiff --git a/apply.c b/apply.c\nindex c49cef063..121e53406 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -762,17 +762,6 @@ static char *find_name_traditional(struct apply_state *state,\n \treturn find_name_common(state, line, def, p_value, line + len, 0);\n }\n \n-static int count_slashes(const char *cp)\n-{\n-\tint cnt = 0;\n-\tchar ch;\n-\n-\twhile ((ch = *cp++))\n-\t\tif (ch == '/')\n-\t\t\tcnt++;\n-\treturn cnt;\n-}\n-\n /*\n  * Given the string after \"--- \" or \"+++ \", guess the appropriate\n  * p_value for the given patch.\ndiff --git a/builtin/show-branch.c b/builtin/show-branch.c\nindex 4a6cc6f49..3636a0559 100644\n--- a/builtin/show-branch.c\n+++ b/builtin/show-branch.c\n@@ -5,6 +5,7 @@\n #include \"color.h\"\n #include \"argv-array.h\"\n #include \"parse-options.h\"\n+#include \"dir.h\"\n \n static const char* show_branch_usage[] = {\n     N_(\"git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\\n\"\n@@ -421,14 +422,6 @@ static int append_tag_ref(const char *refname, const struct object_id *oid,\n \n static const char *match_ref_pattern = NULL;\n static int match_ref_slash = 0;\n-static int count_slash(const char *s)\n-{\n-\tint cnt = 0;\n-\twhile (*s)\n-\t\tif (*s++ == '/')\n-\t\t\tcnt++;\n-\treturn cnt;\n-}\n \n static int append_matching_ref(const char *refname, const struct object_id *oid,\n \t\t\t       int flag, void *cb_data)\n@@ -438,7 +431,7 @@ static int append_matching_ref(const char *refname, const struct object_id *oid,\n \t * refs/tags/v0.99.9a and friends.\n \t */\n \tconst char *tail;\n-\tint slash = count_slash(refname);\n+\tint slash = count_slashes(refname);\n \tfor (tail = refname; *tail && match_ref_slash < slash; )\n \t\tif (*tail++ == '/')\n \t\t\tslash--;\n@@ -529,7 +522,7 @@ static void append_one_rev(const char *av)\n \t\tint saved_matches = ref_name_cnt;\n \n \t\tmatch_ref_pattern = av;\n-\t\tmatch_ref_slash = count_slash(av);\n+\t\tmatch_ref_slash = count_slashes(av);\n \t\tfor_each_ref(append_matching_ref, NULL);\n \t\tif (saved_matches == ref_name_cnt &&\n \t\t    ref_name_cnt < MAX_REVS)\ndiff --git a/dir.c b/dir.c\nindex 9efcf1eab..4a953c16a 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -52,6 +52,15 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,\n static int get_dtype(struct dirent *de, struct index_state *istate,\n \t\t     const char *path, int len);\n \n+int count_slashes(const char *s)\n+{\n+\tint cnt = 0;\n+\twhile (*s)\n+\t\tif (*s++ == '/')\n+\t\t\tcnt++;\n+\treturn cnt;\n+}\n+\n int fspathcmp(const char *a, const char *b)\n {\n \treturn ignore_case ? strcasecmp(a, b) : strcmp(a, b);\ndiff --git a/dir.h b/dir.h\nindex a89c13e27..e3717055d 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -197,6 +197,9 @@ struct dir_struct {\n \tunsigned unmanaged_exclude_files;\n };\n \n+/*Count the number of slashes for string s*/\n+extern int count_slashes(const char *s);\n+\n /*\n  * The ordering of these constants is significant, with\n  * higher-numbered match types signifying \"closer\" (i.e. more\n-- \n2.13.0\n\n"},{"id":"322617","messageId":"20170619215025.10086-2-pc44800@gmail.com","threadId":"46213","inReplyTo":"20170619215025.10086-1-pc44800@gmail.com","subject":"[GSoC][PATCH 2/6] submodule--helper: introduce get_submodule_displaypath and for_each_submodule_list","fromName":"Prathamesh Chavan","fromEmail":"pc44800@gmail.com","sentAt":"2017-06-19T21:50:21Z","receivedAt":"2017-06-19T21:51:09Z","isPatch":true,"sender":{"key":"pc44800@gmail.com","avatar":"https://avatars.githubusercontent.com/u/17272661?v=4"},"body":"Functions get_submodule_displaypath and for_each_submodule_list\nfor using them in the later patches, related to porting submodule\nsubcommands from shell to C.\nThese new functions are also used in ported submodule subcommand\ninit\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Stefan Beller <sbeller@google.com>\nSigned-off-by: Prathamesh Chavan <pc44800@gmail.com>\n---\n builtin/submodule--helper.c | 69 ++++++++++++++++++++++++++++++++-------------\n 1 file changed, 50 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 8cc648d85..f7adca95b 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -13,6 +13,9 @@\n #include \"refs.h\"\n #include \"connect.h\"\n \n+typedef void (*submodule_list_func_t)(const struct cache_entry *list_item,\n+\t\t\t\t      void *cb_data);\n+\n static char *get_default_remote(void)\n {\n \tchar *dest = NULL, *ret;\n@@ -219,6 +222,27 @@ static int resolve_relative_url_test(int argc, const char **argv, const char *pr\n \treturn 0;\n }\n \n+static char *get_submodule_displaypath(const char *path, const char *prefix)\n+{\n+\tconst char *super_prefix = get_super_prefix();\n+\n+\tif (prefix && super_prefix) {\n+\t\tBUG(\"cannot have prefix '%s' and superprefix '%s'\",\n+\t\t    prefix, super_prefix);\n+\t} else if (prefix) {\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tchar *displaypath = xstrdup(relative_path(path, prefix, &sb));\n+\t\tstrbuf_release(&sb);\n+\t\treturn displaypath;\n+\t} else if (super_prefix) {\n+\t\tint len = strlen(super_prefix);\n+\t\tconst char *format = is_dir_sep(super_prefix[len-1]) ? \"%s%s\" : \"%s/%s\";\n+\t\treturn xstrfmt(format, super_prefix, path);\n+\t} else {\n+\t\treturn xstrdup(path);\n+\t}\n+}\n+\n struct module_list {\n \tconst struct cache_entry **entries;\n \tint alloc, nr;\n@@ -330,26 +354,30 @@ static int module_list(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n-static void init_submodule(const char *path, const char *prefix, int quiet)\n+static void for_each_submodule_list(const struct module_list list,\n+\t\t\t\t    submodule_list_func_t fn, void *cb_data)\n {\n+\tint i;\n+\tfor (i = 0; i < list.nr; i++)\n+\t\tfn(list.entries[i], cb_data);\n+}\n+\n+struct init_cb {\n+\tconst char *prefix;\n+\tunsigned int quiet: 1;\n+};\n+#define INIT_CB_INIT { NULL, 0 }\n+\n+static void init_submodule(const struct cache_entry *list_item, void *cb_data)\n+{\n+\tstruct init_cb *info = cb_data;\n \tconst struct submodule *sub;\n \tstruct strbuf sb = STRBUF_INIT;\n \tchar *upd = NULL, *url = NULL, *displaypath;\n \n-\t/* Only loads from .gitmodules, no overlay with .git/config */\n-\tgitmodules_config();\n-\n-\tif (prefix && get_super_prefix())\n-\t\tdie(\"BUG: cannot have prefix and superprefix\");\n-\telse if (prefix)\n-\t\tdisplaypath = xstrdup(relative_path(path, prefix, &sb));\n-\telse if (get_super_prefix()) {\n-\t\tstrbuf_addf(&sb, \"%s%s\", get_super_prefix(), path);\n-\t\tdisplaypath = strbuf_detach(&sb, NULL);\n-\t} else\n-\t\tdisplaypath = xstrdup(path);\n+\tdisplaypath = get_submodule_displaypath(list_item->name, info->prefix);\n \n-\tsub = submodule_from_path(null_sha1, path);\n+\tsub = submodule_from_path(null_sha1, list_item->name);\n \n \tif (!sub)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n@@ -361,7 +389,7 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n \t *\n \t * Set active flag for the submodule being initialized\n \t */\n-\tif (!is_submodule_initialized(path)) {\n+\tif (!is_submodule_initialized(list_item->name)) {\n \t\tstrbuf_reset(&sb);\n \t\tstrbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n \t\tgit_config_set_gently(sb.buf, \"true\");\n@@ -404,7 +432,7 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n \t\tif (git_config_set_gently(sb.buf, url))\n \t\t\tdie(_(\"Failed to register url for submodule path '%s'\"),\n \t\t\t    displaypath);\n-\t\tif (!quiet)\n+\t\tif (!info->quiet)\n \t\t\tfprintf(stderr,\n \t\t\t\t_(\"Submodule '%s' (%s) registered for path '%s'\\n\"),\n \t\t\t\tsub->name, url, displaypath);\n@@ -433,10 +461,10 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n \n static int module_init(int argc, const char **argv, const char *prefix)\n {\n+\tstruct init_cb info = INIT_CB_INIT;\n \tstruct pathspec pathspec;\n \tstruct module_list list = MODULE_LIST_INIT;\n \tint quiet = 0;\n-\tint i;\n \n \tstruct option module_init_options[] = {\n \t\tOPT__QUIET(&quiet, N_(\"Suppress output for initializing a submodule\")),\n@@ -461,8 +489,11 @@ static int module_init(int argc, const char **argv, const char *prefix)\n \tif (!argc && git_config_get_value_multi(\"submodule.active\"))\n \t\tmodule_list_active(&list);\n \n-\tfor (i = 0; i < list.nr; i++)\n-\t\tinit_submodule(list.entries[i]->name, prefix, quiet);\n+\tinfo.prefix = prefix;\n+\tinfo.quiet = !!quiet;\n+\n+\tgitmodules_config();\n+\tfor_each_submodule_list(list, init_submodule, &info);\n \n \treturn 0;\n }\n-- \n2.13.0\n\n"},{"id":"322618","messageId":"20170619215025.10086-3-pc44800@gmail.com","threadId":"46213","inReplyTo":"20170619215025.10086-1-pc44800@gmail.com","subject":"[GSoC][PATCH 3/6] submodule: port set_name_rev from shell to C","fromName":"Prathamesh Chavan","fromEmail":"pc44800@gmail.com","sentAt":"2017-06-19T21:50:22Z","receivedAt":"2017-06-19T21:51:10Z","isPatch":true,"sender":{"key":"pc44800@gmail.com","avatar":"https://avatars.githubusercontent.com/u/17272661?v=4"},"body":"Since later on we want to port submodule subcommand status, and since\nset_name_rev is part of cmd_status, hence this function is ported. It\nhas been ported to function print_name_rev in C, which calls get_name_rev\nto get the revname, and after formatting it, print_name_rev prints it.\nAnd hence in this way, the command `git submodule--helper print-name-rev\n\"sm_path\" \"sha1\"` sets value of revname in git-submodule.sh\n\nThe function get_name_rev returns the stdout of the git describe\ncommands. Since there are four different git-describe commands used for\ngenerating the name rev, four child_process are introduced, each successive\nchild process running only when previous has no stdout. The order of these\nfour git-describe commands is maintained the same as it was in the function\nset_name_rev() in shell script.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Stefan Beller <sbeller@google.com>\nSigned-off-by: Prathamesh Chavan <pc44800@gmail.com>\n---\n builtin/submodule--helper.c | 69 +++++++++++++++++++++++++++++++++++++++++++++\n git-submodule.sh            | 16 ++---------\n 2 files changed, 71 insertions(+), 14 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f7adca95b..6fd861e42 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -243,6 +243,74 @@ static char *get_submodule_displaypath(const char *path, const char *prefix)\n \t}\n }\n \n+enum describe_step {\n+\tstep_bare,\n+\tstep_tags,\n+\tstep_contains,\n+\tstep_all_always,\n+\tstep_end\n+};\n+\n+static char *get_name_rev(const char *sub_path, const char* object_id)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tenum describe_step cur_step;\n+\n+\tfor (cur_step = step_bare; cur_step < step_end; cur_step++) {\n+\t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\t\tprepare_submodule_repo_env(&cp.env_array);\n+\t\tcp.dir = sub_path;\n+\t\tcp.git_cmd = 1;\n+\t\tcp.no_stderr = 1;\n+\n+\t\tswitch (cur_step) {\n+\t\t\tcase step_bare:\n+\t\t\t\targv_array_pushl(&cp.args, \"describe\",\n+\t\t\t\t\t\t object_id, NULL);\n+\t\t\t\tbreak;\n+\t\t\tcase step_tags:\t\n+\t\t\t\targv_array_pushl(&cp.args, \"describe\",\n+\t\t\t\t\t\t \"--tags\", object_id, NULL);\n+\t\t\t\tbreak;\n+\t\t\tcase step_contains:\n+\t\t\t\targv_array_pushl(&cp.args, \"describe\",\n+\t\t\t\t\t\t \"--contains\", object_id,\n+\t\t\t\t\t\t NULL);\n+\t\t\t\tbreak;\n+\t\t\tcase step_all_always:\n+\t\t\t\targv_array_pushl(&cp.args, \"describe\",\n+\t\t\t\t\t\t \"--all\", \"--always\",\n+\t\t\t\t\t\t object_id, NULL);\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tBUG(\"unknown describe step '%d'\", cur_step);\n+\t\t}\n+\n+\t\tif (!capture_command(&cp, &sb, 0) && sb.len) {\n+\t\t\tstrbuf_strip_suffix(&sb, \"\\n\");\n+\t\t\treturn strbuf_detach(&sb, NULL);\n+\t\t}\n+\n+\t}\n+\n+\tstrbuf_release(&sb);\n+\treturn NULL;\n+}\n+\n+static int print_name_rev(int argc, const char **argv, const char *prefix)\n+{\n+\tchar *namerev;\n+\tif (argc != 3)\n+\t\tdie(\"print-name-rev only accepts two arguments: <path> <sha1>\");\n+\n+\tnamerev = get_name_rev(argv[1], argv[2]);\n+\tif (namerev && namerev[0])\n+\t\tprintf(\" (%s)\", namerev);\n+\tprintf(\"\\n\");\n+\n+\treturn 0;\n+}\n+\n struct module_list {\n \tconst struct cache_entry **entries;\n \tint alloc, nr;\n@@ -1242,6 +1310,7 @@ static struct cmd_struct commands[] = {\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{\"print-name-rev\", print_name_rev, 0},\n \t{\"init\", module_init, SUPPORT_SUPER_PREFIX},\n \t{\"remote-branch\", resolve_remote_submodule_branch, 0},\n \t{\"push-check\", push_check, 0},\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex c0d0e9a4c..091051891 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -758,18 +758,6 @@ cmd_update()\n \t}\n }\n \n-set_name_rev () {\n-\trevname=$( (\n-\t\tsanitize_submodule_env\n-\t\tcd \"$1\" && {\n-\t\t\tgit describe \"$2\" 2>/dev/null ||\n-\t\t\tgit describe --tags \"$2\" 2>/dev/null ||\n-\t\t\tgit describe --contains \"$2\" 2>/dev/null ||\n-\t\t\tgit describe --all --always \"$2\"\n-\t\t}\n-\t) )\n-\ttest -z \"$revname\" || revname=\" ($revname)\"\n-}\n #\n # Show commit summary for submodules in index or working tree\n #\n@@ -1041,14 +1029,14 @@ cmd_status()\n \t\tfi\n \t\tif git diff-files --ignore-submodules=dirty --quiet -- \"$sm_path\"\n \t\tthen\n-\t\t\tset_name_rev \"$sm_path\" \"$sha1\"\n+\t\t\trevname=$(git submodule--helper print-name-rev \"$sm_path\" \"$sha1\")\n \t\t\tsay \" $sha1 $displaypath$revname\"\n \t\telse\n \t\t\tif test -z \"$cached\"\n \t\t\tthen\n \t\t\t\tsha1=$(sanitize_submodule_env; cd \"$sm_path\" && git rev-parse --verify HEAD)\n \t\t\tfi\n-\t\t\tset_name_rev \"$sm_path\" \"$sha1\"\n+\t\t\trevname=$(git submodule--helper print-name-rev \"$sm_path\" \"$sha1\")\n \t\t\tsay \"+$sha1 $displaypath$revname\"\n \t\tfi\n \n-- \n2.13.0\n\n"},{"id":"322619","messageId":"20170619215025.10086-6-pc44800@gmail.com","threadId":"46213","inReplyTo":"20170619215025.10086-1-pc44800@gmail.com","subject":"[GSoC][PATCH 6/6] submodule: port submodule subcommand 'deinit' from shell to C","fromName":"Prathamesh Chavan","fromEmail":"pc44800@gmail.com","sentAt":"2017-06-19T21:50:25Z","receivedAt":"2017-06-19T21:51:12Z","isPatch":true,"sender":{"key":"pc44800@gmail.com","avatar":"https://avatars.githubusercontent.com/u/17272661?v=4"},"body":"The same mechanism is used even for porting this submodule\nsubcommand, as used in the ported subcommands till now.\nThe function cmd_deinit in split up after porting into three\nfunctions: module_deinit, for_each_submodule_list and\ndeinit_submodule.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Stefan Beller <sbeller@google.com>\nSigned-off-by: Prathamesh Chavan <pc44800@gmail.com>\n---\n builtin/submodule--helper.c | 140 ++++++++++++++++++++++++++++++++++++++++++++\n git-submodule.sh            |  55 +----------------\n 2 files changed, 141 insertions(+), 54 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex e10cac462..f029f5fae 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -750,6 +750,145 @@ static int module_status(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+struct deinit_cb {\n+\tconst char *prefix;\n+\tunsigned int quiet: 1;\n+\tunsigned int force: 1;\n+\tunsigned int all: 1;\n+};\n+#define DEINIT_CB_INIT { NULL, 0, 0, 0 }\n+\n+static void deinit_submodule(const struct cache_entry *list_item,\n+\t\t\t     void *cb_data)\n+{\n+\tstruct deinit_cb *info = cb_data;\n+\tconst struct submodule *sub;\n+\tchar *displaypath = NULL;\n+\tstruct child_process cp_config = CHILD_PROCESS_INIT;\n+\tstruct strbuf sb_config = STRBUF_INIT;\n+\tchar *sm_path = xstrdup(list_item->name);\n+\tchar *sub_git_dir = xstrfmt(\"%s/.git\", sm_path);\n+\n+\tsub = submodule_from_path(null_sha1, sm_path);\n+\n+\tif (!sub->name)\n+\t\tgoto cleanup;\n+\n+\tdisplaypath = get_submodule_displaypath(sm_path, info->prefix);\n+\n+\t/* remove the submodule work tree (unless the user already did it) */\n+\tif (is_directory(sm_path)) {\n+\t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\n+\t\t/* protect submodules containing a .git directory */\n+\t\tif (is_git_directory(sub_git_dir))\n+\t\t\tdie(_(\"Submodule work tree '%s' contains a .git \"\n+\t\t\t      \"directory use 'rm -rf' if you really want \"\n+\t\t\t      \"to remove it including all of its history\"),\n+\t\t\t      displaypath);\n+\n+\t\tif (!info->force) {\n+\t\t\tstruct child_process cp_rm = CHILD_PROCESS_INIT;\n+\t\t\tcp_rm.git_cmd = 1;\n+\t\t\targv_array_pushl(&cp_rm.args, \"rm\", \"-qn\", sm_path,\n+\t\t\t\t\t NULL);\n+\n+\t\t\t/* list_item->name is changed by cmd_rm() below */\n+\t\t\tif (run_command(&cp_rm))\n+\t\t\t\tdie(_(\"Submodule work tree '%s' contains local \"\n+\t\t\t\t      \"modifications; use '-f' to discard them\"),\n+\t\t\t\t      displaypath);\n+\t\t}\n+\n+\t\tcp.use_shell = 1;\n+\t\targv_array_pushl(&cp.args, \"rm\", \"-rf\", sm_path, NULL);\n+\t\tif (!run_command(&cp)) {\n+\t\t\tif (!info->quiet)\n+\t\t\t\tprintf(_(\"Cleared directory '%s'\\n\"),\n+\t\t\t\t\t displaypath);\n+\t\t} else {\n+\t\t\tif (!info->quiet)\n+\t\t\t\tprintf(_(\"Could not remove submodule work tree '%s'\\n\"),\n+\t\t\t\t\t displaypath);\n+\t\t}\n+\t}\n+\n+\tif (mkdir(sm_path, 0700))\n+\t\tdie(_(\"could not create empty submodule directory %s\"),\n+\t\t      displaypath);\n+\n+\tcp_config.git_cmd = 1;\n+\targv_array_pushl(&cp_config.args, \"config\", \"--get-regexp\", NULL);\n+\targv_array_pushf(&cp_config.args, \"submodule.%s\\\\.\", sub->name);\n+\n+\t/* remove the .git/config entries (unless the user already did it) */\n+\tif (!capture_command(&cp_config, &sb_config, 0) && sb_config.len) {\n+\t\tchar *sub_key = xstrfmt(\"submodule.%s\", sub->name);\n+\t\t/*\n+\t\t * remove the whole section so we have a clean state when\n+\t\t * the user later decides to init this submodule again\n+\t\t */\n+\t\tgit_config_rename_section_in_file(NULL, sub_key, NULL);\n+\t\tif (!info->quiet)\n+\t\t\tprintf(_(\"Submodule '%s' (%s) unregistered for path '%s'\\n\"),\n+\t\t\t\t sub->name, sub->url, displaypath);\n+\t\tfree(sub_key);\n+\t}\n+\n+cleanup:\n+\tfree(displaypath);\n+\tfree(sub_git_dir);\n+\tfree(sm_path);\n+\tstrbuf_release(&sb_config);\n+}\n+\n+static int module_deinit(int argc, const char **argv, const char *prefix)\n+{\n+\tstruct deinit_cb info = DEINIT_CB_INIT;\n+\tstruct pathspec pathspec;\n+\tstruct module_list list = MODULE_LIST_INIT;\n+\tint quiet = 0;\n+\tint force = 0;\n+\tint all = 0;\n+\n+\tstruct option module_deinit_options[] = {\n+\t\tOPT__QUIET(&quiet, N_(\"Suppress submodule status output\")),\n+\t\tOPT__FORCE(&force, N_(\"Remove submodule working trees even if they contain local changes\")),\n+\t\tOPT_BOOL(0, \"all\", &all, N_(\"Unregister all submodules\")),\n+\t\tOPT_END()\n+\t};\n+\n+\tconst char *const git_submodule_helper_usage[] = {\n+\t\tN_(\"git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]\"),\n+\t\tNULL\n+\t};\n+\n+\targc = parse_options(argc, argv, prefix, module_deinit_options,\n+\t\t\t     git_submodule_helper_usage, 0);\n+\n+\tif (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n+\t\tBUG(\"module_list_compute should not choke on empty pathspec\");\n+\n+\tinfo.prefix = prefix;\n+\tinfo.quiet = !!quiet;\n+\tinfo.all = !!all;\n+\tinfo.force = !!force;\n+\n+\tif (all && argc) {\n+\t\terror(\"pathspec and --all are incompatible\");\n+\t\tusage_with_options(git_submodule_helper_usage,\n+\t\t\t\t   module_deinit_options);\n+\t}\n+\n+\tif (!argc && !all)\n+\t\tdie(_(\"Use '--all' if you really want to deinitialize all submodules\"));\n+\n+\tgitmodules_config();\n+\tfor_each_submodule_list(list, deinit_submodule, &info);\n+\n+\treturn 0;\n+}\n+\n static int module_name(int argc, const char **argv, const char *prefix)\n {\n \tconst struct submodule *sub;\n@@ -1644,6 +1783,7 @@ static struct cmd_struct commands[] = {\n \t{\"status\", module_status, SUPPORT_SUPER_PREFIX},\n \t{\"print-default-remote\", print_default_remote, 0},\n \t{\"sync\", module_sync, SUPPORT_SUPER_PREFIX},\n+\t{\"deinit\", module_deinit, SUPPORT_SUPER_PREFIX},\n \t{\"remote-branch\", resolve_remote_submodule_branch, 0},\n \t{\"push-check\", push_check, 0},\n \t{\"absorb-git-dirs\", absorb_git_dirs, SUPPORT_SUPER_PREFIX},\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 33b4b7306..2b2c6f5da 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -427,60 +427,7 @@ cmd_deinit()\n \t\tshift\n \tdone\n \n-\tif test -n \"$deinit_all\" && test \"$#\" -ne 0\n-\tthen\n-\t\techo >&2 \"$(eval_gettext \"pathspec and --all are incompatible\")\"\n-\t\tusage\n-\tfi\n-\tif test $# = 0 && test -z \"$deinit_all\"\n-\tthen\n-\t\tdie \"$(eval_gettext \"Use '--all' if you really want to deinitialize all submodules\")\"\n-\tfi\n-\n-\t{\n-\t\tgit submodule--helper list --prefix \"$wt_prefix\" \"$@\" ||\n-\t\techo \"#unmatched\" $?\n-\t} |\n-\twhile read -r mode sha1 stage sm_path\n-\tdo\n-\t\tdie_if_unmatched \"$mode\" \"$sha1\"\n-\t\tname=$(git submodule--helper name \"$sm_path\") || exit\n-\n-\t\tdisplaypath=$(git submodule--helper relative-path \"$sm_path\" \"$wt_prefix\")\n-\n-\t\t# Remove the submodule work tree (unless the user already did it)\n-\t\tif test -d \"$sm_path\"\n-\t\tthen\n-\t\t\t# Protect submodules containing a .git directory\n-\t\t\tif test -d \"$sm_path/.git\"\n-\t\t\tthen\n-\t\t\t\tdie \"$(eval_gettext \"\\\n-Submodule work tree '\\$displaypath' contains a .git directory\n-(use 'rm -rf' if you really want to remove it including all of its history)\")\"\n-\t\t\tfi\n-\n-\t\t\tif test -z \"$force\"\n-\t\t\tthen\n-\t\t\t\tgit rm -qn \"$sm_path\" ||\n-\t\t\t\tdie \"$(eval_gettext \"Submodule work tree '\\$displaypath' contains local modifications; use '-f' to discard them\")\"\n-\t\t\tfi\n-\t\t\trm -rf \"$sm_path\" &&\n-\t\t\tsay \"$(eval_gettext \"Cleared directory '\\$displaypath'\")\" ||\n-\t\t\tsay \"$(eval_gettext \"Could not remove submodule work tree '\\$displaypath'\")\"\n-\t\tfi\n-\n-\t\tmkdir \"$sm_path\" || say \"$(eval_gettext \"Could not create empty submodule directory '\\$displaypath'\")\"\n-\n-\t\t# Remove the .git/config entries (unless the user already did it)\n-\t\tif test -n \"$(git config --get-regexp submodule.\"$name\\.\")\"\n-\t\tthen\n-\t\t\t# Remove the whole section so we have a clean state when\n-\t\t\t# the user later decides to init this submodule again\n-\t\t\turl=$(git config submodule.\"$name\".url)\n-\t\t\tgit config --remove-section submodule.\"$name\" 2>/dev/null &&\n-\t\t\tsay \"$(eval_gettext \"Submodule '\\$name' (\\$url) unregistered for path '\\$displaypath'\")\"\n-\t\tfi\n-\tdone\n+\tgit ${wt_prefix:+-C \"$wt_prefix\"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${prefix:+--prefix \"$prefix\"} ${force:+--force} ${deinit_all:+--all} \"$@\"\n }\n \n is_tip_reachable () (\n-- \n2.13.0\n\n"},{"id":"322620","messageId":"20170619215025.10086-4-pc44800@gmail.com","threadId":"46213","inReplyTo":"20170619215025.10086-1-pc44800@gmail.com","subject":"[GSoC][PATCH 4/6] submodule: port submodule subcommand status","fromName":"Prathamesh Chavan","fromEmail":"pc44800@gmail.com","sentAt":"2017-06-19T21:50:23Z","receivedAt":"2017-06-19T21:51:13Z","isPatch":true,"sender":{"key":"pc44800@gmail.com","avatar":"https://avatars.githubusercontent.com/u/17272661?v=4"},"body":"The mechanism used for porting submodule subcommand 'status'\nis similar to that used for subcommand 'foreach'.\nThe function cmd_status from git-submodule is ported to three\nfunctions in the builtin submodule--helper namely: module_status,\nfor_each_submodule_list and status_submodule.\n\nprint_status is also introduced for handling the output of\nthe subcommand and also to reduce the code size.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Stefan Beller <sbeller@google.com>\nSigned-off-by: Prathamesh Chavan <pc44800@gmail.com>\n---\n builtin/submodule--helper.c | 152 ++++++++++++++++++++++++++++++++++++++++++++\n git-submodule.sh            |  49 +-------------\n 2 files changed, 153 insertions(+), 48 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 6fd861e42..78b21ab22 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -566,6 +566,157 @@ static int module_init(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+struct status_cb {\n+\tconst char *prefix;\n+\tunsigned int quiet: 1;\n+\tunsigned int recursive: 1;\n+\tunsigned int cached: 1;\n+};\n+#define STATUS_CB_INIT { NULL, 0, 0, 0 }\n+\n+static void print_status(struct status_cb *info, char state, const char *path,\n+\t\t\t char *sub_sha1, char *displaypath)\n+{\n+\tif (info->quiet)\n+\t\treturn;\n+\n+\tprintf(\"%c%s %s\", state, sub_sha1, displaypath);\n+\n+\tif (state == ' ' || state == '+') {\n+\t\tstruct argv_array name_rev_args = ARGV_ARRAY_INIT;\n+\n+\t\targv_array_pushl(&name_rev_args, \"print-name-rev\",\n+\t\t\t\t path, sub_sha1, NULL);\n+\t\tprint_name_rev(name_rev_args.argc, name_rev_args.argv,\n+\t\t\t       info->prefix);\n+\t} else {\n+\t\tprintf(\"\\n\");\n+\t}\n+}\n+\n+static void status_submodule(const struct cache_entry *list_item, void *cb_data)\n+{\n+\tstruct status_cb *info = cb_data;\n+\tchar *sub_sha1 = xstrdup(oid_to_hex(&list_item->oid));\n+\tchar *displaypath;\n+\tstruct argv_array diff_files_args = ARGV_ARRAY_INIT;\n+\n+\tif (!submodule_from_path(null_sha1, list_item->name))\n+\t\tdie(_(\"no submodule mapping found in .gitmodules for path '%s'\"),\n+\t\t      list_item->name);\n+\n+\tdisplaypath = get_submodule_displaypath(list_item->name, info->prefix);\n+\n+\tif (list_item->ce_flags) {\n+\t\tprint_status(info, 'U', list_item->name,\n+\t\t\t     sha1_to_hex(null_sha1), displaypath);\n+\t\tgoto cleanup;\n+\t}\n+\n+\tif (!is_submodule_initialized(list_item->name)) {\n+\t\tprint_status(info, '-', list_item->name, sub_sha1, displaypath);\n+\t\tgoto cleanup;\n+\t}\n+\n+\targv_array_pushl(&diff_files_args, \"diff-files\",\n+\t\t\t \"--ignore-submodules=dirty\", \"--quiet\", \"--\",\n+\t\t\t list_item->name, NULL);\n+\n+\tif (!cmd_diff_files(diff_files_args.argc, diff_files_args.argv,\n+\t\t\t    info->prefix)) {\n+\t\tprint_status(info, ' ', list_item->name, sub_sha1, displaypath);\n+\t} else {\n+\t\tif (!info->cached) {\n+\t\t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\t\t\tstruct strbuf sb = STRBUF_INIT;\n+\n+\t\t\tprepare_submodule_repo_env(&cp.env_array);\n+\t\t\tcp.git_cmd = 1;\n+\t\t\tcp.dir = list_item->name;\n+\n+\t\t\targv_array_pushl(&cp.args, \"rev-parse\",\n+\t\t\t\t\t \"--verify\", \"HEAD\", NULL);\n+\n+\t\t\tif (capture_command(&cp, &sb, 0))\n+\t\t\t\tdie(_(\"could not run 'git rev-parse --verify\"\n+\t\t\t\t      \"HEAD' in submodule %s\"),\n+\t\t\t\t      list_item->name);\n+\n+\t\t\tstrbuf_strip_suffix(&sb, \"\\n\");\n+\t\t\tprint_status(info, '+', list_item->name, sb.buf,\n+\t\t\t\t     displaypath);\n+\t\t\tstrbuf_release(&sb);\n+\t\t} else {\n+\t\t\tprint_status(info, '+', list_item->name, sub_sha1,\n+\t\t\t\t     displaypath);\n+\t\t}\n+\t}\n+\n+\tif (info->recursive) {\n+\t\tstruct child_process cpr = CHILD_PROCESS_INIT;\n+\n+\t\tcpr.git_cmd = 1;\n+\t\tcpr.dir = list_item->name;\n+\t\tprepare_submodule_repo_env(&cpr.env_array);\n+\n+\t\targv_array_pushl(&cpr.args, \"--super-prefix\", displaypath,\n+\t\t\t\t \"submodule--helper\", \"status\", \"--recursive\",\n+\t\t\t\t NULL);\n+\n+\t\tif (info->cached)\n+\t\t\targv_array_push(&cpr.args, \"--cached\");\n+\n+\t\tif (info->quiet)\n+\t\t\targv_array_push(&cpr.args, \"--quiet\");\n+\n+\t\tif (run_command(&cpr))\n+\t\t\tdie(_(\"failed to recurse into submodule '%s'\"),\n+\t\t\t      list_item->name);\n+\t}\n+\n+cleanup:\n+\tfree(displaypath);\n+\tfree(sub_sha1);\n+}\n+\n+static int module_status(int argc, const char **argv, const char *prefix)\n+{\n+\tstruct status_cb info = STATUS_CB_INIT;\n+\tstruct pathspec pathspec;\n+\tstruct module_list list = MODULE_LIST_INIT;\n+\tint quiet = 0;\n+\tint cached = 0;\n+\tint recursive = 0;\n+\n+\tstruct option module_status_options[] = {\n+\t\tOPT__QUIET(&quiet, N_(\"Suppress submodule status output\")),\n+\t\tOPT_BOOL(0, \"cached\", &cached, N_(\"Use commit stored in the index instead of the one stored in the submodule HEAD\")),\n+\t\tOPT_BOOL(0, \"recursive\", &recursive, N_(\"Recurse into nested submodules\")),\n+\t\tOPT_END()\n+\t};\n+\n+\tconst char *const git_submodule_helper_usage[] = {\n+\t\tN_(\"git submodule status [--quiet] [--cached] [--recursive] [<path>]\"),\n+\t\tNULL\n+\t};\n+\n+\targc = parse_options(argc, argv, prefix, module_status_options,\n+\t\t\t     git_submodule_helper_usage, 0);\n+\n+\tif (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n+\t\treturn 1;\n+\n+\tinfo.prefix = prefix;\n+\tinfo.quiet = !!quiet;\n+\tinfo.recursive = !!recursive;\n+\tinfo.cached = !!cached;\n+\n+\tgitmodules_config();\n+\tfor_each_submodule_list(list, status_submodule, &info);\n+\n+\treturn 0;\n+}\n+\n static int module_name(int argc, const char **argv, const char *prefix)\n {\n \tconst struct submodule *sub;\n@@ -1312,6 +1463,7 @@ static struct cmd_struct commands[] = {\n \t{\"resolve-relative-url-test\", resolve_relative_url_test, 0},\n \t{\"print-name-rev\", print_name_rev, 0},\n \t{\"init\", module_init, SUPPORT_SUPER_PREFIX},\n+\t{\"status\", module_status, SUPPORT_SUPER_PREFIX},\n \t{\"remote-branch\", resolve_remote_submodule_branch, 0},\n \t{\"push-check\", push_check, 0},\n \t{\"absorb-git-dirs\", absorb_git_dirs, SUPPORT_SUPER_PREFIX},\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 091051891..a24b1b91b 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1004,54 +1004,7 @@ cmd_status()\n \t\tshift\n \tdone\n \n-\t{\n-\t\tgit submodule--helper list --prefix \"$wt_prefix\" \"$@\" ||\n-\t\techo \"#unmatched\" $?\n-\t} |\n-\twhile read -r mode sha1 stage sm_path\n-\tdo\n-\t\tdie_if_unmatched \"$mode\" \"$sha1\"\n-\t\tname=$(git submodule--helper name \"$sm_path\") || exit\n-\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n-\t\tif test \"$stage\" = U\n-\t\tthen\n-\t\t\tsay \"U$sha1 $displaypath\"\n-\t\t\tcontinue\n-\t\tfi\n-\t\tif ! git submodule--helper is-active \"$sm_path\" ||\n-\t\t{\n-\t\t\t! test -d \"$sm_path\"/.git &&\n-\t\t\t! test -f \"$sm_path\"/.git\n-\t\t}\n-\t\tthen\n-\t\t\tsay \"-$sha1 $displaypath\"\n-\t\t\tcontinue;\n-\t\tfi\n-\t\tif git diff-files --ignore-submodules=dirty --quiet -- \"$sm_path\"\n-\t\tthen\n-\t\t\trevname=$(git submodule--helper print-name-rev \"$sm_path\" \"$sha1\")\n-\t\t\tsay \" $sha1 $displaypath$revname\"\n-\t\telse\n-\t\t\tif test -z \"$cached\"\n-\t\t\tthen\n-\t\t\t\tsha1=$(sanitize_submodule_env; cd \"$sm_path\" && git rev-parse --verify HEAD)\n-\t\t\tfi\n-\t\t\trevname=$(git submodule--helper print-name-rev \"$sm_path\" \"$sha1\")\n-\t\t\tsay \"+$sha1 $displaypath$revname\"\n-\t\tfi\n-\n-\t\tif test -n \"$recursive\"\n-\t\tthen\n-\t\t\t(\n-\t\t\t\tprefix=\"$displaypath/\"\n-\t\t\t\tsanitize_submodule_env\n-\t\t\t\twt_prefix=\n-\t\t\t\tcd \"$sm_path\" &&\n-\t\t\t\teval cmd_status\n-\t\t\t) ||\n-\t\t\tdie \"$(eval_gettext \"Failed to recurse into submodule path '\\$sm_path'\")\"\n-\t\tfi\n-\tdone\n+\tgit ${wt_prefix:+-C \"$wt_prefix\"} ${prefix:+--super-prefix \"$prefix\"} submodule--helper status ${GIT_QUIET:+--quiet} ${cached:+--cached} ${recursive:+--recursive} \"$@\"\n }\n #\n # Sync remote urls for submodules\n-- \n2.13.0\n\n"},{"id":"322621","messageId":"20170619215025.10086-5-pc44800@gmail.com","threadId":"46213","inReplyTo":"20170619215025.10086-1-pc44800@gmail.com","subject":"[GSoC][PATCH 5/6] submodule: port submodule subcommand sync from shell to C","fromName":"Prathamesh Chavan","fromEmail":"pc44800@gmail.com","sentAt":"2017-06-19T21:50:24Z","receivedAt":"2017-06-19T21:51:15Z","isPatch":true,"sender":{"key":"pc44800@gmail.com","avatar":"https://avatars.githubusercontent.com/u/17272661?v=4"},"body":"The mechanism used for porting the submodule subcommand 'sync' is\nsimilar to that of 'foreach', where we split the function cmd_sync\nfrom shell into three functions in C, module_sync,\nfor_each_submodule_list and sync_submodule.\n\nprint_default_remote is introduced as a submodule--helper\nsubcommand for getting the default remote as stdout.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Stefan Beller <sbeller@google.com>\nSigned-off-by: Prathamesh Chavan <pc44800@gmail.com>\n---\n builtin/submodule--helper.c | 180 ++++++++++++++++++++++++++++++++++++++++++++\n git-submodule.sh            |  56 +-------------\n 2 files changed, 181 insertions(+), 55 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 78b21ab22..e10cac462 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -43,6 +43,20 @@ static char *get_default_remote(void)\n \treturn ret;\n }\n \n+static int print_default_remote(int argc, const char **argv, const char *prefix)\n+{\n+\tconst char *remote;\n+\n+\tif (argc != 1)\n+\t\tdie(_(\"submodule--helper print-default-remote takes no arguments\"));\n+\n+\tremote = get_default_remote();\n+\tif (remote)\n+\t\tputs(remote);\n+\n+\treturn 0;\n+}\n+\n static int starts_with_dot_slash(const char *str)\n {\n \treturn str[0] == '.' && is_dir_sep(str[1]);\n@@ -311,6 +325,25 @@ static int print_name_rev(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static char *get_up_path(const char *path)\n+{\n+\tint i = count_slashes(path);\n+\tstruct strbuf sb = STRBUF_INIT;\n+\n+\twhile (i--)\n+\t\tstrbuf_addstr(&sb, \"../\");\n+\n+\t/*\n+\t *Check if 'path' ends with slash or not\n+\t *for having the same output for dir/sub_dir\n+\t *and dir/sub_dir/\n+\t */\n+\tif (!is_dir_sep(path[i - 1]))\n+\t\tstrbuf_addstr(&sb, \"../\");\n+\n+\treturn strbuf_detach(&sb, NULL);\n+}\n+\n struct module_list {\n \tconst struct cache_entry **entries;\n \tint alloc, nr;\n@@ -736,6 +769,151 @@ static int module_name(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+struct sync_cb {\n+\tconst char *prefix;\n+\tunsigned int quiet: 1;\n+\tunsigned int recursive: 1;\n+};\n+#define SYNC_CB_INIT { NULL, 0, 0 }\n+\n+static void sync_submodule(const struct cache_entry *list_item, void *cb_data)\n+{\n+\tstruct sync_cb *info = cb_data;\n+\tconst struct submodule *sub;\n+\tchar *sub_key, *remote_key;\n+\tchar *url, *sub_origin_url, *super_config_url, *displaypath;\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\n+\tif (!is_submodule_initialized(list_item->name))\n+\t\treturn;\n+\n+\tsub = submodule_from_path(null_sha1, list_item->name);\n+\n+\tif (!sub->url)\n+\t\tdie(_(\"no url found for submodule path '%s' in .gitmodules\"),\n+\t\t      list_item->name);\n+\n+\turl = xstrdup(sub->url);\n+\n+\tif (starts_with_dot_dot_slash(url) || starts_with_dot_slash(url)) {\n+\t\tchar *remote_url, *up_path;\n+\t\tchar *remote = get_default_remote();\n+\t\tchar *remote_key = xstrfmt(\"remote.%s.url\", remote);\n+\t\tfree(remote);\n+\n+\t\tif (git_config_get_string(remote_key, &remote_url))\n+\t\t\tremote_url = xgetcwd();\n+\t\tup_path = get_up_path(list_item->name);\n+\t\tsub_origin_url = relative_url(remote_url, url, up_path);\n+\t\tsuper_config_url = relative_url(remote_url, url, NULL);\n+\t\tfree(remote_key);\n+\t\tfree(up_path);\n+\t\tfree(remote_url);\n+\t} else {\n+\t\tsub_origin_url = xstrdup(url);\n+\t\tsuper_config_url = xstrdup(url);\n+\t}\n+\n+\tdisplaypath = get_submodule_displaypath(list_item->name, info->prefix);\n+\n+\tif (!info->quiet)\n+\t\tprintf(_(\"Synchronizing submodule url for '%s'\\n\"),\n+\t\t\t displaypath);\n+\n+\tsub_key = xstrfmt(\"submodule.%s.url\", sub->name);\n+\tif (git_config_set_gently(sub_key, super_config_url))\n+\t\tdie(_(\"failed to register url for submodule path '%s'\"),\n+\t\t      displaypath);\n+\n+\tif (!is_submodule_populated_gently(list_item->name, NULL))\n+\t\tgoto cleanup;\n+\n+\tprepare_submodule_repo_env(&cp.env_array);\n+\tcp.git_cmd = 1;\n+\tcp.dir = list_item->name;\n+\targv_array_pushl(&cp.args, \"submodule--helper\",\n+\t\t\t \"print-default-remote\", NULL);\n+\tif (capture_command(&cp, &sb, 0))\n+\t\tdie(_(\"failed to get the default remote for submodule '%s'\"),\n+\t\t      list_item->name);\n+\n+\tstrbuf_strip_suffix(&sb, \"\\n\");\n+\tremote_key = xstrfmt(\"remote.%s.url\", sb.buf);\n+\tstrbuf_release(&sb);\n+\n+\tchild_process_init(&cp);\n+\tprepare_submodule_repo_env(&cp.env_array);\n+\tcp.git_cmd = 1;\n+\tcp.dir = list_item->name;\n+\targv_array_pushl(&cp.args, \"config\", remote_key, sub_origin_url, NULL);\n+\tif (run_command(&cp))\n+\t\tdie(_(\"failed to update remote for submodule '%s'\"),\n+\t\t      list_item->name);\n+\n+\tif (info->recursive) {\n+\t\tstruct child_process cpr = CHILD_PROCESS_INIT;\n+\n+\t\tcpr.git_cmd = 1;\n+\t\tcpr.dir = list_item->name;\n+\t\tprepare_submodule_repo_env(&cpr.env_array);\n+\n+\t\targv_array_pushl(&cpr.args, \"--super-prefix\", displaypath,\n+\t\t\t\t \"submodule--helper\", \"sync\", \"--recursive\",\n+\t\t\t\t NULL);\n+\n+\t\tif (info->quiet)\n+\t\t\targv_array_push(&cpr.args, \"--quiet\");\n+\n+\t\tif (run_command(&cpr))\n+\t\t\tdie(_(\"failed to recurse into submodule '%s'\"),\n+\t\t\t      list_item->name);\n+\t}\n+\n+cleanup:\n+\tfree(sub_key);\n+\tfree(url);\n+\tfree(super_config_url);\n+\tfree(displaypath);\n+\tfree(sub_origin_url);\n+}\n+\n+static int module_sync(int argc, const char **argv, const char *prefix)\n+{\n+\tstruct sync_cb info = SYNC_CB_INIT;\n+\tstruct pathspec pathspec;\n+\tstruct module_list list = MODULE_LIST_INIT;\n+\tint quiet = 0;\n+\tint recursive = 0;\n+\n+\tstruct option module_sync_options[] = {\n+\t\tOPT__QUIET(&quiet, N_(\"Suppress output of synchronizing submodule url\")),\n+\t\tOPT_BOOL(0, \"recursive\", &recursive,\n+\t\t\tN_(\"Recurse into nested submodules\")),\n+\t\tOPT_END()\n+\t};\n+\n+\tconst char *const git_submodule_helper_usage[] = {\n+\t\tN_(\"git submodule--helper sync [--quiet] [--recursive] [<path>]\"),\n+\t\tNULL\n+\t};\n+\n+\targc = parse_options(argc, argv, prefix, module_sync_options,\n+\t\t\t     git_submodule_helper_usage, 0);\n+\n+\tif (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n+\t\treturn 1;\n+\n+\tinfo.prefix = prefix;\n+\tinfo.quiet = !!quiet;\n+\tinfo.recursive = !!recursive;\n+\n+\tgitmodules_config();\n+\tfor_each_submodule_list(list, sync_submodule, &info);\n+\n+\treturn 0;\n+}\n+\n static int clone_submodule(const char *path, const char *gitdir, const char *url,\n \t\t\t   const char *depth, struct string_list *reference,\n \t\t\t   int quiet, int progress)\n@@ -1464,6 +1642,8 @@ static struct cmd_struct commands[] = {\n \t{\"print-name-rev\", print_name_rev, 0},\n \t{\"init\", module_init, SUPPORT_SUPER_PREFIX},\n \t{\"status\", module_status, SUPPORT_SUPER_PREFIX},\n+\t{\"print-default-remote\", print_default_remote, 0},\n+\t{\"sync\", module_sync, SUPPORT_SUPER_PREFIX},\n \t{\"remote-branch\", resolve_remote_submodule_branch, 0},\n \t{\"push-check\", push_check, 0},\n \t{\"absorb-git-dirs\", absorb_git_dirs, SUPPORT_SUPER_PREFIX},\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex a24b1b91b..33b4b7306 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1036,63 +1036,9 @@ cmd_sync()\n \t\t\t;;\n \t\tesac\n \tdone\n-\tcd_to_toplevel\n-\t{\n-\t\tgit submodule--helper list --prefix \"$wt_prefix\" \"$@\" ||\n-\t\techo \"#unmatched\" $?\n-\t} |\n-\twhile read -r mode sha1 stage sm_path\n-\tdo\n-\t\tdie_if_unmatched \"$mode\" \"$sha1\"\n-\n-\t\t# skip inactive submodules\n-\t\tif ! git submodule--helper is-active \"$sm_path\"\n-\t\tthen\n-\t\t\tcontinue\n-\t\tfi\n-\n-\t\tname=$(git submodule--helper name \"$sm_path\")\n-\t\turl=$(git config -f .gitmodules --get submodule.\"$name\".url)\n-\n-\t\t# Possibly a url relative to parent\n-\t\tcase \"$url\" in\n-\t\t./*|../*)\n-\t\t\t# rewrite foo/bar as ../.. to find path from\n-\t\t\t# submodule work tree to superproject work tree\n-\t\t\tup_path=\"$(printf '%s\\n' \"$sm_path\" | sed \"s/[^/][^/]*/../g\")\" &&\n-\t\t\t# guarantee a trailing /\n-\t\t\tup_path=${up_path%/}/ &&\n-\t\t\t# path from submodule work tree to submodule origin repo\n-\t\t\tsub_origin_url=$(git submodule--helper resolve-relative-url \"$url\" \"$up_path\") &&\n-\t\t\t# path from superproject work tree to submodule origin repo\n-\t\t\tsuper_config_url=$(git submodule--helper resolve-relative-url \"$url\") || exit\n-\t\t\t;;\n-\t\t*)\n-\t\t\tsub_origin_url=\"$url\"\n-\t\t\tsuper_config_url=\"$url\"\n-\t\t\t;;\n-\t\tesac\n \n-\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n-\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n-\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n-\n-\t\tif test -e \"$sm_path\"/.git\n-\t\tthen\n-\t\t(\n-\t\t\tsanitize_submodule_env\n-\t\t\tcd \"$sm_path\"\n-\t\t\tremote=$(get_default_remote)\n-\t\t\tgit config remote.\"$remote\".url \"$sub_origin_url\"\n+\tgit ${wt_prefix:+-C \"$wt_prefix\"} ${prefix:+--super-prefix \"$prefix\"} submodule--helper sync ${GIT_QUIET:+--quiet} ${recursive:+--recursive} \"$@\"\n \n-\t\t\tif test -n \"$recursive\"\n-\t\t\tthen\n-\t\t\t\tprefix=\"$prefix$sm_path/\"\n-\t\t\t\teval cmd_sync\n-\t\t\tfi\n-\t\t)\n-\t\tfi\n-\tdone\n }\n \n cmd_absorbgitdirs()\n-- \n2.13.0\n\n"},{"id":"322629","messageId":"CAH5451n4XDdeAz4T7aAsaSC00hnZ53Gb7j0CSiTg4QLUZKvxXw@mail.gmail.com","threadId":"46213","inReplyTo":"CAME+mvUQJFneV7b1G7zmAidP-5L=nimvY43V0ug-Gtesr83tzg@mail.gmail.com","subject":"Re: [GSoC] Update: Week 5","fromName":"Andrew Ardill","fromEmail":"andrew.ardill@gmail.com","sentAt":"2017-06-20T00:01:29Z","receivedAt":"2017-06-20T00:02:16Z","isPatch":false,"sender":{"key":"andrew.ardill@gmail.com","avatar":"https://gravatar.com/avatar/da14cb7c091dd44dc6c63a4d3361b149acaf25226dc78eb4131a17b93d9b0993?d=mp&s=160"},"body":"On 20 June 2017 at 07:41, Prathamesh Chavan <pc44800@gmail.com> wrote:\n\n>    But as communicating between child_process is still an issue\n>    and so there was no simple was to current carry out the\n>    porting. And hence, a hack was used instead. But after\n>    discussing it, instead using the repository-object patch\n>    series will help to resolve these issues in this situation.\n\nJust wondering, does that mean that your patch series is dependent on\nthe repository-object one? I saw some discussion around it recently\nbut couldn't see it in the latest whats cooking so maybe I missed what\nhas happened to it.\n\nReally enjoying your updates, by the way, they are very clear and show\nwhat looks like great progress!\n\nRegards,\n\nAndrew Ardill\n"},{"id":"322630","messageId":"20170620003827.GB194323@google.com","threadId":"46213","inReplyTo":"CAH5451n4XDdeAz4T7aAsaSC00hnZ53Gb7j0CSiTg4QLUZKvxXw@mail.gmail.com","subject":"Re: [GSoC] Update: Week 5","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-06-20T00:38:27Z","receivedAt":"2017-06-20T00:38:35Z","isPatch":false,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 06/20, Andrew Ardill wrote:\n> On 20 June 2017 at 07:41, Prathamesh Chavan <pc44800@gmail.com> wrote:\n> \n> >    But as communicating between child_process is still an issue\n> >    and so there was no simple was to current carry out the\n> >    porting. And hence, a hack was used instead. But after\n> >    discussing it, instead using the repository-object patch\n> >    series will help to resolve these issues in this situation.\n> \n> Just wondering, does that mean that your patch series is dependent on\n> the repository-object one? I saw some discussion around it recently\n> but couldn't see it in the latest whats cooking so maybe I missed what\n> has happened to it.\n> \n\nDue to some of the discussion (and finding a bug with how git_path works\nwith worktrees) I decided to break the series up into smaller bits since\nthe original series was 30+ patches.  Once 'bw/config-h' and\n'bw/ls-files-sans-the-index' have been merged into next I'll probably\nsend out v3 of the repository object series.\n\n-- \nBrandon Williams\n"},{"id":"322744","messageId":"CAGZ79kb7XTbJ5wHhRwXKURDU3xj_3mHFFmjxS1G_T2X_BoG=dQ@mail.gmail.com","threadId":"46213","inReplyTo":"20170619215025.10086-1-pc44800@gmail.com","subject":"Re: [GSoC][PATCH 1/6] dir: create function count_slashes","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-06-20T17:20:46Z","receivedAt":"2017-06-20T17:20:52Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Mon, Jun 19, 2017 at 2:50 PM, Prathamesh Chavan <pc44800@gmail.com> wrote:\n> Similar functions exist in apply.c and builtin/show-branch.c for\n> counting the number of slashes in a string. Also in the later\n> patches, we introduce a third caller for the same. Hence, we unify\n> it now by cleaning the existing functions and declaring a common\n> function count_slashes in dir.h and implementing it in dir.c to\n> remove this code duplication.\n>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Stefan Beller <sbeller@google.com>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> Signed-off-by: Prathamesh Chavan <pc44800@gmail.com>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n> The complete build report of this is available at:\n> https://travis-ci.org/pratham-pc/git/builds/\n> Branch: All-patch-series\n> Build #111\n\nThis patch was sent separately a couple days ago, see\nthe latest \"What's cooking in git.git\" (Jun 2017, #05; Mon, 19)\nhttps://public-inbox.org/git/xmqqh8zbspm7.fsf@gitster.mtv.corp.google.com/\n\n  * pc/dir-count-slashes (2017-06-12) 1 commit\n    (merged to 'next' on 2017-06-19 at 57351a2771)\n   + dir: create function count_slashes()\n\n   Three instances of the same helper function have been consolidated\n   to one.\n\n   Will merge to 'master'.\n\nso if you pull Junios git and rebase on top of his master branch\nthis should be already included there. (In that case there is no need\nfor you to carry this patch. It is just cumbersome for you and might\nconfuse Junio, which patches exactly to apply)\n\nThanks,\nStefan\n"},{"id":"322745","messageId":"CAGZ79kY=Ws_8BZyLySh0e2ZmUk70gP4RNu=fbzMqRh8n6sLg9Q@mail.gmail.com","threadId":"46213","inReplyTo":"20170619215025.10086-5-pc44800@gmail.com","subject":"Re: [GSoC][PATCH 5/6] submodule: port submodule subcommand sync from shell to C","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-06-20T17:35:53Z","receivedAt":"2017-06-20T17:36:10Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Mon, Jun 19, 2017 at 2:50 PM, Prathamesh Chavan <pc44800@gmail.com> wrote:\n> The mechanism used for porting the submodule subcommand 'sync' is\n> similar to that of 'foreach', where we split the function cmd_sync\n> from shell into three functions in C, module_sync,\n> for_each_submodule_list and sync_submodule.\n>\n> print_default_remote is introduced as a submodule--helper\n> subcommand for getting the default remote as stdout.\n>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Stefan Beller <sbeller@google.com>\n> Signed-off-by: Prathamesh Chavan <pc44800@gmail.com>\n> ---\n\nUp to this patch, all other patches look good to me,\nhere I stumbled upon a small nit.\n\n\n>  builtin/submodule--helper.c | 180 ++++++++++++++++++++++++++++++++++++++++++++\n>  git-submodule.sh            |  56 +-------------\n>  2 files changed, 181 insertions(+), 55 deletions(-)\n>\n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index 78b21ab22..e10cac462 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -43,6 +43,20 @@ static char *get_default_remote(void)\n>         return ret;\n>  }\n>\n> +static int print_default_remote(int argc, const char **argv, const char *prefix)\n> +{\n> +       const char *remote;\n> +\n> +       if (argc != 1)\n> +               die(_(\"submodule--helper print-default-remote takes no arguments\"));\n> +\n> +       remote = get_default_remote();\n> +       if (remote)\n> +               puts(remote);\n> +\n> +       return 0;\n> +}\n> +\n>  static int starts_with_dot_slash(const char *str)\n>  {\n>         return str[0] == '.' && is_dir_sep(str[1]);\n> @@ -311,6 +325,25 @@ static int print_name_rev(int argc, const char **argv, const char *prefix)\n>         return 0;\n>  }\n>\n> +static char *get_up_path(const char *path)\n> +{\n> +       int i = count_slashes(path);\n> +       struct strbuf sb = STRBUF_INIT;\n> +\n> +       while (i--)\n> +               strbuf_addstr(&sb, \"../\");\n> +\n> +       /*\n> +        *Check if 'path' ends with slash or not\n> +        *for having the same output for dir/sub_dir\n> +        *and dir/sub_dir/\n> +        */\n> +       if (!is_dir_sep(path[i - 1]))\n> +               strbuf_addstr(&sb, \"../\");\n> +\n> +       return strbuf_detach(&sb, NULL);\n> +}\n> +\n>  struct module_list {\n>         const struct cache_entry **entries;\n>         int alloc, nr;\n> @@ -736,6 +769,151 @@ static int module_name(int argc, const char **argv, const char *prefix)\n>         return 0;\n>  }\n>\n> +struct sync_cb {\n> +       const char *prefix;\n> +       unsigned int quiet: 1;\n> +       unsigned int recursive: 1;\n> +};\n> +#define SYNC_CB_INIT { NULL, 0, 0 }\n> +\n> +static void sync_submodule(const struct cache_entry *list_item, void *cb_data)\n> +{\n> +       struct sync_cb *info = cb_data;\n> +       const struct submodule *sub;\n> +       char *sub_key, *remote_key;\n> +       char *url, *sub_origin_url, *super_config_url, *displaypath;\n> +       struct strbuf sb = STRBUF_INIT;\n> +       struct child_process cp = CHILD_PROCESS_INIT;\n> +\n> +       if (!is_submodule_initialized(list_item->name))\n> +               return;\n> +\n> +       sub = submodule_from_path(null_sha1, list_item->name);\n> +\n> +       if (!sub->url)\n\n'sub' can be NULL as well, which when used to obtain the ->url\nwill crash. So we'd rather want to have (!sub || !sub->url).\n\nI looked through other use cases, others only need (!sub), so this\nthought did not hint at other bugs in the code base.\n\n\n> +               die(_(\"no url found for submodule path '%s' in .gitmodules\"),\n> +                     list_item->name);\n> +\n> +       url = xstrdup(sub->url);\n\nWhy do we need to duplicate the url here? As we are not modifying it\n(read: I did not spot the url modification), we could just use sub->url\ninstead, saving a variable.\n"},{"id":"322749","messageId":"20170620182225.GA60134@google.com","threadId":"46213","inReplyTo":"20170619215025.10086-2-pc44800@gmail.com","subject":"Re: [GSoC][PATCH 2/6] submodule--helper: introduce get_submodule_displaypath and for_each_submodule_list","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-06-20T18:22:25Z","receivedAt":"2017-06-20T18:22:32Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 06/20, Prathamesh Chavan wrote:\n> Functions get_submodule_displaypath and for_each_submodule_list\n> for using them in the later patches, related to porting submodule\n> subcommands from shell to C.\n> These new functions are also used in ported submodule subcommand\n> init\n\nI didn't see anything wrong with these patches, but one small nit is\nthat this one patch is changing two different things, adding\n'get_submodule_displaypath' and 'for_each_submodule_list'.  Logically\nyou could break this patch into two different parts, first introducing\none and then the other.\n\nI'm not saying you need to re-do this patch though (I don't have a super\nstrong opinion though others might) just wanted to point it out for the\nfuture.\n\n> \n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Stefan Beller <sbeller@google.com>\n> Signed-off-by: Prathamesh Chavan <pc44800@gmail.com>\n> ---\n>  builtin/submodule--helper.c | 69 ++++++++++++++++++++++++++++++++-------------\n>  1 file changed, 50 insertions(+), 19 deletions(-)\n> \n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index 8cc648d85..f7adca95b 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -13,6 +13,9 @@\n>  #include \"refs.h\"\n>  #include \"connect.h\"\n>  \n> +typedef void (*submodule_list_func_t)(const struct cache_entry *list_item,\n> +\t\t\t\t      void *cb_data);\n> +\n>  static char *get_default_remote(void)\n>  {\n>  \tchar *dest = NULL, *ret;\n> @@ -219,6 +222,27 @@ static int resolve_relative_url_test(int argc, const char **argv, const char *pr\n>  \treturn 0;\n>  }\n>  \n> +static char *get_submodule_displaypath(const char *path, const char *prefix)\n> +{\n> +\tconst char *super_prefix = get_super_prefix();\n> +\n> +\tif (prefix && super_prefix) {\n> +\t\tBUG(\"cannot have prefix '%s' and superprefix '%s'\",\n> +\t\t    prefix, super_prefix);\n> +\t} else if (prefix) {\n> +\t\tstruct strbuf sb = STRBUF_INIT;\n> +\t\tchar *displaypath = xstrdup(relative_path(path, prefix, &sb));\n> +\t\tstrbuf_release(&sb);\n> +\t\treturn displaypath;\n> +\t} else if (super_prefix) {\n> +\t\tint len = strlen(super_prefix);\n> +\t\tconst char *format = is_dir_sep(super_prefix[len-1]) ? \"%s%s\" : \"%s/%s\";\n> +\t\treturn xstrfmt(format, super_prefix, path);\n> +\t} else {\n> +\t\treturn xstrdup(path);\n> +\t}\n> +}\n> +\n>  struct module_list {\n>  \tconst struct cache_entry **entries;\n>  \tint alloc, nr;\n> @@ -330,26 +354,30 @@ static int module_list(int argc, const char **argv, const char *prefix)\n>  \treturn 0;\n>  }\n>  \n> -static void init_submodule(const char *path, const char *prefix, int quiet)\n> +static void for_each_submodule_list(const struct module_list list,\n> +\t\t\t\t    submodule_list_func_t fn, void *cb_data)\n>  {\n> +\tint i;\n> +\tfor (i = 0; i < list.nr; i++)\n> +\t\tfn(list.entries[i], cb_data);\n> +}\n> +\n> +struct init_cb {\n> +\tconst char *prefix;\n> +\tunsigned int quiet: 1;\n> +};\n> +#define INIT_CB_INIT { NULL, 0 }\n> +\n> +static void init_submodule(const struct cache_entry *list_item, void *cb_data)\n> +{\n> +\tstruct init_cb *info = cb_data;\n>  \tconst struct submodule *sub;\n>  \tstruct strbuf sb = STRBUF_INIT;\n>  \tchar *upd = NULL, *url = NULL, *displaypath;\n>  \n> -\t/* Only loads from .gitmodules, no overlay with .git/config */\n> -\tgitmodules_config();\n> -\n> -\tif (prefix && get_super_prefix())\n> -\t\tdie(\"BUG: cannot have prefix and superprefix\");\n> -\telse if (prefix)\n> -\t\tdisplaypath = xstrdup(relative_path(path, prefix, &sb));\n> -\telse if (get_super_prefix()) {\n> -\t\tstrbuf_addf(&sb, \"%s%s\", get_super_prefix(), path);\n> -\t\tdisplaypath = strbuf_detach(&sb, NULL);\n> -\t} else\n> -\t\tdisplaypath = xstrdup(path);\n> +\tdisplaypath = get_submodule_displaypath(list_item->name, info->prefix);\n>  \n> -\tsub = submodule_from_path(null_sha1, path);\n> +\tsub = submodule_from_path(null_sha1, list_item->name);\n>  \n>  \tif (!sub)\n>  \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n> @@ -361,7 +389,7 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n>  \t *\n>  \t * Set active flag for the submodule being initialized\n>  \t */\n> -\tif (!is_submodule_initialized(path)) {\n> +\tif (!is_submodule_initialized(list_item->name)) {\n>  \t\tstrbuf_reset(&sb);\n>  \t\tstrbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n>  \t\tgit_config_set_gently(sb.buf, \"true\");\n> @@ -404,7 +432,7 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n>  \t\tif (git_config_set_gently(sb.buf, url))\n>  \t\t\tdie(_(\"Failed to register url for submodule path '%s'\"),\n>  \t\t\t    displaypath);\n> -\t\tif (!quiet)\n> +\t\tif (!info->quiet)\n>  \t\t\tfprintf(stderr,\n>  \t\t\t\t_(\"Submodule '%s' (%s) registered for path '%s'\\n\"),\n>  \t\t\t\tsub->name, url, displaypath);\n> @@ -433,10 +461,10 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n>  \n>  static int module_init(int argc, const char **argv, const char *prefix)\n>  {\n> +\tstruct init_cb info = INIT_CB_INIT;\n>  \tstruct pathspec pathspec;\n>  \tstruct module_list list = MODULE_LIST_INIT;\n>  \tint quiet = 0;\n> -\tint i;\n>  \n>  \tstruct option module_init_options[] = {\n>  \t\tOPT__QUIET(&quiet, N_(\"Suppress output for initializing a submodule\")),\n> @@ -461,8 +489,11 @@ static int module_init(int argc, const char **argv, const char *prefix)\n>  \tif (!argc && git_config_get_value_multi(\"submodule.active\"))\n>  \t\tmodule_list_active(&list);\n>  \n> -\tfor (i = 0; i < list.nr; i++)\n> -\t\tinit_submodule(list.entries[i]->name, prefix, quiet);\n> +\tinfo.prefix = prefix;\n> +\tinfo.quiet = !!quiet;\n> +\n> +\tgitmodules_config();\n> +\tfor_each_submodule_list(list, init_submodule, &info);\n>  \n>  \treturn 0;\n>  }\n> -- \n> 2.13.0\n> \n\n-- \nBrandon Williams\n"},{"id":"322752","messageId":"20170620184427.GB60134@google.com","threadId":"46213","inReplyTo":"20170619215025.10086-4-pc44800@gmail.com","subject":"Re: [GSoC][PATCH 4/6] submodule: port submodule subcommand status","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-06-20T18:44:27Z","receivedAt":"2017-06-20T18:44:35Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 06/20, Prathamesh Chavan wrote:\n> The mechanism used for porting submodule subcommand 'status'\n> is similar to that used for subcommand 'foreach'.\n\nnit: since 'foreach' is stalled atm it may be confusing to reference\nthat change when it hasn't been merged in yet.\n\n> The function cmd_status from git-submodule is ported to three\n> functions in the builtin submodule--helper namely: module_status,\n> for_each_submodule_list and status_submodule.\n> \n> print_status is also introduced for handling the output of\n> the subcommand and also to reduce the code size.\n> \n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Stefan Beller <sbeller@google.com>\n> Signed-off-by: Prathamesh Chavan <pc44800@gmail.com>\n\n-- \nBrandon Williams\n"},{"id":"322914","messageId":"CAP8UFD3_toXcKzMmikkwaiGi7oHJ0BcT4s1fYe6hW4mYjUdmGA@mail.gmail.com","threadId":"46213","inReplyTo":"20170619215025.10086-5-pc44800@gmail.com","subject":"Re: [GSoC][PATCH 5/6] submodule: port submodule subcommand sync from shell to C","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2017-06-22T06:50:25Z","receivedAt":"2017-06-22T06:50:31Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Mon, Jun 19, 2017 at 11:50 PM, Prathamesh Chavan <pc44800@gmail.com> wrote:\n\n> +static char *get_up_path(const char *path)\n> +{\n> +       int i = count_slashes(path);\n> +       struct strbuf sb = STRBUF_INIT;\n> +\n> +       while (i--)\n> +               strbuf_addstr(&sb, \"../\");\n> +\n> +       /*\n> +        *Check if 'path' ends with slash or not\n> +        *for having the same output for dir/sub_dir\n> +        *and dir/sub_dir/\n> +        */\n> +       if (!is_dir_sep(path[i - 1]))\n\ni is always 0 here, as we decrease it until it gets to 0 above.\n\n> +               strbuf_addstr(&sb, \"../\");\n> +\n> +       return strbuf_detach(&sb, NULL);\n> +}\n"},{"id":"322915","messageId":"CAP8UFD3WN=Bik=EX5N4pQxEXu_S5zUyQTA7Km4V61q44crOY3Q@mail.gmail.com","threadId":"46213","inReplyTo":"20170619215025.10086-2-pc44800@gmail.com","subject":"Re: [GSoC][PATCH 2/6] submodule--helper: introduce get_submodule_displaypath and for_each_submodule_list","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2017-06-22T07:01:35Z","receivedAt":"2017-06-22T07:01:44Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Mon, Jun 19, 2017 at 11:50 PM, Prathamesh Chavan <pc44800@gmail.com> wrote:\n\n> +static char *get_submodule_displaypath(const char *path, const char *prefix)\n> +{\n> +       const char *super_prefix = get_super_prefix();\n> +\n> +       if (prefix && super_prefix) {\n> +               BUG(\"cannot have prefix '%s' and superprefix '%s'\",\n> +                   prefix, super_prefix);\n> +       } else if (prefix) {\n> +               struct strbuf sb = STRBUF_INIT;\n> +               char *displaypath = xstrdup(relative_path(path, prefix, &sb));\n> +               strbuf_release(&sb);\n> +               return displaypath;\n> +       } else if (super_prefix) {\n> +               int len = strlen(super_prefix);\n> +               const char *format = is_dir_sep(super_prefix[len-1]) ? \"%s%s\" : \"%s/%s\";\n\nStyle nit: please add spaces around \"-\", so \"len - 1\" instead of \"len-1\".\n\n> +               return xstrfmt(format, super_prefix, path);\n> +       } else {\n> +               return xstrdup(path);\n> +       }\n> +}\n"},{"id":"323304","messageId":"CAME+mvXpjZUoKqfuLyQ_p9MLh1UJFpqhAWZBwi2qEM5kHHWwcA@mail.gmail.com","threadId":"46213","inReplyTo":"CAH5451n4XDdeAz4T7aAsaSC00hnZ53Gb7j0CSiTg4QLUZKvxXw@mail.gmail.com","subject":"Re: [GSoC] Update: Week 5","fromName":"Prathamesh Chavan","fromEmail":"pc44800@gmail.com","sentAt":"2017-06-26T23:24:21Z","receivedAt":"2017-06-26T23:24:28Z","isPatch":false,"sender":{"key":"pc44800@gmail.com","avatar":"https://avatars.githubusercontent.com/u/17272661?v=4"},"body":"On Tue, Jun 20, 2017 at 5:31 AM, Andrew Ardill <andrew.ardill@gmail.com> wrote:\n> On 20 June 2017 at 07:41, Prathamesh Chavan <pc44800@gmail.com> wrote:\n>\n>>    But as communicating between child_process is still an issue\n>>    and so there was no simple was to current carry out the\n>>    porting. And hence, a hack was used instead. But after\n>>    discussing it, instead using the repository-object patch\n>>    series will help to resolve these issues in this situation.\n>\n> Just wondering, does that mean that your patch series is dependent on\n> the repository-object one? I saw some discussion around it recently\n> but couldn't see it in the latest whats cooking so maybe I missed what\n> has happened to it.\n\nSorry for such a late reply. In this update, and even in the latest update[1],\nthe patches aren't dependent on the 'repository-object' series.\nBut there are certain issues encountered which I aim to resolve\nusing them.\n\n>\n> Really enjoying your updates, by the way, they are very clear and show\n> what looks like great progress!\n\nThanks a lot for this, and I hope to keep improving it. :)\n\nThanks,\nPrathamesh Chavan\n\n[1]: https://public-inbox.org/git/CAME+mvUrr8EA-6jbCZdpB7dMZ5CN3RyY7yoRoUBoiZw=sH6Ysw@mail.gmail.com/\n"}]}