diff --git a/services/git-bridge/pom.xml b/services/git-bridge/pom.xml index 74eaefe50d..f5e7f3176a 100644 --- a/services/git-bridge/pom.xml +++ b/services/git-bridge/pom.xml @@ -9,6 +9,7 @@ 1.0-SNAPSHOT UTF-8 + true diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java index 9ee76263de..d4c680afff 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java @@ -37,6 +37,7 @@ import uk.ac.ic.wlgitbridge.server.PostbackContents; import uk.ac.ic.wlgitbridge.server.PostbackHandler; import uk.ac.ic.wlgitbridge.snapshot.base.MissingRepositoryException; import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException; +import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocResult; import uk.ac.ic.wlgitbridge.snapshot.getforversion.SnapshotAttachment; import uk.ac.ic.wlgitbridge.snapshot.push.PostbackManager; import uk.ac.ic.wlgitbridge.snapshot.push.PostbackPromise; @@ -299,7 +300,7 @@ public class Bridge { * Synchronises the given repository with Overleaf. * * It acquires the project lock and calls - * {@link #getUpdatedRepoCritical(Optional, String)}. + * {@link #getUpdatedRepoCritical(Optional, String, GetDocResult)}. * @param oauth2 The oauth2 to use * @param projectName The name of the project * @throws IOException @@ -310,11 +311,13 @@ public class Bridge { String projectName ) throws IOException, GitUserException { try (LockGuard __ = lock.lockGuard(projectName)) { - if (!snapshotAPI.projectExists(oauth2, projectName)) { + Optional maybeDoc = snapshotAPI.getDoc(oauth2, projectName); + if (!maybeDoc.isPresent()) { throw new RepositoryNotFoundException(projectName); } + GetDocResult doc = maybeDoc.get(); Log.info("[{}] Updating repository", projectName); - return getUpdatedRepoCritical(oauth2, projectName); + return getUpdatedRepoCritical(oauth2, projectName, doc); } } @@ -346,14 +349,49 @@ public class Bridge { */ private ProjectRepo getUpdatedRepoCritical( Optional oauth2, - String projectName + String projectName, + GetDocResult doc ) throws IOException, GitUserException { ProjectRepo repo; ProjectState state = dbStore.getProjectState(projectName); + Log.info(">>>> RepoStore {}", repoStore.getRepoStorePath()); + Log.info( + ">>>> getUpdatedRepoCritical, {} migratedFrom {}", + projectName, + doc.getMigratedFromID() + ); switch (state) { case NOT_PRESENT: - repo = repoStore.initRepo(projectName); - break; + Log.info(">>>> Not present {}", projectName); + String migratedFromID = doc.getMigratedFromID(); + if (migratedFromID != null) { + Log.info(">>>> has a migratedFromId {} {}", projectName, migratedFromID); + ProjectState sourceState = dbStore.getProjectState(migratedFromID); + try (LockGuard __ = lock.lockGuard(migratedFromID)) { + switch (sourceState) { + case NOT_PRESENT: + // Normal init-repo + Log.info(">>>> migrated-from-id not present, proceed as normal"); + repo = repoStore.initRepo(projectName); + break; + case SWAPPED: + // Swap back and then copy + Log.info(">>>> migrated-from-id swapped, unswap and proceed"); + swapJob.restore(migratedFromID); + /* Fallthrough */ + default: + // Copy data, and set version to zero + Log.info(">>>> migrated-from-id init from existing"); + repo = repoStore.initRepoFromExisting(projectName, migratedFromID); + dbStore.setLatestVersionForProject(migratedFromID, 0); + } + } + break; + } else { + Log.info(">>>> no migrated-from-id {}", projectName); + repo = repoStore.initRepo(projectName); + break; + } case SWAPPED: swapJob.restore(projectName); /* Fallthrough */ diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/FSGitRepoStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/FSGitRepoStore.java index a3bfe30928..55ae573337 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/FSGitRepoStore.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/FSGitRepoStore.java @@ -4,6 +4,7 @@ import com.google.api.client.repackaged.com.google.common.base.Preconditions; import org.apache.commons.io.FileUtils; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; +import uk.ac.ic.wlgitbridge.util.Log; import uk.ac.ic.wlgitbridge.util.Project; import uk.ac.ic.wlgitbridge.util.Tar; @@ -74,6 +75,38 @@ public class FSGitRepoStore implements RepoStore { ret, Optional.of(maxFileSize), Optional.empty()); } + @Override + public ProjectRepo initRepoFromExisting( + String project, String fromProject + ) throws IOException { + GitProjectRepo ret = GitProjectRepo.fromName(project); + // GitProjectRepo origin = GitProjectRepo.fromName(fromProject); + ret.initRepo(this); + Log.info(">>>> Copy from {} to {}", fromProject, project); + String repoRoot = getRepoStorePath(); + String sourcePath = repoRoot + "/" + fromProject; + String destinationPath = repoRoot + "/" + project; + Log.info(">>>> paths from: {} and to: {}", sourcePath, destinationPath); + new ProcessBuilder( + "rm", "-rf", + destinationPath + ).start(); + Process copyProcess = new ProcessBuilder( + "cp", "-ra", + sourcePath, + destinationPath + "/" + ).start(); + Log.info(">>>> done copy"); + try { + copyProcess.waitFor(); + } catch (InterruptedException e) { + e.printStackTrace(); + throw new IOException("copy failed" + e.getLocalizedMessage()); + } + return new WalkOverrideGitRepo( + ret, Optional.of(maxFileSize), Optional.empty()); + } + @Override public ProjectRepo getExistingRepo(String project) throws IOException { GitProjectRepo ret = GitProjectRepo.fromName(project); diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStore.java index a5eb289942..18bea89cd5 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStore.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStore.java @@ -22,6 +22,8 @@ public interface RepoStore { ProjectRepo initRepo(String project) throws IOException; + ProjectRepo initRepoFromExisting(String project, String fromProject) throws IOException; + ProjectRepo getExistingRepo(String project) throws IOException; ProjectRepo useJGitRepo(Repository repo, ObjectId commitId); diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApiFacade.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApiFacade.java index f9085febcb..07f19640fa 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApiFacade.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApiFacade.java @@ -44,6 +44,15 @@ public class SnapshotApiFacade { } } + public Optional getDoc( + Optional oauth2, + String projectName + ) throws FailedConnectionException, GitUserException { + GetDocResult doc = SnapshotApi + .getResult(api.getDoc(oauth2, projectName)); + return Optional.ofNullable(doc); + } + public Deque getSnapshots( Optional oauth2, String projectName, diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLRepositoryResolver.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLRepositoryResolver.java index 022101fc5b..0405323298 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLRepositoryResolver.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLRepositoryResolver.java @@ -90,7 +90,7 @@ public class WLRepositoryResolver return bridge.getUpdatedRepo(oauth2, projName).getJGitRepository(); } catch (RepositoryNotFoundException e) { Log.info("Repository not found: " + name); - throw e; + throw new RepositoryNotFoundException("derp"); /* } catch (ServiceNotAuthorizedException e) { cannot occur