Re: [GSoC][PATCH 5/8] submodule: port submodule subcommand 'sync' from shell to C

2017-07-20 Thread Stefan Beller
On Thu, Jul 20, 2017 at 12:36 PM, Prathamesh Chavan  wrote:
> Firstly, thanks for reviewing my patches. I have even checked out the
> other reviews
> and improvised the other patches according to reviews as well.
> I had a few doubts about this one though.
>
>>> +   const struct submodule *sub;
>>> +   char *sub_key, *remote_key;
>>> +   char *sub_origin_url, *super_config_url, *displaypath;
>>> +   struct strbuf sb = STRBUF_INIT;
>>> +   struct child_process cp = CHILD_PROCESS_INIT;
>>> +
>>> +   if (!is_submodule_active(the_repository, list_item->name))
>>> +   return;
>>
>> We can use the_repository here, as we also use child processes to
>> recurse, such that we always operate on the_repository as the
>> superproject.
>>
>
> Sorry, but can you explain this a bit more?

Well that was more thinking out out, in the sense of explaining why
it is the correct thing to do.

As the recursion is handled via spawning processes, each process
has the_repository pointing at a different repository (and the correct
repository for each process), at least to my understanding.

>
>>
>>> +
>>> +   sub = submodule_from_path(null_sha1, list_item->name);
>>> +
>>> +   if (!sub || !sub->url)
>>> +   die(_("no url found for submodule path '%s' in 
>>> .gitmodules"),
>>> + list_item->name);
>>
>> We do not die in the shell script when the url is missing in the
>> .gitmodules file.
>>
>
> Then to have a faithful conversion, IMO, deleting the above lines
> would be the correct way?

Well, then we may run into segfaults due to dereferencing a NULL pointer.
So we have to figure out, what the code actually does when there is
no URL set. According to my understanding this would

url=$(git config -f .gitmodules --get submodule."$name".url)
# second case, but empty vars:
sub_origin_url="$url"
super_config_url="$url"



The issue with this shell script is that there is no difference between
"" and NULL, so the place where we do

sub_origin_url="$url"
super_config_url="$url"

we would need to translate NULL -> empty string

>
>>> +
>>> +   prepare_submodule_repo_env(_array);
>>> +   cp.git_cmd = 1;
>>> +   cp.dir = list_item->name;
>>> +   argv_array_pushl(, "submodule--helper",
>>> +"print-default-remote", NULL);
>>> +   if (capture_command(, , 0))
>>> +   die(_("failed to get the default remote for submodule 
>>> '%s'"),
>>> + list_item->name);
>>> +
>>> +   strbuf_strip_suffix(, "\n");
>>> +   remote_key = xstrfmt("remote.%s.url", sb.buf);
>>> +   strbuf_release();
>>> +
>>> +   child_process_init();
>>> +   prepare_submodule_repo_env(_array);
>>> +   cp.git_cmd = 1;
>>> +   cp.dir = list_item->name;
>>> +   argv_array_pushl(, "config", remote_key, sub_origin_url, 
>>> NULL);
>>> +   if (run_command())
>>> +   die(_("failed to update remote for submodule '%s'"),
>>> + list_item->name);
>>
>> While it is a strict conversion from the shell script, we could also
>> try to do this in-process:
>> 1) we'd find out the submodules git dir using submodule_to_gitdir
>> 2) construct the path the the config file as "%s/.gitconfig"
>> 3) using git_config_set_in_file (which presumably takes file name,
>>   key and value) the value can be set
>
> Thanks for pointing that out. That surely reduced a child_process.
> Although the path of the config file for the case of submodules
> would be constructed by "%s/config".

Ah yes, that is correct.


>
> Thanks,
> Prathamesh Chavan


Re: [GSoC][PATCH 5/8] submodule: port submodule subcommand 'sync' from shell to C

2017-07-20 Thread Prathamesh Chavan
Firstly, thanks for reviewing my patches. I have even checked out the
other reviews
and improvised the other patches according to reviews as well.
I had a few doubts about this one though.

>> +   const struct submodule *sub;
>> +   char *sub_key, *remote_key;
>> +   char *sub_origin_url, *super_config_url, *displaypath;
>> +   struct strbuf sb = STRBUF_INIT;
>> +   struct child_process cp = CHILD_PROCESS_INIT;
>> +
>> +   if (!is_submodule_active(the_repository, list_item->name))
>> +   return;
>
> We can use the_repository here, as we also use child processes to
> recurse, such that we always operate on the_repository as the
> superproject.
>

