mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Fully implement max file size
- add `repoStore.maxFileSize` key to config - use maxFileSize in ResourceCache on both header path and blob download path - make failures during commit less fragile
This commit is contained in:
parent
dc93df6bc8
commit
1e4ef0cc5b
28 changed files with 367 additions and 83 deletions
|
@ -11,6 +11,9 @@
|
||||||
"oauth2ClientSecret": "asdf",
|
"oauth2ClientSecret": "asdf",
|
||||||
"oauth2Server": "https://localhost"
|
"oauth2Server": "https://localhost"
|
||||||
},
|
},
|
||||||
|
"repoStore": {
|
||||||
|
"maxFileSize": 52428800
|
||||||
|
},
|
||||||
"swapStore": {
|
"swapStore": {
|
||||||
"type": "s3",
|
"type": "s3",
|
||||||
"awsAccessKey": "asdf",
|
"awsAccessKey": "asdf",
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import uk.ac.ic.wlgitbridge.application.exception.ConfigFileException;
|
import uk.ac.ic.wlgitbridge.application.exception.ConfigFileException;
|
||||||
|
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStoreConfig;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJobConfig;
|
import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJobConfig;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStoreConfig;
|
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStoreConfig;
|
||||||
import uk.ac.ic.wlgitbridge.snapshot.base.JSONSource;
|
import uk.ac.ic.wlgitbridge.snapshot.base.JSONSource;
|
||||||
|
@ -30,6 +31,7 @@ public class Config implements JSONSource {
|
||||||
config.postbackURL,
|
config.postbackURL,
|
||||||
config.serviceName,
|
config.serviceName,
|
||||||
Oauth2.asSanitised(config.oauth2),
|
Oauth2.asSanitised(config.oauth2),
|
||||||
|
config.repoStore,
|
||||||
SwapStoreConfig.sanitisedCopy(config.swapStore),
|
SwapStoreConfig.sanitisedCopy(config.swapStore),
|
||||||
config.swapJob
|
config.swapJob
|
||||||
);
|
);
|
||||||
|
@ -45,6 +47,8 @@ public class Config implements JSONSource {
|
||||||
@Nullable
|
@Nullable
|
||||||
private Oauth2 oauth2;
|
private Oauth2 oauth2;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
private RepoStoreConfig repoStore;
|
||||||
|
@Nullable
|
||||||
private SwapStoreConfig swapStore;
|
private SwapStoreConfig swapStore;
|
||||||
@Nullable
|
@Nullable
|
||||||
private SwapJobConfig swapJob;
|
private SwapJobConfig swapJob;
|
||||||
|
@ -69,6 +73,7 @@ public class Config implements JSONSource {
|
||||||
String postbackURL,
|
String postbackURL,
|
||||||
String serviceName,
|
String serviceName,
|
||||||
Oauth2 oauth2,
|
Oauth2 oauth2,
|
||||||
|
RepoStoreConfig repoStore,
|
||||||
SwapStoreConfig swapStore,
|
SwapStoreConfig swapStore,
|
||||||
SwapJobConfig swapJob
|
SwapJobConfig swapJob
|
||||||
) {
|
) {
|
||||||
|
@ -80,6 +85,7 @@ public class Config implements JSONSource {
|
||||||
this.postbackURL = postbackURL;
|
this.postbackURL = postbackURL;
|
||||||
this.serviceName = serviceName;
|
this.serviceName = serviceName;
|
||||||
this.oauth2 = oauth2;
|
this.oauth2 = oauth2;
|
||||||
|
this.repoStore = repoStore;
|
||||||
this.swapStore = swapStore;
|
this.swapStore = swapStore;
|
||||||
this.swapJob = swapJob;
|
this.swapJob = swapJob;
|
||||||
}
|
}
|
||||||
|
@ -108,6 +114,8 @@ public class Config implements JSONSource {
|
||||||
postbackURL += "/";
|
postbackURL += "/";
|
||||||
}
|
}
|
||||||
oauth2 = new Gson().fromJson(configObject.get("oauth2"), Oauth2.class);
|
oauth2 = new Gson().fromJson(configObject.get("oauth2"), Oauth2.class);
|
||||||
|
repoStore = new Gson().fromJson(
|
||||||
|
configObject.get("repoStore"), RepoStoreConfig.class);
|
||||||
swapStore = new Gson().fromJson(
|
swapStore = new Gson().fromJson(
|
||||||
configObject.get("swapStore"),
|
configObject.get("swapStore"),
|
||||||
SwapStoreConfig.class
|
SwapStoreConfig.class
|
||||||
|
@ -161,6 +169,10 @@ public class Config implements JSONSource {
|
||||||
return oauth2;
|
return oauth2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<RepoStoreConfig> getRepoStore() {
|
||||||
|
return Optional.ofNullable(repoStore);
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<SwapStoreConfig> getSwapStore() {
|
public Optional<SwapStoreConfig> getSwapStore() {
|
||||||
return Optional.ofNullable(swapStore);
|
return Optional.ofNullable(swapStore);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package uk.ac.ic.wlgitbridge.bridge;
|
||||||
|
|
||||||
import com.google.api.client.auth.oauth2.Credential;
|
import com.google.api.client.auth.oauth2.Credential;
|
||||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
|
import uk.ac.ic.wlgitbridge.application.config.Config;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
|
import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SqliteDBStore;
|
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SqliteDBStore;
|
||||||
|
@ -9,20 +10,16 @@ import uk.ac.ic.wlgitbridge.bridge.gc.GcJob;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.gc.GcJobImpl;
|
import uk.ac.ic.wlgitbridge.bridge.gc.GcJobImpl;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.lock.LockGuard;
|
import uk.ac.ic.wlgitbridge.bridge.lock.LockGuard;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock;
|
import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.repo.FSGitRepoStore;
|
import uk.ac.ic.wlgitbridge.bridge.repo.*;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.repo.GitProjectRepo;
|
|
||||||
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.ResourceCache;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.resource.UrlResourceCache;
|
import uk.ac.ic.wlgitbridge.bridge.resource.UrlResourceCache;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.NetSnapshotApi;
|
import uk.ac.ic.wlgitbridge.bridge.snapshot.NetSnapshotApi;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotApi;
|
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.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.job.SwapJobImpl;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.swap.store.S3SwapStore;
|
import uk.ac.ic.wlgitbridge.bridge.swap.store.S3SwapStore;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStore;
|
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.CandidateSnapshot;
|
||||||
import uk.ac.ic.wlgitbridge.data.ProjectLockImpl;
|
import uk.ac.ic.wlgitbridge.data.ProjectLockImpl;
|
||||||
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
|
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
|
||||||
|
@ -118,6 +115,7 @@ import java.util.*;
|
||||||
*
|
*
|
||||||
* 6. The Snapshot API, which provides data from the Overleaf app.
|
* 6. The Snapshot API, which provides data from the Overleaf app.
|
||||||
*
|
*
|
||||||
|
* @see SnapshotApiFacade - wraps a concrete instance of the Snapshot API.
|
||||||
* @see SnapshotApi - the interface for the Snapshot API.
|
* @see SnapshotApi - the interface for the Snapshot API.
|
||||||
* @see NetSnapshotApi - the default concrete implementation
|
* @see NetSnapshotApi - the default concrete implementation
|
||||||
*
|
*
|
||||||
|
@ -139,6 +137,8 @@ import java.util.*;
|
||||||
*/
|
*/
|
||||||
public class Bridge {
|
public class Bridge {
|
||||||
|
|
||||||
|
private final Config config;
|
||||||
|
|
||||||
private final ProjectLock lock;
|
private final ProjectLock lock;
|
||||||
|
|
||||||
private final RepoStore repoStore;
|
private final RepoStore repoStore;
|
||||||
|
@ -157,29 +157,31 @@ public class Bridge {
|
||||||
* swap store, and the swap job config.
|
* swap store, and the swap job config.
|
||||||
*
|
*
|
||||||
* This should be the method used to create a Bridge.
|
* This should be the method used to create a Bridge.
|
||||||
|
* @param config The config to use
|
||||||
* @param repoStore The repo store to use
|
* @param repoStore The repo store to use
|
||||||
* @param dbStore The db store to use
|
* @param dbStore The db store to use
|
||||||
* @param swapStore The swap store to use
|
* @param swapStore The swap store to use
|
||||||
* @param swapJobConfig The swap config to use, or empty for no-op
|
* @param snapshotApi The snapshot api to use
|
||||||
* @return The constructed Bridge.
|
* @return The constructed Bridge.
|
||||||
*/
|
*/
|
||||||
public static Bridge make(
|
public static Bridge make(
|
||||||
|
Config config,
|
||||||
RepoStore repoStore,
|
RepoStore repoStore,
|
||||||
DBStore dbStore,
|
DBStore dbStore,
|
||||||
SwapStore swapStore,
|
SwapStore swapStore,
|
||||||
Optional<SwapJobConfig> swapJobConfig,
|
|
||||||
SnapshotApi snapshotApi
|
SnapshotApi snapshotApi
|
||||||
) {
|
) {
|
||||||
ProjectLock lock = new ProjectLockImpl((int threads) ->
|
ProjectLock lock = new ProjectLockImpl((int threads) ->
|
||||||
Log.info("Waiting for " + threads + " projects...")
|
Log.info("Waiting for " + threads + " projects...")
|
||||||
);
|
);
|
||||||
return new Bridge(
|
return new Bridge(
|
||||||
|
config,
|
||||||
lock,
|
lock,
|
||||||
repoStore,
|
repoStore,
|
||||||
dbStore,
|
dbStore,
|
||||||
swapStore,
|
swapStore,
|
||||||
SwapJob.fromConfig(
|
SwapJob.fromConfig(
|
||||||
swapJobConfig,
|
config.getSwapJob(),
|
||||||
lock,
|
lock,
|
||||||
repoStore,
|
repoStore,
|
||||||
dbStore,
|
dbStore,
|
||||||
|
@ -205,6 +207,7 @@ public class Bridge {
|
||||||
* @param resourceCache the {@link ResourceCache} to use
|
* @param resourceCache the {@link ResourceCache} to use
|
||||||
*/
|
*/
|
||||||
Bridge(
|
Bridge(
|
||||||
|
Config config,
|
||||||
ProjectLock lock,
|
ProjectLock lock,
|
||||||
RepoStore repoStore,
|
RepoStore repoStore,
|
||||||
DBStore dbStore,
|
DBStore dbStore,
|
||||||
|
@ -214,6 +217,7 @@ public class Bridge {
|
||||||
SnapshotApiFacade snapshotAPI,
|
SnapshotApiFacade snapshotAPI,
|
||||||
ResourceCache resourceCache
|
ResourceCache resourceCache
|
||||||
) {
|
) {
|
||||||
|
this.config = config;
|
||||||
this.lock = lock;
|
this.lock = lock;
|
||||||
this.repoStore = repoStore;
|
this.repoStore = repoStore;
|
||||||
this.dbStore = dbStore;
|
this.dbStore = dbStore;
|
||||||
|
@ -621,6 +625,11 @@ public class Bridge {
|
||||||
|
|
||||||
makeCommitsFromSnapshots(repo, snapshots);
|
makeCommitsFromSnapshots(repo, snapshots);
|
||||||
|
|
||||||
|
// TODO: in case crashes around here, add an
|
||||||
|
// "updating_from_commit" column to the DB as a way to rollback the
|
||||||
|
// any failed partial updates before re-trying
|
||||||
|
// Also need to consider the empty state (a new git init'd repo being
|
||||||
|
// the rollback target)
|
||||||
if (!snapshots.isEmpty()) {
|
if (!snapshots.isEmpty()) {
|
||||||
dbStore.setLatestVersionForProject(
|
dbStore.setLatestVersionForProject(
|
||||||
projectName,
|
projectName,
|
||||||
|
@ -635,7 +644,7 @@ public class Bridge {
|
||||||
* Performs the actual Git commits on the disk.
|
* Performs the actual Git commits on the disk.
|
||||||
*
|
*
|
||||||
* Each commit adds files to the db store
|
* Each commit adds files to the db store
|
||||||
* ({@link ResourceCache#get(String, String, String, Map, Map)},
|
* ({@link ResourceCache#get(String, String, String, Map, Map, Optional)},
|
||||||
* and then removes any files that were deleted.
|
* and then removes any files that were deleted.
|
||||||
* @param repo The repository to commit to
|
* @param repo The repository to commit to
|
||||||
* @param snapshots The snapshots to commit
|
* @param snapshots The snapshots to commit
|
||||||
|
@ -647,10 +656,25 @@ public class Bridge {
|
||||||
Collection<Snapshot> snapshots
|
Collection<Snapshot> snapshots
|
||||||
) throws IOException, GitUserException {
|
) throws IOException, GitUserException {
|
||||||
String name = repo.getProjectName();
|
String name = repo.getProjectName();
|
||||||
|
Optional<Long> maxSize = config
|
||||||
|
.getRepoStore()
|
||||||
|
.flatMap(RepoStoreConfig::getMaxFileSize);
|
||||||
for (Snapshot snapshot : snapshots) {
|
for (Snapshot snapshot : snapshots) {
|
||||||
Map<String, RawFile> fileTable = repo.getFiles();
|
RawDirectory directory = repo.getDirectory();
|
||||||
List<RawFile> files = new LinkedList<>();
|
Map<String, RawFile> fileTable = directory.getFileTable();
|
||||||
|
List<RawFile> files = new ArrayList<>();
|
||||||
files.addAll(snapshot.getSrcs());
|
files.addAll(snapshot.getSrcs());
|
||||||
|
for (RawFile file : files) {
|
||||||
|
long size = file.size();
|
||||||
|
/* Can't throw in ifPresent... */
|
||||||
|
if (maxSize.isPresent()) {
|
||||||
|
long maxSize_ = maxSize.get();
|
||||||
|
if (size >= maxSize_) {
|
||||||
|
throw new SizeLimitExceededException(
|
||||||
|
Optional.of(file.getPath()), size, maxSize_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Map<String, byte[]> fetchedUrls = new HashMap<>();
|
Map<String, byte[]> fetchedUrls = new HashMap<>();
|
||||||
for (SnapshotAttachment snapshotAttachment : snapshot.getAtts()) {
|
for (SnapshotAttachment snapshotAttachment : snapshot.getAtts()) {
|
||||||
files.add(
|
files.add(
|
||||||
|
@ -659,7 +683,8 @@ public class Bridge {
|
||||||
snapshotAttachment.getUrl(),
|
snapshotAttachment.getUrl(),
|
||||||
snapshotAttachment.getPath(),
|
snapshotAttachment.getPath(),
|
||||||
fileTable,
|
fileTable,
|
||||||
fetchedUrls
|
fetchedUrls,
|
||||||
|
maxSize
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package uk.ac.ic.wlgitbridge.bridge.repo;
|
||||||
|
|
||||||
import com.google.api.client.repackaged.com.google.common.base.Preconditions;
|
import com.google.api.client.repackaged.com.google.common.base.Preconditions;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import uk.ac.ic.wlgitbridge.util.Project;
|
import uk.ac.ic.wlgitbridge.util.Project;
|
||||||
import uk.ac.ic.wlgitbridge.util.Tar;
|
import uk.ac.ic.wlgitbridge.util.Tar;
|
||||||
|
|
||||||
|
@ -12,6 +14,7 @@ import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static uk.ac.ic.wlgitbridge.util.Util.deleteInDirectoryApartFrom;
|
import static uk.ac.ic.wlgitbridge.util.Util.deleteInDirectoryApartFrom;
|
||||||
|
@ -21,17 +24,35 @@ import static uk.ac.ic.wlgitbridge.util.Util.deleteInDirectoryApartFrom;
|
||||||
*/
|
*/
|
||||||
public class FSGitRepoStore implements RepoStore {
|
public class FSGitRepoStore implements RepoStore {
|
||||||
|
|
||||||
|
private static final long DEFAULT_MAX_FILE_SIZE = 50 * 1024 * 1024;
|
||||||
|
|
||||||
private final String repoStorePath;
|
private final String repoStorePath;
|
||||||
|
|
||||||
private final File rootDirectory;
|
private final File rootDirectory;
|
||||||
|
|
||||||
|
private final long maxFileSize;
|
||||||
|
|
||||||
private final Function<File, Long> fsSizer;
|
private final Function<File, Long> fsSizer;
|
||||||
|
|
||||||
public FSGitRepoStore(String repoStorePath) {
|
public FSGitRepoStore(
|
||||||
this(repoStorePath, d -> d.getTotalSpace() - d.getFreeSpace());
|
String repoStorePath,
|
||||||
|
Optional<Long> maxFileSize
|
||||||
|
) {
|
||||||
|
this(
|
||||||
|
repoStorePath,
|
||||||
|
maxFileSize.orElse(DEFAULT_MAX_FILE_SIZE),
|
||||||
|
d -> d.getTotalSpace() - d.getFreeSpace()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FSGitRepoStore(String repoStorePath, Function<File, Long> fsSizer) {
|
public FSGitRepoStore(
|
||||||
|
String repoStorePath,
|
||||||
|
long maxFileSize,
|
||||||
|
Function<File, Long> fsSizer
|
||||||
|
) {
|
||||||
this.repoStorePath = repoStorePath;
|
this.repoStorePath = repoStorePath;
|
||||||
rootDirectory = initRootGitDirectory(repoStorePath);
|
rootDirectory = initRootGitDirectory(repoStorePath);
|
||||||
|
this.maxFileSize = maxFileSize;
|
||||||
this.fsSizer = fsSizer;
|
this.fsSizer = fsSizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,16 +68,25 @@ public class FSGitRepoStore implements RepoStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProjectRepo initRepo(String project) throws IOException {
|
public ProjectRepo initRepo(String project) throws IOException {
|
||||||
GitProjectRepo ret = new GitProjectRepo(project);
|
GitProjectRepo ret = GitProjectRepo.fromName(project);
|
||||||
ret.initRepo(this);
|
ret.initRepo(this);
|
||||||
return ret;
|
return new WalkOverrideGitRepo(
|
||||||
|
ret, Optional.of(maxFileSize), Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProjectRepo getExistingRepo(String project) throws IOException {
|
public ProjectRepo getExistingRepo(String project) throws IOException {
|
||||||
GitProjectRepo ret = new GitProjectRepo(project);
|
GitProjectRepo ret = GitProjectRepo.fromName(project);
|
||||||
ret.useExistingRepository(this);
|
ret.useExistingRepository(this);
|
||||||
return ret;
|
return new WalkOverrideGitRepo(
|
||||||
|
ret, Optional.of(maxFileSize), Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProjectRepo useJGitRepo(Repository repo, ObjectId commitId) {
|
||||||
|
GitProjectRepo ret = GitProjectRepo.fromJGitRepo(repo);
|
||||||
|
return new WalkOverrideGitRepo(
|
||||||
|
ret, Optional.of(maxFileSize), Optional.of(commitId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Perhaps we should just delete bad directories on the fly. */
|
/* TODO: Perhaps we should just delete bad directories on the fly. */
|
||||||
|
|
|
@ -9,7 +9,7 @@ import org.eclipse.jgit.lib.PersonIdent;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
||||||
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
|
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
|
||||||
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
|
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
|
||||||
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
||||||
import uk.ac.ic.wlgitbridge.git.util.RepositoryObjectTreeWalker;
|
import uk.ac.ic.wlgitbridge.git.util.RepositoryObjectTreeWalker;
|
||||||
import uk.ac.ic.wlgitbridge.util.Log;
|
import uk.ac.ic.wlgitbridge.util.Log;
|
||||||
|
@ -43,10 +43,19 @@ public class GitProjectRepo implements ProjectRepo {
|
||||||
private final String projectName;
|
private final String projectName;
|
||||||
private Optional<Repository> repository;
|
private Optional<Repository> repository;
|
||||||
|
|
||||||
public GitProjectRepo(String projectName) {
|
public static GitProjectRepo fromJGitRepo(Repository repo) {
|
||||||
|
return new GitProjectRepo(
|
||||||
|
repo.getWorkTree().getName(), Optional.of(repo));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GitProjectRepo fromName(String projectName) {
|
||||||
|
return new GitProjectRepo(projectName, Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
GitProjectRepo(String projectName, Optional<Repository> repository) {
|
||||||
Preconditions.checkArgument(Project.isValidProjectName(projectName));
|
Preconditions.checkArgument(Project.isValidProjectName(projectName));
|
||||||
this.projectName = projectName;
|
this.projectName = projectName;
|
||||||
repository = Optional.empty();
|
this.repository = repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,7 +70,10 @@ public class GitProjectRepo implements ProjectRepo {
|
||||||
initRepositoryField(repoStore);
|
initRepositoryField(repoStore);
|
||||||
Preconditions.checkState(repository.isPresent());
|
Preconditions.checkState(repository.isPresent());
|
||||||
Repository repo = this.repository.get();
|
Repository repo = this.repository.get();
|
||||||
Preconditions.checkState(!repo.getObjectDatabase().exists());
|
// TODO: assert that this is a fresh repo. At the moment, we can't be
|
||||||
|
// sure whether the repo to be init'd doesn't exist or is just fresh
|
||||||
|
// and we crashed / aborted while committing
|
||||||
|
if (repo.getObjectDatabase().exists()) return;
|
||||||
repo.create();
|
repo.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,12 +89,12 @@ public class GitProjectRepo implements ProjectRepo {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, RawFile> getFiles()
|
public RawDirectory getDirectory()
|
||||||
throws IOException, GitUserException {
|
throws IOException, GitUserException {
|
||||||
Preconditions.checkState(repository.isPresent());
|
Preconditions.checkState(repository.isPresent());
|
||||||
return new RepositoryObjectTreeWalker(
|
return new RepositoryObjectTreeWalker(
|
||||||
repository.get()
|
repository.get()
|
||||||
).getDirectoryContents().getFileTable();
|
).getDirectoryContents(Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,13 +2,12 @@ package uk.ac.ic.wlgitbridge.bridge.repo;
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
|
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
|
||||||
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
|
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
|
||||||
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by winston on 20/08/2016.
|
* Created by winston on 20/08/2016.
|
||||||
|
@ -25,12 +24,12 @@ public interface ProjectRepo {
|
||||||
RepoStore repoStore
|
RepoStore repoStore
|
||||||
) throws IOException;
|
) throws IOException;
|
||||||
|
|
||||||
Map<String, RawFile> getFiles(
|
RawDirectory getDirectory(
|
||||||
) throws IOException, GitUserException;
|
) throws IOException, GitUserException;
|
||||||
|
|
||||||
Collection<String> commitAndGetMissing(
|
Collection<String> commitAndGetMissing(
|
||||||
GitDirectoryContents gitDirectoryContents
|
GitDirectoryContents gitDirectoryContents
|
||||||
) throws IOException;
|
) throws IOException, GitUserException;
|
||||||
|
|
||||||
void runGC() throws IOException;
|
void runGC() throws IOException;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package uk.ac.ic.wlgitbridge.bridge.repo;
|
package uk.ac.ic.wlgitbridge.bridge.repo;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -21,6 +24,8 @@ public interface RepoStore {
|
||||||
|
|
||||||
ProjectRepo getExistingRepo(String project) throws IOException;
|
ProjectRepo getExistingRepo(String project) throws IOException;
|
||||||
|
|
||||||
|
ProjectRepo useJGitRepo(Repository repo, ObjectId commitId);
|
||||||
|
|
||||||
void purgeNonexistentProjects(
|
void purgeNonexistentProjects(
|
||||||
Collection<String> existingProjectNames
|
Collection<String> existingProjectNames
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package uk.ac.ic.wlgitbridge.bridge.repo;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by winston on 02/07/2017.
|
||||||
|
*/
|
||||||
|
public class RepoStoreConfig {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final Long maxFileSize;
|
||||||
|
|
||||||
|
public RepoStoreConfig(Long maxFileSize) {
|
||||||
|
this.maxFileSize = maxFileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Long> getMaxFileSize() {
|
||||||
|
return Optional.ofNullable(maxFileSize);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package uk.ac.ic.wlgitbridge.bridge.repo;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
|
||||||
|
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
|
||||||
|
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
||||||
|
import uk.ac.ic.wlgitbridge.git.util.RepositoryObjectTreeWalker;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class takes a GitProjectRepo and delegates all calls to it.
|
||||||
|
*
|
||||||
|
* The purpose is to insert a file size check in {@link #getDirectory()}.
|
||||||
|
*
|
||||||
|
* We delegate instead of subclass because we can't override the static
|
||||||
|
* constructors in {@link GitProjectRepo}.
|
||||||
|
*/
|
||||||
|
public class WalkOverrideGitRepo implements ProjectRepo {
|
||||||
|
|
||||||
|
private final GitProjectRepo gitRepo;
|
||||||
|
|
||||||
|
private final Optional<Long> maxFileSize;
|
||||||
|
|
||||||
|
private final Optional<ObjectId> commitId;
|
||||||
|
|
||||||
|
public WalkOverrideGitRepo(
|
||||||
|
GitProjectRepo gitRepo,
|
||||||
|
Optional<Long> maxFileSize,
|
||||||
|
Optional<ObjectId> commitId
|
||||||
|
) {
|
||||||
|
this.gitRepo = gitRepo;
|
||||||
|
this.maxFileSize = maxFileSize;
|
||||||
|
this.commitId = commitId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProjectName() {
|
||||||
|
return gitRepo.getProjectName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initRepo(RepoStore repoStore) throws IOException {
|
||||||
|
gitRepo.initRepo(repoStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void useExistingRepository(RepoStore repoStore) throws IOException {
|
||||||
|
gitRepo.useExistingRepository(repoStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RawDirectory getDirectory() throws IOException, GitUserException {
|
||||||
|
Repository repo = gitRepo.getJGitRepository();
|
||||||
|
RepositoryObjectTreeWalker walker;
|
||||||
|
if (commitId.isPresent()) {
|
||||||
|
walker = new RepositoryObjectTreeWalker(repo, commitId.get());
|
||||||
|
} else {
|
||||||
|
walker = new RepositoryObjectTreeWalker(repo);
|
||||||
|
}
|
||||||
|
return walker.getDirectoryContents(maxFileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> commitAndGetMissing(
|
||||||
|
GitDirectoryContents gitDirectoryContents
|
||||||
|
) throws GitUserException, IOException {
|
||||||
|
return gitRepo.commitAndGetMissing(gitDirectoryContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runGC() throws IOException {
|
||||||
|
gitRepo.runGC();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteIncomingPacks() throws IOException {
|
||||||
|
gitRepo.deleteIncomingPacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getProjectDir() {
|
||||||
|
return gitRepo.getProjectDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Repository getJGitRepository() {
|
||||||
|
return gitRepo.getJGitRepository();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
package uk.ac.ic.wlgitbridge.bridge.resource;
|
package uk.ac.ic.wlgitbridge.bridge.resource;
|
||||||
|
|
||||||
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
|
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
|
||||||
|
import uk.ac.ic.wlgitbridge.git.exception.SizeLimitExceededException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by winston on 20/08/2016.
|
* Created by winston on 20/08/2016.
|
||||||
|
@ -15,7 +17,8 @@ public interface ResourceCache {
|
||||||
String url,
|
String url,
|
||||||
String newPath,
|
String newPath,
|
||||||
Map<String, RawFile> fileTable,
|
Map<String, RawFile> fileTable,
|
||||||
Map<String, byte[]> fetchedUrls
|
Map<String, byte[]> fetchedUrls,
|
||||||
) throws IOException;
|
Optional<Long> maxFileSize
|
||||||
|
) throws IOException, SizeLimitExceededException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
package uk.ac.ic.wlgitbridge.bridge.resource;
|
package uk.ac.ic.wlgitbridge.bridge.resource;
|
||||||
|
|
||||||
import com.ning.http.client.AsyncCompletionHandler;
|
import com.ning.http.client.*;
|
||||||
import com.ning.http.client.HttpResponseBodyPart;
|
|
||||||
import com.ning.http.client.Response;
|
|
||||||
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
||||||
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
|
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
|
||||||
import uk.ac.ic.wlgitbridge.data.filestore.RepositoryFile;
|
import uk.ac.ic.wlgitbridge.data.filestore.RepositoryFile;
|
||||||
|
import uk.ac.ic.wlgitbridge.git.exception.SizeLimitExceededException;
|
||||||
import uk.ac.ic.wlgitbridge.snapshot.base.Request;
|
import uk.ac.ic.wlgitbridge.snapshot.base.Request;
|
||||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||||
import uk.ac.ic.wlgitbridge.util.Log;
|
import uk.ac.ic.wlgitbridge.util.Log;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,13 +33,14 @@ public class UrlResourceCache implements ResourceCache {
|
||||||
String url,
|
String url,
|
||||||
String newPath,
|
String newPath,
|
||||||
Map<String, RawFile> fileTable,
|
Map<String, RawFile> fileTable,
|
||||||
Map<String, byte[]> fetchedUrls
|
Map<String, byte[]> fetchedUrls,
|
||||||
) throws IOException {
|
Optional<Long> maxFileSize
|
||||||
|
) throws IOException, SizeLimitExceededException {
|
||||||
String path = dbStore.getPathForURLInProject(projectName, url);
|
String path = dbStore.getPathForURLInProject(projectName, url);
|
||||||
byte[] contents;
|
byte[] contents;
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
path = newPath;
|
path = newPath;
|
||||||
contents = fetch(projectName, url, path);
|
contents = fetch(projectName, url, path, maxFileSize);
|
||||||
fetchedUrls.put(url, contents);
|
fetchedUrls.put(url, contents);
|
||||||
} else {
|
} else {
|
||||||
Log.info("Found (" + projectName + "): " + url);
|
Log.info("Found (" + projectName + "): " + url);
|
||||||
|
@ -54,7 +56,7 @@ public class UrlResourceCache implements ResourceCache {
|
||||||
+ "File url is: "
|
+ "File url is: "
|
||||||
+ url
|
+ url
|
||||||
);
|
);
|
||||||
contents = fetch(projectName, url, path);
|
contents = fetch(projectName, url, path, maxFileSize);
|
||||||
} else {
|
} else {
|
||||||
contents = rawFile.getContents();
|
contents = rawFile.getContents();
|
||||||
}
|
}
|
||||||
|
@ -66,8 +68,9 @@ public class UrlResourceCache implements ResourceCache {
|
||||||
private byte[] fetch(
|
private byte[] fetch(
|
||||||
String projectName,
|
String projectName,
|
||||||
final String url,
|
final String url,
|
||||||
String path
|
String path,
|
||||||
) throws FailedConnectionException {
|
Optional<Long> maxFileSize
|
||||||
|
) throws FailedConnectionException, SizeLimitExceededException {
|
||||||
byte[] contents;
|
byte[] contents;
|
||||||
Log.info("GET -> " + url);
|
Log.info("GET -> " + url);
|
||||||
try {
|
try {
|
||||||
|
@ -76,6 +79,28 @@ public class UrlResourceCache implements ResourceCache {
|
||||||
|
|
||||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public STATE onHeadersReceived(
|
||||||
|
HttpResponseHeaders headers
|
||||||
|
) throws SizeLimitExceededException {
|
||||||
|
List<String> contentLengths
|
||||||
|
= headers.getHeaders().get("Content-Length");
|
||||||
|
if (!maxFileSize.isPresent()) {
|
||||||
|
return STATE.CONTINUE;
|
||||||
|
}
|
||||||
|
if (contentLengths.isEmpty()) {
|
||||||
|
return STATE.CONTINUE;
|
||||||
|
}
|
||||||
|
long contentLength = Long.parseLong(contentLengths.get(0));
|
||||||
|
long maxFileSize_ = maxFileSize.get();
|
||||||
|
if (contentLength <= maxFileSize_) {
|
||||||
|
return STATE.CONTINUE;
|
||||||
|
}
|
||||||
|
throw new SizeLimitExceededException(
|
||||||
|
Optional.of(path), contentLength, maxFileSize_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public STATE onBodyPartReceived(
|
public STATE onBodyPartReceived(
|
||||||
HttpResponseBodyPart bodyPart
|
HttpResponseBodyPart bodyPart
|
||||||
|
@ -115,6 +140,10 @@ public class UrlResourceCache implements ResourceCache {
|
||||||
);
|
);
|
||||||
throw new FailedConnectionException();
|
throw new FailedConnectionException();
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
|
Throwable cause = e.getCause();
|
||||||
|
if (cause instanceof SizeLimitExceededException) {
|
||||||
|
throw (SizeLimitExceededException) cause;
|
||||||
|
}
|
||||||
Log.warn(
|
Log.warn(
|
||||||
"ExecutionException when fetching project: " +
|
"ExecutionException when fetching project: " +
|
||||||
projectName +
|
projectName +
|
||||||
|
@ -126,6 +155,10 @@ public class UrlResourceCache implements ResourceCache {
|
||||||
);
|
);
|
||||||
throw new FailedConnectionException();
|
throw new FailedConnectionException();
|
||||||
}
|
}
|
||||||
|
if (maxFileSize.isPresent() && contents.length > maxFileSize.get()) {
|
||||||
|
throw new SizeLimitExceededException(
|
||||||
|
Optional.of(path), contents.length, maxFileSize.get());
|
||||||
|
}
|
||||||
dbStore.addURLIndexForProject(projectName, url, path);
|
dbStore.addURLIndexForProject(projectName, url, path);
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,11 @@ public class ServletFile extends RawFile {
|
||||||
return file.getContents();
|
return file.getContents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long size() {
|
||||||
|
return getContents().length;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isChanged() {
|
public boolean isChanged() {
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package uk.ac.ic.wlgitbridge.data.filestore;
|
package uk.ac.ic.wlgitbridge.data.filestore;
|
||||||
|
|
||||||
|
import uk.ac.ic.wlgitbridge.git.exception.SizeLimitExceededException;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Winston on 16/11/14.
|
* Created by Winston on 16/11/14.
|
||||||
|
|
|
@ -17,6 +17,8 @@ public abstract class RawFile {
|
||||||
|
|
||||||
public abstract byte[] getContents();
|
public abstract byte[] getContents();
|
||||||
|
|
||||||
|
public abstract long size();
|
||||||
|
|
||||||
public final void writeToDisk(File directory) throws IOException {
|
public final void writeToDisk(File directory) throws IOException {
|
||||||
File file = new File(directory, getPath());
|
File file = new File(directory, getPath());
|
||||||
file.getParentFile().mkdirs();
|
file.getParentFile().mkdirs();
|
||||||
|
|
|
@ -23,4 +23,9 @@ public class RepositoryFile extends RawFile {
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long size() {
|
||||||
|
return contents.length;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.transport.ReceivePack;
|
import org.eclipse.jgit.transport.ReceivePack;
|
||||||
import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
|
import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.Bridge;
|
import uk.ac.ic.wlgitbridge.bridge.Bridge;
|
||||||
|
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
|
||||||
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.handler.hook.WriteLatexPutHook;
|
||||||
import uk.ac.ic.wlgitbridge.git.servlet.WLGitServlet;
|
import uk.ac.ic.wlgitbridge.git.servlet.WLGitServlet;
|
||||||
|
@ -28,9 +29,12 @@ import java.util.Optional;
|
||||||
public class WLReceivePackFactory
|
public class WLReceivePackFactory
|
||||||
implements ReceivePackFactory<HttpServletRequest> {
|
implements ReceivePackFactory<HttpServletRequest> {
|
||||||
|
|
||||||
|
private final RepoStore repoStore;
|
||||||
|
|
||||||
private final Bridge bridge;
|
private final Bridge bridge;
|
||||||
|
|
||||||
public WLReceivePackFactory(Bridge bridge) {
|
public WLReceivePackFactory(RepoStore repoStore, Bridge bridge) {
|
||||||
|
this.repoStore = repoStore;
|
||||||
this.bridge = bridge;
|
this.bridge = bridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +73,7 @@ public class WLReceivePackFactory
|
||||||
hostname = httpServletRequest.getLocalName();
|
hostname = httpServletRequest.getLocalName();
|
||||||
}
|
}
|
||||||
receivePack.setPreReceiveHook(
|
receivePack.setPreReceiveHook(
|
||||||
new WriteLatexPutHook(bridge, hostname, oauth2)
|
new WriteLatexPutHook(repoStore, bridge, hostname, oauth2)
|
||||||
);
|
);
|
||||||
return receivePack;
|
return receivePack;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,12 @@ import org.eclipse.jgit.transport.ReceiveCommand;
|
||||||
import org.eclipse.jgit.transport.ReceiveCommand.Result;
|
import org.eclipse.jgit.transport.ReceiveCommand.Result;
|
||||||
import org.eclipse.jgit.transport.ReceivePack;
|
import org.eclipse.jgit.transport.ReceivePack;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.Bridge;
|
import uk.ac.ic.wlgitbridge.bridge.Bridge;
|
||||||
|
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
|
||||||
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
|
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
|
||||||
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
||||||
import uk.ac.ic.wlgitbridge.git.handler.WLReceivePackFactory;
|
import uk.ac.ic.wlgitbridge.git.handler.WLReceivePackFactory;
|
||||||
import uk.ac.ic.wlgitbridge.git.handler.hook.exception.ForcedPushException;
|
import uk.ac.ic.wlgitbridge.git.handler.hook.exception.ForcedPushException;
|
||||||
import uk.ac.ic.wlgitbridge.git.handler.hook.exception.WrongBranchException;
|
import uk.ac.ic.wlgitbridge.git.handler.hook.exception.WrongBranchException;
|
||||||
import uk.ac.ic.wlgitbridge.git.util.RepositoryObjectTreeWalker;
|
|
||||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.InternalErrorException;
|
import uk.ac.ic.wlgitbridge.snapshot.push.exception.InternalErrorException;
|
||||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.OutOfDateException;
|
import uk.ac.ic.wlgitbridge.snapshot.push.exception.OutOfDateException;
|
||||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.SnapshotPostException;
|
import uk.ac.ic.wlgitbridge.snapshot.push.exception.SnapshotPostException;
|
||||||
|
@ -33,6 +33,8 @@ import java.util.Optional;
|
||||||
*/
|
*/
|
||||||
public class WriteLatexPutHook implements PreReceiveHook {
|
public class WriteLatexPutHook implements PreReceiveHook {
|
||||||
|
|
||||||
|
private final RepoStore repoStore;
|
||||||
|
|
||||||
private final Bridge bridge;
|
private final Bridge bridge;
|
||||||
private final String hostname;
|
private final String hostname;
|
||||||
private final Optional<Credential> oauth2;
|
private final Optional<Credential> oauth2;
|
||||||
|
@ -41,15 +43,18 @@ public class WriteLatexPutHook implements PreReceiveHook {
|
||||||
* The constructor to use, which provides the hook with the {@link Bridge},
|
* The constructor to use, which provides the hook with the {@link Bridge},
|
||||||
* the hostname (used to construct a URL to give to Overleaf to postback),
|
* the hostname (used to construct a URL to give to Overleaf to postback),
|
||||||
* and the oauth2 (used to authenticate with the Snapshot API).
|
* and the oauth2 (used to authenticate with the Snapshot API).
|
||||||
|
* @param repoStore
|
||||||
* @param bridge the {@link Bridge}
|
* @param bridge the {@link Bridge}
|
||||||
* @param hostname the hostname used for postback from the Snapshot API
|
* @param hostname the hostname used for postback from the Snapshot API
|
||||||
* @param oauth2 used to authenticate with the snapshot API, or null
|
* @param oauth2 used to authenticate with the snapshot API, or null
|
||||||
*/
|
*/
|
||||||
public WriteLatexPutHook(
|
public WriteLatexPutHook(
|
||||||
|
RepoStore repoStore,
|
||||||
Bridge bridge,
|
Bridge bridge,
|
||||||
String hostname,
|
String hostname,
|
||||||
Optional<Credential> oauth2
|
Optional<Credential> oauth2
|
||||||
) {
|
) {
|
||||||
|
this.repoStore = repoStore;
|
||||||
this.bridge = bridge;
|
this.bridge = bridge;
|
||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
this.oauth2 = oauth2;
|
this.oauth2 = oauth2;
|
||||||
|
@ -152,18 +157,17 @@ public class WriteLatexPutHook implements PreReceiveHook {
|
||||||
Repository repository,
|
Repository repository,
|
||||||
ReceiveCommand receiveCommand
|
ReceiveCommand receiveCommand
|
||||||
) throws IOException, GitUserException {
|
) throws IOException, GitUserException {
|
||||||
return new RepositoryObjectTreeWalker(
|
return repoStore
|
||||||
repository,
|
.useJGitRepo(repository, receiveCommand.getNewId())
|
||||||
receiveCommand.getNewId()
|
.getDirectory();
|
||||||
).getDirectoryContents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private RawDirectory getOldDirectoryContents(
|
private RawDirectory getOldDirectoryContents(
|
||||||
Repository repository
|
Repository repository
|
||||||
) throws IOException, GitUserException {
|
) throws IOException, GitUserException {
|
||||||
return new RepositoryObjectTreeWalker(
|
return repoStore
|
||||||
repository
|
.useJGitRepo(repository, repository.resolve("HEAD"))
|
||||||
).getDirectoryContents();
|
.getDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package uk.ac.ic.wlgitbridge.git.servlet;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jgit.http.server.GitServlet;
|
import org.eclipse.jgit.http.server.GitServlet;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.Bridge;
|
import uk.ac.ic.wlgitbridge.bridge.Bridge;
|
||||||
|
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
|
||||||
import uk.ac.ic.wlgitbridge.git.handler.WLReceivePackFactory;
|
import uk.ac.ic.wlgitbridge.git.handler.WLReceivePackFactory;
|
||||||
import uk.ac.ic.wlgitbridge.git.handler.WLRepositoryResolver;
|
import uk.ac.ic.wlgitbridge.git.handler.WLRepositoryResolver;
|
||||||
import uk.ac.ic.wlgitbridge.git.handler.WLUploadPackFactory;
|
import uk.ac.ic.wlgitbridge.git.handler.WLUploadPackFactory;
|
||||||
|
@ -39,10 +40,11 @@ public class WLGitServlet extends GitServlet {
|
||||||
*/
|
*/
|
||||||
public WLGitServlet(
|
public WLGitServlet(
|
||||||
ServletContextHandler ctxHandler,
|
ServletContextHandler ctxHandler,
|
||||||
|
RepoStore repoStore,
|
||||||
Bridge bridge
|
Bridge bridge
|
||||||
) throws ServletException {
|
) throws ServletException {
|
||||||
setRepositoryResolver(new WLRepositoryResolver(bridge));
|
setRepositoryResolver(new WLRepositoryResolver(bridge));
|
||||||
setReceivePackFactory(new WLReceivePackFactory(bridge));
|
setReceivePackFactory(new WLReceivePackFactory(repoStore, bridge));
|
||||||
setUploadPackFactory(new WLUploadPackFactory());
|
setUploadPackFactory(new WLUploadPackFactory());
|
||||||
init(new WLGitServletConfig(ctxHandler));
|
init(new WLGitServletConfig(ctxHandler));
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,19 +47,7 @@ public class RepositoryObjectTreeWalker {
|
||||||
this(repository, repository.resolve("HEAD~" + fromHead));
|
this(repository, repository.resolve("HEAD~" + fromHead));
|
||||||
}
|
}
|
||||||
|
|
||||||
public RawDirectory getDirectoryContents(
|
public RawDirectory getDirectoryContents(Optional<Long> maxFileSize)
|
||||||
) throws IOException, SizeLimitExceededException, InvalidGitRepository {
|
|
||||||
return getDirectoryContents(Optional.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
public RawDirectory getDirectoryContents(long maxFileSize)
|
|
||||||
throws InvalidGitRepository,
|
|
||||||
SizeLimitExceededException,
|
|
||||||
IOException {
|
|
||||||
return getDirectoryContents(Optional.of(maxFileSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
private RawDirectory getDirectoryContents(Optional<Long> maxFileSize)
|
|
||||||
throws IOException,
|
throws IOException,
|
||||||
SizeLimitExceededException,
|
SizeLimitExceededException,
|
||||||
InvalidGitRepository {
|
InvalidGitRepository {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SqliteDBStore;
|
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SqliteDBStore;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.repo.FSGitRepoStore;
|
import uk.ac.ic.wlgitbridge.bridge.repo.FSGitRepoStore;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
|
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
|
||||||
|
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStoreConfig;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.NetSnapshotApi;
|
import uk.ac.ic.wlgitbridge.bridge.snapshot.NetSnapshotApi;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotApi;
|
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotApi;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStore;
|
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStore;
|
||||||
|
@ -52,7 +53,10 @@ public class GitBridgeServer {
|
||||||
org.eclipse.jetty.util.log.Log.setLog(new NullLogger());
|
org.eclipse.jetty.util.log.Log.setLog(new NullLogger());
|
||||||
this.port = config.getPort();
|
this.port = config.getPort();
|
||||||
this.rootGitDirectoryPath = config.getRootGitDirectory();
|
this.rootGitDirectoryPath = config.getRootGitDirectory();
|
||||||
RepoStore repoStore = new FSGitRepoStore(rootGitDirectoryPath);
|
RepoStore repoStore = new FSGitRepoStore(
|
||||||
|
rootGitDirectoryPath,
|
||||||
|
config.getRepoStore().flatMap(RepoStoreConfig::getMaxFileSize)
|
||||||
|
);
|
||||||
DBStore dbStore = new SqliteDBStore(
|
DBStore dbStore = new SqliteDBStore(
|
||||||
Paths.get(
|
Paths.get(
|
||||||
repoStore.getRootDirectory().getAbsolutePath()
|
repoStore.getRootDirectory().getAbsolutePath()
|
||||||
|
@ -61,14 +65,14 @@ public class GitBridgeServer {
|
||||||
SwapStore swapStore = SwapStore.fromConfig(config.getSwapStore());
|
SwapStore swapStore = SwapStore.fromConfig(config.getSwapStore());
|
||||||
SnapshotApi snapshotApi = new NetSnapshotApi();
|
SnapshotApi snapshotApi = new NetSnapshotApi();
|
||||||
bridge = Bridge.make(
|
bridge = Bridge.make(
|
||||||
|
config,
|
||||||
repoStore,
|
repoStore,
|
||||||
dbStore,
|
dbStore,
|
||||||
swapStore,
|
swapStore,
|
||||||
config.getSwapJob(),
|
|
||||||
snapshotApi
|
snapshotApi
|
||||||
);
|
);
|
||||||
jettyServer = new Server(port);
|
jettyServer = new Server(port);
|
||||||
configureJettyServer(config, snapshotApi);
|
configureJettyServer(config, repoStore, snapshotApi);
|
||||||
SnapshotAPIRequest.setBasicAuth(
|
SnapshotAPIRequest.setBasicAuth(
|
||||||
config.getUsername(),
|
config.getUsername(),
|
||||||
config.getPassword()
|
config.getPassword()
|
||||||
|
@ -110,11 +114,12 @@ public class GitBridgeServer {
|
||||||
|
|
||||||
private void configureJettyServer(
|
private void configureJettyServer(
|
||||||
Config config,
|
Config config,
|
||||||
|
RepoStore repoStore,
|
||||||
SnapshotApi snapshotApi
|
SnapshotApi snapshotApi
|
||||||
) throws ServletException {
|
) throws ServletException {
|
||||||
HandlerCollection handlers = new HandlerList();
|
HandlerCollection handlers = new HandlerList();
|
||||||
handlers.addHandler(initApiHandler());
|
handlers.addHandler(initApiHandler());
|
||||||
handlers.addHandler(initGitHandler(config, snapshotApi));
|
handlers.addHandler(initGitHandler(config, repoStore, snapshotApi));
|
||||||
jettyServer.setHandler(handlers);
|
jettyServer.setHandler(handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +141,7 @@ public class GitBridgeServer {
|
||||||
|
|
||||||
private Handler initGitHandler(
|
private Handler initGitHandler(
|
||||||
Config config,
|
Config config,
|
||||||
|
RepoStore repoStore,
|
||||||
SnapshotApi snapshotApi
|
SnapshotApi snapshotApi
|
||||||
) throws ServletException {
|
) throws ServletException {
|
||||||
final ServletContextHandler servletContextHandler =
|
final ServletContextHandler servletContextHandler =
|
||||||
|
@ -153,6 +159,7 @@ public class GitBridgeServer {
|
||||||
new ServletHolder(
|
new ServletHolder(
|
||||||
new WLGitServlet(
|
new WLGitServlet(
|
||||||
servletContextHandler,
|
servletContextHandler,
|
||||||
|
repoStore,
|
||||||
bridge
|
bridge
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
|
@ -44,6 +44,11 @@ public class SnapshotFile extends RawFile implements JSONSource {
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long size() {
|
||||||
|
return contents.length;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mock server */
|
/* Mock server */
|
||||||
|
|
||||||
public SnapshotFile(String contents, String path) {
|
public SnapshotFile(String contents, String path) {
|
||||||
|
|
|
@ -21,9 +21,11 @@ public class Instance {
|
||||||
|
|
||||||
public static final JsonFactory jsonFactory = new GsonFactory();
|
public static final JsonFactory jsonFactory = new GsonFactory();
|
||||||
|
|
||||||
public static final Gson prettyGson =
|
public static final Gson prettyGson = new GsonBuilder()
|
||||||
new GsonBuilder(
|
.setPrettyPrinting()
|
||||||
).setPrettyPrinting().disableHtmlEscaping().create();
|
.serializeNulls()
|
||||||
|
.disableHtmlEscaping()
|
||||||
|
.create();
|
||||||
|
|
||||||
public static final Gson gson = new Gson();
|
public static final Gson gson = new Gson();
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,10 @@ public class ConfigTest {
|
||||||
" \"oauth2ClientID\": \"<oauth2ClientID>\",\n" +
|
" \"oauth2ClientID\": \"<oauth2ClientID>\",\n" +
|
||||||
" \"oauth2ClientSecret\": \"<oauth2ClientSecret>\",\n" +
|
" \"oauth2ClientSecret\": \"<oauth2ClientSecret>\",\n" +
|
||||||
" \"oauth2Server\": \"https://www.overleaf.com\"\n" +
|
" \"oauth2Server\": \"https://www.overleaf.com\"\n" +
|
||||||
" }\n" +
|
" },\n" +
|
||||||
|
" \"repoStore\": null,\n" +
|
||||||
|
" \"swapStore\": null,\n" +
|
||||||
|
" \"swapJob\": null\n" +
|
||||||
"}";
|
"}";
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"sanitised config did not hide sensitive fields",
|
"sanitised config did not hide sensitive fields",
|
||||||
|
|
|
@ -2,6 +2,7 @@ package uk.ac.ic.wlgitbridge.bridge;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import uk.ac.ic.wlgitbridge.application.config.Config;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
|
import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.gc.GcJob;
|
import uk.ac.ic.wlgitbridge.bridge.gc.GcJob;
|
||||||
|
@ -50,6 +51,18 @@ public class BridgeTest {
|
||||||
swapJob = mock(SwapJob.class);
|
swapJob = mock(SwapJob.class);
|
||||||
gcJob = mock(GcJob.class);
|
gcJob = mock(GcJob.class);
|
||||||
bridge = new Bridge(
|
bridge = new Bridge(
|
||||||
|
new Config(
|
||||||
|
0,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null),
|
||||||
lock,
|
lock,
|
||||||
repoStore,
|
repoStore,
|
||||||
dbStore,
|
dbStore,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.io.*;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ public class FSGitRepoStoreTest {
|
||||||
File tmp = makeTempRepoDir(tmpFolder, "rootdir");
|
File tmp = makeTempRepoDir(tmpFolder, "rootdir");
|
||||||
original = tmpFolder.newFolder("original");
|
original = tmpFolder.newFolder("original");
|
||||||
FileUtils.copyDirectory(tmp, original);
|
FileUtils.copyDirectory(tmp, original);
|
||||||
repoStore = new FSGitRepoStore(tmp.getAbsolutePath());
|
repoStore = new FSGitRepoStore(tmp.getAbsolutePath(), Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class GitProjectRepoTest {
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws IOException {
|
public void setup() throws IOException {
|
||||||
rootdir = makeTempRepoDir(tmpFolder, "rootdir");
|
rootdir = makeTempRepoDir(tmpFolder, "rootdir");
|
||||||
repoStore = new FSGitRepoStore(rootdir.getAbsolutePath());
|
repoStore = new FSGitRepoStore(rootdir.getAbsolutePath(), Optional.empty());
|
||||||
repo = fromExistingDir("repo");
|
repo = fromExistingDir("repo");
|
||||||
badGitignore = fromExistingDir("badgitignore");
|
badGitignore = fromExistingDir("badgitignore");
|
||||||
incoming = fromExistingDir("incoming");
|
incoming = fromExistingDir("incoming");
|
||||||
|
@ -64,7 +64,7 @@ public class GitProjectRepoTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private GitProjectRepo fromExistingDir(String dir) throws IOException {
|
private GitProjectRepo fromExistingDir(String dir) throws IOException {
|
||||||
GitProjectRepo ret = new GitProjectRepo(dir);
|
GitProjectRepo ret = GitProjectRepo.fromName(dir);
|
||||||
ret.useExistingRepository(repoStore);
|
ret.useExistingRepository(repoStore);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ public class SwapJobImplTest {
|
||||||
tmpFolder,
|
tmpFolder,
|
||||||
"repostore"
|
"repostore"
|
||||||
).getAbsolutePath(),
|
).getAbsolutePath(),
|
||||||
|
100_000,
|
||||||
FileUtils::sizeOfDirectory
|
FileUtils::sizeOfDirectory
|
||||||
);
|
);
|
||||||
dbStore = new SqliteDBStore(tmpFolder.newFile());
|
dbStore = new SqliteDBStore(tmpFolder.newFile());
|
||||||
|
|
|
@ -9,7 +9,6 @@ import org.mockserver.client.server.MockServerClient;
|
||||||
import org.mockserver.junit.MockServerRule;
|
import org.mockserver.junit.MockServerRule;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.repo.FSGitRepoStore;
|
import uk.ac.ic.wlgitbridge.bridge.repo.FSGitRepoStore;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.repo.GitProjectRepo;
|
|
||||||
import uk.ac.ic.wlgitbridge.bridge.repo.ProjectRepo;
|
import uk.ac.ic.wlgitbridge.bridge.repo.ProjectRepo;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
|
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
|
||||||
import uk.ac.ic.wlgitbridge.bridge.resource.ResourceCache;
|
import uk.ac.ic.wlgitbridge.bridge.resource.ResourceCache;
|
||||||
|
@ -20,6 +19,7 @@ import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.mockserver.model.HttpRequest.request;
|
import static org.mockserver.model.HttpRequest.request;
|
||||||
|
@ -67,12 +67,13 @@ public class ResourceFetcherTest {
|
||||||
TemporaryFolder repositoryFolder = new TemporaryFolder();
|
TemporaryFolder repositoryFolder = new TemporaryFolder();
|
||||||
repositoryFolder.create();
|
repositoryFolder.create();
|
||||||
String repoStorePath = repositoryFolder.getRoot().getAbsolutePath();
|
String repoStorePath = repositoryFolder.getRoot().getAbsolutePath();
|
||||||
RepoStore repoStore = new FSGitRepoStore(repoStorePath);
|
RepoStore repoStore = new FSGitRepoStore(repoStorePath, Optional.empty());
|
||||||
ProjectRepo repo = new GitProjectRepo("repo");
|
ProjectRepo repo = repoStore.initRepo("repo");
|
||||||
repo.initRepo(repoStore);
|
Map<String, RawFile> fileTable = repo.getDirectory().getFileTable();
|
||||||
Map<String, RawFile> fileTable = repo.getFiles();
|
Map<String, byte[]> fetchedUrls = new HashMap<>();
|
||||||
Map<String, byte[]> fetchedUrls = new HashMap<String, byte[]>();
|
resources.get(
|
||||||
resources.get(testProjectName, testUrl, newTestPath, fileTable, fetchedUrls);
|
testProjectName, testUrl, newTestPath,
|
||||||
|
fileTable, fetchedUrls, Optional.empty());
|
||||||
|
|
||||||
// We don't bother caching in this case, at present.
|
// We don't bother caching in this case, at present.
|
||||||
assertEquals(0, fetchedUrls.size());
|
assertEquals(0, fetchedUrls.size());
|
||||||
|
|
Loading…
Reference in a new issue