summaryrefslogtreecommitdiffstats
path: root/git-access.c
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2015-06-10 17:18:44 -0700
committerGravatar Dirk Hohndel <dirk@hohndel.org>2015-06-10 20:57:13 -0700
commit971f1c66742508161c023623aef260d9b777f55c (patch)
tree3adf5ebc1fea996bcead92a2dfb691510a445d0b /git-access.c
parent1379f3479278b4a7c6de1ada9e21161d2117c210 (diff)
downloadsubsurface-971f1c66742508161c023623aef260d9b777f55c.tar.gz
git storage: re-organize code to make 'origin' remote more widely available
I'm going to try to update the remote if the local cache is more recent when we fetch the data, which requires access to the remote over a wider range of code. This re-organizes the code so that we can free the remote later without having to have nasty error handling. We avoid the whole "if an error happened, free the remote and return" by creating helper functions and freeing the remote in the caller, so that all paths end up freeing it naturally. NOTE! We want to try to update the remote when we save the local cache too, so this whole "update remote when opening it" is incomplete. But (a) we do want to do it here as well and (b) this is the easiest place to create the initial "push to remote" code without any new "sync with cloud" interfaces. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'git-access.c')
-rw-r--r--git-access.c70
1 files changed, 39 insertions, 31 deletions
diff --git a/git-access.c b/git-access.c
index bf238a191..ded065e01 100644
--- a/git-access.c
+++ b/git-access.c
@@ -99,7 +99,13 @@ static int reset_to_remote(git_repository *repo, git_reference *local, const git
return 0;
}
-static int try_to_update(git_repository *repo, git_reference *local, git_reference *remote)
+static int update_remote(git_repository *repo, git_remote *origin, git_reference *local, git_reference *remote)
+{
+ report_error("Local cache more recent than remote");
+ return 0;
+}
+
+static int try_to_update(git_repository *repo, git_remote *origin, git_reference *local, git_reference *remote)
{
git_oid base;
const git_oid *local_id, *remote_id;
@@ -107,6 +113,11 @@ static int try_to_update(git_repository *repo, git_reference *local, git_referen
if (!git_reference_cmp(local, remote))
return 0;
+ // Dirty modified state in the working tree? We're not going
+ // to update either way
+ if (git_status_foreach(repo, check_clean, NULL))
+ return report_error("local cached copy is dirty, skipping update");
+
local_id = git_reference_target(local);
remote_id = git_reference_target(remote);
@@ -120,11 +131,9 @@ static int try_to_update(git_repository *repo, git_reference *local, git_referen
if (git_oid_equal(&base, local_id))
return reset_to_remote(repo, local, remote_id);
- /* Is the local repo the more recent one? We're done */
- if (git_oid_equal(&base, remote_id)) {
- report_error("Local cache more recent than remote");
- return 0;
- }
+ /* Is the local repo the more recent one? See if we can update upstream */
+ if (git_oid_equal(&base, remote_id))
+ return update_remote(repo, origin, local, remote);
/* Merging a bare repository always needs user action */
if (git_repository_is_bare(repo))
@@ -140,7 +149,8 @@ static int try_to_update(git_repository *repo, git_reference *local, git_referen
* But I couldn't find any good examples of this, so for now
* you'd need to merge divergent histories manually. But we've
* at least verified above that we have a working tree and the
- * current branch is checked out, so we *could* try to merge.
+ * current branch is checked out and clean, so we *could* try
+ * to merge.
*/
return report_error("Local and remote have diverged, need to merge");
}
@@ -169,12 +179,28 @@ int credential_https_cb(git_cred **out,
}
#endif
+static int check_remote_status(git_repository *repo, git_remote *origin, const char *branch)
+{
+ git_reference *local_ref, *remote_ref;
+
+ if (git_branch_lookup(&local_ref, repo, branch, GIT_BRANCH_LOCAL))
+ return report_error("Git cache branch %s no longer exists", branch);
+
+ if (git_branch_upstream(&remote_ref, local_ref)) {
+ git_reference_free(local_ref);
+ return report_error("Git cache branch %s no longer has an upstream branch", branch);
+ }
+
+ try_to_update(repo, origin, local_ref, remote_ref);
+ git_reference_free(local_ref);
+ git_reference_free(remote_ref);
+}
+
static git_repository *update_local_repo(const char *localdir, const char *remote, const char *branch)
{
int error;
git_repository *repo = NULL;
git_remote *origin;
- git_reference *local_ref, *remote_ref;
error = git_repository_open(&repo, localdir);
if (error) {
@@ -205,31 +231,13 @@ static git_repository *update_local_repo(const char *localdir, const char *remot
#else
error = git_remote_fetch(origin, NULL, NULL, NULL);
#endif
- git_remote_free(origin);
- if (error) {
- report_error("Unable to update cache for remote '%s'", remote);
- return repo;
- }
-
- // Dirty modified state in the working tree? We're not going
- // to tru to update
- if (git_status_foreach(repo, check_clean, NULL))
- return repo;
- if (git_branch_lookup(&local_ref, repo, branch, GIT_BRANCH_LOCAL)) {
- report_error("Git cache branch %s no longer exists", branch);
- return repo;
- }
-
- if (git_branch_upstream(&remote_ref, local_ref)) {
- report_error("Git cache branch %s no longer has an upstream branch", branch);
- git_reference_free(local_ref);
- return repo;
- }
+ if (error)
+ report_error("Unable to fetch remote '%s'", remote);
+ else
+ check_remote_status(repo, origin, branch);
- try_to_update(repo, local_ref, remote_ref);
- git_reference_free(local_ref);
- git_reference_free(remote_ref);
+ git_remote_free(origin);
return repo;
}