Sorry, but can you explain this a bit more?

>
>> +
>> +   sub = submodule_from_path(null_sha1, list_item->name);
>> +
>> +   if (!sub || !sub->url)
>> +   die(_("no url found for submodule path '%s' in .gitmodules"),
>> + list_item->name);
>
> We do not die in the shell script when the url is missing in the
> .gitmodules file.
>

Then to have a faithful conversion, IMO, deleting the above lines
would be the correct way?

>> +
>> +   prepare_submodule_repo_env(_array);
>> +   cp.git_cmd = 1;
>> +   cp.dir = list_item->name;
>> +   argv_array_pushl(, "submodule--helper",
>> +"print-default-remote", NULL);
>> +   if (capture_command(, , 0))
>> +   die(_("failed to get the default remote for submodule '%s'"),
>> + list_item->name);
>> +
>> +   strbuf_strip_suffix(, "\n");
>> +   remote_key = xstrfmt("remote.%s.url", sb.buf);
>> +   strbuf_release();
>> +
>> +   child_process_init();
>> +   prepare_submodule_repo_env(_array);
>> +   cp.git_cmd = 1;
>> +   cp.dir = list_item->name;
>> +   argv_array_pushl(, "config", remote_key, sub_origin_url, 
>> NULL);
>> +   if (run_command())
>> +   die(_("failed to update remote for submodule '%s'"),
>> + list_item->name);
>
> While it is a strict conversion from the shell script, we could also
> try to do this in-process:
> 1) we'd find out the submodules git dir using submodule_to_gitdir
> 2) construct the path the the config file as "%s/.gitconfig"
> 3) using git_config_set_in_file (which presumably takes file name,
>   key and value) the value can be set

Thanks for pointing that out. That surely reduced a child_process.
Although the path of the config file for the case of submodules
would be constructed by "%s/config".

Thanks,
Prathamesh Chavan


Re: [GSoC][PATCH 5/8] submodule: port submodule subcommand 'sync' from shell to C

