Am 17.12.2015 um 01:26 schrieb Stefan Beller:
> This reimplements the helper function `resolve_relative_url` in shell
> in C. This functionality is needed in C for introducing the groups
> feature later on. When using groups, the user should not need to run
> `git submodule init`, but it should be implicit at all appropriate places,
> which are all in C code. As the we would not just call out to `git
> submodule init`, but do a more fine grained structure there, we actually
> need all the init functionality in C before attempting the groups
> feature. To get the init functionality in C, rewriting the
> resolve_relative_url subfunction is a major step.
>
> This also improves the performance:
> (Best out of 3) time ./t7400-submodule-basic.sh
> Before:
> real 0m9.575s
> user 0m2.683s
> sys 0m6.773s
> After:
> real 0m9.293s
> user 0m2.691s
> sys 0m6.549s
>
> That's about 3%.
I appreciate this effort as it should help us on Windows. Although the
numbers (and my own timings) suggest that this is only a small step
forward. That's not surprising as the patch removes only two forks.
As to the implementation, find a patch below that removes the ifdefs
and a few other suggestions. It is a mechanical conversion without
understanding what relative_url() does. I have the gut feeling that the
two strbuf_addf towards the end of the function can be contracted and
the temporarily allocate copy in 'out' can be removed.
If there were a few examples in the comment above the function, it
would be much simpler to understand.
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index b925bed..8ec0975 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -11,6 +11,7 @@
#include "run-command.h"
#include "remote.h"
#include "refs.h"
+#include "connect.h"
static const char *get_default_remote(void)
{
@@ -31,34 +32,23 @@ static const char *get_default_remote(void)
return xstrdup(dest);
}
-static int has_same_dir_prefix(const char *str, const char **out)
+static int starts_with_dot_slash(const char *str)
{
-#ifdef GIT_WINDOWS_NATIVE
- return skip_prefix(str, "./", out)
- || skip_prefix(str, ".\\", out);
-#else
- return skip_prefix(str, "./", out);
-#endif
+ return str[0] == '.' && is_dir_sep(str[1]);
}
-static int has_upper_dir_prefix(const char *str, const char **out)
+static int starts_with_dot_dot_slash(const char *str)
{
-#ifdef GIT_WINDOWS_NATIVE
- return skip_prefix(str, "../", out)
- || skip_prefix(str, "..\\", out);
-#else
- return skip_prefix(str, "../", out);
-#endif
+ return str[0] == '.' && str[1] == '.' && is_dir_sep(str[2]);
}
-static char *last_dir_separator(const char *str)
+static char *last_dir_separator(char *str)
{
-#ifdef GIT_WINDOWS_NATIVE
- return strrchr(str, "/")
- || strrchr(str, "\\");
-#else
- return strrchr(str, '/');
-#endif
+ char* p = str + strlen(str);
+ while (p-- != str)
+ if (is_dir_sep(*p))
+ return p;
+ return NULL;
}
/*
@@ -85,9 +75,10 @@ static const char *relative_url(const char *url, const char
*up_path)
size_t len;
char *remoteurl = NULL;
char *sep = "/";
- const char *out;
+ char *out;
struct strbuf sb = STRBUF_INIT;
const char *remote = get_default_remote();
+
strbuf_addf(&sb, "remote.%s.url", remote);
if (git_config_get_string(sb.buf, &remoteurl))
@@ -98,22 +89,23 @@ static const char *relative_url(const char *url, const char
*up_path)
if (is_dir_sep(remoteurl[len]))
remoteurl[len] = '\0';
- if (strchr(remoteurl, ':') || is_dir_sep(*remoteurl))
+ if (!url_is_local_not_ssh(remoteurl) || is_absolute_path(remoteurl))
is_relative = 0;
- else if (has_same_dir_prefix(remoteurl, &out) ||
- has_upper_dir_prefix(remoteurl, &out))
+ else if (starts_with_dot_slash(remoteurl) ||
+ starts_with_dot_dot_slash(remoteurl))
is_relative = 1;
else {
is_relative = 1;
strbuf_reset(&sb);
strbuf_addf(&sb, "./%s", remoteurl);
+ free(remoteurl);
remoteurl = strbuf_detach(&sb, NULL);
}
while (url) {
- if (has_upper_dir_prefix(url, &out)) {
+ if (starts_with_dot_dot_slash(url)) {
char *rfind;
- url = out;
+ url += 3;
rfind = last_dir_separator(remoteurl);
if (rfind)
@@ -130,22 +122,23 @@ static const char *relative_url(const char *url, const
char *up_path)
remoteurl = ".";
}
}
- } else if (has_same_dir_prefix(url, &out))
- url = out;
- else
+ } else if (starts_with_dot_slash(url)) {
+ url += 2;
+ } else
break;
}
strbuf_reset(&sb);
strbuf_addf(&sb, "%s%s%s", remoteurl, sep, url);
- if (!has_same_dir_prefix(sb.buf, &out))
- out = sb.buf;
- out = xstrdup(out);
+ if (starts_with_dot_slash(sb.buf))
+ out = strdup(sb.buf + 2);
+ else
+ out = xstrdup(sb.buf);
strbuf_reset(&sb);
strbuf_addf(&sb, "%s%s", is_relative && up_path ? up_path : "", out);
- free((char*)out);
+ free(out);
return strbuf_detach(&sb, NULL);
}
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html