InitGitDBRepo: refactored

This commit is contained in:
Paul Campbell 2018-07-19 17:26:45 +01:00
parent a2c97b6170
commit 297a952f43
2 changed files with 73 additions and 43 deletions

View file

@ -23,6 +23,7 @@ package net.kemitix.gitdb.impl;
import net.kemitix.gitdb.FormatVersion; import net.kemitix.gitdb.FormatVersion;
import net.kemitix.mon.result.Result; import net.kemitix.mon.result.Result;
import net.kemitix.mon.result.WithResultContinuation;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache; import org.eclipse.jgit.lib.RepositoryCache;
@ -31,13 +32,16 @@ import org.eclipse.jgit.util.FS;
import java.io.File; import java.io.File;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.*; import java.nio.file.*;
import java.util.concurrent.Callable;
import static net.kemitix.conditional.Condition.where;
/** /**
* Initialise a new GitDB Repo. * Initialise a new GitDB Repo.
* *
* @author Paul Campbell (pcampbell@kemitix.net) * @author Paul Campbell (pcampbell@kemitix.net)
*/ */
class InitGitDBRepo { final class InitGitDBRepo {
private static final String INIT_MESSAGE = "Initialise GitDB v1"; private static final String INIT_MESSAGE = "Initialise GitDB v1";
private static final String INIT_USER = "GitDB"; private static final String INIT_USER = "GitDB";
@ -46,6 +50,10 @@ class InitGitDBRepo {
private static final String GIT_DB_VERSION = "GitDB.Version"; private static final String GIT_DB_VERSION = "GitDB.Version";
private static final String REFS_HEADS_FORMAT = "refs/heads/%s"; private static final String REFS_HEADS_FORMAT = "refs/heads/%s";
private InitGitDBRepo() {
throw new UnsupportedOperationException();
}
/** /**
* Initialise a new GitDB repo. * Initialise a new GitDB repo.
* *
@ -53,69 +61,73 @@ class InitGitDBRepo {
* @return a Result containing the created Repository * @return a Result containing the created Repository
*/ */
static Result<Repository> create(final Path dbDir) { static Result<Repository> create(final Path dbDir) {
final InitGitDBRepo initRepo = new InitGitDBRepo(); return validDbDir(dbDir.toFile())
return initRepo.validDbDir(dbDir.toFile())
.peek(File::mkdirs) .peek(File::mkdirs)
.map(dir -> RepositoryCache.FileKey.exact(dir, FS.DETECTED)) .map(InitGitDBRepo::exactDirectory)
.andThen(fileKey -> () -> fileKey.open(false)) .andThen(InitGitDBRepo::openRepository)
.thenWith(repository -> () -> repository.create(true)) .thenWith(InitGitDBRepo::createRepoDirectory)
.thenWith(repository -> () -> initRepo.createInitialBranchOnMaster(repository)); .thenWith(InitGitDBRepo::createInitialMasterBranch);
} }
private Result<File> validDbDir(final File dbDir) { private static Result<File> validDbDir(final File dbDir) {
return Result.ok(dbDir) return Result.ok(dbDir)
.flatMap(this::verifyIsNotAFile) .flatMap(InitGitDBRepo::isNotAFile)
.flatMap(this::isEmptyIfExists); .flatMap(InitGitDBRepo::ifExistsThenIsEmpty);
} }
private Result<Void> createInitialBranchOnMaster(final Repository repository) { private static Result<File> isNotAFile(final File dbDir) {
final GitDBRepo repo = new GitDBRepo(repository); return Result.ok(dbDir)
return new ValueWriter(repository) .thenWith(dir -> () -> where(dir.isFile()).thenThrow(new NotDirectoryException(dbDir.toString())));
.write(new FormatVersion().toBytes())
.flatMap(oid -> repo.insertNewTree(GIT_DB_VERSION, oid))
.flatMap(tid -> repo.initialCommit(tid, INIT_MESSAGE, INIT_USER, INIT_EMAIL))
.flatMap(cid -> Result.of(() -> {
createBranch(repository, cid, MASTER);
return null;
}));
} }
private Result<File> verifyIsNotAFile(final File dbDir) { private static Result<File> ifExistsThenIsEmpty(final File dbDir) {
if (dbDir.isFile()) { return Result.ok(dbDir)
return Result.error(new NotDirectoryException(dbDir.toString())); .thenWith(dir -> () -> {
} if (dir.exists()) {
return Result.ok(dbDir);
}
private Result<File> isEmptyIfExists(final File dbDir) {
if (dbDir.exists()) {
return Result.of(() -> {
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(dbDir.toPath())) { try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(dbDir.toPath())) {
if (directoryStream.iterator().hasNext()) { where(directoryStream.iterator().hasNext())
throw new DirectoryNotEmptyException(dbDir.toString()); .thenThrow(new DirectoryNotEmptyException(dbDir.toString()));
}
} }
return dbDir;
} }
); });
}
return Result.ok(dbDir);
} }
private Result<Void> createBranch( private static RepositoryCache.FileKey exactDirectory(final File dir) {
return RepositoryCache.FileKey.exact(dir, FS.DETECTED);
}
private static Callable<Repository> openRepository(final RepositoryCache.FileKey fileKey) {
return () -> fileKey.open(false);
}
private static WithResultContinuation<Repository> createRepoDirectory(final Repository repository) {
return () -> repository.create(true);
}
private static WithResultContinuation<Repository> createInitialMasterBranch(
final Repository repository
) {
return () -> {
final GitDBRepo repo = new GitDBRepo(repository);
new ValueWriter(repository)
.write(new FormatVersion().toBytes())
.flatMap(oid -> repo.insertNewTree(GIT_DB_VERSION, oid))
.flatMap(tid -> repo.initialCommit(tid, INIT_MESSAGE, INIT_USER, INIT_EMAIL))
.flatMap(cid -> createBranch(repository, cid, MASTER));
};
}
private static Result<Path> createBranch(
final Repository repository, final Repository repository,
final ObjectId commitId, final ObjectId commitId,
final String branchName final String branchName
) { ) {
final Path branchRefPath = branchRefPath(repository, branchName); final Path branchRefPath = branchRefPath(repository, branchName);
final byte[] commitIdBytes = commitId.name().getBytes(StandardCharsets.UTF_8); final byte[] commitIdBytes = commitId.name().getBytes(StandardCharsets.UTF_8);
return Result.of(() -> { return Result.of(() -> Files.write(branchRefPath, commitIdBytes));
Files.write(branchRefPath, commitIdBytes);
return null;
});
} }
private Path branchRefPath( private static Path branchRefPath(
final Repository repository, final Repository repository,
final String branchName final String branchName
) { ) {

View file

@ -0,0 +1,18 @@
package net.kemitix.gitdb.impl;
import org.assertj.core.api.WithAssertions;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Constructor;
class InitGitDBRepoTest implements WithAssertions {
@Test
void utilityClassCannotBeInstantiated() throws NoSuchMethodException {
final Constructor<InitGitDBRepo> constructor = InitGitDBRepo.class.getDeclaredConstructor();
constructor.setAccessible(true);
assertThatCode(constructor::newInstance)
.hasCauseInstanceOf(UnsupportedOperationException.class);
}
}