2017-07-18 Thread Stefan Beller
On Tue, Jul 18, 2017 at 1:49 PM, Prathamesh Chavan  wrote:
> Port the submodule subcommand 'sync' from shell to C using the same
> mechanism as that used for porting submodule subcommand 'status'.
> Hence, here the function cmd_sync() is ported from shell to C.
> This is done by introducing three functions: module_sync(),
> sync_submodule() and print_default_remote().
>
> The function print_default_remote() is introduced for getting
> the default remote as stdout.
>
> Mentored-by: Christian Couder 
> Mentored-by: Stefan Beller 
> Signed-off-by: Prathamesh Chavan 
> ---
>  builtin/submodule--helper.c | 179 
> 
>  git-submodule.sh|  56 +-
>  2 files changed, 180 insertions(+), 55 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 9c1630495..da91c489b 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -44,6 +44,20 @@ static char *get_default_remote(void)
> return ret;
>  }
>
> +static int print_default_remote(int argc, const char **argv, const char 
> *prefix)
> +{
> +   const char *remote;
> +
> +   if (argc != 1)
> +   die(_("submodule--helper print-default-remote takes no 
> arguments"));
> +
> +   remote = get_default_remote();
> +   if (remote)
> +   puts(remote);
> +
> +   return 0;
> +}
> +
>  static int starts_with_dot_slash(const char *str)
>  {
> return str[0] == '.' && is_dir_sep(str[1]);
> @@ -379,6 +393,25 @@ static void module_list_active(struct module_list *list)
> *list = active_modules;
>  }
>
> +static char *get_up_path(const char *path)
> +{
> +   int i;
> +   struct strbuf sb = STRBUF_INIT;
> +
> +   for (i = count_slashes(path); i; i--)
> +   strbuf_addstr(, "../");
> +
> +   /*
> +* Check if 'path' ends with slash or not
> +* for having the same output for dir/sub_dir
> +* and dir/sub_dir/
> +*/
> +   if (!is_dir_sep(path[strlen(path) - 1]))
> +   strbuf_addstr(, "../");
> +
> +   return strbuf_detach(, NULL);
> +}
> +
>  static int module_list(int argc, const char **argv, const char *prefix)
>  {
> int i;
> @@ -724,6 +757,150 @@ static int module_name(int argc, const char **argv, 
> const char *prefix)
> return 0;
>  }
>
> +struct sync_cb {
> +   const char *prefix;
> +   unsigned int quiet: 1;
> +   unsigned int recursive: 1;
> +};
> +#define SYNC_CB_INIT { NULL, 0, 0 }
> +
> +static void sync_submodule(const struct cache_entry *list_item, void 
> *cb_data)
> +{
> +   struct sync_cb *info = cb_data;
> +   const struct submodule *sub;
> +   char *sub_key, *remote_key;
> +   char *sub_origin_url, *super_config_url, *displaypath;
> +   struct strbuf sb = STRBUF_INIT;
> +   struct child_process cp = CHILD_PROCESS_INIT;
> +
> +   if (!is_submodule_active(the_repository, list_item->name))
> +   return;

We can use the_repository here, as we also use child processes to
recurse, such that we always operate on the_repository as the
superproject.


> +
> +   sub = submodule_from_path(null_sha1, list_item->name);
> +
> +   if (!sub || !sub->url)
> +   die(_("no url found for submodule path '%s' in .gitmodules"),
> + list_item->name);

We do not die in the shell script when the url is missing in the
.gitmodules file.

> +
> +   if (starts_with_dot_dot_slash(sub->url) || 
> starts_with_dot_slash(sub->url)) {
> +   char *remote_url, *up_path;
> +   char *remote = get_default_remote();
> +   char *remote_key = xstrfmt("remote.%s.url", remote);
> +
> +   if (git_config_get_string(remote_key, _url))
> +   remote_url = xgetcwd();
> +
> +   up_path = get_up_path(list_item->name);
> +   sub_origin_url = relative_url(remote_url, sub->url, up_path);
> +   super_config_url = relative_url(remote_url, sub->url, NULL);
> +
> +   free(remote);
> +   free(remote_key);
> +   free(up_path);
> +   free(remote_url);
> +   } else {
> +   sub_origin_url = xstrdup(sub->url);
> +   super_config_url = xstrdup(sub->url);
> +   }
> +
> +   displaypath = get_submodule_displaypath(list_item->name, 
> info->prefix);
> +
> +   if (!info->quiet)
> +   printf(_("Synchronizing submodule url for '%s'\n"),
> +displaypath);
> +
> +   sub_key = xstrfmt("submodule.%s.url", sub->name);
> +   if (git_config_set_gently(sub_key, super_config_url))
> +   die(_("failed to register url for submodule path '%s'"),
> + displaypath);
> +
> +   if (!is_submodule_populated_gently(list_item->name, 

[GSoC][PATCH 5/8] submodule: port submodule subcommand 'sync' from shell to C

2017-07-18 Thread Prathamesh Chavan
Port the submodule subcommand 'sync' from shell to C using the same
mechanism as that used for porting submodule subcommand 'status'.
Hence, here the function cmd_sync() is ported from shell to C.
This is done by introducing three functions: module_sync(),
sync_submodule() and print_default_remote().

The function print_default_remote() is introduced for getting
the default remote as stdout.

Mentored-by: Christian Couder 
Mentored-by: Stefan Beller 
Signed-off-by: Prathamesh Chavan 
---
 builtin/submodule--helper.c | 179 
 git-submodule.sh|  56 +-
 2 files changed, 180 insertions(+), 55 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 9c1630495..da91c489b 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -44,6 +44,20 @@ static char *get_default_remote(void)
return ret;
 }
 
+static int print_default_remote(int argc, const char **argv, const char 
*prefix)
+{
+   const char *remote;
+
+   if (argc != 1)
+   die(_("submodule--helper print-default-remote takes no 
arguments"));
+
+   remote = get_default_remote();
+   if (remote)
+   puts(remote);
+
+   return 0;
+}
+
 static int starts_with_dot_slash(const char *str)
 {
return str[0] == '.' && is_dir_sep(str[1]);
@@ -379,6 +393,25 @@ static void module_list_active(struct module_list *list)
*list = active_modules;
 }
 
+static char *get_up_path(const char *path)
+{
+   int i;
+   struct strbuf sb = STRBUF_INIT;
+
+   for (i = count_slashes(path); i; i--)
+   strbuf_addstr(, "../");
+
+   /*
+* Check if 'path' ends with slash or not
+* for having the same output for dir/sub_dir
+* and dir/sub_dir/
+*/
+   if (!is_dir_sep(path[strlen(path) - 1]))
+   strbuf_addstr(, "../");
+
+   return strbuf_detach(, NULL);
+}
+
 static int module_list(int argc, const char **argv, const char *prefix)
 {
int i;
@@ -724,6 +757,150 @@ static int module_name(int argc, const char **argv, const 
char *prefix)
return 0;
 }
 
+struct sync_cb {
+   const char *prefix;
+   unsigned int quiet: 1;
+   unsigned int recursive: 1;
+};
+#define SYNC_CB_INIT { NULL, 0, 0 }
+
+static void sync_submodule(const struct cache_entry *list_item, void *cb_data)
+{
+   struct sync_cb *info = cb_data;
+   const struct submodule *sub;
+   char *sub_key, *remote_key;
+   char *sub_origin_url, *super_config_url, *displaypath;
+   struct strbuf sb = STRBUF_INIT;
+   struct child_process cp = CHILD_PROCESS_INIT;
+
+   if (!is_submodule_active(the_repository, list_item->name))
+   return;
+
+   sub = submodule_from_path(null_sha1, list_item->name);
+
+   if (!sub || !sub->url)
+   die(_("no url found for submodule path '%s' in .gitmodules"),
+ list_item->name);
+
+   if (starts_with_dot_dot_slash(sub->url) || 
starts_with_dot_slash(sub->url)) {
+   char *remote_url, *up_path;
+   char *remote = get_default_remote();
+   char *remote_key = xstrfmt("remote.%s.url", remote);
+
+   if (git_config_get_string(remote_key, _url))
+   remote_url = xgetcwd();
+
+   up_path = get_up_path(list_item->name);
+   sub_origin_url = relative_url(remote_url, sub->url, up_path);
+   super_config_url = relative_url(remote_url, sub->url, NULL);
+
+   free(remote);
+   free(remote_key);
+   free(up_path);
+   free(remote_url);
+   } else {
+   sub_origin_url = xstrdup(sub->url);
+   super_config_url = xstrdup(sub->url);
+   }
+
+   displaypath = get_submodule_displaypath(list_item->name, info->prefix);
+
+   if (!info->quiet)
+   printf(_("Synchronizing submodule url for '%s'\n"),
+displaypath);
+
+   sub_key = xstrfmt("submodule.%s.url", sub->name);
+   if (git_config_set_gently(sub_key, super_config_url))
+   die(_("failed to register url for submodule path '%s'"),
+ displaypath);
+
+   if (!is_submodule_populated_gently(list_item->name, NULL))
+   goto cleanup;
+
+   prepare_submodule_repo_env(_array);
+   cp.git_cmd = 1;
+   cp.dir = list_item->name;
+   argv_array_pushl(, "submodule--helper",
+"print-default-remote", NULL);
+   if (capture_command(, , 0))
+   die(_("failed to get the default remote for submodule '%s'"),
+ list_item->name);
+
+   strbuf_strip_suffix(, "\n");
+   remote_key = xstrfmt("remote.%s.url", sb.buf);
+   strbuf_release();
+
+   child_process_init();
+   

Re: [GSoC][PATCH 5/8] submodule: port submodule subcommand 'sync' from shell to C

2017-07-10 Thread Brandon Williams
On 07/11, Prathamesh Chavan wrote:
> Port the submodule subcommand 'sync' from shell to C using the same
> mechanism as that used for porting submodule subcommand 'status'.
> Hence, here the function cmd_sync() is ported from shell to C.
> This is done by introducing three functions: module_sync(),
> sync_submodule() and print_default_remote().
> 
> The function print_default_remote() is introduced for getting
> the default remote as stdout.
> 
> Mentored-by: Christian Couder 
> Mentored-by: Stefan Beller 
> Signed-off-by: Prathamesh Chavan 
> ---
>  builtin/submodule--helper.c | 181 
> +++-
>  git-submodule.sh|  56 +-
>  2 files changed, 181 insertions(+), 56 deletions(-)
> 
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 980b8ed27..4e04b93f3 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -44,6 +44,20 @@ static char *get_default_remote(void)
>   return ret;
>  }
>  
> +static int print_default_remote(int argc, const char **argv, const char 
> *prefix)
> +{
> + const char *remote;
> +
> + if (argc != 1)
> + die(_("submodule--helper print-default-remote takes no 
> arguments"));
> +
> + remote = get_default_remote();
> + if (remote)
> + puts(remote);
> +
> + return 0;
> +}
> +
>  static int starts_with_dot_slash(const char *str)
>  {
>   return str[0] == '.' && is_dir_sep(str[1]);
> @@ -379,6 +393,25 @@ static void module_list_active(struct module_list *list)
>   *list = active_modules;
>  }
>  
> +static char *get_up_path(const char *path)
> +{
> + int i;
> + struct strbuf sb = STRBUF_INIT;
> +
> + for (i = count_slashes(path); i; i--)
> + strbuf_addstr(, "../");
> +
> + /*
> +  * Check if 'path' ends with slash or not
> +  * for having the same output for dir/sub_dir
> +  * and dir/sub_dir/
> +  */
> + if (!is_dir_sep(path[strlen(path) - 1]))
> + strbuf_addstr(, "../");
> +
> + return strbuf_detach(, NULL);
> +}
> +
>  static int module_list(int argc, const char **argv, const char *prefix)
>  {
>   int i;
> @@ -478,16 +511,18 @@ static void init_submodule(const struct cache_entry 
> *list_item, void *cb_data)
>   char *remote = get_default_remote();
>   struct strbuf remotesb = STRBUF_INIT;
>   strbuf_addf(, "remote.%s.url", remote);
> - free(remote);
>  
>   if (git_config_get_string(remotesb.buf, )) {
>   warning(_("could not lookup configuration '%s'. 
> Assuming this repository is its own authoritative upstream."), remotesb.buf);
>   remoteurl = xgetcwd();
>   }
>   relurl = relative_url(remoteurl, url, NULL);
> +
> + free(remote);
>   strbuf_release();
>   free(remoteurl);
>   free(url);
> +
>   url = relurl;

The changes in this function seem unintended.

>   }
>  
> @@ -732,6 +767,148 @@ static int module_name(int argc, const char **argv, 
> const char *prefix)
>   return 0;
>  }
>  
> +struct sync_cb {
> + const char *prefix;
> + unsigned int quiet: 1;
> + unsigned int recursive: 1;
> +};
> +#define SYNC_CB_INIT { NULL, 0, 0 }
> +
> +static void sync_submodule(const struct cache_entry *list_item, void 
> *cb_data)
> +{
> + struct sync_cb *info = cb_data;
> + const struct submodule *sub;
> + char *sub_key, *remote_key;
> + char *sub_origin_url, *super_config_url, *displaypath;
> + struct strbuf sb = STRBUF_INIT;
> + struct child_process cp = CHILD_PROCESS_INIT;
> +
> + if (!is_submodule_active(the_repository, list_item->name))
> + return;
> +
> + sub = submodule_from_path(null_sha1, list_item->name);
> +
> + if (!sub || !sub->url)
> + die(_("no url found for submodule path '%s' in .gitmodules"),
> +   list_item->name);
> +
> + if (starts_with_dot_dot_slash(sub->url) || 
> starts_with_dot_slash(sub->url)) {
> + char *remote_url, *up_path;
> + char *remote = get_default_remote();
> + char *remote_key = xstrfmt("remote.%s.url", remote);
> + free(remote);
> +
> + if (git_config_get_string(remote_key, _url))
> + remote_url = xgetcwd();
> + up_path = get_up_path(list_item->name);
> + sub_origin_url = relative_url(remote_url, sub->url, up_path);
> + super_config_url = relative_url(remote_url, sub->url, NULL);
> + free(remote_key);
> + free(up_path);
> + free(remote_url);
> + } else {
> + sub_origin_url = xstrdup(sub->url);
> 

[GSoC][PATCH 5/8] submodule: port submodule subcommand 'sync' from shell to C

2017-07-10 Thread Prathamesh Chavan
Port the submodule subcommand 'sync' from shell to C using the same
mechanism as that used for porting submodule subcommand 'status'.
Hence, here the function cmd_sync() is ported from shell to C.
This is done by introducing three functions: module_sync(),
sync_submodule() and print_default_remote().

The function print_default_remote() is introduced for getting
the default remote as stdout.

Mentored-by: Christian Couder 
Mentored-by: Stefan Beller 
Signed-off-by: Prathamesh Chavan 
---
 builtin/submodule--helper.c | 181 +++-
 git-submodule.sh|  56 +-
 2 files changed, 181 insertions(+), 56 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 980b8ed27..4e04b93f3 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -44,6 +44,20 @@ static char *get_default_remote(void)
return ret;
 }
 
+static int print_default_remote(int argc, const char **argv, const char 
*prefix)
+{
+   const char *remote;
+
+   if (argc != 1)
+   die(_("submodule--helper print-default-remote takes no 
arguments"));
+
+   remote = get_default_remote();
+   if (remote)
+   puts(remote);
+
+   return 0;
+}
+
 static int starts_with_dot_slash(const char *str)
 {
return str[0] == '.' && is_dir_sep(str[1]);
@@ -379,6 +393,25 @@ static void module_list_active(struct module_list *list)
*list = active_modules;
 }
 
+static char *get_up_path(const char *path)
+{
+   int i;
+   struct strbuf sb = STRBUF_INIT;
+
+   for (i = count_slashes(path); i; i--)
+   strbuf_addstr(, "../");
+
+   /*
+* Check if 'path' ends with slash or not
+* for having the same output for dir/sub_dir
+* and dir/sub_dir/
+*/
+   if (!is_dir_sep(path[strlen(path) - 1]))
+   strbuf_addstr(, "../");
+
+   return strbuf_detach(, NULL);
+}
+
 static int module_list(int argc, const char **argv, const char *prefix)
 {
int i;
@@ -478,16 +511,18 @@ static void init_submodule(const struct cache_entry 
*list_item, void *cb_data)
char *remote = get_default_remote();
struct strbuf remotesb = STRBUF_INIT;
strbuf_addf(, "remote.%s.url", remote);
-   free(remote);
 
if (git_config_get_string(remotesb.buf, )) {
warning(_("could not lookup configuration '%s'. 
Assuming this repository is its own authoritative upstream."), remotesb.buf);
remoteurl = xgetcwd();
}
relurl = relative_url(remoteurl, url, NULL);
+
+   free(remote);
strbuf_release();
free(remoteurl);
free(url);
+
url = relurl;
}
 
@@ -732,6 +767,148 @@ static int module_name(int argc, const char **argv, const 
char *prefix)
return 0;
 }
 
+struct sync_cb {
+   const char *prefix;
+   unsigned int quiet: 1;
+   unsigned int recursive: 1;
+};
+#define SYNC_CB_INIT { NULL, 0, 0 }
+
+static void sync_submodule(const struct cache_entry *list_item, void *cb_data)
+{
+   struct sync_cb *info = cb_data;
+   const struct submodule *sub;
+   char *sub_key, *remote_key;
+   char *sub_origin_url, *super_config_url, *displaypath;
+   struct strbuf sb = STRBUF_INIT;
+   struct child_process cp = CHILD_PROCESS_INIT;
+
+   if (!is_submodule_active(the_repository, list_item->name))
+   return;
+
+   sub = submodule_from_path(null_sha1, list_item->name);
+
+   if (!sub || !sub->url)
+   die(_("no url found for submodule path '%s' in .gitmodules"),
+ list_item->name);
+
+   if (starts_with_dot_dot_slash(sub->url) || 
starts_with_dot_slash(sub->url)) {
+   char *remote_url, *up_path;
+   char *remote = get_default_remote();
+   char *remote_key = xstrfmt("remote.%s.url", remote);
+   free(remote);
+
+   if (git_config_get_string(remote_key, _url))
+   remote_url = xgetcwd();
+   up_path = get_up_path(list_item->name);
+   sub_origin_url = relative_url(remote_url, sub->url, up_path);
+   super_config_url = relative_url(remote_url, sub->url, NULL);
+   free(remote_key);
+   free(up_path);
+   free(remote_url);
+   } else {
+   sub_origin_url = xstrdup(sub->url);
+   super_config_url = xstrdup(sub->url);
+   }
+
+   displaypath = get_submodule_displaypath(list_item->name, info->prefix);
+
+   if (!info->quiet)
+   printf(_("Synchronizing submodule url