mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Decouple Bridge from network, JGit from disk
This commit is contained in:
parent
918e3d9975
commit
6b94fcf1b4
18 changed files with 302 additions and 204 deletions
|
@ -1,7 +1,7 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import org.eclipse.jgit.transport.ServiceMayNotContinueException;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SqliteDBStore;
|
||||
|
@ -15,13 +15,14 @@ import uk.ac.ic.wlgitbridge.bridge.repo.ProjectRepo;
|
|||
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
|
||||
import uk.ac.ic.wlgitbridge.bridge.resource.ResourceCache;
|
||||
import uk.ac.ic.wlgitbridge.bridge.resource.UrlResourceCache;
|
||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.NetSnapshotAPI;
|
||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotAPI;
|
||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.NetSnapshotApi;
|
||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotApi;
|
||||
import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJob;
|
||||
import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJobConfig;
|
||||
import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJobImpl;
|
||||
import uk.ac.ic.wlgitbridge.bridge.swap.store.S3SwapStore;
|
||||
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStore;
|
||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotApiFacade;
|
||||
import uk.ac.ic.wlgitbridge.data.CandidateSnapshot;
|
||||
import uk.ac.ic.wlgitbridge.data.ProjectLockImpl;
|
||||
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
|
||||
|
@ -38,12 +39,9 @@ import uk.ac.ic.wlgitbridge.server.FileHandler;
|
|||
import uk.ac.ic.wlgitbridge.server.PostbackContents;
|
||||
import uk.ac.ic.wlgitbridge.server.PostbackHandler;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.exception.InvalidProjectException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getforversion.SnapshotAttachment;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.PostbackManager;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.PostbackPromise;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.PushRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.PushResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.*;
|
||||
import uk.ac.ic.wlgitbridge.util.Log;
|
||||
|
@ -120,8 +118,8 @@ import java.util.*;
|
|||
*
|
||||
* 6. The Snapshot API, which provides data from the Overleaf app.
|
||||
*
|
||||
* @see SnapshotAPI - the interface for the Snapshot API.
|
||||
* @see NetSnapshotAPI - the default concrete implementation
|
||||
* @see SnapshotApi - the interface for the Snapshot API.
|
||||
* @see NetSnapshotApi - the default concrete implementation
|
||||
*
|
||||
* 7. The Resource Cache, which provides the data for attachment resources from
|
||||
* URLs. It will generally fetch from the source on a cache miss.
|
||||
|
@ -149,7 +147,7 @@ public class Bridge {
|
|||
private final SwapJob swapJob;
|
||||
private final GcJob gcJob;
|
||||
|
||||
private final SnapshotAPI snapshotAPI;
|
||||
private final SnapshotApiFacade snapshotAPI;
|
||||
private final ResourceCache resourceCache;
|
||||
|
||||
private final PostbackManager postbackManager;
|
||||
|
@ -169,7 +167,8 @@ public class Bridge {
|
|||
RepoStore repoStore,
|
||||
DBStore dbStore,
|
||||
SwapStore swapStore,
|
||||
Optional<SwapJobConfig> swapJobConfig
|
||||
Optional<SwapJobConfig> swapJobConfig,
|
||||
SnapshotApi snapshotApi
|
||||
) {
|
||||
ProjectLock lock = new ProjectLockImpl((int threads) ->
|
||||
Log.info("Waiting for " + threads + " projects...")
|
||||
|
@ -187,7 +186,7 @@ public class Bridge {
|
|||
swapStore
|
||||
),
|
||||
new GcJobImpl(repoStore, lock),
|
||||
new NetSnapshotAPI(),
|
||||
new SnapshotApiFacade(snapshotApi),
|
||||
new UrlResourceCache(dbStore)
|
||||
);
|
||||
}
|
||||
|
@ -202,7 +201,7 @@ public class Bridge {
|
|||
* @param swapStore the {@link SwapStore} to use
|
||||
* @param swapJob the {@link SwapJob} to use
|
||||
* @param gcJob
|
||||
* @param snapshotAPI the {@link SnapshotAPI} to use
|
||||
* @param snapshotAPI the {@link SnapshotApi} to use
|
||||
* @param resourceCache the {@link ResourceCache} to use
|
||||
*/
|
||||
Bridge(
|
||||
|
@ -212,7 +211,7 @@ public class Bridge {
|
|||
SwapStore swapStore,
|
||||
SwapJob swapJob,
|
||||
GcJob gcJob,
|
||||
SnapshotAPI snapshotAPI,
|
||||
SnapshotApiFacade snapshotAPI,
|
||||
ResourceCache resourceCache
|
||||
) {
|
||||
this.lock = lock;
|
||||
|
@ -291,63 +290,26 @@ public class Bridge {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a project exists by asking the snapshot API.
|
||||
*
|
||||
* The snapshot API is the source of truth because we can't know by
|
||||
* ourselves whether a project exists. If a user creates a project on the
|
||||
* app, and clones, the project is not on the git bridge disk and must ask
|
||||
* the snapshot API whether it exists.
|
||||
*
|
||||
* 1. Acquires the project lock.
|
||||
* 2. Makes a docs request and tries to get the version ID.
|
||||
* 3. If the version ID is valid, returns true.
|
||||
* 4. Otherwise, the version ID is invalid, and throws
|
||||
* InvalidProjectException, returning false.
|
||||
*
|
||||
* @param oauth2 The oauth2 to use for the snapshot API
|
||||
* @param projectName The project name
|
||||
* @return true iff the project exists
|
||||
* @throws ServiceMayNotContinueException if the connection fails
|
||||
* @throws GitUserException if the user is not allowed access
|
||||
*/
|
||||
public boolean projectExists(
|
||||
Credential oauth2,
|
||||
String projectName
|
||||
) throws ServiceMayNotContinueException,
|
||||
GitUserException {
|
||||
Log.info("[{}] Checking that project exists", projectName);
|
||||
try (LockGuard __ = lock.lockGuard(projectName)) {
|
||||
GetDocRequest getDocRequest = new GetDocRequest(
|
||||
oauth2,
|
||||
projectName
|
||||
);
|
||||
getDocRequest.request();
|
||||
getDocRequest.getResult().getVersionID();
|
||||
return true;
|
||||
} catch (InvalidProjectException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronises the given repository with Overleaf.
|
||||
*
|
||||
* It acquires the project lock and calls
|
||||
* {@link #updateRepositoryCritical(Credential, ProjectRepo)}
|
||||
* {@link #getUpdatedRepoCritical(Optional, String)}.
|
||||
* @param oauth2 The oauth2 to use
|
||||
* @param repo the repository to use
|
||||
* @param projectName The name of the project
|
||||
* @throws IOException
|
||||
* @throws GitUserException
|
||||
*/
|
||||
public void updateRepository(
|
||||
Credential oauth2,
|
||||
ProjectRepo repo
|
||||
public ProjectRepo getUpdatedRepo(
|
||||
Optional<Credential> oauth2,
|
||||
String projectName
|
||||
) throws IOException, GitUserException {
|
||||
String projectName = repo.getProjectName();
|
||||
try (LockGuard __ = lock.lockGuard(projectName)) {
|
||||
if (!snapshotAPI.projectExists(oauth2, projectName)) {
|
||||
throw new RepositoryNotFoundException(projectName);
|
||||
}
|
||||
Log.info("[{}] Updating repository", projectName);
|
||||
updateRepositoryCritical(oauth2, repo);
|
||||
return getUpdatedRepoCritical(oauth2, projectName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,9 +321,7 @@ public class Bridge {
|
|||
* 1. Queries the project state for the given project name.
|
||||
* a. NOT_PRESENT = We've never seen it before, and the row for the
|
||||
* project doesn't even exist. The project definitely
|
||||
* exists because
|
||||
* {@link #projectExists(Credential, String)} would
|
||||
* have had to return true to get here.
|
||||
* exists because we would have aborted otherwise.
|
||||
* b. PRESENT = The project is on disk.
|
||||
* c. SWAPPED = The project is in the {@link SwapStore}
|
||||
*
|
||||
|
@ -370,43 +330,44 @@ public class Bridge {
|
|||
* present.
|
||||
*
|
||||
* With the project present, snapshots are downloaded from the snapshot
|
||||
* API with {@link #updateProject(Credential, ProjectRepo)}.
|
||||
* API with {@link #updateProject(Optional, ProjectRepo)}.
|
||||
*
|
||||
* Then, the last accessed time of the project is set to the current time.
|
||||
* This is to support the LRU of the swap store.
|
||||
* @param oauth2
|
||||
* @param repo
|
||||
* @param projectName The name of the project
|
||||
* @throws IOException
|
||||
* @throws GitUserException
|
||||
*/
|
||||
private void updateRepositoryCritical(
|
||||
Credential oauth2,
|
||||
ProjectRepo repo
|
||||
private ProjectRepo getUpdatedRepoCritical(
|
||||
Optional<Credential> oauth2,
|
||||
String projectName
|
||||
) throws IOException, GitUserException {
|
||||
String projectName = repo.getProjectName();
|
||||
ProjectRepo repo;
|
||||
ProjectState state = dbStore.getProjectState(projectName);
|
||||
switch (state) {
|
||||
case NOT_PRESENT:
|
||||
repo.initRepo(repoStore);
|
||||
repo = repoStore.initRepo(projectName);
|
||||
break;
|
||||
case SWAPPED:
|
||||
swapJob.restore(projectName);
|
||||
/* Fallthrough */
|
||||
default:
|
||||
repo.useExistingRepository(repoStore);
|
||||
repo = repoStore.getExistingRepo(projectName);
|
||||
}
|
||||
updateProject(oauth2, repo);
|
||||
dbStore.setLastAccessedTime(
|
||||
projectName,
|
||||
Timestamp.valueOf(LocalDateTime.now())
|
||||
);
|
||||
return repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* The public call to push a project.
|
||||
*
|
||||
* It acquires the lock and calls {@link #pushCritical(
|
||||
* Credential,
|
||||
* Optional,
|
||||
* String,
|
||||
* RawDirectory,
|
||||
* RawDirectory
|
||||
|
@ -421,7 +382,7 @@ public class Bridge {
|
|||
* @throws ForbiddenException
|
||||
*/
|
||||
public void push(
|
||||
Credential oauth2,
|
||||
Optional<Credential> oauth2,
|
||||
String projectName,
|
||||
RawDirectory directoryContents,
|
||||
RawDirectory oldDirectoryContents,
|
||||
|
@ -499,7 +460,7 @@ public class Bridge {
|
|||
* @throws SnapshotPostException
|
||||
*/
|
||||
private void pushCritical(
|
||||
Credential oauth2,
|
||||
Optional<Credential> oauth2,
|
||||
String projectName,
|
||||
RawDirectory directoryContents,
|
||||
RawDirectory oldDirectoryContents
|
||||
|
@ -523,13 +484,8 @@ public class Bridge {
|
|||
projectName,
|
||||
candidate
|
||||
);
|
||||
PushRequest pushRequest = new PushRequest(
|
||||
oauth2,
|
||||
candidate,
|
||||
postbackKey
|
||||
);
|
||||
pushRequest.request();
|
||||
PushResult result = pushRequest.getResult();
|
||||
PushResult result
|
||||
= snapshotAPI.push(oauth2, candidate, postbackKey);
|
||||
if (result.wasSuccessful()) {
|
||||
Log.info(
|
||||
"[{}] Push to Overleaf successful",
|
||||
|
@ -587,7 +543,7 @@ public class Bridge {
|
|||
* {@link PostbackContents#processPostback()}, i.e. once the Overleaf app
|
||||
* has fetched all the atts and has committed the push and is happy, it
|
||||
* calls back here, fulfilling the promise that the push
|
||||
* {@link #push(Credential, String, RawDirectory, RawDirectory, String)}
|
||||
* {@link #push(Optional, String, RawDirectory, RawDirectory, String)}
|
||||
* is waiting on.
|
||||
*
|
||||
* The Overleaf app will have invented a new version for the push, which is
|
||||
|
@ -642,7 +598,7 @@ public class Bridge {
|
|||
/* PRIVATE */
|
||||
|
||||
/**
|
||||
* Called by {@link #updateRepositoryCritical(Credential, ProjectRepo)}.
|
||||
* Called by {@link #getUpdatedRepoCritical(Optional, String)}
|
||||
*
|
||||
* Does the actual work of getting the snapshots for a project from the
|
||||
* snapshot API and committing them to a repo.
|
||||
|
@ -655,16 +611,13 @@ public class Bridge {
|
|||
* @throws GitUserException
|
||||
*/
|
||||
private void updateProject(
|
||||
Credential oauth2,
|
||||
Optional<Credential> oauth2,
|
||||
ProjectRepo repo
|
||||
) throws IOException, GitUserException {
|
||||
String projectName = repo.getProjectName();
|
||||
Deque<Snapshot> snapshots =
|
||||
snapshotAPI.getSnapshotsForProjectAfterVersion(
|
||||
oauth2,
|
||||
projectName,
|
||||
dbStore.getLatestVersionForProject(projectName)
|
||||
);
|
||||
int latestVersionId = dbStore.getLatestVersionForProject(projectName);
|
||||
Deque<Snapshot> snapshots = snapshotAPI.getSnapshots(
|
||||
oauth2, projectName, latestVersionId);
|
||||
|
||||
makeCommitsFromSnapshots(repo, snapshots);
|
||||
|
||||
|
@ -677,7 +630,7 @@ public class Bridge {
|
|||
}
|
||||
|
||||
/**
|
||||
* Called by {@link #updateProject(Credential, ProjectRepo)}.
|
||||
* Called by {@link #updateProject(Optional, ProjectRepo)}.
|
||||
*
|
||||
* Performs the actual Git commits on the disk.
|
||||
*
|
||||
|
@ -732,7 +685,7 @@ public class Bridge {
|
|||
|
||||
/**
|
||||
* Called by
|
||||
* {@link #pushCritical(Credential, String, RawDirectory, RawDirectory)}.
|
||||
* {@link #pushCritical(Optional, String, RawDirectory, RawDirectory)}.
|
||||
*
|
||||
* This call consists of 2 things: Creating the candidate snapshot,
|
||||
* and writing the atts to the atts directory.
|
||||
|
@ -761,7 +714,7 @@ public class Bridge {
|
|||
|
||||
/**
|
||||
* Called by
|
||||
* {@link #pushCritical(Credential, String, RawDirectory, RawDirectory)}.
|
||||
* {@link #pushCritical(Optional, String, RawDirectory, RawDirectory)}.
|
||||
*
|
||||
* This method approves a push by setting the latest version and removing
|
||||
* any deleted files from the db store (files were already added by the
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge.gc;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import uk.ac.ic.wlgitbridge.bridge.Bridge;
|
||||
import uk.ac.ic.wlgitbridge.bridge.repo.ProjectRepo;
|
||||
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
|
@ -12,9 +12,9 @@ import java.util.concurrent.CompletableFuture;
|
|||
* GC which executes every hour or so.
|
||||
*
|
||||
* We don't queue it into a more immediate Executor because there is no way to
|
||||
* know if a call to {@link Bridge#updateProject(Credential, ProjectRepo)},
|
||||
* know if a call to {@link Bridge#updateProject(Optional, ProjectRepo)},
|
||||
* which releases the lock, is going to call
|
||||
* {@link Bridge#push(Credential, String, RawDirectory, RawDirectory, String)}.
|
||||
* {@link Bridge#push(Optional, String, RawDirectory, RawDirectory, String)}.
|
||||
*
|
||||
* We don't want the GC to run in between an update and a push.
|
||||
*/
|
||||
|
|
|
@ -45,6 +45,13 @@ public class FSGitRepoStore implements RepoStore {
|
|||
return rootDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectRepo initRepo(String project) throws IOException {
|
||||
GitProjectRepo ret = new GitProjectRepo(project);
|
||||
ret.initRepo(this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectRepo getExistingRepo(String project) throws IOException {
|
||||
GitProjectRepo ret = new GitProjectRepo(project);
|
||||
|
|
|
@ -199,6 +199,7 @@ public class GitProjectRepo implements ProjectRepo {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Repository getJGitRepository() {
|
||||
return repository.get();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge.repo;
|
||||
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
|
||||
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
|
||||
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
||||
|
@ -37,4 +38,5 @@ public interface ProjectRepo {
|
|||
|
||||
File getProjectDir();
|
||||
|
||||
Repository getJGitRepository();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ public interface RepoStore {
|
|||
|
||||
File getRootDirectory();
|
||||
|
||||
ProjectRepo initRepo(String project) throws IOException;
|
||||
|
||||
ProjectRepo getExistingRepo(String project) throws IOException;
|
||||
|
||||
void purgeNonexistentProjects(
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge.snapshot;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import uk.ac.ic.wlgitbridge.data.CandidateSnapshot;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getforversion.GetForVersionRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getforversion.GetForVersionResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getsavedvers.GetSavedVersRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getsavedvers.GetSavedVersResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.PushRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.PushResult;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Created by winston on 20/08/2016.
|
||||
*/
|
||||
public class NetSnapshotApi implements SnapshotApi {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<GetDocResult> getDoc(
|
||||
Optional<Credential> oath2, String projectName) {
|
||||
return new GetDocRequest(opt(oath2), projectName).request();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<GetForVersionResult> getForVersion(
|
||||
Optional<Credential> oauth2, String projectName, int versionId) {
|
||||
return new GetForVersionRequest(
|
||||
opt(oauth2), projectName, versionId).request();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<GetSavedVersResult> getSavedVers(
|
||||
Optional<Credential> oauth2, String projectName) {
|
||||
return new GetSavedVersRequest(opt(oauth2), projectName).request();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<PushResult> push(
|
||||
Optional<Credential> oauth2,
|
||||
CandidateSnapshot candidateSnapshot,
|
||||
String postbackKey
|
||||
) {
|
||||
return new PushRequest(
|
||||
opt(oauth2), candidateSnapshot, postbackKey).request();
|
||||
}
|
||||
|
||||
private static Credential opt(Optional<Credential> oath2) {
|
||||
return oath2.orElse(null);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge.snapshot;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import uk.ac.ic.wlgitbridge.data.model.Snapshot;
|
||||
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||
|
||||
import java.util.Deque;
|
||||
|
||||
/**
|
||||
* Created by winston on 20/08/2016.
|
||||
*/
|
||||
public interface SnapshotAPI {
|
||||
|
||||
Deque<Snapshot> getSnapshotsForProjectAfterVersion(
|
||||
Credential oauth2,
|
||||
String projectName,
|
||||
int latestVersion
|
||||
) throws FailedConnectionException, GitUserException;
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge.snapshot;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import uk.ac.ic.wlgitbridge.data.CandidateSnapshot;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getforversion.GetForVersionResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getsavedvers.GetSavedVersResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.PushResult;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
/**
|
||||
* Created by winston on 20/08/2016.
|
||||
*/
|
||||
public interface SnapshotApi {
|
||||
|
||||
CompletableFuture<GetDocResult> getDoc(
|
||||
Optional<Credential> oath2, String projectName);
|
||||
|
||||
CompletableFuture<GetForVersionResult> getForVersion(
|
||||
Optional<Credential> oauth2, String projectName, int versionId);
|
||||
|
||||
CompletableFuture<GetSavedVersResult> getSavedVers(
|
||||
Optional<Credential> oauth2, String projectName);
|
||||
|
||||
CompletableFuture<PushResult> push(
|
||||
Optional<Credential> oauth2,
|
||||
CandidateSnapshot candidateSnapshot,
|
||||
String postbackKey);
|
||||
|
||||
static <T> T getResult(CompletableFuture<T> result)
|
||||
throws FailedConnectionException, ForbiddenException {
|
||||
try {
|
||||
return result.join();
|
||||
} catch (CompletionException e) {
|
||||
try {
|
||||
throw e.getCause();
|
||||
} catch (FailedConnectionException
|
||||
| ForbiddenException
|
||||
| RuntimeException r) {
|
||||
throw r;
|
||||
} catch (Throwable __) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,34 +1,57 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge.snapshot;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import uk.ac.ic.wlgitbridge.data.CandidateSnapshot;
|
||||
import uk.ac.ic.wlgitbridge.data.model.Snapshot;
|
||||
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getforversion.GetForVersionRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getforversion.GetForVersionResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getforversion.SnapshotData;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getsavedvers.GetSavedVersRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getsavedvers.GetSavedVersResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getsavedvers.SnapshotInfo;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.PushResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.InvalidProjectException;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by winston on 20/08/2016.
|
||||
* Created by winston on 02/07/2017.
|
||||
*/
|
||||
public class NetSnapshotAPI implements SnapshotAPI {
|
||||
public class SnapshotApiFacade {
|
||||
|
||||
@Override
|
||||
public Deque<Snapshot> getSnapshotsForProjectAfterVersion(
|
||||
Credential oauth2,
|
||||
String projectName,
|
||||
int version
|
||||
private final SnapshotApi api;
|
||||
|
||||
public SnapshotApiFacade(SnapshotApi api) {
|
||||
this.api = api;
|
||||
}
|
||||
|
||||
public boolean projectExists(
|
||||
Optional<Credential> oauth2,
|
||||
String projectName
|
||||
) throws FailedConnectionException, GitUserException {
|
||||
try {
|
||||
SnapshotApi
|
||||
.getResult(api.getDoc(oauth2, projectName))
|
||||
.getVersionID();
|
||||
return true;
|
||||
} catch (InvalidProjectException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Deque<Snapshot> getSnapshots(
|
||||
Optional<Credential> oauth2,
|
||||
String projectName,
|
||||
int afterVersionId
|
||||
) throws GitUserException, FailedConnectionException {
|
||||
List<SnapshotInfo> snapshotInfos = getSnapshotInfosAfterVersion(
|
||||
oauth2,
|
||||
projectName,
|
||||
version
|
||||
afterVersionId
|
||||
);
|
||||
List<SnapshotData> snapshotDatas = getMatchingSnapshotData(
|
||||
oauth2,
|
||||
|
@ -38,25 +61,31 @@ public class NetSnapshotAPI implements SnapshotAPI {
|
|||
return combine(snapshotInfos, snapshotDatas);
|
||||
}
|
||||
|
||||
public PushResult push(
|
||||
Optional<Credential> oauth2,
|
||||
CandidateSnapshot candidateSnapshot,
|
||||
String postbackKey
|
||||
) throws FailedConnectionException, ForbiddenException {
|
||||
return SnapshotApi.getResult(api.push(
|
||||
oauth2, candidateSnapshot, postbackKey));
|
||||
}
|
||||
|
||||
private List<SnapshotInfo> getSnapshotInfosAfterVersion(
|
||||
Credential oauth2,
|
||||
Optional<Credential> oauth2,
|
||||
String projectName,
|
||||
int version
|
||||
) throws FailedConnectionException, GitUserException {
|
||||
SortedSet<SnapshotInfo> versions = new TreeSet<>();
|
||||
GetDocRequest getDoc = new GetDocRequest(oauth2, projectName);
|
||||
GetSavedVersRequest getSavedVers = new GetSavedVersRequest(
|
||||
oauth2,
|
||||
projectName
|
||||
);
|
||||
getDoc.request();
|
||||
getSavedVers.request();
|
||||
GetDocResult latestDoc = getDoc.getResult();
|
||||
CompletableFuture<GetDocResult> getDoc
|
||||
= api.getDoc(oauth2, projectName);
|
||||
CompletableFuture<GetSavedVersResult> savedVers
|
||||
= api.getSavedVers(oauth2, projectName);
|
||||
GetDocResult latestDoc = SnapshotApi.getResult(getDoc);
|
||||
int latest = latestDoc.getVersionID();
|
||||
if (latest > version) {
|
||||
for (
|
||||
SnapshotInfo snapshotInfo :
|
||||
getSavedVers.getResult().getSavedVers()
|
||||
SnapshotApi.getResult(savedVers).getSavedVers()
|
||||
) {
|
||||
if (snapshotInfo.getVersionId() > version) {
|
||||
versions.add(snapshotInfo);
|
||||
|
@ -70,45 +99,36 @@ public class NetSnapshotAPI implements SnapshotAPI {
|
|||
));
|
||||
|
||||
}
|
||||
return new LinkedList<SnapshotInfo>(versions);
|
||||
return new ArrayList<>(versions);
|
||||
}
|
||||
|
||||
private List<SnapshotData> getMatchingSnapshotData(
|
||||
Credential oauth2,
|
||||
Optional<Credential> oauth2,
|
||||
String projectName,
|
||||
List<SnapshotInfo> snapshotInfos
|
||||
) throws FailedConnectionException, ForbiddenException {
|
||||
List<GetForVersionRequest> firedRequests = fireDataRequests(
|
||||
oauth2,
|
||||
projectName,
|
||||
snapshotInfos
|
||||
);
|
||||
List<CompletableFuture<GetForVersionResult>> firedRequests
|
||||
= fireDataRequests(oauth2, projectName, snapshotInfos);
|
||||
List<SnapshotData> snapshotDataList = new ArrayList<>();
|
||||
for (GetForVersionRequest fired : firedRequests) {
|
||||
snapshotDataList.add(fired.getResult().getSnapshotData());
|
||||
for (CompletableFuture<GetForVersionResult> fired : firedRequests) {
|
||||
snapshotDataList.add(fired.join().getSnapshotData());
|
||||
}
|
||||
return snapshotDataList;
|
||||
}
|
||||
|
||||
private List<GetForVersionRequest> fireDataRequests(
|
||||
Credential oauth2,
|
||||
private List<CompletableFuture<GetForVersionResult>> fireDataRequests(
|
||||
Optional<Credential> oauth2,
|
||||
String projectName,
|
||||
List<SnapshotInfo> snapshotInfos
|
||||
) {
|
||||
List<GetForVersionRequest> requests = new ArrayList<>();
|
||||
for (SnapshotInfo snapshotInfo : snapshotInfos) {
|
||||
GetForVersionRequest request = new GetForVersionRequest(
|
||||
oauth2,
|
||||
projectName,
|
||||
snapshotInfo.getVersionId()
|
||||
);
|
||||
requests.add(request);
|
||||
request.request();
|
||||
}
|
||||
return requests;
|
||||
return snapshotInfos
|
||||
.stream()
|
||||
.map(snap -> api.getForVersion(
|
||||
oauth2, projectName, snap.getVersionId()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Deque<Snapshot> combine(
|
||||
private static Deque<Snapshot> combine(
|
||||
List<SnapshotInfo> snapshotInfos,
|
||||
List<SnapshotData> snapshotDatas
|
||||
) {
|
|
@ -5,7 +5,7 @@ import org.eclipse.jgit.lib.Repository;
|
|||
import org.eclipse.jgit.transport.ReceivePack;
|
||||
import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
|
||||
import uk.ac.ic.wlgitbridge.bridge.Bridge;
|
||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotAPI;
|
||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotApi;
|
||||
import uk.ac.ic.wlgitbridge.git.handler.hook.WriteLatexPutHook;
|
||||
import uk.ac.ic.wlgitbridge.git.servlet.WLGitServlet;
|
||||
import uk.ac.ic.wlgitbridge.server.Oauth2Filter;
|
||||
|
@ -13,6 +13,7 @@ import uk.ac.ic.wlgitbridge.util.Log;
|
|||
import uk.ac.ic.wlgitbridge.util.Util;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Created by Winston on 02/11/14.
|
||||
|
@ -38,7 +39,7 @@ public class WLReceivePackFactory
|
|||
*
|
||||
* The {@link WriteLatexPutHook} needs our hostname, which we get from the
|
||||
* original {@link HttpServletRequest}, used to provide a postback URL to
|
||||
* the {@link SnapshotAPI}. We also give it the oauth2 that we injected in
|
||||
* the {@link SnapshotApi}. We also give it the oauth2 that we injected in
|
||||
* the {@link Oauth2Filter}, and the {@link Bridge}.
|
||||
*
|
||||
* At this point, the repository will have been synced to the latest on
|
||||
|
@ -59,9 +60,9 @@ public class WLReceivePackFactory
|
|||
"[{}] Creating receive-pack",
|
||||
repository.getWorkTree().getName()
|
||||
);
|
||||
Credential oauth2 = (Credential) httpServletRequest.getAttribute(
|
||||
Oauth2Filter.ATTRIBUTE_KEY
|
||||
);
|
||||
Optional<Credential> oauth2 = Optional.ofNullable(
|
||||
(Credential) httpServletRequest.getAttribute(
|
||||
Oauth2Filter.ATTRIBUTE_KEY));
|
||||
ReceivePack receivePack = new ReceivePack(repository);
|
||||
String hostname = Util.getPostbackURL();
|
||||
if (hostname == null) {
|
||||
|
|
|
@ -7,7 +7,6 @@ import org.eclipse.jgit.transport.ServiceMayNotContinueException;
|
|||
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
|
||||
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
|
||||
import uk.ac.ic.wlgitbridge.bridge.Bridge;
|
||||
import uk.ac.ic.wlgitbridge.bridge.repo.GitProjectRepo;
|
||||
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
||||
import uk.ac.ic.wlgitbridge.git.handler.hook.WriteLatexPutHook;
|
||||
import uk.ac.ic.wlgitbridge.git.servlet.WLGitServlet;
|
||||
|
@ -19,6 +18,7 @@ import uk.ac.ic.wlgitbridge.util.Util;
|
|||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Created by Winston on 02/11/14.
|
||||
|
@ -82,17 +82,12 @@ public class WLRepositoryResolver
|
|||
ServiceNotAuthorizedException,
|
||||
ServiceMayNotContinueException {
|
||||
Log.info("[{}] Request to open git repo", name);
|
||||
Credential oauth2 = (Credential) httpServletRequest.getAttribute(
|
||||
Oauth2Filter.ATTRIBUTE_KEY
|
||||
);
|
||||
Optional<Credential> oauth2 = Optional.ofNullable(
|
||||
(Credential) httpServletRequest.getAttribute(
|
||||
Oauth2Filter.ATTRIBUTE_KEY));
|
||||
String projName = Util.removeAllSuffixes(name, "/", ".git");
|
||||
try {
|
||||
if (!bridge.projectExists(oauth2, projName)) {
|
||||
throw new RepositoryNotFoundException(projName);
|
||||
}
|
||||
GitProjectRepo repo = new GitProjectRepo(projName);
|
||||
bridge.updateRepository(oauth2, repo);
|
||||
return repo.getJGitRepository();
|
||||
return bridge.getUpdatedRepo(oauth2, projName).getJGitRepository();
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
Log.info("Repository not found: " + name);
|
||||
throw e;
|
||||
|
|
|
@ -21,6 +21,7 @@ import uk.ac.ic.wlgitbridge.util.Log;
|
|||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Created by Winston on 03/11/14.
|
||||
|
@ -34,7 +35,7 @@ public class WriteLatexPutHook implements PreReceiveHook {
|
|||
|
||||
private final Bridge bridge;
|
||||
private final String hostname;
|
||||
private final Credential oauth2;
|
||||
private final Optional<Credential> oauth2;
|
||||
|
||||
/**
|
||||
* The constructor to use, which provides the hook with the {@link Bridge},
|
||||
|
@ -47,7 +48,7 @@ public class WriteLatexPutHook implements PreReceiveHook {
|
|||
public WriteLatexPutHook(
|
||||
Bridge bridge,
|
||||
String hostname,
|
||||
Credential oauth2
|
||||
Optional<Credential> oauth2
|
||||
) {
|
||||
this.bridge = bridge;
|
||||
this.hostname = hostname;
|
||||
|
@ -112,7 +113,7 @@ public class WriteLatexPutHook implements PreReceiveHook {
|
|||
}
|
||||
|
||||
private void handleReceiveCommand(
|
||||
Credential oauth2,
|
||||
Optional<Credential> oauth2,
|
||||
Repository repository,
|
||||
ReceiveCommand receiveCommand
|
||||
) throws IOException, GitUserException {
|
||||
|
|
|
@ -49,10 +49,17 @@ public class RepositoryObjectTreeWalker {
|
|||
|
||||
public RawDirectory getDirectoryContents(
|
||||
) throws IOException, SizeLimitExceededException, InvalidGitRepository {
|
||||
return getDirectoryContents(50 * 1024 * 1024);
|
||||
return getDirectoryContents(Optional.empty());
|
||||
}
|
||||
|
||||
private RawDirectory getDirectoryContents(long maxFileSize)
|
||||
public RawDirectory getDirectoryContents(long maxFileSize)
|
||||
throws InvalidGitRepository,
|
||||
SizeLimitExceededException,
|
||||
IOException {
|
||||
return getDirectoryContents(Optional.of(maxFileSize));
|
||||
}
|
||||
|
||||
private RawDirectory getDirectoryContents(Optional<Long> maxFileSize)
|
||||
throws IOException,
|
||||
SizeLimitExceededException,
|
||||
InvalidGitRepository {
|
||||
|
@ -73,7 +80,7 @@ public class RepositoryObjectTreeWalker {
|
|||
return treeWalk;
|
||||
}
|
||||
|
||||
private Map<String, RawFile> walkGitObjectTree(long maxFileSize)
|
||||
private Map<String, RawFile> walkGitObjectTree(Optional<Long> maxFileSize)
|
||||
throws IOException,
|
||||
SizeLimitExceededException,
|
||||
InvalidGitRepository {
|
||||
|
@ -90,9 +97,9 @@ public class RepositoryObjectTreeWalker {
|
|||
}
|
||||
ObjectLoader obj = repository.open(objectId);
|
||||
long size = obj.getSize();
|
||||
if (size > maxFileSize) {
|
||||
if (maxFileSize.isPresent() && size > maxFileSize.get()) {
|
||||
throw new SizeLimitExceededException(
|
||||
Optional.ofNullable(path), size, maxFileSize);
|
||||
Optional.ofNullable(path), size, maxFileSize.get());
|
||||
}
|
||||
try (ByteArrayOutputStream o = new ByteArrayOutputStream(
|
||||
CastUtil.assumeInt(size))) {
|
||||
|
|
|
@ -13,6 +13,8 @@ import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
|||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SqliteDBStore;
|
||||
import uk.ac.ic.wlgitbridge.bridge.repo.FSGitRepoStore;
|
||||
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
|
||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.NetSnapshotApi;
|
||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotApi;
|
||||
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStore;
|
||||
import uk.ac.ic.wlgitbridge.git.servlet.WLGitServlet;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.SnapshotAPIRequest;
|
||||
|
@ -57,14 +59,16 @@ public class GitBridgeServer {
|
|||
).resolve(".wlgb").resolve("wlgb.db").toFile()
|
||||
);
|
||||
SwapStore swapStore = SwapStore.fromConfig(config.getSwapStore());
|
||||
SnapshotApi snapshotApi = new NetSnapshotApi();
|
||||
bridge = Bridge.make(
|
||||
repoStore,
|
||||
dbStore,
|
||||
swapStore,
|
||||
config.getSwapJob()
|
||||
config.getSwapJob(),
|
||||
snapshotApi
|
||||
);
|
||||
jettyServer = new Server(port);
|
||||
configureJettyServer(config);
|
||||
configureJettyServer(config, snapshotApi);
|
||||
SnapshotAPIRequest.setBasicAuth(
|
||||
config.getUsername(),
|
||||
config.getPassword()
|
||||
|
@ -105,11 +109,12 @@ public class GitBridgeServer {
|
|||
}
|
||||
|
||||
private void configureJettyServer(
|
||||
Config config
|
||||
Config config,
|
||||
SnapshotApi snapshotApi
|
||||
) throws ServletException {
|
||||
HandlerCollection handlers = new HandlerList();
|
||||
handlers.addHandler(initApiHandler());
|
||||
handlers.addHandler(initGitHandler(config));
|
||||
handlers.addHandler(initGitHandler(config, snapshotApi));
|
||||
jettyServer.setHandler(handlers);
|
||||
}
|
||||
|
||||
|
@ -130,12 +135,13 @@ public class GitBridgeServer {
|
|||
}
|
||||
|
||||
private Handler initGitHandler(
|
||||
Config config
|
||||
Config config,
|
||||
SnapshotApi snapshotApi
|
||||
) throws ServletException {
|
||||
final ServletContextHandler servletContextHandler =
|
||||
new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
if (config.isUsingOauth2()) {
|
||||
Filter filter = new Oauth2Filter(config.getOauth2());
|
||||
Filter filter = new Oauth2Filter(snapshotApi, config.getOauth2());
|
||||
servletContextHandler.addFilter(
|
||||
new FilterHolder(filter),
|
||||
"/*",
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.google.api.client.http.GenericUrl;
|
|||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import uk.ac.ic.wlgitbridge.application.config.Oauth2;
|
||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotApi;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocRequest;
|
||||
import uk.ac.ic.wlgitbridge.util.Instance;
|
||||
|
@ -17,6 +18,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Optional;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
|
@ -26,9 +28,12 @@ public class Oauth2Filter implements Filter {
|
|||
|
||||
public static final String ATTRIBUTE_KEY = "oauth2";
|
||||
|
||||
private final SnapshotApi snapshotApi;
|
||||
|
||||
private final Oauth2 oauth2;
|
||||
|
||||
public Oauth2Filter(Oauth2 oauth2) {
|
||||
public Oauth2Filter(SnapshotApi snapshotApi, Oauth2 oauth2) {
|
||||
this.snapshotApi = snapshotApi;
|
||||
this.oauth2 = oauth2;
|
||||
}
|
||||
|
||||
|
@ -60,7 +65,8 @@ public class Oauth2Filter implements Filter {
|
|||
GetDocRequest doc = new GetDocRequest(project);
|
||||
doc.request();
|
||||
try {
|
||||
doc.getResult();
|
||||
SnapshotApi.getResult(
|
||||
snapshotApi.getDoc(Optional.empty(), project));
|
||||
} catch (ForbiddenException e) {
|
||||
Log.info("[{}] Auth needed", project);
|
||||
getAndInjectCredentials(
|
||||
|
|
|
@ -9,8 +9,7 @@ import uk.ac.ic.wlgitbridge.util.Log;
|
|||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* Created by Winston on 06/11/14.
|
||||
|
@ -19,6 +18,8 @@ public abstract class Request<T extends Result> {
|
|||
|
||||
public static final AsyncHttpClient httpClient = new AsyncHttpClient();
|
||||
|
||||
private static final Executor executor = Executors.newCachedThreadPool();
|
||||
|
||||
private final String url;
|
||||
|
||||
private Future<HttpResponse> future;
|
||||
|
@ -27,7 +28,7 @@ public abstract class Request<T extends Result> {
|
|||
this.url = url;
|
||||
}
|
||||
|
||||
public void request() {
|
||||
public CompletableFuture<T> request() {
|
||||
switch (httpMethod()) {
|
||||
case GET:
|
||||
performGetRequest();
|
||||
|
@ -38,9 +39,18 @@ public abstract class Request<T extends Result> {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
CompletableFuture<T> ret = new CompletableFuture<>();
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
ret.complete(getResult());
|
||||
} catch (Throwable t) {
|
||||
ret.completeExceptionally(t);
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
public T getResult() throws FailedConnectionException, ForbiddenException {
|
||||
private T getResult() throws FailedConnectionException, ForbiddenException {
|
||||
try {
|
||||
HttpResponse response = future.get();
|
||||
Log.info(
|
||||
|
|
|
@ -9,14 +9,14 @@ import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock;
|
|||
import uk.ac.ic.wlgitbridge.bridge.repo.ProjectRepo;
|
||||
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.snapshot.SnapshotApiFacade;
|
||||
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 java.util.Optional;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
|
@ -34,7 +34,7 @@ public class BridgeTest {
|
|||
private RepoStore repoStore;
|
||||
private DBStore dbStore;
|
||||
private SwapStore swapStore;
|
||||
private SnapshotAPI snapshotAPI;
|
||||
private SnapshotApiFacade snapshotAPI;
|
||||
private ResourceCache resourceCache;
|
||||
private SwapJob swapJob;
|
||||
private GcJob gcJob;
|
||||
|
@ -45,7 +45,7 @@ public class BridgeTest {
|
|||
repoStore = mock(RepoStore.class);
|
||||
dbStore = mock(DBStore.class);
|
||||
swapStore = mock(SwapStore.class);
|
||||
snapshotAPI = mock(SnapshotAPI.class);
|
||||
snapshotAPI = mock(SnapshotApiFacade.class);
|
||||
resourceCache = mock(ResourceCache.class);
|
||||
swapJob = mock(SwapJob.class);
|
||||
gcJob = mock(GcJob.class);
|
||||
|
@ -75,16 +75,17 @@ public class BridgeTest {
|
|||
public void updatingRepositorySetsLastAccessedTime(
|
||||
) throws IOException, GitUserException {
|
||||
ProjectRepo repo = mock(ProjectRepo.class);
|
||||
when(repo.getProjectName()).thenReturn("asdf");
|
||||
when(repoStore.getExistingRepo("asdf")).thenReturn(repo);
|
||||
when(dbStore.getProjectState("asdf")).thenReturn(ProjectState.PRESENT);
|
||||
when(snapshotAPI.projectExists(Optional.empty(), "asdf")).thenReturn(true);
|
||||
when(
|
||||
snapshotAPI.getSnapshotsForProjectAfterVersion(
|
||||
snapshotAPI.getSnapshots(
|
||||
any(),
|
||||
any(),
|
||||
anyInt()
|
||||
)
|
||||
).thenReturn(new ArrayDeque<Snapshot>());
|
||||
bridge.updateRepository(null, repo);
|
||||
).thenReturn(new ArrayDeque<>());
|
||||
bridge.getUpdatedRepo(Optional.empty(), "asdf");
|
||||
verify(dbStore).setLastAccessedTime(eq("asdf"), any());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue