Преглед изворни кода

Memory store works except the project name still needs to be passed to writeToFile.

Winston Li пре 12 година
родитељ
комит
abc8854f59
28 измењених фајлова са 453 додато и 160 уклоњено
  1. 8 6
      services/git-bridge/src/uk/ac/ic/wlgitbridge/bridge/WLBridgedProject.java
  2. 0 10
      services/git-bridge/src/uk/ac/ic/wlgitbridge/bridge/Writable.java
  3. 18 0
      services/git-bridge/src/uk/ac/ic/wlgitbridge/bridge/WritableRepositoryContents.java
  4. 13 1
      services/git-bridge/src/uk/ac/ic/wlgitbridge/git/handler/WLRepositoryResolver.java
  5. 8 8
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/SnapshotFetcher.java
  6. 2 1
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/api/SnapshotDBAPI.java
  7. 16 9
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotAttachment.java
  8. 1 10
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotFile.java
  9. 0 25
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/FileIndexStore.java
  10. 52 0
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/GitDirectoryContents.java
  11. 0 33
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/WLFileStore.java
  12. 15 0
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/blob/AttachmentBlob.java
  13. 12 0
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/blob/Blob.java
  14. 19 0
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/blob/ByteBlob.java
  15. 61 0
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/blob/ExternalBlob.java
  16. 14 0
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/blob/SnapshotFileBlob.java
  17. 28 3
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/AttachmentNode.java
  18. 11 5
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/BlobNode.java
  19. 21 4
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/FileNode.java
  20. 11 0
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/FileNodeIndexer.java
  21. 18 23
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/WLDirectoryNode.java
  22. 1 1
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/store/BlobHash.java
  23. 51 0
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/store/FileIndexStore.java
  24. 49 0
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/store/WLFileStore.java
  25. 11 12
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/Snapshot.java
  26. 9 6
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/WLDataModel.java
  27. 3 3
      services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/WLProject.java
  28. 1 0
      services/git-bridge/test/uk/ac/ic/wlgitbridge/writelatex/filestore/BlobHashTest.java

+ 8 - 6
services/git-bridge/src/uk/ac/ic/wlgitbridge/bridge/WLBridgedProject.java

@@ -8,7 +8,6 @@ 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.getdoc.exception.InvalidProjectException;
-import uk.ac.ic.wlgitbridge.writelatex.model.Snapshot;
 
 import java.io.File;
 import java.io.IOException;
@@ -40,18 +39,21 @@ public class WLBridgedProject {
     }
 
     private void updateRepositoryFromSnapshots(Repository repository) throws ServiceNotEnabledException, RepositoryNotFoundException, FailedConnectionException {
-        List<Snapshot> snapshotsToAdd;
+        List<WritableRepositoryContents> writableRepositories;
         try {
-            snapshotsToAdd = snapshotDBAPI.getSnapshotsToAddToProject(name);
+            writableRepositories = snapshotDBAPI.getWritableRepositories(name);
         } catch (InvalidProjectException e) {
             throw new RepositoryNotFoundException(name);
         }
         try {
-            for (Snapshot snapshot : snapshotsToAdd) {
-                snapshot.writeToDisk(repositoryDirectory.getAbsolutePath());
+            for (WritableRepositoryContents writableRepositoryContents : writableRepositories) {
+                writableRepositoryContents.write();
                 Git git = new Git(repository);
                 git.add().addFilepattern(".").call();
-                git.commit().setAuthor(snapshot.getUserName(), snapshot.getUserEmail()).setMessage(snapshot.getComment()).call();
+                git.commit().setAuthor(writableRepositoryContents.getUserName(),
+                                       writableRepositoryContents.getUserEmail())
+                            .setMessage(writableRepositoryContents.getCommitMessage())
+                            .call();
             }
         } catch (GitAPIException e) {
             throw new ServiceNotEnabledException();

+ 0 - 10
services/git-bridge/src/uk/ac/ic/wlgitbridge/bridge/Writable.java

@@ -1,10 +0,0 @@
-package uk.ac.ic.wlgitbridge.bridge;
-
-/**
- * Created by Winston on 14/11/14.
- */
-public interface Writable {
-
-    public void write();
-
-}

+ 18 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/bridge/WritableRepositoryContents.java

@@ -0,0 +1,18 @@
+package uk.ac.ic.wlgitbridge.bridge;
+
+import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
+
+import java.io.IOException;
+
+/**
+ * Created by Winston on 14/11/14.
+ */
+public interface WritableRepositoryContents {
+
+    public void write() throws IOException, FailedConnectionException;
+
+    public String getUserName();
+    public String getUserEmail();
+    public String getCommitMessage();
+
+}

+ 13 - 1
services/git-bridge/src/uk/ac/ic/wlgitbridge/git/handler/WLRepositoryResolver.java

@@ -28,7 +28,19 @@ public class WLRepositoryResolver implements RepositoryResolver<HttpServletReque
 
     @Override
     public Repository open(HttpServletRequest httpServletRequest, String name) throws RepositoryNotFoundException, ServiceNotAuthorizedException, ServiceNotEnabledException, ServiceMayNotContinueException {
-        return repositorySource.getRepositoryWithNameAtRootDirectory(name, rootGitDirectory);
+        try {
+            return repositorySource.getRepositoryWithNameAtRootDirectory(name, rootGitDirectory);
+        } catch (RepositoryNotFoundException e) {
+            e.printStackTrace();
+            throw e;
+        } catch (ServiceNotEnabledException e) {
+            e.printStackTrace();
+            throw e;
+        } catch (Throwable e) {
+            e.printStackTrace();
+            System.out.println("An exception occurred");
+            throw new ServiceNotEnabledException();
+        }
     }
 
     private void initRootGitDirectory(String rootGitDirectoryPath) throws InvalidRootDirectoryPathException {

+ 8 - 8
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/SnapshotFetcher.java

@@ -27,9 +27,10 @@ public class SnapshotFetcher {
         versions = new TreeSet<Integer>();
     }
 
-    public List<Snapshot> fetchNewSnapshots() throws FailedConnectionException, InvalidProjectException {
-        List<Snapshot> newSnapshots = new LinkedList<Snapshot>();
+    public SortedSet<Snapshot> fetchNewSnapshots() throws FailedConnectionException, InvalidProjectException {
+        SortedSet<Snapshot> newSnapshots = new TreeSet<Snapshot>();
         while (getNew(newSnapshots));
+        System.out.println("Snapshots fetched: " + newSnapshots);
         return newSnapshots;
     }
 
@@ -37,7 +38,7 @@ public class SnapshotFetcher {
         return snapshots.get(versions.last());
     }
 
-    private boolean getNew(List<Snapshot> newSnapshots) throws FailedConnectionException, InvalidProjectException {
+    private boolean getNew(SortedSet<Snapshot> newSnapshots) throws FailedConnectionException, InvalidProjectException {
         SnapshotGetDocRequest getDoc = new SnapshotGetDocRequest(projectName);
         SnapshotGetSavedVersRequest getSavedVers = new SnapshotGetSavedVersRequest(projectName);
 
@@ -87,16 +88,15 @@ public class SnapshotFetcher {
         return idsToUpdate;
     }
 
-    private boolean updateIDs(List<Integer> idsToUpdate, Map<Integer, SnapshotInfo> fetchedSnapshotInfos, List<Snapshot> newSnapshots) throws FailedConnectionException {
+    private boolean updateIDs(List<Integer> idsToUpdate, Map<Integer, SnapshotInfo> fetchedSnapshotInfos, SortedSet<Snapshot> newSnapshots) throws FailedConnectionException {
         if (idsToUpdate.isEmpty()) {
             return false;
         }
-        System.out.println("Fetching versions: " + idsToUpdate);
         fetchVersions(idsToUpdate, fetchedSnapshotInfos, newSnapshots);
         return true;
     }
 
-    private void fetchVersions(List<Integer> idsToUpdate, Map<Integer, SnapshotInfo> fetchedSnapshotInfos, List<Snapshot> newSnapshots) throws FailedConnectionException {
+    private void fetchVersions(List<Integer> idsToUpdate, Map<Integer, SnapshotInfo> fetchedSnapshotInfos, SortedSet<Snapshot> newSnapshots) throws FailedConnectionException {
         List<SnapshotGetForVersionRequest> requests = createFiredRequests(idsToUpdate);
         processResults(fetchedSnapshotInfos, newSnapshots, requests);
     }
@@ -111,13 +111,13 @@ public class SnapshotFetcher {
         return requests;
     }
 
-    private void processResults(Map<Integer, SnapshotInfo> fetchedSnapshotInfos, List<Snapshot> newSnapshots, List<SnapshotGetForVersionRequest> requests) throws FailedConnectionException {
+    private void processResults(Map<Integer, SnapshotInfo> fetchedSnapshotInfos, SortedSet<Snapshot> newSnapshots, List<SnapshotGetForVersionRequest> requests) throws FailedConnectionException {
         for (SnapshotGetForVersionRequest request : requests) {
             processResult(fetchedSnapshotInfos, newSnapshots, request);
         }
     }
 
-    private void processResult(Map<Integer, SnapshotInfo> fetchedSnapshotInfos, List<Snapshot> newSnapshots, SnapshotGetForVersionRequest request) throws FailedConnectionException {
+    private void processResult(Map<Integer, SnapshotInfo> fetchedSnapshotInfos, SortedSet<Snapshot> newSnapshots, SnapshotGetForVersionRequest request) throws FailedConnectionException {
         SnapshotGetForVersionResult result = request.getResult();
         SnapshotData data = result.getSnapshotData();
         Snapshot snapshot = new Snapshot(fetchedSnapshotInfos.get(request.getVersionID()), data);

+ 2 - 1
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/api/SnapshotDBAPI.java

@@ -1,5 +1,6 @@
 package uk.ac.ic.wlgitbridge.writelatex.api;
 
+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.getdoc.exception.InvalidProjectException;
 import uk.ac.ic.wlgitbridge.writelatex.model.Snapshot;
@@ -12,6 +13,6 @@ import java.util.List;
 public interface SnapshotDBAPI {
 
     public boolean repositoryExists(String name) throws FailedConnectionException;
-    public List<Snapshot> getSnapshotsToAddToProject(String name) throws FailedConnectionException, InvalidProjectException;
+    public List<WritableRepositoryContents> getWritableRepositories(String name) throws FailedConnectionException, InvalidProjectException;
 
 }

+ 16 - 9
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotAttachment.java

@@ -19,25 +19,28 @@ import java.util.concurrent.Future;
 public class SnapshotAttachment extends SnapshotFile {
 
     private Future<byte[]> future;
+    private String url;
 
     public SnapshotAttachment(JsonElement json) throws FailedConnectionException {
         super(json);
     }
 
     @Override
-    public byte[] getContents() throws FailedConnectionException {
-        try {
-            return future.get();
-        } catch (InterruptedException e) {
-            throw new FailedConnectionException();
-        } catch (ExecutionException e) {
-            throw new FailedConnectionException();
-        }
+    public byte[] getContents() {
+        return null;
+//        try {
+//            return future.get();
+//        } catch (InterruptedException e) {
+//            throw new FailedConnectionException();
+//        } catch (ExecutionException e) {
+//            throw new FailedConnectionException();
+//        }
     }
 
     @Override
     protected void getContentsFromJSON(JsonArray jsonArray) throws FailedConnectionException {
-        fetchContents(jsonArray.get(0).getAsString());
+        url = jsonArray.get(0).getAsString();
+//        fetchContents(jsonArray.get(0).getAsString());
     }
 
     private void fetchContents(String url) throws FailedConnectionException {
@@ -64,4 +67,8 @@ public class SnapshotAttachment extends SnapshotFile {
         }
     }
 
+    public String getUrl() {
+        return url;
+    }
+
 }

+ 1 - 10
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/api/request/getforversion/SnapshotFile.java

@@ -30,7 +30,7 @@ public class SnapshotFile implements JSONSource {
         getPathFromJSON(jsonArray);
     }
 
-    public byte[] getContents() throws FailedConnectionException {
+    public byte[] getContents() {
         return contents;
     }
 
@@ -46,13 +46,4 @@ public class SnapshotFile implements JSONSource {
         path = jsonArray.get(1).getAsString();
     }
 
-    public void writeToDisk(String repoDir) throws FailedConnectionException, IOException {
-        File file = new File(repoDir, path);
-        file.getParentFile().mkdirs();
-        file.createNewFile();
-        OutputStream out = new FileOutputStream(file);
-        out.write(getContents());
-        out.close();
-    }
-
 }

+ 0 - 25
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/FileIndexStore.java

@@ -1,25 +0,0 @@
-package uk.ac.ic.wlgitbridge.writelatex.filestore;
-
-import uk.ac.ic.wlgitbridge.writelatex.filestore.node.FileNode;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Created by Winston on 08/11/14.
- */
-public class FileIndexStore {
-
-    private final Map<BlobHash, FileNode> blobHashMappings;
-    private final Map<String, FileNode> urlMappings;
-
-    public FileIndexStore() {
-        blobHashMappings = new HashMap<BlobHash, FileNode>();
-        urlMappings = new HashMap<String, FileNode>();
-    }
-
-    public void addAttachment(String url, FileNode fileNode) {
-        urlMappings.put(url, fileNode);
-    }
-
-}

+ 52 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/GitDirectoryContents.java

@@ -0,0 +1,52 @@
+package uk.ac.ic.wlgitbridge.writelatex.filestore;
+
+import uk.ac.ic.wlgitbridge.bridge.WritableRepositoryContents;
+import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.FileNode;
+import uk.ac.ic.wlgitbridge.writelatex.model.Snapshot;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Created by Winston on 14/11/14.
+ */
+public class GitDirectoryContents implements WritableRepositoryContents {
+
+    private final List<FileNode> fileNodes;
+    private final String rootGitDirectoryPath;
+    private final String userName;
+    private final String userEmail;
+    private final String commitMessage;
+
+    public GitDirectoryContents(List<FileNode> fileNodes, String rootGitDirectoryPath, Snapshot snapshot) {
+        this.fileNodes = fileNodes;
+        this.rootGitDirectoryPath = rootGitDirectoryPath;
+        userName = snapshot.getUserName();
+        userEmail = snapshot.getUserEmail();
+        commitMessage = snapshot.getComment();
+    }
+
+    @Override
+    public void write() throws IOException, FailedConnectionException {
+        for (FileNode fileNode : fileNodes) {
+            fileNode.writeToDisk(rootGitDirectoryPath);
+        }
+    }
+
+    @Override
+    public String getUserName() {
+        return userName;
+    }
+
+    @Override
+    public String getUserEmail() {
+        return userEmail;
+    }
+
+    @Override
+    public String getCommitMessage() {
+        return commitMessage;
+    }
+
+}

+ 0 - 33
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/WLFileStore.java

@@ -1,33 +0,0 @@
-package uk.ac.ic.wlgitbridge.writelatex.filestore;
-
-import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
-import uk.ac.ic.wlgitbridge.writelatex.filestore.node.WLDirectoryNode;
-import uk.ac.ic.wlgitbridge.writelatex.model.WLProject;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Created by Winston on 08/11/14.
- */
-public class WLFileStore {
-
-    private final Map<String, WLDirectoryNode> fileStore;
-    private final String rootGitDirectoryPath;
-
-    public WLFileStore(String rootGitDirectoryPath) {
-        fileStore = new HashMap<String, WLDirectoryNode>();
-        this.rootGitDirectoryPath = rootGitDirectoryPath;
-    }
-
-    public void updateForProject(WLProject project) throws FailedConnectionException {
-        String projectName = project.getName();
-        WLDirectoryNode directoryNode = fileStore.get(projectName);
-        if (directoryNode == null) {
-            directoryNode = new WLDirectoryNode(rootGitDirectoryPath, projectName);
-            fileStore.put(projectName, directoryNode);
-        }
-        directoryNode.updateFromSnapshot(project.getLatestSnapshot());
-    }
-
-}

+ 15 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/blob/AttachmentBlob.java

@@ -0,0 +1,15 @@
+package uk.ac.ic.wlgitbridge.writelatex.filestore.blob;
+
+import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.FileNode;
+
+/**
+ * Created by Winston on 14/11/14.
+ */
+public class AttachmentBlob extends ByteBlob {
+
+    public AttachmentBlob(FileNode fileNode) throws FailedConnectionException {
+        super(fileNode.getContents());
+    }
+
+}

+ 12 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/blob/Blob.java

@@ -0,0 +1,12 @@
+package uk.ac.ic.wlgitbridge.writelatex.filestore.blob;
+
+import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
+
+/**
+ * Created by Winston on 14/11/14.
+ */
+public abstract class Blob {
+
+    public abstract byte[] getContents() throws FailedConnectionException;
+
+}

+ 19 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/blob/ByteBlob.java

@@ -0,0 +1,19 @@
+package uk.ac.ic.wlgitbridge.writelatex.filestore.blob;
+
+/**
+ * Created by Winston on 14/11/14.
+ */
+public abstract class ByteBlob extends Blob {
+
+    private final byte[] contents;
+
+    public ByteBlob(byte[] contents) {
+        this.contents = contents;
+    }
+
+    @Override
+    public byte[] getContents() {
+        return contents;
+    }
+
+}

+ 61 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/blob/ExternalBlob.java

@@ -0,0 +1,61 @@
+package uk.ac.ic.wlgitbridge.writelatex.filestore.blob;
+
+import com.ning.http.client.AsyncCompletionHandler;
+import com.ning.http.client.AsyncHttpClient;
+import com.ning.http.client.HttpResponseBodyPart;
+import com.ning.http.client.Response;
+import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/**
+ * Created by Winston on 14/11/14.
+ */
+public class ExternalBlob extends Blob {
+
+    private Future<byte[]> future;
+
+    public ExternalBlob(String url) throws FailedConnectionException {
+        super();
+        fetchContents(url);
+    }
+
+    @Override
+    public byte[] getContents() throws FailedConnectionException {
+        try {
+            return future.get();
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        } catch (ExecutionException e) {
+            throw new FailedConnectionException();
+        }
+    }
+
+    private void fetchContents(String url) throws FailedConnectionException {
+        AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
+        try {
+            future = asyncHttpClient.prepareGet(url).execute(new AsyncCompletionHandler<byte[]>() {
+
+                ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+
+                @Override
+                public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
+                    bytes.write(bodyPart.getBodyPartBytes());
+                    return STATE.CONTINUE;
+                }
+
+                @Override
+                public byte[] onCompleted(Response response) throws Exception {
+                    return bytes.toByteArray();
+                }
+
+            });
+        } catch (IOException e) {
+            throw new FailedConnectionException();
+        }
+    }
+
+}

+ 14 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/blob/SnapshotFileBlob.java

@@ -0,0 +1,14 @@
+package uk.ac.ic.wlgitbridge.writelatex.filestore.blob;
+
+import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotFile;
+
+/**
+ * Created by Winston on 14/11/14.
+ */
+public class SnapshotFileBlob extends ByteBlob {
+
+    public SnapshotFileBlob(SnapshotFile snapshotFile) {
+        super(snapshotFile.getContents());
+    }
+
+}

+ 28 - 3
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/AttachmentNode.java

@@ -2,7 +2,10 @@ package uk.ac.ic.wlgitbridge.writelatex.filestore.node;
 
 import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotAttachment;
-import uk.ac.ic.wlgitbridge.writelatex.filestore.FileIndexStore;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.blob.AttachmentBlob;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.store.FileIndexStore;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.blob.Blob;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.blob.ExternalBlob;
 
 import java.util.Map;
 
@@ -11,14 +14,36 @@ import java.util.Map;
  */
 public class AttachmentNode extends FileNode {
 
+    private final String url;
+    private Blob blob;
+
     public AttachmentNode(SnapshotAttachment snapshotAttachment, Map<String, FileNode> context, FileIndexStore fileIndexes) throws FailedConnectionException {
         super(snapshotAttachment, context);
+        url = snapshotAttachment.getUrl();
+        initBlob(fileIndexes);
+    }
 
+    @Override
+    public void handleIndexer(FileNodeIndexer fileNodeIndexer) {
+        fileNodeIndexer.index(this);
     }
 
     @Override
-    public byte[] initContents() {
-        return new byte[0];
+    protected Blob getBlob() {
+        return blob;
+    }
+
+    public String getURL() {
+        return url;
+    }
+
+    private void initBlob(FileIndexStore fileIndexes) throws FailedConnectionException {
+        if (fileIndexes.hasAttachmentWithURL(url)) {
+            FileNode attachment = fileIndexes.getAttachment(url);
+            blob = new AttachmentBlob(attachment);
+        } else {
+            blob = new ExternalBlob(url);
+        }
     }
 
 }

+ 11 - 5
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/BlobNode.java

@@ -2,7 +2,8 @@ package uk.ac.ic.wlgitbridge.writelatex.filestore.node;
 
 import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotFile;
-import uk.ac.ic.wlgitbridge.writelatex.filestore.FileIndexStore;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.blob.Blob;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.blob.SnapshotFileBlob;
 
 import java.util.Map;
 
@@ -11,16 +12,21 @@ import java.util.Map;
  */
 public class BlobNode extends FileNode {
 
-    private SnapshotFile snapshotFile;
+    private SnapshotFileBlob blob;
 
     public BlobNode(SnapshotFile snapshotFile, Map<String, FileNode> context) throws FailedConnectionException {
         super(snapshotFile, context);
-        this.snapshotFile = snapshotFile;
+        blob = new SnapshotFileBlob(snapshotFile);
     }
 
     @Override
-    public byte[] initContents() throws FailedConnectionException {
-        return snapshotFile.getContents();
+    public void handleIndexer(FileNodeIndexer fileNodeIndexer) {
+        fileNodeIndexer.index(this);
+    }
+
+    @Override
+    protected Blob getBlob() {
+        return blob;
     }
 
 }

+ 21 - 4
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/FileNode.java

@@ -2,8 +2,12 @@ package uk.ac.ic.wlgitbridge.writelatex.filestore.node;
 
 import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotFile;
-import uk.ac.ic.wlgitbridge.writelatex.filestore.FileIndexStore;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.blob.Blob;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
 import java.util.Map;
 
 /**
@@ -13,19 +17,32 @@ public abstract class FileNode {
 
     private final String filePath;
     private final boolean unchanged;
-    private byte[] contents;
 
     public FileNode(SnapshotFile snapshotFile, Map<String, FileNode> context) throws FailedConnectionException {
         filePath = snapshotFile.getPath();
         FileNode currentFileNode = context.get(filePath);
         unchanged = currentFileNode != null && equals(currentFileNode);
-        contents = initContents();
     }
 
     public String getFilePath() {
         return filePath;
     }
 
-    public abstract byte[] initContents() throws FailedConnectionException;
+    public byte[] getContents() throws FailedConnectionException {
+        return getBlob().getContents();
+    }
+
+    public void writeToDisk(String repoDir) throws FailedConnectionException, IOException {
+        File file = new File(repoDir, filePath);
+        file.getParentFile().mkdirs();
+        file.createNewFile();
+        OutputStream out = new FileOutputStream(file);
+        out.write(getContents());
+        out.close();
+    }
+
+    public abstract void handleIndexer(FileNodeIndexer fileNodeIndexer);
+
+    protected abstract Blob getBlob();
 
 }

+ 11 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/FileNodeIndexer.java

@@ -0,0 +1,11 @@
+package uk.ac.ic.wlgitbridge.writelatex.filestore.node;
+
+/**
+ * Created by Winston on 14/11/14.
+ */
+public interface FileNodeIndexer {
+
+    public void index(BlobNode blobNode);
+    public void index(AttachmentNode attachmentNode);
+
+}

+ 18 - 23
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/node/WLDirectoryNode.java

@@ -3,11 +3,11 @@ package uk.ac.ic.wlgitbridge.writelatex.filestore.node;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotAttachment;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotFile;
-import uk.ac.ic.wlgitbridge.writelatex.filestore.FileIndexStore;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.store.FileIndexStore;
 import uk.ac.ic.wlgitbridge.writelatex.model.Snapshot;
-import uk.ac.ic.wlgitbridge.writelatex.model.WLProject;
 
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
@@ -16,40 +16,35 @@ import java.util.Map;
  */
 public class WLDirectoryNode {
 
-    private Map<String, FileNode> files;
-    private FileIndexStore fileIndexes;
-    private final String rootGitDirectoryPath;
+    private Map<String, FileNode> fileNodeTable;
+    private FileIndexStore fileIndexStore;
 
-    public WLDirectoryNode(String rootGitDirectoryPath, String projectName) {
-        this.rootGitDirectoryPath = rootGitDirectoryPath;
-        files = new HashMap<String, FileNode>();
-        fileIndexes = new FileIndexStore();
+    public WLDirectoryNode() {
+        fileNodeTable = new HashMap<String, FileNode>();
+        fileIndexStore = new FileIndexStore();
     }
 
-    public void updateFromSnapshot(Snapshot snapshot) throws FailedConnectionException {
-        Map<String, FileNode> updatedFiles = new HashMap<String, FileNode>();
+    public List<FileNode> updateFromSnapshot(Snapshot snapshot) throws FailedConnectionException {
+        Map<String, FileNode> updatedFileNodeTable = new HashMap<String, FileNode>();
         List<SnapshotFile> srcs = snapshot.getSrcs();
         List<SnapshotAttachment> atts = snapshot.getAtts();
         for (SnapshotFile src : srcs) {
-            BlobNode blobNode = new BlobNode(src, files);
-            updatedFiles.put(blobNode.getFilePath(), blobNode);
+            BlobNode blobNode = new BlobNode(src, fileNodeTable);
+            updatedFileNodeTable.put(blobNode.getFilePath(), blobNode);
         }
         for (SnapshotAttachment att : atts) {
-            AttachmentNode attachmentNode = new AttachmentNode(att, files, fileIndexes);
-            updatedFiles.put(attachmentNode.getFilePath(), attachmentNode);
+            AttachmentNode attachmentNode = new AttachmentNode(att, fileNodeTable, fileIndexStore);
+            updatedFileNodeTable.put(attachmentNode.getFilePath(), attachmentNode);
         }
-        files = updatedFiles;
-        try {
-            throw new Throwable();
-        } catch (Throwable t) {
-            t.printStackTrace();
-        }
-        System.out.println(this);
+        fileNodeTable = updatedFileNodeTable;
+        LinkedList<FileNode> fileNodes = new LinkedList<FileNode>(updatedFileNodeTable.values());
+        fileIndexStore = new FileIndexStore(fileNodes);
+        return fileNodes;
     }
 
     @Override
     public String toString() {
-        return files.toString();
+        return fileNodeTable.toString();
     }
 
 }

+ 1 - 1
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/BlobHash.java → services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/store/BlobHash.java

@@ -1,4 +1,4 @@
-package uk.ac.ic.wlgitbridge.writelatex.filestore;
+package uk.ac.ic.wlgitbridge.writelatex.filestore.store;
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;

+ 51 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/store/FileIndexStore.java

@@ -0,0 +1,51 @@
+package uk.ac.ic.wlgitbridge.writelatex.filestore.store;
+
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.AttachmentNode;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.BlobNode;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.FileNode;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.FileNodeIndexer;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by Winston on 08/11/14.
+ */
+public class FileIndexStore implements FileNodeIndexer {
+
+    private final Map<BlobHash, FileNode> blobHashMappings;
+    private final Map<String, FileNode> urlMappings;
+
+    public FileIndexStore(List<FileNode> fileNodes) {
+        blobHashMappings = new HashMap<BlobHash, FileNode>();
+        urlMappings = new HashMap<String, FileNode>();
+        for (FileNode fileNode : fileNodes) {
+            fileNode.handleIndexer(this);
+        }
+    }
+
+    public FileIndexStore() {
+        this(new LinkedList<FileNode>());
+    }
+
+    @Override
+    public void index(BlobNode blobNode) {
+
+    }
+
+    @Override
+    public void index(AttachmentNode attachmentNode) {
+        urlMappings.put(attachmentNode.getURL(), attachmentNode);
+    }
+
+    public boolean hasAttachmentWithURL(String url) {
+        return urlMappings.containsKey(url);
+    }
+
+    public FileNode getAttachment(String url) {
+        return urlMappings.get(url);
+    }
+
+}

+ 49 - 0
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/filestore/store/WLFileStore.java

@@ -0,0 +1,49 @@
+package uk.ac.ic.wlgitbridge.writelatex.filestore.store;
+
+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.getdoc.exception.InvalidProjectException;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.GitDirectoryContents;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.node.WLDirectoryNode;
+import uk.ac.ic.wlgitbridge.writelatex.model.Snapshot;
+import uk.ac.ic.wlgitbridge.writelatex.model.WLProject;
+
+import java.util.*;
+
+/**
+ * Created by Winston on 08/11/14.
+ */
+public class WLFileStore {
+
+    private final Map<String, WLDirectoryNode> fileStore;
+    private final String rootGitDirectoryPath;
+
+    public WLFileStore(String rootGitDirectoryPath) {
+        fileStore = new HashMap<String, WLDirectoryNode>();
+        this.rootGitDirectoryPath = rootGitDirectoryPath;
+    }
+
+    public List<WritableRepositoryContents> updateForProject(WLProject project) throws FailedConnectionException,
+                                                                                       InvalidProjectException {
+        SortedSet<Snapshot> snapshots = project.fetchNewSnapshots();
+        String projectName = project.getName();
+        WLDirectoryNode directoryNode = getDirectoryNodeForProjectName(projectName);
+        List<WritableRepositoryContents> writableRepositories = new LinkedList<WritableRepositoryContents>();
+        for (Snapshot snapshot : snapshots) {
+            writableRepositories.add(new GitDirectoryContents(directoryNode.updateFromSnapshot(snapshot),
+                                                              rootGitDirectoryPath,
+                                                              snapshot));
+        }
+        return writableRepositories;
+    }
+
+    private WLDirectoryNode getDirectoryNodeForProjectName(String projectName) {
+        WLDirectoryNode directoryNode = fileStore.get(projectName);
+        if (directoryNode == null) {
+            directoryNode = new WLDirectoryNode();
+            fileStore.put(projectName, directoryNode);
+        }
+        return directoryNode;
+    }
+
+}

+ 11 - 12
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/Snapshot.java

@@ -1,19 +1,17 @@
 package uk.ac.ic.wlgitbridge.writelatex.model;
 
-import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionException;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotAttachment;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotData;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getforversion.SnapshotFile;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getsavedvers.SnapshotInfo;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getsavedvers.WLUser;
 
-import java.io.IOException;
 import java.util.List;
 
 /**
  * Created by Winston on 03/11/14.
  */
-public class Snapshot {
+public class Snapshot implements Comparable<Snapshot> {
 
     private final int versionID;
     private final String comment;
@@ -34,15 +32,6 @@ public class Snapshot {
         atts = data.getAtts();
     }
 
-    public void writeToDisk(String basePath) throws IOException, FailedConnectionException {
-        for (SnapshotFile file : srcs) {
-            file.writeToDisk(basePath);
-        }
-        for (SnapshotFile file : atts) {
-            file.writeToDisk(basePath);
-        }
-    }
-
     public int getVersionID() {
         return versionID;
     }
@@ -67,4 +56,14 @@ public class Snapshot {
         return atts;
     }
 
+    @Override
+    public int compareTo(Snapshot snapshot) {
+        return Integer.compare(versionID, snapshot.versionID);
+    }
+
+    @Override
+    public String toString() {
+        return String.valueOf(versionID);
+    }
+
 }

+ 9 - 6
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/WLDataModel.java

@@ -1,10 +1,11 @@
 package uk.ac.ic.wlgitbridge.writelatex.model;
 
+import uk.ac.ic.wlgitbridge.bridge.WritableRepositoryContents;
 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.getdoc.SnapshotGetDocRequest;
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException;
-import uk.ac.ic.wlgitbridge.writelatex.filestore.WLFileStore;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.store.WLFileStore;
 
 import java.util.HashMap;
 import java.util.List;
@@ -36,11 +37,15 @@ public class WLDataModel implements SnapshotDBAPI {
     }
 
     @Override
-    public List<Snapshot> getSnapshotsToAddToProject(String name) throws FailedConnectionException, InvalidProjectException {
+    public List<WritableRepositoryContents> getWritableRepositories(String name) throws FailedConnectionException, InvalidProjectException {
         return updateProjectWithName(name);
     }
 
-    private List<Snapshot> updateProjectWithName(String name) throws FailedConnectionException, InvalidProjectException {
+    private List<WritableRepositoryContents> updateProjectWithName(String name) throws FailedConnectionException, InvalidProjectException {
+        return fileStore.updateForProject(getProjectWithName(name));
+    }
+
+    private WLProject getProjectWithName(String name) {
         WLProject project;
         if (projects.containsKey(name)) {
             project = projects.get(name);
@@ -48,9 +53,7 @@ public class WLDataModel implements SnapshotDBAPI {
             project = new WLProject(name);
             projects.put(name, project);
         }
-        List<Snapshot> newSnapshots = project.fetchNewSnapshots();
-        fileStore.updateForProject(project);
-        return newSnapshots;
+        return project;
     }
 
 }

+ 3 - 3
services/git-bridge/src/uk/ac/ic/wlgitbridge/writelatex/model/WLProject.java

@@ -5,8 +5,8 @@ import uk.ac.ic.wlgitbridge.writelatex.api.request.exception.FailedConnectionExc
 import uk.ac.ic.wlgitbridge.writelatex.api.request.getdoc.exception.InvalidProjectException;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
+import java.util.SortedSet;
 
 /**
  * Created by Winston on 06/11/14.
@@ -25,8 +25,8 @@ public class WLProject {
         snapshotFetcher = new SnapshotFetcher(name, snapshots);
     }
 
-    public List<Snapshot> fetchNewSnapshots() throws FailedConnectionException, InvalidProjectException {
-        List<Snapshot> newSnapshots = snapshotFetcher.fetchNewSnapshots();
+    public SortedSet<Snapshot> fetchNewSnapshots() throws FailedConnectionException, InvalidProjectException {
+        SortedSet<Snapshot> newSnapshots = snapshotFetcher.fetchNewSnapshots();
         latestSnapshot = snapshotFetcher.getLatestSnapshot();
         return newSnapshots;
     }

+ 1 - 0
services/git-bridge/test/uk/ac/ic/wlgitbridge/writelatex/filestore/BlobHashTest.java

@@ -1,6 +1,7 @@
 package uk.ac.ic.wlgitbridge.writelatex.filestore;
 
 import org.junit.Test;
+import uk.ac.ic.wlgitbridge.writelatex.filestore.store.BlobHash;
 
 public class BlobHashTest {