Made RepositoryObjectTreeWalker and associated classes and methods.

This commit is contained in:
Winston Li 2014-11-16 12:43:21 +00:00
parent ba7d0d318c
commit 3cd94af7e9
15 changed files with 203 additions and 96 deletions

View file

@ -5,7 +5,7 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import uk.ac.ic.wlgitbridge.application.jetty.NullLogger; import uk.ac.ic.wlgitbridge.application.jetty.NullLogger;
import uk.ac.ic.wlgitbridge.git.WLGitServlet; import uk.ac.ic.wlgitbridge.git.servlet.WLGitServlet;
import uk.ac.ic.wlgitbridge.git.exception.InvalidRootDirectoryPathException; import uk.ac.ic.wlgitbridge.git.exception.InvalidRootDirectoryPathException;
import uk.ac.ic.wlgitbridge.writelatex.model.WLDataModel; import uk.ac.ic.wlgitbridge.writelatex.model.WLDataModel;

View file

@ -0,0 +1,15 @@
package uk.ac.ic.wlgitbridge.bridge;
import com.google.gson.JsonElement;
import uk.ac.ic.wlgitbridge.writelatex.filestore.node.WLDirectoryNode;
/**
* Created by Winston on 16/11/14.
*/
public interface CandidateSnapshot {
public JsonElement getJsonRepresentation();
public void approveWithVersionID(int versionID);
public WLDirectoryNode getDirectoryNode();
}

View file

@ -0,0 +1,11 @@
package uk.ac.ic.wlgitbridge.bridge;
import java.util.Map;
/**
* Created by Winston on 16/11/14.
*/
public interface RawDirectoryContents {
public Map<String, byte[]> getFileContentsTable();
}

View file

@ -5,11 +5,9 @@ import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import uk.ac.ic.wlgitbridge.writelatex.api.SnapshotDBAPI;
import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException; import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException; import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -20,14 +18,12 @@ public class WLBridgedProject {
private final Repository repository; private final Repository repository;
private final String name; private final String name;
private final File repositoryDirectory; private final WriteLatexDataSource writeLatexDataSource;
private final SnapshotDBAPI snapshotDBAPI;
public WLBridgedProject(Repository repository, String name, File repositoryDirectory, SnapshotDBAPI snapshotDBAPI) { public WLBridgedProject(Repository repository, String name, WriteLatexDataSource writeLatexDataSource) {
this.repository = repository; this.repository = repository;
this.name = name; this.name = name;
this.repositoryDirectory = repositoryDirectory; this.writeLatexDataSource = writeLatexDataSource;
this.snapshotDBAPI = snapshotDBAPI;
} }
public void buildRepository() throws RepositoryNotFoundException, ServiceNotEnabledException, FailedConnectionException { public void buildRepository() throws RepositoryNotFoundException, ServiceNotEnabledException, FailedConnectionException {
@ -41,7 +37,7 @@ public class WLBridgedProject {
private void updateRepositoryFromSnapshots(Repository repository) throws ServiceNotEnabledException, RepositoryNotFoundException, FailedConnectionException { private void updateRepositoryFromSnapshots(Repository repository) throws ServiceNotEnabledException, RepositoryNotFoundException, FailedConnectionException {
List<WritableRepositoryContents> writableRepositories; List<WritableRepositoryContents> writableRepositories;
try { try {
writableRepositories = snapshotDBAPI.getWritableRepositories(name); writableRepositories = writeLatexDataSource.getWritableRepositories(name);
} catch (InvalidProjectException e) { } catch (InvalidProjectException e) {
throw new RepositoryNotFoundException(name); throw new RepositoryNotFoundException(name);
} }
@ -63,13 +59,13 @@ public class WLBridgedProject {
} }
private void buildRepositoryFromScratch(Repository repository) throws RepositoryNotFoundException, ServiceNotEnabledException, FailedConnectionException { private void buildRepositoryFromScratch(Repository repository) throws RepositoryNotFoundException, ServiceNotEnabledException, FailedConnectionException {
if (!snapshotDBAPI.repositoryExists(name)) { if (!writeLatexDataSource.repositoryExists(name)) {
throw new RepositoryNotFoundException(name); throw new RepositoryNotFoundException(name);
} }
try { try {
repository.create(); repository.create();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); throw new ServiceNotEnabledException();
} }
updateRepositoryFromSnapshots(repository); updateRepositoryFromSnapshots(repository);
} }

View file

@ -1,18 +1,18 @@
package uk.ac.ic.wlgitbridge.writelatex.api; package uk.ac.ic.wlgitbridge.bridge;
import uk.ac.ic.wlgitbridge.bridge.WritableRepositoryContents;
import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException; import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException; import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException;
import uk.ac.ic.wlgitbridge.writelatex.model.Snapshot;
import java.util.List; import java.util.List;
/** /**
* Created by Winston on 03/11/14. * Created by Winston on 03/11/14.
*/ */
public interface SnapshotDBAPI { public interface WriteLatexDataSource {
public boolean repositoryExists(String name) throws FailedConnectionException; public boolean repositoryExists(String name) throws FailedConnectionException;
public List<WritableRepositoryContents> getWritableRepositories(String name) throws FailedConnectionException, InvalidProjectException; public List<WritableRepositoryContents> getWritableRepositories(String name) throws FailedConnectionException, InvalidProjectException;
public CandidateSnapshot createCandidateSnapshot(RawDirectoryContents rawDirectoryContents);
public void approveCandidateSnapshot(CandidateSnapshot candidateSnapshot);
} }

View file

@ -5,8 +5,8 @@ import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.resolver.ReceivePackFactory; import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import uk.ac.ic.wlgitbridge.git.handler.hook.CheckNonFastForwardHook; import uk.ac.ic.wlgitbridge.git.handler.hook.WriteLatexPutHook;
import uk.ac.ic.wlgitbridge.writelatex.api.SnapshotDBAPI; import uk.ac.ic.wlgitbridge.bridge.WriteLatexDataSource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -16,14 +16,16 @@ import javax.servlet.http.HttpServletRequest;
/* */ /* */
public class WLReceivePackFactory implements ReceivePackFactory<HttpServletRequest> { public class WLReceivePackFactory implements ReceivePackFactory<HttpServletRequest> {
public WLReceivePackFactory(SnapshotDBAPI snapshotDBAPI) { private final WriteLatexDataSource writeLatexDataSource;
public WLReceivePackFactory(WriteLatexDataSource writeLatexDataSource) {
this.writeLatexDataSource = writeLatexDataSource;
} }
@Override @Override
public ReceivePack create(HttpServletRequest httpServletRequest, Repository repository) throws ServiceNotEnabledException, ServiceNotAuthorizedException { public ReceivePack create(HttpServletRequest httpServletRequest, Repository repository) throws ServiceNotEnabledException, ServiceNotAuthorizedException {
ReceivePack receivePack = new ReceivePack(repository); ReceivePack receivePack = new ReceivePack(repository);
receivePack.setPreReceiveHook(new CheckNonFastForwardHook()); receivePack.setPreReceiveHook(new WriteLatexPutHook(writeLatexDataSource));
return receivePack; return receivePack;
} }

View file

@ -1,63 +0,0 @@
package uk.ac.ic.wlgitbridge.git.handler.hook;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.PreReceiveHook;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.treewalk.TreeWalk;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
/**
* Created by Winston on 03/11/14.
*/
public class CheckNonFastForwardHook implements PreReceiveHook {
@Override
public void onPreReceive(ReceivePack receivePack, Collection<ReceiveCommand> receiveCommands) {
System.out.println("There are " + receiveCommands.size() + " receive commands.");
System.out.println("All commits: ");
System.out.println(receiveCommands);
for (ReceiveCommand receiveCommand : receiveCommands) {
// receiveCommand.setResult(RefUpdate.Result.REJECTED);
try {
System.out.println("Old: " + receiveCommand.getOldId());
System.out.println("New: " + receiveCommand.getNewId());
// a RevWalk allows to walk over commits based on some filtering that is
// defined
RevWalk walk = new RevWalk(receivePack.getRepository());
RevCommit commit = walk.parseCommit(receiveCommand.getNewId());
System.out.println("Parent commit: " + commit.getParents()[0].getId());
RevTree tree = commit.getTree();
System.out.println("Having tree: " + tree);
// now use a TreeWalk to iterate over all files in the Tree recursively
// you can set Filters to narrow down the results if needed
TreeWalk treeWalk = new TreeWalk(receivePack.getRepository());
treeWalk.addTree(tree);
treeWalk.setRecursive(true);
while (treeWalk.next()) {
File file = new File("/Users/Roxy/git/testing/" + treeWalk.getPathString());
file.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(file);
receivePack.getRepository().open(treeWalk.getObjectId(0)).copyTo(out);
}
} catch (IOException e) {
e.printStackTrace();
}
if (receiveCommand.getType() == ReceiveCommand.Type.UPDATE_NONFASTFORWARD) {
receivePack.sendError("You can't do a force push");
receiveCommand.setResult(RefUpdate.Result.REJECTED);
}
}
System.out.println("Pre receive");
}
}

View file

@ -0,0 +1,58 @@
package uk.ac.ic.wlgitbridge.git.handler.hook;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.transport.PreReceiveHook;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.ReceivePack;
import uk.ac.ic.wlgitbridge.bridge.RawDirectoryContents;
import uk.ac.ic.wlgitbridge.bridge.WriteLatexDataSource;
import uk.ac.ic.wlgitbridge.git.handler.hook.exception.ForcedPushException;
import uk.ac.ic.wlgitbridge.git.util.RepositoryObjectTreeWalker;
import java.io.IOException;
import java.util.Collection;
/**
* Created by Winston on 03/11/14.
*/
public class WriteLatexPutHook implements PreReceiveHook {
private final WriteLatexDataSource writeLatexDataSource;
public WriteLatexPutHook(WriteLatexDataSource writeLatexDataSource) {
this.writeLatexDataSource = writeLatexDataSource;
}
@Override
public void onPreReceive(ReceivePack receivePack, Collection<ReceiveCommand> receiveCommands) {
for (ReceiveCommand receiveCommand : receiveCommands) {
try {
handleReceiveCommand(receivePack, receiveCommand);
} catch (ForcedPushException e) {
receivePack.sendError("You can't do a force push");
receiveCommand.setResult(Result.REJECTED);
} catch (IOException e) {
receivePack.sendError("IOException");
receiveCommand.setResult(Result.REJECTED);
}
}
}
private void handleReceiveCommand(ReceivePack receivePack, ReceiveCommand receiveCommand) throws ForcedPushException, IOException {
checkForcedPush(receiveCommand);
RawDirectoryContents directoryContents = getPushedDirectoryContents(receivePack, receiveCommand);
}
private void checkForcedPush(ReceiveCommand receiveCommand) throws ForcedPushException {
if (receiveCommand.getType() == ReceiveCommand.Type.UPDATE_NONFASTFORWARD) {
throw new ForcedPushException();
}
}
private RawDirectoryContents getPushedDirectoryContents(ReceivePack receivePack, ReceiveCommand receiveCommand) throws IOException {
return new RepositoryObjectTreeWalker(receivePack.getRepository(),
receiveCommand.getNewId())
.getDirectoryContents();
}
}

View file

@ -0,0 +1,7 @@
package uk.ac.ic.wlgitbridge.git.handler.hook.exception;
/**
* Created by Winston on 16/11/14.
*/
public class ForcedPushException extends Exception {
}

View file

@ -1,4 +1,4 @@
package uk.ac.ic.wlgitbridge.git; 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;
@ -7,7 +7,7 @@ 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;
import uk.ac.ic.wlgitbridge.writelatex.SnapshotRepositoryBuilder; import uk.ac.ic.wlgitbridge.writelatex.SnapshotRepositoryBuilder;
import uk.ac.ic.wlgitbridge.writelatex.api.SnapshotDBAPI; import uk.ac.ic.wlgitbridge.bridge.WriteLatexDataSource;
import javax.servlet.ServletException; import javax.servlet.ServletException;
@ -16,9 +16,9 @@ import javax.servlet.ServletException;
*/ */
public class WLGitServlet extends GitServlet { public class WLGitServlet extends GitServlet {
public WLGitServlet(ServletContextHandler servletContextHandler, SnapshotDBAPI snapshotDBAPI, String rootGitDirectoryPath) throws ServletException, InvalidRootDirectoryPathException { public WLGitServlet(ServletContextHandler servletContextHandler, WriteLatexDataSource writeLatexDataSource, String rootGitDirectoryPath) throws ServletException, InvalidRootDirectoryPathException {
setRepositoryResolver(new WLRepositoryResolver(rootGitDirectoryPath, new SnapshotRepositoryBuilder(snapshotDBAPI))); setRepositoryResolver(new WLRepositoryResolver(rootGitDirectoryPath, new SnapshotRepositoryBuilder(writeLatexDataSource)));
setReceivePackFactory(new WLReceivePackFactory(snapshotDBAPI)); setReceivePackFactory(new WLReceivePackFactory(writeLatexDataSource));
setUploadPackFactory(new WLUploadPackFactory()); setUploadPackFactory(new WLUploadPackFactory());
init(new WLGitServletConfig(servletContextHandler)); init(new WLGitServletConfig(servletContextHandler));
} }

View file

@ -1,4 +1,4 @@
package uk.ac.ic.wlgitbridge.git; package uk.ac.ic.wlgitbridge.git.servlet;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;

View file

@ -0,0 +1,23 @@
package uk.ac.ic.wlgitbridge.git.util;
import uk.ac.ic.wlgitbridge.bridge.RawDirectoryContents;
import java.util.Map;
/**
* Created by Winston on 16/11/14.
*/
public class FileDirectoryContents implements RawDirectoryContents {
private final Map<String, byte[]> fileContentsTable;
public FileDirectoryContents(Map<String, byte[]> fileContentsTable) {
this.fileContentsTable = fileContentsTable;
}
@Override
public Map<String, byte[]> getFileContentsTable() {
return fileContentsTable;
}
}

View file

@ -0,0 +1,46 @@
package uk.ac.ic.wlgitbridge.git.util;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import uk.ac.ic.wlgitbridge.bridge.RawDirectoryContents;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Winston on 16/11/14.
*/
public class RepositoryObjectTreeWalker {
private final TreeWalk treeWalk;
private final Repository repository;
public RepositoryObjectTreeWalker(Repository repository, ObjectId objectId) throws IOException {
treeWalk = initTreeWalk(repository, objectId);
this.repository = repository;
}
public RawDirectoryContents getDirectoryContents() throws IOException {
return new FileDirectoryContents(walkGitObjectTree());
}
private TreeWalk initTreeWalk(Repository repository, ObjectId objectId) throws IOException {
RevWalk walk = new RevWalk(repository);
TreeWalk treeWalk = new TreeWalk(repository);
treeWalk.addTree(walk.parseCommit(objectId).getTree());
treeWalk.setRecursive(true);
return treeWalk;
}
private Map<String, byte[]> walkGitObjectTree() throws IOException {
Map<String, byte[]> fileContentsTable = new HashMap<String, byte[]>();
while (treeWalk.next()) {
fileContentsTable.put(treeWalk.getPathString(), repository.open(treeWalk.getObjectId(0)).getBytes());
}
return fileContentsTable;
}
}

View file

@ -6,7 +6,7 @@ import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import uk.ac.ic.wlgitbridge.bridge.RepositorySource; import uk.ac.ic.wlgitbridge.bridge.RepositorySource;
import uk.ac.ic.wlgitbridge.bridge.WLBridgedProject; import uk.ac.ic.wlgitbridge.bridge.WLBridgedProject;
import uk.ac.ic.wlgitbridge.writelatex.api.SnapshotDBAPI; import uk.ac.ic.wlgitbridge.bridge.WriteLatexDataSource;
import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException; import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
import java.io.File; import java.io.File;
@ -17,20 +17,20 @@ import java.io.IOException;
*/ */
public class SnapshotRepositoryBuilder implements RepositorySource { public class SnapshotRepositoryBuilder implements RepositorySource {
private final SnapshotDBAPI snapshotDBAPI; private final WriteLatexDataSource writeLatexDataSource;
public SnapshotRepositoryBuilder(SnapshotDBAPI snapshotDBAPI) { public SnapshotRepositoryBuilder(WriteLatexDataSource writeLatexDataSource) {
this.snapshotDBAPI = snapshotDBAPI; this.writeLatexDataSource = writeLatexDataSource;
} }
@Override @Override
public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory) throws RepositoryNotFoundException, ServiceNotEnabledException { public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory) throws RepositoryNotFoundException, ServiceNotEnabledException {
File repositoryDirectory = new File(rootDirectory.getAbsolutePath(), name); File repositoryDirectory = new File(rootDirectory, name);
Repository repository = null; Repository repository = null;
try { try {
repository = new FileRepositoryBuilder().setWorkTree(repositoryDirectory).build(); repository = new FileRepositoryBuilder().setWorkTree(repositoryDirectory).build();
new WLBridgedProject(repository, name, repositoryDirectory, snapshotDBAPI).buildRepository(); new WLBridgedProject(repository, name, writeLatexDataSource).buildRepository();
} catch (FailedConnectionException e) { } catch (FailedConnectionException e) {
throw new ServiceNotEnabledException(); throw new ServiceNotEnabledException();
} catch (IOException e) { } catch (IOException e) {

View file

@ -1,7 +1,9 @@
package uk.ac.ic.wlgitbridge.writelatex.model; package uk.ac.ic.wlgitbridge.writelatex.model;
import uk.ac.ic.wlgitbridge.bridge.CandidateSnapshot;
import uk.ac.ic.wlgitbridge.bridge.RawDirectoryContents;
import uk.ac.ic.wlgitbridge.bridge.WritableRepositoryContents; import uk.ac.ic.wlgitbridge.bridge.WritableRepositoryContents;
import uk.ac.ic.wlgitbridge.writelatex.api.SnapshotDBAPI; import uk.ac.ic.wlgitbridge.bridge.WriteLatexDataSource;
import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException; import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.SnapshotGetDocRequest; import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.SnapshotGetDocRequest;
import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException; import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException;
@ -14,7 +16,7 @@ import java.util.Map;
/** /**
* Created by Winston on 06/11/14. * Created by Winston on 06/11/14.
*/ */
public class WLDataModel implements SnapshotDBAPI { public class WLDataModel implements WriteLatexDataSource {
private final Map<String, WLProject> projects; private final Map<String, WLProject> projects;
private final WLFileStore fileStore; private final WLFileStore fileStore;
@ -41,6 +43,16 @@ public class WLDataModel implements SnapshotDBAPI {
return updateProjectWithName(name); return updateProjectWithName(name);
} }
@Override
public CandidateSnapshot createCandidateSnapshot(RawDirectoryContents rawDirectoryContents) {
return null;
}
@Override
public void approveCandidateSnapshot(CandidateSnapshot candidateSnapshot) {
}
private List<WritableRepositoryContents> updateProjectWithName(String name) throws FailedConnectionException, InvalidProjectException { private List<WritableRepositoryContents> updateProjectWithName(String name) throws FailedConnectionException, InvalidProjectException {
return fileStore.updateForProject(getProjectWithName(name)); return fileStore.updateForProject(getProjectWithName(name));
} }