summaryrefslogtreecommitdiffstats
path: root/git-access.c
diff options
context:
space:
mode:
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;
}