On Wed, Jun 10, 2015 at 2:04 PM, Linus Torvalds <torva...@linux-foundation.org> wrote: > > I'll try to get the "push to remote" done too.
Ok, I think this is it. It's not particularly well-tested, but it is fairly straightforward. HOWEVER, note the big commit message comment about why technically this works in the sense that it can now sync both ways to the remote git repository, but the whole "cloud sync" needs more thought from a interface standpoint. I could add some "sync up to remote" after doing a local save, but I didn't add that, because I do believe we need more smarts than that (or if not "smarts", then an actual GUI). Because I don't think it's a good idea to just try to do the whole network thing unconditionally, when you often don't have good (or any) internet access when actually diving with subsurface. So I think the local git cache should basically always load/store to the local cache, and we should add some GUI to actually trigger this "sync with cloud" code. Right now it always triggers when you load from the cache (but *not* when saving to it). Dirk, I haven't actually tried your cloud infrastructure, I've just been testing with my "remote repository on local disk" setup. Linus
From 03343b65a32845bae05f18f9aba131ad441f22c6 Mon Sep 17 00:00:00 2001 From: Linus Torvalds <torva...@linux-foundation.org> Date: Wed, 10 Jun 2015 17:18:44 -0700 Subject: [PATCH 2/3] 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 <torva...@linux-foundation.org> --- git-access.c | 70 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/git-access.c b/git-access.c index bf238a191983..ded065e01f61 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; } -- 2.4.2.337.gfae46aa
From 5bb3bae4a6ef1efe2dee5a42488acc8134ea3c01 Mon Sep 17 00:00:00 2001 From: Linus Torvalds <torva...@linux-foundation.org> Date: Wed, 10 Jun 2015 18:03:37 -0700 Subject: [PATCH 3/3] git storage: actually update the remote repository if the local cache is more recent Again, note that this currently only happens when you initially open the repository. So if you do subsurface https://.../repo[myubranch] it will start up by fetching the remote information, and updating the local cache. If you then download new dives, and do a save-and-exit, it will save to the local cache, but it doesn't do the fetch at this point, so the remote is now begind. The *next* time you start subsurface, and load that git branch again, it will fetch the remote, and now notice that the local cache is ahead of it (because you downloaded new dives and saved them locally), and *then* it will try to update the remote with the new information. This is obviously bogus, but we will need to decide exactly how we want to sync with the remote repository. But now the core functionality is there, it's just that we need some interface to say "sync now". Especially in the face of spotty (or non-working) internet, you want a GUI etc for this whole remote sync, rather than doing it unconditionally and silently whenever you load the local cache initially. With that caveat: Signed-off-by: Linus Torvalds <torva...@linux-foundation.org> --- git-access.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/git-access.c b/git-access.c index ded065e01f61..0cfd27483832 100644 --- a/git-access.c +++ b/git-access.c @@ -101,6 +101,17 @@ static int reset_to_remote(git_repository *repo, git_reference *local, const git static int update_remote(git_repository *repo, git_remote *origin, git_reference *local, git_reference *remote) { + git_push_options opts = GIT_PUSH_OPTIONS_INIT; + git_strarray refspec; + const char *name = git_reference_name(local); + + refspec.count = 1; + refspec.strings = (char **)&name; + + if (git_remote_push(origin, &refspec, &opts)) + return report_error("Unable to update remote with current local cache state (%s)", giterr_last()->message); + + // Not actually an error, just informational report_error("Local cache more recent than remote"); return 0; } -- 2.4.2.337.gfae46aa
_______________________________________________ subsurface mailing list subsurface@subsurface-divelog.org http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface