diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java index 6e3f049cf6..5c909c3da3 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java @@ -25,7 +25,7 @@ public class GitBridgeApp implements Runnable { "usage: writelatex-git-bridge config_file"; private String configFilePath; - private Config config; + Config config; private GitBridgeServer server; /** diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java index 26ffa495fd..eb64fe15be 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java @@ -98,6 +98,14 @@ public class Config implements JSONSource { postbackURL += "/"; } oauth2 = new Gson().fromJson(configObject.get("oauth2"), Oauth2.class); + swapStore = new Gson().fromJson( + configObject.get("swapStore"), + SwapStoreConfig.class + ); + swapJob = new Gson().fromJson( + configObject.get("swapJob"), + SwapJobConfig.class + ); } public String getSanitisedString() { 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 ed328079a4..bdb95ac828 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 @@ -10,6 +10,9 @@ import java.util.Collection; */ public interface RepoStore { + /* Still need to get rid of these two methods. + Main dependency: GitRepoStore needs a Repository which needs a directory. + Instead, use a visitor or something. */ String getRepoStorePath(); File getRootDirectory(); @@ -20,7 +23,7 @@ public interface RepoStore { long totalSize(); - /* + /** * Tars and bzip2s the .git directory of the given project. Throws an * IOException if the project doesn't exist. The returned stream is a copy * of the original .git directory, which must be deleted using remove(). diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java index dfacc0001e..057cb8148e 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java @@ -5,9 +5,6 @@ package uk.ac.ic.wlgitbridge.bridge.swap.job; */ public class SwapJobConfig { - public static final SwapJobConfig DEFAULT = - new SwapJobConfig(1, 1, 2, 3600000); - private final int minProjects; private final int lowGiB; private final int highGiB; diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/InMemorySwapStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/InMemorySwapStore.java index d4c5a11136..a507e7e829 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/InMemorySwapStore.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/InMemorySwapStore.java @@ -19,6 +19,10 @@ public class InMemorySwapStore implements SwapStore { store = new HashMap<>(); } + public InMemorySwapStore(SwapStoreConfig __) { + this(); + } + @Override public void upload( String projectName, diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStore.java index 1f582230bb..168e959313 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStore.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStore.java @@ -17,6 +17,7 @@ public interface SwapStore { { put("noop", NoopSwapStore::new); + put("memory", InMemorySwapStore::new); put("s3", S3SwapStore::new); } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLReceivePackFactory.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLReceivePackFactory.java index 542963767d..5ca19ba7d5 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLReceivePackFactory.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLReceivePackFactory.java @@ -19,10 +19,10 @@ import javax.servlet.http.HttpServletRequest; /* */ public class WLReceivePackFactory implements ReceivePackFactory { - private final Bridge bridgeAPI; + private final Bridge bridge; - public WLReceivePackFactory(Bridge bridgeAPI) { - this.bridgeAPI = bridgeAPI; + public WLReceivePackFactory(Bridge bridge) { + this.bridge = bridge; } @Override @@ -33,7 +33,7 @@ public class WLReceivePackFactory implements ReceivePackFactory() {{ put("state", new SnapshotAPIStateBuilder(getResourceAsStream("/canServePushedFiles/state/state.json")).build()); }}); + put("wlgbCanSwapProjects", new HashMap() {{ + put("state", new SnapshotAPIStateBuilder(getResourceAsStream("/wlgbCanSwapProjects/state/state.json")).build()); + }}); }}; @Rule @@ -587,6 +591,38 @@ public class WLGitBridgeIntegrationTest { wlgb.stop(); } + @Test + public void wlgbCanSwapProjects( + ) throws IOException, GitAPIException, InterruptedException { + MockSnapshotServer server = new MockSnapshotServer( + 3874, + getResource("/wlgbCanSwapProjects").toFile() + ); + server.start(); + server.setState(states.get("wlgbCanSwapProjects").get("state")); + GitBridgeApp wlgb = new GitBridgeApp(new String[] { + makeConfigFile(33874, 3874, new SwapJobConfig(1, 0, 0, 250)) + }); + wlgb.run(); + File dir = folder.newFolder(); + File rootGitDir = new File(wlgb.config.getRootGitDirectory()); + File testProj1ServerDir = new File(rootGitDir, "testproj1"); + File testProj2ServerDir = new File(rootGitDir, "testproj2"); + File testProj1Dir = cloneRepository("testproj1", 33874, dir); + assertTrue(testProj1ServerDir.exists()); + assertFalse(testProj2ServerDir.exists()); + cloneRepository("testproj2", 33874, dir); + while (testProj1ServerDir.exists()); + assertFalse(testProj1ServerDir.exists()); + assertTrue(testProj2ServerDir.exists()); + FileUtils.deleteDirectory(testProj1Dir); + cloneRepository("testproj1", 33874, dir); + while (testProj2ServerDir.exists()); + assertTrue(testProj1ServerDir.exists()); + assertFalse(testProj2ServerDir.exists()); + wlgb.stop(); + } + private File cloneRepository(String repositoryName, int port, File dir) throws IOException, InterruptedException { String repo = "git clone http://127.0.0.1:" + port + "/" + repositoryName + ".git"; Process gitProcess = runtime.exec(repo, null, dir); @@ -606,30 +642,72 @@ public class WLGitBridgeIntegrationTest { return repositoryDir; } - private String makeConfigFile(int port, int apiPort) throws IOException { + private String makeConfigFile( + int port, + int apiPort + ) throws IOException { + return makeConfigFile(port, apiPort, null); + } + + private String makeConfigFile( + int port, + int apiPort, + SwapJobConfig swapCfg + ) throws IOException { File wlgb = folder.newFolder(); File config = folder.newFile(); PrintWriter writer = new PrintWriter(config); - writer.println("{\n" + - "\t\"port\": " + port + ",\n" + - "\t\"rootGitDirectory\": \"" + wlgb.getAbsolutePath() + "\",\n" + - "\t\"apiBaseUrl\": \"http://127.0.0.1:" + apiPort + "/api/v0\",\n" + - "\t\"username\": \"\",\n" + - "\t\"password\": \"\",\n" + - "\t\"postbackBaseUrl\": \"http://127.0.0.1:" + port + "\",\n" + - "\t\"serviceName\": \"Overleaf\"\n," + - " \"oauth2\": {\n" + - " \"oauth2ClientID\": \"clientID\",\n" + - " \"oauth2ClientSecret\": \"oauth2 client secret\",\n" + - " \"oauth2Server\": \"https://www.overleaf.com\"\n" + - " }\n" + - "}\n"); + String cfgStr = + "{\n" + + " \"port\": " + port + ",\n" + + " \"rootGitDirectory\": \"" + + wlgb.getAbsolutePath() + + "\",\n" + + " \"apiBaseUrl\": \"http://127.0.0.1:" + + apiPort + + "/api/v0\",\n" + + " \"username\": \"\",\n" + + " \"password\": \"\",\n" + + " \"postbackBaseUrl\": \"http://127.0.0.1:" + + port + + "\",\n" + + " \"serviceName\": \"Overleaf\",\n" + + " \"oauth2\": {\n" + + " \"oauth2ClientID\": \"clientID\",\n" + + " \"oauth2ClientSecret\": \"oauth2 client secret\",\n" + + " \"oauth2Server\": \"https://www.overleaf.com\"\n" + + " }"; + if (swapCfg != null) { + cfgStr += ",\n" + + " \"swapStore\": {\n" + + " \"type\": \"memory\"\n" + + " },\n" + + " \"swapJob\": {\n" + + " \"minProjects\": " + + swapCfg.getMinProjects() + + ",\n" + + " \"lowGiB\": " + + swapCfg.getLowGiB() + + ",\n" + + " \"highGiB\": " + + swapCfg.getHighGiB() + + ",\n" + + " \"intervalMillis\": " + + swapCfg.getIntervalMillis() + + "\n" + + " }\n"; + } + cfgStr += "}\n"; + writer.print(cfgStr); writer.close(); return config.getAbsolutePath(); } private Path getResource(String path) { - return Paths.get("src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest" + path); + return Paths.get( + "src/test/resources/" + + "uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest" + path + ); } private InputStream getResourceAsStream(String path) { diff --git a/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/BridgeTest.java b/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/BridgeTest.java index ebe3b31fc0..a2ecda2850 100644 --- a/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/BridgeTest.java +++ b/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/BridgeTest.java @@ -3,15 +3,25 @@ package uk.ac.ic.wlgitbridge.bridge; import org.junit.Before; import org.junit.Test; import uk.ac.ic.wlgitbridge.bridge.db.DBStore; +import uk.ac.ic.wlgitbridge.bridge.db.ProjectState; import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock; import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore; import uk.ac.ic.wlgitbridge.bridge.resource.ResourceCache; import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotAPI; import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJob; import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStore; +import uk.ac.ic.wlgitbridge.data.model.Snapshot; +import uk.ac.ic.wlgitbridge.git.exception.GitUserException; +import java.io.IOException; +import java.util.ArrayDeque; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; /** * Created by winston on 20/08/2016. @@ -56,4 +66,21 @@ public class BridgeTest { verify(swapJob).stop(); } + @Test + public void updatingRepositorySetsLastAccessedTime( + ) throws IOException, GitUserException { + ProjectRepo repo = mock(ProjectRepo.class); + when(repo.getProjectName()).thenReturn("asdf"); + when(dbStore.getProjectState("asdf")).thenReturn(ProjectState.PRESENT); + when( + snapshotAPI.getSnapshotsForProjectAfterVersion( + any(), + any(), + anyInt() + ) + ).thenReturn(new ArrayDeque()); + bridge.updateRepository(null, repo); + verify(dbStore).setLastAccessedTime(eq("asdf"), any()); + } + } \ No newline at end of file diff --git a/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/state.json b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/state.json new file mode 100644 index 0000000000..77d610d756 --- /dev/null +++ b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/state.json @@ -0,0 +1,90 @@ +[ + { + "project": "testproj1", + "getDoc": { + "versionID": 1, + "createdAt": "2014-11-30T18:40:58.123Z", + "email": "jdleesmiller+1@gmail.com", + "name": "John+1" + }, + "getSavedVers": [ + { + "versionID": 1, + "comment": "added more info on doc GET and error details", + "email": "jdleesmiller+1@gmail.com", + "name": "John+1", + "createdAt": "2014-11-30T18:47:01.456Z" + } + ], + "getForVers": [ + { + "versionID": 1, + "srcs": [ + { + "content": "content\n", + "path": "main.tex" + }, + { + "content": "This text is from another file.", + "path": "foo/bar/test.tex" + } + ], + "atts": [ + { + "url": "http://127.0.0.1:3874/state/testproj1/overleaf-white-410.png", + "path": "overleaf-white-410.png" + } + ] + } + ], + "push": "success", + "postback": { + "type": "success", + "versionID": 2 + } + }, + { + "project": "testproj2", + "getDoc": { + "versionID": 1, + "createdAt": "2014-11-30T18:40:58.123Z", + "email": "jdleesmiller+1@gmail.com", + "name": "John+1" + }, + "getSavedVers": [ + { + "versionID": 1, + "comment": "added more info on doc GET and error details", + "email": "jdleesmiller+1@gmail.com", + "name": "John+1", + "createdAt": "2014-11-30T18:47:01.456Z" + } + ], + "getForVers": [ + { + "versionID": 1, + "srcs": [ + { + "content": "different content\n", + "path": "main.tex" + }, + { + "content": "a different one", + "path": "foo/bar/test.tex" + } + ], + "atts": [ + { + "url": "http://127.0.0.1:3874/state/testproj2/editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png", + "path": "editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png" + } + ] + } + ], + "push": "success", + "postback": { + "type": "success", + "versionID": 2 + } + } +] \ No newline at end of file diff --git a/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/foo/bar/test.tex b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/foo/bar/test.tex new file mode 100644 index 0000000000..046794f19a --- /dev/null +++ b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/foo/bar/test.tex @@ -0,0 +1 @@ +This text is from another file. \ No newline at end of file diff --git a/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/main.tex b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/main.tex new file mode 100644 index 0000000000..d95f3ad14d --- /dev/null +++ b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/main.tex @@ -0,0 +1 @@ +content diff --git a/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/overleaf-white-410.png b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/overleaf-white-410.png new file mode 100644 index 0000000000..6a23d10c15 Binary files /dev/null and b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/overleaf-white-410.png differ diff --git a/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png new file mode 100644 index 0000000000..7fa339be7a Binary files /dev/null and b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png differ diff --git a/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/foo/bar/test.tex b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/foo/bar/test.tex new file mode 100644 index 0000000000..1c05c0183f --- /dev/null +++ b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/foo/bar/test.tex @@ -0,0 +1 @@ +a different one \ No newline at end of file diff --git a/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/main.tex b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/main.tex new file mode 100644 index 0000000000..802d4bbd2e --- /dev/null +++ b/services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/main.tex @@ -0,0 +1 @@ +different content