Start redefining GitDB interface with a new test plan
This commit is contained in:
parent
fe81c6a67a
commit
a88763958c
3 changed files with 294 additions and 113 deletions
|
@ -1,33 +1,64 @@
|
||||||
package net.kemitix.gitdb;
|
package net.kemitix.gitdb;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.api.Git;
|
||||||
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public interface GitDB {
|
public interface GitDB extends Closeable {
|
||||||
|
|
||||||
static GitDB local(Path dbDir) {
|
/**
|
||||||
return new GitDBLocal(dbDir);
|
* Open an existing local gitdb.
|
||||||
|
*
|
||||||
|
* @param dbDir the path to the local repo
|
||||||
|
* @return a GitDB instance for the local gitdb
|
||||||
|
*/
|
||||||
|
static GitDB local(final Path dbDir) throws IOException {
|
||||||
|
return new GitDBLocal(Git.open(dbDir.toFile()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void close();
|
/**
|
||||||
|
* Initialise a new local gitdb.
|
||||||
String get(Branch branch, Key key);
|
*
|
||||||
|
* @param dbDir the path to initialise the local repo in
|
||||||
<T> T get(Branch branch, Key key, Class<T> type);
|
* @return a GitDB instance for the created local gitdb
|
||||||
|
*/
|
||||||
Stream<String> getFiles(Branch branch, Key key);
|
static GitDB initLocal(final Path dbDir) throws GitAPIException {
|
||||||
|
return new GitDBLocal(Git.init()
|
||||||
<T> Stream<T> getFiles(Branch branch, Key key, Class<T> type);
|
.setGitDir(dbDir.toFile())
|
||||||
|
.setBare(true)
|
||||||
String save(Branch branch, Message message, Document<String> document, Author author);
|
.call());
|
||||||
|
}
|
||||||
String delete(Branch branch, Key key, Message message, Author author);
|
|
||||||
|
/**
|
||||||
void tag(Reference reference);
|
* Select a branch.
|
||||||
|
*
|
||||||
void createBranch(Reference reference);
|
* @param branch the branch to select
|
||||||
|
* @return a branch within the gitdb
|
||||||
Stream<String> getAllBranches();
|
*/
|
||||||
|
GitDbBranch branch(Branch branch);
|
||||||
Transaction createTransaction(Branch branch);
|
|
||||||
|
interface GitDbBranch {
|
||||||
|
|
||||||
|
// String get(Key key);
|
||||||
|
//
|
||||||
|
// <T> T get(Key key, Class<T> type);
|
||||||
|
//
|
||||||
|
// Key put(Message message, Document<String> document, Author author);
|
||||||
|
//
|
||||||
|
// GitDbBranch delete(Branch branch, Key key, Message message, Author author);
|
||||||
|
//
|
||||||
|
// GitDbBranch tag(Reference reference);
|
||||||
|
//
|
||||||
|
// Transaction startTransaction(Branch branch);
|
||||||
|
//
|
||||||
|
// GitDbBranch fork(Branch branch);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<Branch> allBranches();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,101 +1,182 @@
|
||||||
package net.kemitix.gitdb;
|
package net.kemitix.gitdb;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.eclipse.jgit.api.Git;
|
import org.eclipse.jgit.api.Git;
|
||||||
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||||
import org.eclipse.jgit.lib.*;
|
import org.eclipse.jgit.lib.*;
|
||||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
class GitDBLocal implements GitDB {
|
class GitDBLocal implements GitDB {
|
||||||
|
|
||||||
private final Repository repository;
|
private final Git git;
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
GitDBLocal(final Path gitDir) {
|
|
||||||
this.repository = openRepo(gitDir)
|
|
||||||
.orElseGet(() -> initRepo(gitDir));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private Repository initRepo(Path gitDir) {
|
|
||||||
return Git.init()
|
|
||||||
.setGitDir(gitDir.toFile())
|
|
||||||
.setBare(true)
|
|
||||||
.call()
|
|
||||||
.getRepository();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<Repository> openRepo(final Path gitDir) throws IOException {
|
|
||||||
final Repository build = new FileRepositoryBuilder()
|
|
||||||
.setBare()
|
|
||||||
.setMustExist(false)
|
|
||||||
.setGitDir(gitDir.toFile())
|
|
||||||
.setup()
|
|
||||||
.build();
|
|
||||||
if (build.getObjectDatabase().exists()) {
|
|
||||||
return Optional.of(build);
|
|
||||||
} else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
repository.close();
|
git.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String get(Branch branch, Key key) {
|
public GitDbBranch branch(Branch branch) {
|
||||||
return get(branch, key, String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T get(Branch branch, Key key, Class<T> type) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stream<String> getFiles(Branch branch, Key key) {
|
public Stream<Branch> allBranches() {
|
||||||
return getFiles(branch, key, String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> Stream<T> getFiles(Branch branch, Key key, Class<T> type) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// @Override
|
||||||
public String save(Branch branch, Message message, Document<String> document, Author author) {
|
// public String get(Branch branch, Key key) {
|
||||||
return document.getValue();
|
// return get(branch, key, String.class);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// @SneakyThrows
|
||||||
|
// public <T> T get(Branch branch, Key key, Class<T> type) {
|
||||||
|
//branch
|
||||||
|
// final RefDatabase refDatabase = repository.getRefDatabase();
|
||||||
|
// final String branchValue = branch.getValue();
|
||||||
|
// final Ref refDatabaseRef = refDatabase.getRef(branchValue);
|
||||||
|
// final ObjectId commitId = refDatabaseRef.getObjectId();
|
||||||
|
//
|
||||||
|
// final RevCommit revCommit = repository.parseCommit(commitId);
|
||||||
|
// final RevTree tree = revCommit.getTree();
|
||||||
|
// tree.copyTo(System.out);
|
||||||
|
//
|
||||||
|
// final ObjectLoader open = repository.getObjectDatabase().open(objectId, Constants.OBJ_TREE);
|
||||||
|
// final byte[] bytes = open.getBytes();
|
||||||
|
// final String s = new String(bytes);
|
||||||
|
// System.out.println("s = " + s);
|
||||||
|
// //key
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
@Override
|
// @Override
|
||||||
public String delete(Branch branch, Key key, Message message, Author author) {
|
// @SneakyThrows
|
||||||
return null;
|
// public String put(Branch branch, Message message, Document<String> document, Author author) {
|
||||||
}
|
//// return document.getValue();
|
||||||
|
//
|
||||||
|
// final ObjectInserter objectInserter = repository.newObjectInserter();
|
||||||
|
// final ObjectReader objectReader = repository.newObjectReader();
|
||||||
|
// final RevWalk revWalk = new RevWalk(repository);
|
||||||
|
//
|
||||||
|
// //blob
|
||||||
|
// System.out.println("document = " + document.getKey());
|
||||||
|
// final ObjectId blobId = objectInserter.insert(Constants.OBJ_BLOB, document.getValue().getBytes(UTF_8));
|
||||||
|
// //tree
|
||||||
|
// final TreeFormatter treeFormatter = new TreeFormatter();
|
||||||
|
// treeFormatter.append(document.getKey().getValue(), FileMode.REGULAR_FILE, blobId);
|
||||||
|
// final ObjectId treeId = objectInserter.insert(treeFormatter);
|
||||||
|
// //commit
|
||||||
|
// final CommitBuilder commitBuilder = new CommitBuilder();
|
||||||
|
// final PersonIdent ident = new PersonIdent(author.getName(), author.getEmail());
|
||||||
|
// commitBuilder.setCommitter(ident);
|
||||||
|
// commitBuilder.setAuthor(ident);
|
||||||
|
// commitBuilder.setTreeId(treeId);
|
||||||
|
// commitBuilder.setMessage(message.getValue());
|
||||||
|
// //TODO: setParentId()
|
||||||
|
// final ObjectId commitId = objectInserter.insert(commitBuilder);
|
||||||
|
// //branch
|
||||||
|
// final RevCommit revCommit = revWalk.parseCommit(commitId);
|
||||||
|
// revCommit.getShortMessage();
|
||||||
|
// git.branchCreate()
|
||||||
|
// .setStartPoint(revCommit)
|
||||||
|
// .setName(branch.getValue())
|
||||||
|
// .setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.NOTRACK)
|
||||||
|
// .call();
|
||||||
|
//
|
||||||
|
// //READ
|
||||||
|
//
|
||||||
|
// //block
|
||||||
|
// final String readBlob = new String(objectReader.open(blobId).getBytes());
|
||||||
|
// System.out.println("readBlob = " + readBlob);
|
||||||
|
// final RevBlob revBlob = revWalk.lookupBlob(blobId);
|
||||||
|
// System.out.println("revBlob = " + revBlob);
|
||||||
|
// final String blobName = revBlob.name();
|
||||||
|
// System.out.println("blobName = " + blobName);
|
||||||
|
// //tree
|
||||||
|
// final RevTree revTree = revWalk.lookupTree(treeId);
|
||||||
|
// System.out.println("revTree = " + revTree);
|
||||||
|
// final String treeName = revTree.name();
|
||||||
|
// System.out.println("treeName = " + treeName);
|
||||||
|
// //commit
|
||||||
|
// System.out.println("revCommit= " + revCommit);
|
||||||
|
// final String commitName = revCommit.getName();
|
||||||
|
// System.out.println("commitName= " + commitName);
|
||||||
|
// //branch
|
||||||
|
// final Ref branchRef = repository.getRefDatabase().getRef(branch.getValue());
|
||||||
|
// System.out.println("branchRef = " + branchRef.getName());
|
||||||
|
//
|
||||||
|
//// final TreeWalk treeWalk = new TreeWalk(repository);
|
||||||
|
//// treeWalk.addTree(treeId);
|
||||||
|
//// treeWalk.next();
|
||||||
|
//// final String nameString = treeWalk.getNameString();
|
||||||
|
//// System.out.println("name = " + nameString);
|
||||||
|
//// final ObjectId objectId = treeWalk.getObjectId(0);
|
||||||
|
//// System.out.println("objectId = " + objectId);
|
||||||
|
//
|
||||||
|
//// final ObjectLoader openTree = repository.newObjectReader().open(treeId);
|
||||||
|
//// final int type = openTree.openStream().getType();
|
||||||
|
//// final long size = openTree.openStream().getSize();
|
||||||
|
//// final String readTree = new String(openTree.getBytes());
|
||||||
|
//
|
||||||
|
////
|
||||||
|
//// //commit
|
||||||
|
//// final CommitBuilder commitBuilder = new CommitBuilder();
|
||||||
|
//// commitBuilder.setAuthor(new PersonIdent(author.getName(), author.getEmail()));
|
||||||
|
//// commitBuilder.setCommitter(new PersonIdent(author.getName(), author.getEmail()));
|
||||||
|
//// commitBuilder.setMessage(message.getValue());
|
||||||
|
//// findParentCommit(branch)
|
||||||
|
//// .ifPresent(commitBuilder::setParentId);
|
||||||
|
//// commitBuilder.setTreeId(treeId);
|
||||||
|
//// final ObjectId commitId = repository.newObjectInserter().insert(commitBuilder);
|
||||||
|
////
|
||||||
|
//// //branch
|
||||||
|
//// repository.updateRef(branch.getValue()).setNewObjectId(commitId);
|
||||||
|
////
|
||||||
|
//// //get
|
||||||
|
//// return get(branch, document.getKey());
|
||||||
|
// return document.getValue();
|
||||||
|
// }
|
||||||
|
|
||||||
@Override
|
// @SneakyThrows
|
||||||
public void tag(Reference reference) {
|
// private Optional<ObjectId> findParentCommit(final Branch branch) {
|
||||||
|
// return Optional.ofNullable(
|
||||||
}
|
// repository.getRefDatabase()
|
||||||
|
// .getRef(branch.getValue()))
|
||||||
@Override
|
// .map(Ref::getObjectId);
|
||||||
public void createBranch(Reference reference) {
|
// }
|
||||||
|
|
||||||
}
|
// @Override
|
||||||
|
// public String delete(Branch branch, Key key, Message message, Author author) {
|
||||||
@Override
|
// return null;
|
||||||
public Stream<String> getAllBranches() {
|
// }
|
||||||
return null;
|
//
|
||||||
}
|
// @Override
|
||||||
|
// public void tag(Reference reference) {
|
||||||
@Override
|
//
|
||||||
public Transaction createTransaction(Branch branch) {
|
// }
|
||||||
return null;
|
//
|
||||||
}
|
// @Override
|
||||||
|
// public void createBranch(Reference reference) {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Stream<String> getAllBranches() {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Transaction createTransaction(Branch branch) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,39 @@
|
||||||
package net.kemitix.gitdb;
|
package net.kemitix.gitdb;
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.DirectoryStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
class GitDBTest {
|
class GitDBTest {
|
||||||
|
|
||||||
private final Path dbDir = Files.createTempDirectory("gitdb");
|
|
||||||
private final GitDB gitDB = GitDB.local(dbDir);
|
|
||||||
private final Branch master = Branch.name("master");
|
private final Branch master = Branch.name("master");
|
||||||
private final Message message = Message.message(UUID.randomUUID().toString());
|
private final Message message = Message.message(UUID.randomUUID().toString());
|
||||||
private final Key key = Key.name(UUID.randomUUID().toString());
|
private final Key key = Key.name(UUID.randomUUID().toString());
|
||||||
private final Author author = Author.name("junit", "gitdb@kemitix.net");
|
private final Author author = Author.name("junit", "gitdb@kemitix.net");
|
||||||
|
|
||||||
GitDBTest() throws IOException {
|
// When initialising a repo in a dir that doesn't exist then a bare repo is created
|
||||||
|
@Test
|
||||||
|
void initRepo_whenDirNotExist_thenCreateBareRepo() throws IOException, GitAPIException {
|
||||||
|
//given
|
||||||
|
final Path dir = dirDoesNotExist();
|
||||||
|
//when
|
||||||
|
final GitDB gitdb = GitDB.initLocal(dir);
|
||||||
|
//then
|
||||||
|
assertThat(gitdb).isNotNull();
|
||||||
|
assertThatIsBareRepo(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
private void assertThatIsBareRepo(final Path dbDir) throws IOException {
|
||||||
void shouldInitialiseGitDB() throws IOException {
|
final DirectoryStream<Path> paths = Files.newDirectoryStream(dbDir);
|
||||||
//then
|
assertThat(paths.iterator())
|
||||||
assertThat(gitDB).isNotNull();
|
|
||||||
assertThat(Files.isDirectory(dbDir)).isTrue();
|
|
||||||
assertThat(Files.newDirectoryStream(dbDir).iterator())
|
|
||||||
.contains(
|
.contains(
|
||||||
dbDir.resolve("branches"),
|
dbDir.resolve("branches"),
|
||||||
dbDir.resolve("HEAD"),
|
dbDir.resolve("HEAD"),
|
||||||
|
@ -37,25 +43,88 @@ class GitDBTest {
|
||||||
dbDir.resolve("hooks"),
|
dbDir.resolve("hooks"),
|
||||||
dbDir.resolve("objects")
|
dbDir.resolve("objects")
|
||||||
);
|
);
|
||||||
|
final List<String> config = Files.readAllLines(dbDir.resolve("config"));
|
||||||
|
assertThat(config).contains("\tbare = true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Path dirDoesNotExist() throws IOException {
|
||||||
|
return Files.createTempDirectory("gitdb");
|
||||||
|
}
|
||||||
|
|
||||||
|
// When initialising a repo in a dir that is a file then an exception is thrown
|
||||||
@Test
|
@Test
|
||||||
void saveDocumentGivesSavedValue() {
|
void initRepo_whenDirIsFile_thenThrowException() {
|
||||||
//given
|
|
||||||
final String value = UUID.randomUUID().toString();
|
|
||||||
final Document<String> document = Document.create(key, value);
|
|
||||||
//when
|
|
||||||
final String result = gitDB.save(master, message, document, author);
|
|
||||||
//then
|
|
||||||
assertThat(result).isEqualTo(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
// When initialising a repo in a dir is exists then an exception is thrown
|
||||||
void tearDown() throws IOException {
|
@Test
|
||||||
gitDB.close();
|
void initRepo_whenDirExists_thenThrowException() {
|
||||||
Files.walk(dbDir)
|
|
||||||
.sorted(Comparator.reverseOrder())
|
|
||||||
.map(Path::toFile)
|
|
||||||
.forEach(File::delete);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When opening a repo in a dir that doesn't exist then an exception is thrown
|
||||||
|
// When opening a repo in a dir that is a file then an exception is thrown
|
||||||
|
// When opening a repo in a dir that is not a bare repo then an exception is thrown
|
||||||
|
// When opening a repo in a dir that is a bare repo then GitDb is returned
|
||||||
|
|
||||||
|
// Given a valid GitDb handle
|
||||||
|
// When select a branch that doesn't exist then an exception is thrown
|
||||||
|
// When select a valid branch then a GitDbBranch is returned
|
||||||
|
|
||||||
|
// Given a valid GitDbBranch handle
|
||||||
|
// When getting a key that does not exist then return an empty Optional
|
||||||
|
// When putting a key/value pair then a GitDbBranch is returned
|
||||||
|
// When getting a key that does exist then the value is returned inside an Optional
|
||||||
|
// When removing a key that does not exist then the GitDbBranch is returned
|
||||||
|
// When removing a key that does exist then a GitDbBranch is returned
|
||||||
|
// When starting a named transaction then GitDbTransaction is returned
|
||||||
|
// When starting an anonymous transaction then a GitDbTransaction is returned
|
||||||
|
|
||||||
|
// Given a GitDbTransaction handle
|
||||||
|
// When putting a new key/value pair then the GitDbBranch can't find it
|
||||||
|
// When putting an existing key/value pair then the GitDbBranch finds the original value
|
||||||
|
// When removing a key from then the GitDbBRanch still finds it
|
||||||
|
|
||||||
|
// Given a GitDbTransaction handle with a added, updated and removed keys
|
||||||
|
// When closing the transaction an GitDbBranch is returned
|
||||||
|
// When closing the transaction the added key/value is found
|
||||||
|
// When closing the transaction the updated value is found
|
||||||
|
// When closing the transaction the removed key is not found
|
||||||
|
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
// void saveFirstDocumentCreatesNewMasterBranch() {
|
||||||
|
// //given
|
||||||
|
// final String value = "{\"key\":\"value\"}";
|
||||||
|
// final Document<String> document = Document.create(key, value);
|
||||||
|
// final JsonObject expected = Json.createObjectBuilder()
|
||||||
|
// .add("key", "value")
|
||||||
|
// .build();
|
||||||
|
// //when
|
||||||
|
// final Key savedKey = gitDB.branch(master)
|
||||||
|
// .put(message, document, author);
|
||||||
|
// //then
|
||||||
|
// final String retrievedObject = gitDB.branch(master).get(savedKey);
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
// void getGivesSavedValue() {
|
||||||
|
// //given
|
||||||
|
// final String value = UUID.randomUUID().toString();
|
||||||
|
// final Document<String> document = Document.create(key, value);
|
||||||
|
// gitDB.save(master, message, document, author);
|
||||||
|
// //when
|
||||||
|
// final String result = gitDB.get(master, key);
|
||||||
|
// //then
|
||||||
|
// assertThat(result).isEqualTo(value);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @AfterEach
|
||||||
|
// void tearDown() throws IOException {
|
||||||
|
// gitDB.close();
|
||||||
|
// //Files.walk(dbDir)
|
||||||
|
// // .sorted(Comparator.reverseOrder())
|
||||||
|
// // .map(Path::toFile)
|
||||||
|
// // .forEach(File::delete);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue