Commit e402d2f1 by Russell Belfer

Submodule sync refactoring

Turns out there was already a helper to do what I wanted to do,
so I just made it so that I could use it for sync and switched to
that instead.
parent 8286300a
...@@ -119,6 +119,14 @@ GIT_INLINE(void) git_path_mkposix(char *path) ...@@ -119,6 +119,14 @@ GIT_INLINE(void) git_path_mkposix(char *path)
# define git_path_mkposix(p) /* blank */ # define git_path_mkposix(p) /* blank */
#endif #endif
/**
* Check if string is a relative path (i.e. starts with "./" or "../")
*/
GIT_INLINE(int) git_path_is_relative(const char *p)
{
return (p[0] == '.' && (p[1] == '/' || (p[1] == '.' && p[2] == '/')));
}
extern int git__percent_decode(git_buf *decoded_out, const char *input); extern int git__percent_decode(git_buf *decoded_out, const char *input);
/** /**
......
...@@ -79,6 +79,7 @@ __KHASH_IMPL( ...@@ -79,6 +79,7 @@ __KHASH_IMPL(
static int load_submodule_config(git_repository *repo, bool reload); static int load_submodule_config(git_repository *repo, bool reload);
static git_config_backend *open_gitmodules(git_repository *, bool, const git_oid *); static git_config_backend *open_gitmodules(git_repository *, bool, const git_oid *);
static int lookup_head_remote_key(git_buf *key, git_repository *repo);
static int lookup_head_remote(git_buf *url, git_repository *repo); static int lookup_head_remote(git_buf *url, git_repository *repo);
static int submodule_get(git_submodule **, git_repository *, const char *, const char *); static int submodule_get(git_submodule **, git_repository *, const char *, const char *);
static int submodule_load_from_config(const git_config_entry *, void *); static int submodule_load_from_config(const git_config_entry *, void *);
...@@ -271,8 +272,7 @@ int git_submodule_add_setup( ...@@ -271,8 +272,7 @@ int git_submodule_add_setup(
} }
/* resolve parameters */ /* resolve parameters */
error = git_submodule_resolve_url(&real_url, repo, url); if ((error = git_submodule_resolve_url(&real_url, repo, url)) < 0)
if (error)
goto cleanup; goto cleanup;
/* validate and normalize path */ /* validate and normalize path */
...@@ -576,7 +576,7 @@ int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *ur ...@@ -576,7 +576,7 @@ int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *ur
assert(url); assert(url);
if (url[0] == '.' && (url[1] == '/' || (url[1] == '.' && url[2] == '/'))) { if (git_path_is_relative(url)) {
if (!(error = lookup_head_remote(out, repo))) if (!(error = lookup_head_remote(out, repo)))
error = git_path_apply_relative(out, url); error = git_path_apply_relative(out, url);
} else if (strchr(url, ':') != NULL || url[0] == '/') { } else if (strchr(url, ':') != NULL || url[0] == '/') {
...@@ -762,6 +762,7 @@ int git_submodule_sync(git_submodule *sm) ...@@ -762,6 +762,7 @@ int git_submodule_sync(git_submodule *sm)
int error = 0; int error = 0;
git_config *cfg = NULL; git_config *cfg = NULL;
git_buf key = GIT_BUF_INIT; git_buf key = GIT_BUF_INIT;
git_repository *smrepo = NULL;
if (!sm->url) { if (!sm->url) {
giterr_set(GITERR_SUBMODULE, giterr_set(GITERR_SUBMODULE,
...@@ -777,37 +778,17 @@ int git_submodule_sync(git_submodule *sm) ...@@ -777,37 +778,17 @@ int git_submodule_sync(git_submodule *sm)
/* if submodule exists in the working directory, update remote url */ /* if submodule exists in the working directory, update remote url */
if (!error && (sm->flags & GIT_SUBMODULE_STATUS_IN_WD) != 0) { if (!error &&
git_repository *smrepo = NULL; (sm->flags & GIT_SUBMODULE_STATUS_IN_WD) != 0 &&
git_reference *smhead = NULL; !(error = git_submodule_open(&smrepo, sm)))
const char *remote = "origin"; {
if ((error = lookup_head_remote_key(&key, smrepo)) < 0) {
if ((error = git_submodule_open(&smrepo, sm)) < 0 || giterr_clear();
(error = git_repository_head(&smhead, smrepo)) < 0 || git_buf_sets(&key, "branch.origin.remote");
(error = git_repository_config__weakptr(&cfg, smrepo)) < 0)
goto smcleanup;
/* get remote for default branch and set remote.<name>.url */
if (git_reference_type(smhead) == GIT_REF_SYMBOLIC) {
const char *bname = git_reference_shorthand(smhead);
const git_config_entry *ce;
git_buf_clear(&key);
if ((error = git_buf_printf(&key, "branch.%s.remote", bname)) < 0 ||
(error = git_config__lookup_entry(&ce, cfg, key.ptr, 0)) < 0)
goto smcleanup;
if (ce && ce->value)
remote = ce->value;
} }
git_buf_clear(&key); error = git_config__update_entry(cfg, key.ptr, sm->url, true, true);
if (!(error = git_buf_printf(&key, "remote.%s.url", remote)))
error = git_config__update_entry(cfg, key.ptr, sm->url, true, true);
smcleanup:
git_reference_free(smhead);
git_repository_free(smrepo); git_repository_free(smrepo);
} }
...@@ -1633,27 +1614,27 @@ cleanup: ...@@ -1633,27 +1614,27 @@ cleanup:
return error; return error;
} }
static int lookup_head_remote(git_buf *url, git_repository *repo) static int lookup_head_remote_key(git_buf *key, git_repository *repo)
{ {
int error; int error;
git_config *cfg; git_config *cfg;
git_reference *head = NULL, *remote = NULL; git_reference *head = NULL, *remote = NULL;
const char *tgt, *scan; const char *tgt, *scan;
git_buf key = GIT_BUF_INIT;
/* 1. resolve HEAD -> refs/heads/BRANCH /* 1. resolve HEAD -> refs/heads/BRANCH
* 2. lookup config branch.BRANCH.remote -> ORIGIN * 2. lookup config branch.BRANCH.remote -> ORIGIN
* 3. lookup remote.ORIGIN.url * 3. return remote.ORIGIN.url
*/ */
git_buf_clear(key);
if ((error = git_repository_config__weakptr(&cfg, repo)) < 0) if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
return error; return error;
if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0) { if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0) {
giterr_set(GITERR_SUBMODULE, giterr_set(GITERR_SUBMODULE,
"Cannot resolve relative URL when HEAD cannot be resolved"); "Cannot resolve relative URL when HEAD cannot be resolved");
error = GIT_ENOTFOUND; return GIT_ENOTFOUND;
goto cleanup;
} }
if (git_reference_type(head) != GIT_REF_SYMBOLIC) { if (git_reference_type(head) != GIT_REF_SYMBOLIC) {
...@@ -1669,7 +1650,8 @@ static int lookup_head_remote(git_buf *url, git_repository *repo) ...@@ -1669,7 +1650,8 @@ static int lookup_head_remote(git_buf *url, git_repository *repo)
/* remote should refer to something like refs/remotes/ORIGIN/BRANCH */ /* remote should refer to something like refs/remotes/ORIGIN/BRANCH */
if (git_reference_type(remote) != GIT_REF_SYMBOLIC || if (git_reference_type(remote) != GIT_REF_SYMBOLIC ||
git__prefixcmp(git_reference_symbolic_target(remote), GIT_REFS_REMOTES_DIR) != 0) git__prefixcmp(
git_reference_symbolic_target(remote), GIT_REFS_REMOTES_DIR) != 0)
{ {
giterr_set(GITERR_SUBMODULE, giterr_set(GITERR_SUBMODULE,
"Cannot resolve relative URL when HEAD is not symbolic"); "Cannot resolve relative URL when HEAD is not symbolic");
...@@ -1677,27 +1659,39 @@ static int lookup_head_remote(git_buf *url, git_repository *repo) ...@@ -1677,27 +1659,39 @@ static int lookup_head_remote(git_buf *url, git_repository *repo)
goto cleanup; goto cleanup;
} }
scan = tgt = git_reference_symbolic_target(remote) + strlen(GIT_REFS_REMOTES_DIR); scan = tgt = git_reference_symbolic_target(remote) +
strlen(GIT_REFS_REMOTES_DIR);
while (*scan && (*scan != '/' || (scan > tgt && scan[-1] != '\\'))) while (*scan && (*scan != '/' || (scan > tgt && scan[-1] != '\\')))
scan++; /* find non-escaped slash to end ORIGIN name */ scan++; /* find non-escaped slash to end ORIGIN name */
error = git_buf_printf(&key, "remote.%.*s.url", (int)(scan - tgt), tgt); error = git_buf_printf(key, "remote.%.*s.url", (int)(scan - tgt), tgt);
if (error < 0)
goto cleanup;
if ((error = git_config_get_string(&tgt, cfg, key.ptr)) < 0)
goto cleanup;
error = git_buf_sets(url, tgt);
cleanup: cleanup:
git_buf_free(&key); if (error < 0)
git_buf_clear(key);
git_reference_free(head); git_reference_free(head);
git_reference_free(remote); git_reference_free(remote);
return error; return error;
} }
static int lookup_head_remote(git_buf *url, git_repository *repo)
{
int error;
git_config *cfg;
const char *tgt;
git_buf key = GIT_BUF_INIT;
if (!(error = lookup_head_remote_key(&key, repo)) &&
!(error = git_repository_config__weakptr(&cfg, repo)) &&
!(error = git_config_get_string(&tgt, cfg, key.ptr)))
error = git_buf_sets(url, tgt);
git_buf_free(&key);
return error;
}
static void submodule_get_index_status(unsigned int *status, git_submodule *sm) static void submodule_get_index_status(unsigned int *status, git_submodule *sm)
{ {
const git_oid *head_oid = git_submodule_head_id(sm); const git_oid *head_oid = git_submodule_head_id(sm);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment