When removing a key that does exist then an updated GitDbBranch is returned
This commit is contained in:
parent
50a304a941
commit
d6f8bcbc0f
5 changed files with 160 additions and 5 deletions
|
@ -46,7 +46,7 @@ public interface GitDBBranch {
|
||||||
* @param key the key to place the value under
|
* @param key the key to place the value under
|
||||||
* @param value the value (must be Serializable)
|
* @param value the value (must be Serializable)
|
||||||
* @return an updated branch containing the new key/value
|
* @return an updated branch containing the new key/value
|
||||||
* @throws IOException if there was an error writing the value
|
* @throws IOException if there was an error writing the key/value
|
||||||
*/
|
*/
|
||||||
GitDBBranch put(String key, String value) throws IOException;
|
GitDBBranch put(String key, String value) throws IOException;
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ public interface GitDBBranch {
|
||||||
*
|
*
|
||||||
* @param key the key to remove
|
* @param key the key to remove
|
||||||
* @return an updated branch without the key, or the original if the key was not found
|
* @return an updated branch without the key, or the original if the key was not found
|
||||||
|
* @throws IOException if there was an error removing the key/value
|
||||||
*/
|
*/
|
||||||
GitDBBranch remove(String key);
|
GitDBBranch remove(String key) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,17 @@ class GitDBBranchImpl implements GitDBBranch {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GitDBBranch remove(final String key) {
|
public GitDBBranch remove(final String key) throws IOException {
|
||||||
|
final Optional<ObjectId> newTree = gitDBRepo.removeKey(branchRef, KEY_PREFIX + key);
|
||||||
|
if (newTree.isPresent()) {
|
||||||
|
final Ref newBranch =
|
||||||
|
gitDBRepo.writeCommit(
|
||||||
|
branchRef, newTree.get(),
|
||||||
|
commitMessageForRemove(key),
|
||||||
|
userName,
|
||||||
|
userEmailAddress);
|
||||||
|
return select(newBranch, gitDBRepo, userName, userEmailAddress);
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,4 +103,8 @@ class GitDBBranchImpl implements GitDBBranch {
|
||||||
return String.format("Add key [%s] = [%s]", key, value);
|
return String.format("Add key [%s] = [%s]", key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String commitMessageForRemove(final String key) {
|
||||||
|
return String.format("Remove Key [%s]", key);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ class GitDBRepo {
|
||||||
private final ValueWriter valueWriter;
|
private final ValueWriter valueWriter;
|
||||||
private final KeyWriter keyWriter;
|
private final KeyWriter keyWriter;
|
||||||
private final CommitWriter commitWriter;
|
private final CommitWriter commitWriter;
|
||||||
|
private final KeyRemover keyRemover;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of this class.
|
* Creates a new instance of this class.
|
||||||
|
@ -52,6 +53,7 @@ class GitDBRepo {
|
||||||
valueWriter = new ValueWriter(repository);
|
valueWriter = new ValueWriter(repository);
|
||||||
keyWriter = new KeyWriter(repository);
|
keyWriter = new KeyWriter(repository);
|
||||||
commitWriter = new CommitWriter(repository);
|
commitWriter = new CommitWriter(repository);
|
||||||
|
keyRemover = new KeyRemover(repository);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,11 +159,11 @@ class GitDBRepo {
|
||||||
/**
|
/**
|
||||||
* Add the key/value to the repo, returning the tree containing the update.
|
* Add the key/value to the repo, returning the tree containing the update.
|
||||||
*
|
*
|
||||||
* <p>N.B. this creates a tree that has not been committed remains unaware of the update.</p>
|
* <p>N.B. this creates a tree that has not been committed, the branch remains unaware of the update.</p>
|
||||||
*
|
*
|
||||||
* @param branchRef the branch to start from
|
* @param branchRef the branch to start from
|
||||||
* @param key the key to place the value under
|
* @param key the key to place the value under
|
||||||
* @param value the value (must be Serializable)
|
* @param value the value
|
||||||
* @return the id of the updated tree containing the update
|
* @return the id of the updated tree containing the update
|
||||||
* @throws IOException if there was an error writing the value
|
* @throws IOException if there was an error writing the value
|
||||||
*/
|
*/
|
||||||
|
@ -210,4 +212,19 @@ class GitDBRepo {
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
return commitWriter.write(treeId, ObjectId.zeroId(), initMessage, initUser, initEmail);
|
return commitWriter.write(treeId, ObjectId.zeroId(), initMessage, initUser, initEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the key from the branch, returning the tree containing the update.
|
||||||
|
*
|
||||||
|
* <p>N.B. this creates a tree that has not been committed, the branch remains unaware of the update.</p>
|
||||||
|
*
|
||||||
|
* @param branchRef the branch to start from
|
||||||
|
* @param key the key to place the value under
|
||||||
|
* @return an Optional containing the id of the updated tree containing the update, if the key was found, or an
|
||||||
|
* empty Optional if there key was not found, the there was no changes made
|
||||||
|
* @throws IOException if there was an error writing the value
|
||||||
|
*/
|
||||||
|
Optional<ObjectId> removeKey(final Ref branchRef, final String key) throws IOException {
|
||||||
|
return keyRemover.remove(branchRef, key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
113
src/main/java/net/kemitix/gitdb/impl/KeyRemover.java
Normal file
113
src/main/java/net/kemitix/gitdb/impl/KeyRemover.java
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2018 Paul Campbell
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies
|
||||||
|
or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.kemitix.gitdb.impl;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Ref;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.lib.TreeFormatter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove Key from the Git Repository.
|
||||||
|
*
|
||||||
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
class KeyRemover {
|
||||||
|
|
||||||
|
private final Repository repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the boolean to true if the key matches a NamedRevBlob's name.
|
||||||
|
*
|
||||||
|
* @param key the key to match
|
||||||
|
* @param removed the boolean to update
|
||||||
|
* @return a Consumer
|
||||||
|
*/
|
||||||
|
private static Consumer<GitTreeReader.NamedRevBlob> flagIfFound(final String key, final AtomicBoolean removed) {
|
||||||
|
return nvb -> {
|
||||||
|
if (nvb.getName().equals(key)) {
|
||||||
|
removed.set(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter to exclude named blobs where the name matches the key.
|
||||||
|
*
|
||||||
|
* @param key the key to match
|
||||||
|
* @return a Predicate
|
||||||
|
*/
|
||||||
|
private static Predicate<GitTreeReader.NamedRevBlob> isNotKey(final String key) {
|
||||||
|
return item -> !item.getName().equals(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the named value blob to the tree formatter.
|
||||||
|
*
|
||||||
|
* @param treeFormatter the tree formatter to add to
|
||||||
|
* @return a Consumer
|
||||||
|
*/
|
||||||
|
private static Consumer<GitTreeReader.NamedRevBlob> addToTree(final TreeFormatter treeFormatter) {
|
||||||
|
return item -> treeFormatter.append(item.getName(), item.getRevBlob());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a key from the repository.
|
||||||
|
*
|
||||||
|
* @param branchRef the branch to update
|
||||||
|
* @param key the key to remove
|
||||||
|
* @return the id of the updated tree
|
||||||
|
* @throws IOException if there is an error writing the value
|
||||||
|
*/
|
||||||
|
Optional<ObjectId> remove(final Ref branchRef, final String key) throws IOException {
|
||||||
|
final TreeFormatter treeFormatter = new TreeFormatter();
|
||||||
|
final AtomicBoolean removed = new AtomicBoolean(false);
|
||||||
|
new GitTreeReader(repository)
|
||||||
|
.stream(branchRef)
|
||||||
|
.peek(flagIfFound(key, removed))
|
||||||
|
.filter(isNotKey(key))
|
||||||
|
.forEach(addToTree(treeFormatter));
|
||||||
|
if (removed.get()) {
|
||||||
|
return Optional.of(insertTree(treeFormatter));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a tree into the repo, returning its id.
|
||||||
|
*
|
||||||
|
* @param treeFormatter the formatter containing the proposed tree's data.
|
||||||
|
* @return the name of the tree object.
|
||||||
|
* @throws IOException the object could not be stored.
|
||||||
|
*/
|
||||||
|
private ObjectId insertTree(final TreeFormatter treeFormatter) throws IOException {
|
||||||
|
return repository.getObjectDatabase().newInserter().insert(treeFormatter);
|
||||||
|
}
|
||||||
|
}
|
|
@ -249,6 +249,16 @@ class GitDBTest implements WithAssertions {
|
||||||
}
|
}
|
||||||
|
|
||||||
// When removing a key that does exist then a GitDbBranch is returned
|
// When removing a key that does exist then a GitDbBranch is returned
|
||||||
|
@Test
|
||||||
|
void removeKey_whenExists_thenReturnUpdatedBranch() throws IOException {
|
||||||
|
//given
|
||||||
|
final GitDBBranch originalBranch = gitDBBranch().put("key-name", "value");
|
||||||
|
//when
|
||||||
|
final GitDBBranch updatedBranch = originalBranch.remove("key-name");
|
||||||
|
//then
|
||||||
|
assertThat(updatedBranch).isNotSameAs(originalBranch);
|
||||||
|
}
|
||||||
|
|
||||||
// When removing a key that does exist then original GitDbBranch can still find it
|
// When removing a key that does exist then original GitDbBranch can still find it
|
||||||
// When removing a key that does exist then the updated GitDbBranch can't find it
|
// When removing a key that does exist then the updated GitDbBranch can't find it
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue