|
@@ -1,6 +1,7 @@
|
|
|
package uk.ac.ic.wlgitbridge.bridge.repo;
|
|
package uk.ac.ic.wlgitbridge.bridge.repo;
|
|
|
|
|
|
|
|
import com.google.common.base.Preconditions;
|
|
import com.google.common.base.Preconditions;
|
|
|
|
|
+import org.apache.commons.io.IOUtils;
|
|
|
import org.eclipse.jgit.api.Git;
|
|
import org.eclipse.jgit.api.Git;
|
|
|
import org.eclipse.jgit.api.ResetCommand;
|
|
import org.eclipse.jgit.api.ResetCommand;
|
|
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
|
@@ -10,7 +11,6 @@ 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.RawFile;
|
|
|
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
|
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
|
|
|
-import uk.ac.ic.wlgitbridge.git.exception.SizeLimitExceededException;
|
|
|
|
|
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;
|
|
|
import uk.ac.ic.wlgitbridge.util.Project;
|
|
import uk.ac.ic.wlgitbridge.util.Project;
|
|
@@ -18,10 +18,25 @@ import uk.ac.ic.wlgitbridge.util.Util;
|
|
|
|
|
|
|
|
import java.io.File;
|
|
import java.io.File;
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
|
|
+import java.nio.file.FileVisitResult;
|
|
|
|
|
+import java.nio.file.FileVisitor;
|
|
|
|
|
+import java.nio.file.Files;
|
|
|
|
|
+import java.nio.file.Path;
|
|
|
|
|
+import java.nio.file.attribute.BasicFileAttributes;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Created by winston on 20/08/2016.
|
|
|
|
|
|
|
+ * Class representing a Git repository.
|
|
|
|
|
+ *
|
|
|
|
|
+ * It stores the projectName and repo separately because the hooks need to be
|
|
|
|
|
+ * able to construct one of these without knowing whether the repo exists yet.
|
|
|
|
|
+ *
|
|
|
|
|
+ * It can then be passed to the Bridge, which will either
|
|
|
|
|
+ * {@link #initRepo(RepoStore)} for a never-seen-before repo, or
|
|
|
|
|
+ * {@link #useExistingRepository(RepoStore)} for an existing repo.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Make sure to acquire the project lock before calling methods here.
|
|
|
*/
|
|
*/
|
|
|
public class GitProjectRepo implements ProjectRepo {
|
|
public class GitProjectRepo implements ProjectRepo {
|
|
|
|
|
|
|
@@ -81,6 +96,100 @@ public class GitProjectRepo implements ProjectRepo {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void runGC() throws IOException {
|
|
|
|
|
+ Preconditions.checkState(
|
|
|
|
|
+ repository.isPresent(),
|
|
|
|
|
+ "Repo is not present"
|
|
|
|
|
+ );
|
|
|
|
|
+ File dir = getProjectDir();
|
|
|
|
|
+ Preconditions.checkState(dir.isDirectory());
|
|
|
|
|
+ Log.info("[{}] Running git gc", projectName);
|
|
|
|
|
+ Process proc = new ProcessBuilder(
|
|
|
|
|
+ "git", "gc"
|
|
|
|
|
+ ).directory(dir).start();
|
|
|
|
|
+ int exitCode;
|
|
|
|
|
+ try {
|
|
|
|
|
+ exitCode = proc.waitFor();
|
|
|
|
|
+ Log.info("Exit: {}", exitCode);
|
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
|
+ throw new RuntimeException(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (exitCode != 0) {
|
|
|
|
|
+ Log.warn("[{}] Git gc failed", dir.getAbsolutePath());
|
|
|
|
|
+ Log.warn(IOUtils.toString(
|
|
|
|
|
+ proc.getInputStream(),
|
|
|
|
|
+ StandardCharsets.UTF_8
|
|
|
|
|
+ ));
|
|
|
|
|
+ Log.warn(IOUtils.toString(
|
|
|
|
|
+ proc.getErrorStream(),
|
|
|
|
|
+ StandardCharsets.UTF_8
|
|
|
|
|
+ ));
|
|
|
|
|
+ throw new IOException("git gc error");
|
|
|
|
|
+ }
|
|
|
|
|
+ Log.info("[{}] git gc successful", projectName);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void deleteIncomingPacks() throws IOException {
|
|
|
|
|
+ Log.info(
|
|
|
|
|
+ "[{}] Checking for garbage `incoming` files",
|
|
|
|
|
+ projectName
|
|
|
|
|
+ );
|
|
|
|
|
+ Files.walkFileTree(getDotGitDir().toPath(), new FileVisitor<Path>() {
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public FileVisitResult preVisitDirectory(
|
|
|
|
|
+ Path dir,
|
|
|
|
|
+ BasicFileAttributes attrs
|
|
|
|
|
+ ) throws IOException {
|
|
|
|
|
+ return FileVisitResult.CONTINUE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public FileVisitResult visitFile(
|
|
|
|
|
+ Path file,
|
|
|
|
|
+ BasicFileAttributes attrs
|
|
|
|
|
+ ) throws IOException {
|
|
|
|
|
+ File file_ = file.toFile();
|
|
|
|
|
+ String name = file_.getName();
|
|
|
|
|
+ if (name.startsWith("incoming_") && name.endsWith(".pack")) {
|
|
|
|
|
+ Log.info("Deleting garbage `incoming` file: {}", file_);
|
|
|
|
|
+ Preconditions.checkState(file_.delete());
|
|
|
|
|
+ }
|
|
|
|
|
+ return FileVisitResult.CONTINUE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public FileVisitResult visitFileFailed(
|
|
|
|
|
+ Path file,
|
|
|
|
|
+ IOException exc
|
|
|
|
|
+ ) throws IOException {
|
|
|
|
|
+ Preconditions.checkNotNull(file);
|
|
|
|
|
+ Preconditions.checkNotNull(exc);
|
|
|
|
|
+ Log.warn("Failed to visit file: " + file, exc);
|
|
|
|
|
+ return FileVisitResult.TERMINATE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public FileVisitResult postVisitDirectory(
|
|
|
|
|
+ Path dir,
|
|
|
|
|
+ IOException exc
|
|
|
|
|
+ ) throws IOException {
|
|
|
|
|
+ Preconditions.checkNotNull(dir);
|
|
|
|
|
+ if (exc != null) {
|
|
|
|
|
+ return FileVisitResult.TERMINATE;
|
|
|
|
|
+ }
|
|
|
|
|
+ return FileVisitResult.CONTINUE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public File getProjectDir() {
|
|
|
|
|
+ return getJGitRepository().getDirectory().getParentFile();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public void resetHard() throws IOException {
|
|
public void resetHard() throws IOException {
|
|
|
Git git = new Git(getJGitRepository());
|
|
Git git = new Git(getJGitRepository());
|
|
|
try {
|
|
try {
|
|
@@ -94,7 +203,7 @@ public class GitProjectRepo implements ProjectRepo {
|
|
|
return repository.get();
|
|
return repository.get();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public File getDirectory() {
|
|
|
|
|
|
|
+ public File getDotGitDir() {
|
|
|
return getJGitRepository().getWorkTree();
|
|
return getJGitRepository().getWorkTree();
|
|
|
}
|
|
}
|
|
|
|
|
|