summaryrefslogtreecommitdiff
path: root/src/submodule.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2013-12-18 11:48:57 -0800
committerRussell Belfer <rb@github.com>2014-04-01 09:45:20 -0700
commit8286300a1e2d24dfe184316c0f9798f2c69d0ef4 (patch)
treeb0ffb64c15a84f0cb1d138587e395986da7b1c7a /src/submodule.c
parent18234b14ad55157581ca26ec763afc1af3ec6e76 (diff)
downloadlibgit2-8286300a1e2d24dfe184316c0f9798f2c69d0ef4.tar.gz
Fix git_submodule_sync and add new config helper
This fixes `git_submodule_sync` to correctly update the remote URL of the default branch of the submodule along with the URL in the parent repository config (i.e. match core Git's behavior). Also move some useful helper logic from the submodule code into a shared config API `git_config__update_entry` that can either set or delete an entry with constraints like not overwriting or not creating a new entry. I used that helper to update a couple other places in the code.
Diffstat (limited to 'src/submodule.c')
-rw-r--r--src/submodule.c138
1 files changed, 76 insertions, 62 deletions
diff --git a/src/submodule.c b/src/submodule.c
index a0ce5317f..dc0ea435e 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -83,7 +83,6 @@ 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_load_from_config(const git_config_entry *, void *);
static int submodule_load_from_wd_lite(git_submodule *);
-static int submodule_update_config(git_submodule *, const char *, const char *, bool, bool);
static void submodule_get_index_status(unsigned int *, git_submodule *);
static void submodule_get_wd_status(unsigned int *, git_submodule *, git_repository *, git_submodule_ignore_t);
@@ -716,46 +715,105 @@ git_submodule_recurse_t git_submodule_set_fetch_recurse_submodules(
return old;
}
-int git_submodule_init(git_submodule *submodule, int overwrite)
+int git_submodule_init(git_submodule *sm, int overwrite)
{
int error;
const char *val;
+ git_buf key = GIT_BUF_INIT;
+ git_config *cfg = NULL;
- /* write "submodule.NAME.url" */
-
- if (!submodule->url) {
+ if (!sm->url) {
giterr_set(GITERR_SUBMODULE,
- "No URL configured for submodule '%s'", submodule->name);
+ "No URL configured for submodule '%s'", sm->name);
return -1;
}
- error = submodule_update_config(
- submodule, "url", submodule->url, overwrite != 0, false);
- if (error < 0)
+ if ((error = git_repository_config(&cfg, sm->repo)) < 0)
return error;
+ /* write "submodule.NAME.url" */
+
+ if ((error = git_buf_printf(&key, "submodule.%s.url", sm->name)) < 0 ||
+ (error = git_config__update_entry(
+ cfg, key.ptr, sm->url, overwrite != 0, false)) < 0)
+ goto cleanup;
+
/* write "submodule.NAME.update" if not default */
- val = (submodule->update == GIT_SUBMODULE_UPDATE_CHECKOUT) ?
- NULL : git_submodule_update_to_str(submodule->update);
- error = submodule_update_config(
- submodule, "update", val, (overwrite != 0), false);
+ val = (sm->update == GIT_SUBMODULE_UPDATE_CHECKOUT) ?
+ NULL : git_submodule_update_to_str(sm->update);
+
+ if ((error = git_buf_printf(&key, "submodule.%s.update", sm->name)) < 0 ||
+ (error = git_config__update_entry(
+ cfg, key.ptr, val, overwrite != 0, false)) < 0)
+ goto cleanup;
+
+ /* success */
+
+cleanup:
+ git_config_free(cfg);
+ git_buf_free(&key);
return error;
}
-int git_submodule_sync(git_submodule *submodule)
+int git_submodule_sync(git_submodule *sm)
{
- if (!submodule->url) {
+ int error = 0;
+ git_config *cfg = NULL;
+ git_buf key = GIT_BUF_INIT;
+
+ if (!sm->url) {
giterr_set(GITERR_SUBMODULE,
- "No URL configured for submodule '%s'", submodule->name);
+ "No URL configured for submodule '%s'", sm->name);
return -1;
}
/* copy URL over to config only if it already exists */
- return submodule_update_config(
- submodule, "url", submodule->url, true, true);
+ if (!(error = git_repository_config__weakptr(&cfg, sm->repo)) &&
+ !(error = git_buf_printf(&key, "submodule.%s.url", sm->name)))
+ error = git_config__update_entry(cfg, key.ptr, sm->url, true, true);
+
+ /* if submodule exists in the working directory, update remote url */
+
+ if (!error && (sm->flags & GIT_SUBMODULE_STATUS_IN_WD) != 0) {
+ git_repository *smrepo = NULL;
+ git_reference *smhead = NULL;
+ const char *remote = "origin";
+
+ if ((error = git_submodule_open(&smrepo, sm)) < 0 ||
+ (error = git_repository_head(&smhead, smrepo)) < 0 ||
+ (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);
+ 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_buf_free(&key);
+
+ return error;
}
static int git_submodule__open(
@@ -1640,50 +1698,6 @@ cleanup:
return error;
}
-static int submodule_update_config(
- git_submodule *submodule,
- const char *attr,
- const char *value,
- bool overwrite,
- bool only_existing)
-{
- int error;
- git_config *config;
- git_buf key = GIT_BUF_INIT;
- const git_config_entry *ce = NULL;
-
- assert(submodule);
-
- error = git_repository_config__weakptr(&config, submodule->repo);
- if (error < 0)
- return error;
-
- error = git_buf_printf(&key, "submodule.%s.%s", submodule->name, attr);
- if (error < 0)
- goto cleanup;
-
- if ((error = git_config__lookup_entry(&ce, config, key.ptr, false)) < 0)
- goto cleanup;
-
- if (!ce && only_existing)
- goto cleanup;
- if (ce && !overwrite)
- goto cleanup;
- if (value && ce && ce->value && !strcmp(ce->value, value))
- goto cleanup;
- if (!value && (!ce || !ce->value))
- goto cleanup;
-
- if (!value)
- error = git_config_delete_entry(config, key.ptr);
- else
- error = git_config_set_string(config, key.ptr, value);
-
-cleanup:
- git_buf_free(&key);
- return error;
-}
-
static void submodule_get_index_status(unsigned int *status, git_submodule *sm)
{
const git_oid *head_oid = git_submodule_head_id(sm);