remote: move relative_url()
This method was initially written in 63e95beb0 (submodule: port
resolve_relative_url from shell to C, 2016-05-15). As we will need
similar functionality in the bundle URI feature, extract this to be
available in remote.h.
The code is almost exactly the same, except for the following trivial
differences:
* Fix whitespace and wrapping issues with the prototype and argument
lists.
* Let's call starts_with_dot_{,dot_}slash_native() instead of the
functionally identical "starts_with_dot_{,dot_}slash()" wrappers
"builtin/submodule--helper.c".
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
c1d024b843
commit
1d04e719e7
91
remote.c
91
remote.c
@ -14,6 +14,7 @@
|
||||
#include "strvec.h"
|
||||
#include "commit-reach.h"
|
||||
#include "advice.h"
|
||||
#include "connect.h"
|
||||
|
||||
enum map_direction { FROM_SRC, FROM_DST };
|
||||
|
||||
@ -2727,3 +2728,93 @@ void remote_state_clear(struct remote_state *remote_state)
|
||||
hashmap_clear_and_free(&remote_state->remotes_hash, struct remote, ent);
|
||||
hashmap_clear_and_free(&remote_state->branches_hash, struct remote, ent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if it was the last chop before ':'.
|
||||
*/
|
||||
static int chop_last_dir(char **remoteurl, int is_relative)
|
||||
{
|
||||
char *rfind = find_last_dir_sep(*remoteurl);
|
||||
if (rfind) {
|
||||
*rfind = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
rfind = strrchr(*remoteurl, ':');
|
||||
if (rfind) {
|
||||
*rfind = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (is_relative || !strcmp(".", *remoteurl))
|
||||
die(_("cannot strip one component off url '%s'"),
|
||||
*remoteurl);
|
||||
|
||||
free(*remoteurl);
|
||||
*remoteurl = xstrdup(".");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *relative_url(const char *remote_url, const char *url,
|
||||
const char *up_path)
|
||||
{
|
||||
int is_relative = 0;
|
||||
int colonsep = 0;
|
||||
char *out;
|
||||
char *remoteurl = xstrdup(remote_url);
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
size_t len = strlen(remoteurl);
|
||||
|
||||
if (is_dir_sep(remoteurl[len-1]))
|
||||
remoteurl[len-1] = '\0';
|
||||
|
||||
if (!url_is_local_not_ssh(remoteurl) || is_absolute_path(remoteurl))
|
||||
is_relative = 0;
|
||||
else {
|
||||
is_relative = 1;
|
||||
/*
|
||||
* Prepend a './' to ensure all relative
|
||||
* remoteurls start with './' or '../'
|
||||
*/
|
||||
if (!starts_with_dot_slash_native(remoteurl) &&
|
||||
!starts_with_dot_dot_slash_native(remoteurl)) {
|
||||
strbuf_reset(&sb);
|
||||
strbuf_addf(&sb, "./%s", remoteurl);
|
||||
free(remoteurl);
|
||||
remoteurl = strbuf_detach(&sb, NULL);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* When the url starts with '../', remove that and the
|
||||
* last directory in remoteurl.
|
||||
*/
|
||||
while (url) {
|
||||
if (starts_with_dot_dot_slash_native(url)) {
|
||||
url += 3;
|
||||
colonsep |= chop_last_dir(&remoteurl, is_relative);
|
||||
} else if (starts_with_dot_slash_native(url))
|
||||
url += 2;
|
||||
else
|
||||
break;
|
||||
}
|
||||
strbuf_reset(&sb);
|
||||
strbuf_addf(&sb, "%s%s%s", remoteurl, colonsep ? ":" : "/", url);
|
||||
if (ends_with(url, "/"))
|
||||
strbuf_setlen(&sb, sb.len - 1);
|
||||
free(remoteurl);
|
||||
|
||||
if (starts_with_dot_slash_native(sb.buf))
|
||||
out = xstrdup(sb.buf + 2);
|
||||
else
|
||||
out = xstrdup(sb.buf);
|
||||
|
||||
if (!up_path || !is_relative) {
|
||||
strbuf_release(&sb);
|
||||
return out;
|
||||
}
|
||||
|
||||
strbuf_reset(&sb);
|
||||
strbuf_addf(&sb, "%s%s", up_path, out);
|
||||
free(out);
|
||||
return strbuf_detach(&sb, NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user