mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-11 07:55:47 +01:00
Add flag to optionally overwrite files with create
This commit is contained in:
@@ -16,12 +16,14 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this {@link ModifyCommandBuilder} to make file changes to the head of a branch. You can
|
* Use this {@link ModifyCommandBuilder} to make file changes to the head of a branch. You can
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>create new files ({@link #createFile(String)}</li>
|
* <li>create new files ({@link #createFile(String)} (with the option to overwrite a file, if it already exists; by
|
||||||
|
* default a {@link sonia.scm.AlreadyExistsException} will be thrown)</li>
|
||||||
* <li>modify existing files ({@link #modifyFile(String)}</li>
|
* <li>modify existing files ({@link #modifyFile(String)}</li>
|
||||||
* <li>delete existing files ({@link #deleteFile(String)}</li>
|
* <li>delete existing files ({@link #deleteFile(String)}</li>
|
||||||
* <li>move/rename existing files ({@link #moveFile(String, String)}</li>
|
* <li>move/rename existing files ({@link #moveFile(String, String)}</li>
|
||||||
@@ -66,24 +68,24 @@ public class ModifyCommandBuilder {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new file. The content of the file will be specified in a subsequent call to
|
* Create a new file. The content of the file will be specified in a subsequent call to
|
||||||
* {@link ContentLoader#withData(ByteSource)} or {@link ContentLoader#withData(InputStream)}.
|
* {@link SimpleContentLoader#withData(ByteSource)} or {@link SimpleContentLoader#withData(InputStream)}.
|
||||||
* @param path The path and the name of the file that should be created.
|
* @param path The path and the name of the file that should be created.
|
||||||
* @return The loader to specify the content of the new file.
|
* @return The loader to specify the content of the new file.
|
||||||
*/
|
*/
|
||||||
public ContentLoader createFile(String path) {
|
public WithOverwriteFlagContentLoader createFile(String path) {
|
||||||
return new ContentLoader(
|
return new WithOverwriteFlagContentLoader(
|
||||||
content -> request.addRequest(new ModifyCommandRequest.CreateFileRequest(path, content))
|
(content, overwrite) -> request.addRequest(new ModifyCommandRequest.CreateFileRequest(path, content, overwrite))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modify an existing file. The new content of the file will be specified in a subsequent call to
|
* Modify an existing file. The new content of the file will be specified in a subsequent call to
|
||||||
* {@link ContentLoader#withData(ByteSource)} or {@link ContentLoader#withData(InputStream)}.
|
* {@link SimpleContentLoader#withData(ByteSource)} or {@link SimpleContentLoader#withData(InputStream)}.
|
||||||
* @param path The path and the name of the file that should be modified.
|
* @param path The path and the name of the file that should be modified.
|
||||||
* @return The loader to specify the new content of the file.
|
* @return The loader to specify the new content of the file.
|
||||||
*/
|
*/
|
||||||
public ContentLoader modifyFile(String path) {
|
public SimpleContentLoader modifyFile(String path) {
|
||||||
return new ContentLoader(
|
return new SimpleContentLoader(
|
||||||
content -> request.addRequest(new ModifyCommandRequest.ModifyFileRequest(path, content))
|
content -> request.addRequest(new ModifyCommandRequest.ModifyFileRequest(path, content))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -153,30 +155,39 @@ public class ModifyCommandBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ContentLoader {
|
public interface ContentLoader {
|
||||||
|
|
||||||
private final Consumer<File> contentConsumer;
|
|
||||||
|
|
||||||
private ContentLoader(Consumer<File> contentConsumer) {
|
|
||||||
this.contentConsumer = contentConsumer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the data of the file using a {@link ByteSource}.
|
* Specify the data of the file using a {@link ByteSource}.
|
||||||
|
*
|
||||||
* @return The builder instance.
|
* @return The builder instance.
|
||||||
* @throws IOException If the data could not be read.
|
* @throws IOException If the data could not be read.
|
||||||
*/
|
*/
|
||||||
public ModifyCommandBuilder withData(ByteSource data) throws IOException {
|
ModifyCommandBuilder withData(ByteSource data) throws IOException;
|
||||||
File content = loadData(data);
|
|
||||||
contentConsumer.accept(content);
|
|
||||||
return ModifyCommandBuilder.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the data of the file using an {@link InputStream}.
|
* Specify the data of the file using an {@link InputStream}.
|
||||||
* @return The builder instance.
|
* @return The builder instance.
|
||||||
* @throws IOException If the data could not be read.
|
* @throws IOException If the data could not be read.
|
||||||
*/
|
*/
|
||||||
|
ModifyCommandBuilder withData(InputStream data) throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SimpleContentLoader implements ContentLoader {
|
||||||
|
|
||||||
|
private final Consumer<File> contentConsumer;
|
||||||
|
|
||||||
|
private SimpleContentLoader(Consumer<File> contentConsumer) {
|
||||||
|
this.contentConsumer = contentConsumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModifyCommandBuilder withData(ByteSource data) throws IOException {
|
||||||
|
File content = loadData(data);
|
||||||
|
contentConsumer.accept(content);
|
||||||
|
return ModifyCommandBuilder.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ModifyCommandBuilder withData(InputStream data) throws IOException {
|
public ModifyCommandBuilder withData(InputStream data) throws IOException {
|
||||||
File content = loadData(data);
|
File content = loadData(data);
|
||||||
contentConsumer.accept(content);
|
contentConsumer.accept(content);
|
||||||
@@ -184,6 +195,36 @@ public class ModifyCommandBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class WithOverwriteFlagContentLoader implements ContentLoader {
|
||||||
|
|
||||||
|
private final ContentLoader contentLoader;
|
||||||
|
private boolean overwrite = false;
|
||||||
|
|
||||||
|
private WithOverwriteFlagContentLoader(BiConsumer<File, Boolean> contentConsumer) {
|
||||||
|
this.contentLoader = new SimpleContentLoader(file -> contentConsumer.accept(file, overwrite));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this to <code>true</code> to overwrite the file if it already exists. Otherwise an
|
||||||
|
* {@link sonia.scm.AlreadyExistsException} will be thrown.
|
||||||
|
* @return This loader instance.
|
||||||
|
*/
|
||||||
|
public WithOverwriteFlagContentLoader setOverwrite(boolean overwrite) {
|
||||||
|
this.overwrite = overwrite;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModifyCommandBuilder withData(ByteSource data) throws IOException {
|
||||||
|
return contentLoader.withData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModifyCommandBuilder withData(InputStream data) throws IOException {
|
||||||
|
return contentLoader.withData(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("UnstableApiUsage") // Files only used internal
|
@SuppressWarnings("UnstableApiUsage") // Files only used internal
|
||||||
private File loadData(ByteSource data) throws IOException {
|
private File loadData(ByteSource data) throws IOException {
|
||||||
File file = createTemporaryFile();
|
File file = createTemporaryFile();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public interface ModifyCommand {
|
|||||||
interface Worker {
|
interface Worker {
|
||||||
void delete(String toBeDeleted);
|
void delete(String toBeDeleted);
|
||||||
|
|
||||||
void create(String toBeCreated, File file) throws IOException;
|
void create(String toBeCreated, File file, boolean overwrite) throws IOException;
|
||||||
|
|
||||||
void modify(String path, File file);
|
void modify(String path, File file);
|
||||||
|
|
||||||
|
|||||||
@@ -124,15 +124,17 @@ public class ModifyCommandRequest implements Resetable, Validateable {
|
|||||||
public static class CreateFileRequest extends ContentModificationRequest {
|
public static class CreateFileRequest extends ContentModificationRequest {
|
||||||
|
|
||||||
private final String path;
|
private final String path;
|
||||||
|
private final boolean overwrite;
|
||||||
|
|
||||||
public CreateFileRequest(String path, File content) {
|
public CreateFileRequest(String path, File content, boolean overwrite) {
|
||||||
super(content);
|
super(content);
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
this.overwrite = overwrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ModifyCommand.Worker worker) throws IOException {
|
public void execute(ModifyCommand.Worker worker) throws IOException {
|
||||||
worker.create(path, getContent());
|
worker.create(path, getContent(), overwrite);
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package sonia.scm.repository.api;
|
package sonia.scm.repository.api;
|
||||||
|
|
||||||
import com.google.common.io.ByteSource;
|
import com.google.common.io.ByteSource;
|
||||||
|
import com.sun.org.apache.xpath.internal.operations.Bool;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -25,6 +26,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doAnswer;
|
||||||
import static org.mockito.Mockito.doNothing;
|
import static org.mockito.Mockito.doNothing;
|
||||||
import static org.mockito.Mockito.lenient;
|
import static org.mockito.Mockito.lenient;
|
||||||
@@ -96,7 +98,7 @@ class ModifyCommandBuilderTest {
|
|||||||
void shouldExecuteCreateWithByteSourceContent() throws IOException {
|
void shouldExecuteCreateWithByteSourceContent() throws IOException {
|
||||||
ArgumentCaptor<String> nameCaptor = ArgumentCaptor.forClass(String.class);
|
ArgumentCaptor<String> nameCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
List<String> contentCaptor = new ArrayList<>();
|
List<String> contentCaptor = new ArrayList<>();
|
||||||
doAnswer(new ExtractContent(contentCaptor)).when(worker).create(nameCaptor.capture(), any());
|
doAnswer(new ExtractContent(contentCaptor)).when(worker).create(nameCaptor.capture(), any(), anyBoolean());
|
||||||
|
|
||||||
initCommand()
|
initCommand()
|
||||||
.createFile("toBeCreated").withData(ByteSource.wrap("content".getBytes()))
|
.createFile("toBeCreated").withData(ByteSource.wrap("content".getBytes()))
|
||||||
@@ -110,7 +112,7 @@ class ModifyCommandBuilderTest {
|
|||||||
void shouldExecuteCreateWithInputStreamContent() throws IOException {
|
void shouldExecuteCreateWithInputStreamContent() throws IOException {
|
||||||
ArgumentCaptor<String> nameCaptor = ArgumentCaptor.forClass(String.class);
|
ArgumentCaptor<String> nameCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
List<String> contentCaptor = new ArrayList<>();
|
List<String> contentCaptor = new ArrayList<>();
|
||||||
doAnswer(new ExtractContent(contentCaptor)).when(worker).create(nameCaptor.capture(), any());
|
doAnswer(new ExtractContent(contentCaptor)).when(worker).create(nameCaptor.capture(), any(), anyBoolean());
|
||||||
|
|
||||||
initCommand()
|
initCommand()
|
||||||
.createFile("toBeCreated").withData(new ByteArrayInputStream("content".getBytes()))
|
.createFile("toBeCreated").withData(new ByteArrayInputStream("content".getBytes()))
|
||||||
@@ -120,11 +122,43 @@ class ModifyCommandBuilderTest {
|
|||||||
assertThat(contentCaptor).contains("content");
|
assertThat(contentCaptor).contains("content");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldExecuteCreateWithOverwriteFalseAsDefault() throws IOException {
|
||||||
|
ArgumentCaptor<String> nameCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
ArgumentCaptor<Boolean> overwriteCaptor = ArgumentCaptor.forClass(Boolean.class);
|
||||||
|
List<String> contentCaptor = new ArrayList<>();
|
||||||
|
doAnswer(new ExtractContent(contentCaptor)).when(worker).create(nameCaptor.capture(), any(), overwriteCaptor.capture());
|
||||||
|
|
||||||
|
initCommand()
|
||||||
|
.createFile("toBeCreated").withData(new ByteArrayInputStream("content".getBytes()))
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
assertThat(nameCaptor.getValue()).isEqualTo("toBeCreated");
|
||||||
|
assertThat(overwriteCaptor.getValue()).isFalse();
|
||||||
|
assertThat(contentCaptor).contains("content");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldExecuteCreateWithOverwriteIfSet() throws IOException {
|
||||||
|
ArgumentCaptor<String> nameCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
ArgumentCaptor<Boolean> overwriteCaptor = ArgumentCaptor.forClass(Boolean.class);
|
||||||
|
List<String> contentCaptor = new ArrayList<>();
|
||||||
|
doAnswer(new ExtractContent(contentCaptor)).when(worker).create(nameCaptor.capture(), any(), overwriteCaptor.capture());
|
||||||
|
|
||||||
|
initCommand()
|
||||||
|
.createFile("toBeCreated").setOverwrite(true).withData(new ByteArrayInputStream("content".getBytes()))
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
assertThat(nameCaptor.getValue()).isEqualTo("toBeCreated");
|
||||||
|
assertThat(overwriteCaptor.getValue()).isTrue();
|
||||||
|
assertThat(contentCaptor).contains("content");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldExecuteCreateMultipleTimes() throws IOException {
|
void shouldExecuteCreateMultipleTimes() throws IOException {
|
||||||
ArgumentCaptor<String> nameCaptor = ArgumentCaptor.forClass(String.class);
|
ArgumentCaptor<String> nameCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
List<String> contentCaptor = new ArrayList<>();
|
List<String> contentCaptor = new ArrayList<>();
|
||||||
doAnswer(new ExtractContent(contentCaptor)).when(worker).create(nameCaptor.capture(), any());
|
doAnswer(new ExtractContent(contentCaptor)).when(worker).create(nameCaptor.capture(), any(), anyBoolean());
|
||||||
|
|
||||||
initCommand()
|
initCommand()
|
||||||
.createFile("toBeCreated_1").withData(new ByteArrayInputStream("content_1".getBytes()))
|
.createFile("toBeCreated_1").withData(new ByteArrayInputStream("content_1".getBytes()))
|
||||||
|
|||||||
@@ -8,9 +8,14 @@ import sonia.scm.repository.Repository;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.FileAlreadyExistsException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||||
|
import static sonia.scm.AlreadyExistsException.alreadyExists;
|
||||||
|
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
||||||
|
|
||||||
public class GitModifyCommand extends AbstractGitCommand implements ModifyCommand {
|
public class GitModifyCommand extends AbstractGitCommand implements ModifyCommand {
|
||||||
|
|
||||||
private final GitWorkdirFactory workdirFactory;
|
private final GitWorkdirFactory workdirFactory;
|
||||||
@@ -48,10 +53,18 @@ public class GitModifyCommand extends AbstractGitCommand implements ModifyComman
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(String toBeCreated, File file) throws IOException {
|
public void create(String toBeCreated, File file, boolean overwrite) throws IOException {
|
||||||
Path targetFile = new File(workDir, toBeCreated).toPath();
|
Path targetFile = new File(workDir, toBeCreated).toPath();
|
||||||
Files.createDirectories(targetFile.getParent());
|
Files.createDirectories(targetFile.getParent());
|
||||||
|
if (overwrite) {
|
||||||
|
Files.copy(file.toPath(), targetFile, REPLACE_EXISTING);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
Files.copy(file.toPath(), targetFile);
|
Files.copy(file.toPath(), targetFile);
|
||||||
|
} catch (FileAlreadyExistsException e) {
|
||||||
|
throw alreadyExists(entity("file", toBeCreated).in("branch", request.getBranch()).in(context.getRepository()));
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
getClone().add().addFilepattern(toBeCreated).call();
|
getClone().add().addFilepattern(toBeCreated).call();
|
||||||
} catch (GitAPIException e) {
|
} catch (GitAPIException e) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.eclipse.jgit.treewalk.CanonicalTreeParser;
|
|||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.rules.TemporaryFolder;
|
||||||
|
import sonia.scm.AlreadyExistsException;
|
||||||
import sonia.scm.repository.Person;
|
import sonia.scm.repository.Person;
|
||||||
import sonia.scm.repository.util.WorkdirProvider;
|
import sonia.scm.repository.util.WorkdirProvider;
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ public class GitModifyCommandTest extends AbstractGitCommandTestBase {
|
|||||||
ModifyCommandRequest request = new ModifyCommandRequest();
|
ModifyCommandRequest request = new ModifyCommandRequest();
|
||||||
request.setBranch("master");
|
request.setBranch("master");
|
||||||
request.setCommitMessage("test commit");
|
request.setCommitMessage("test commit");
|
||||||
request.addRequest(new ModifyCommandRequest.CreateFileRequest("new_file", newFile));
|
request.addRequest(new ModifyCommandRequest.CreateFileRequest("new_file", newFile, false));
|
||||||
request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det"));
|
request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det"));
|
||||||
|
|
||||||
String newRef = command.execute(request);
|
String newRef = command.execute(request);
|
||||||
@@ -63,7 +64,7 @@ public class GitModifyCommandTest extends AbstractGitCommandTestBase {
|
|||||||
ModifyCommandRequest request = new ModifyCommandRequest();
|
ModifyCommandRequest request = new ModifyCommandRequest();
|
||||||
request.setBranch("master");
|
request.setBranch("master");
|
||||||
request.setCommitMessage("test commit");
|
request.setCommitMessage("test commit");
|
||||||
request.addRequest(new ModifyCommandRequest.CreateFileRequest("new_file", newFile));
|
request.addRequest(new ModifyCommandRequest.CreateFileRequest("new_file", newFile, false));
|
||||||
request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det"));
|
request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det"));
|
||||||
|
|
||||||
command.execute(request);
|
command.execute(request);
|
||||||
@@ -73,6 +74,40 @@ public class GitModifyCommandTest extends AbstractGitCommandTestBase {
|
|||||||
assertInTree(assertions);
|
assertInTree(assertions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = AlreadyExistsException.class)
|
||||||
|
public void shouldFailIfOverwritingExistingFileWithoutOverwriteFlag() throws IOException, GitAPIException {
|
||||||
|
File newFile = Files.write(temporaryFolder.newFile().toPath(), "new content".getBytes()).toFile();
|
||||||
|
|
||||||
|
GitModifyCommand command = createCommand();
|
||||||
|
|
||||||
|
ModifyCommandRequest request = new ModifyCommandRequest();
|
||||||
|
request.setBranch("master");
|
||||||
|
request.setCommitMessage("test commit");
|
||||||
|
request.addRequest(new ModifyCommandRequest.CreateFileRequest("a.txt", newFile, false));
|
||||||
|
request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det"));
|
||||||
|
|
||||||
|
command.execute(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldOverwriteExistingFileIfOverwriteFlagSet() throws IOException, GitAPIException {
|
||||||
|
File newFile = Files.write(temporaryFolder.newFile().toPath(), "new content".getBytes()).toFile();
|
||||||
|
|
||||||
|
GitModifyCommand command = createCommand();
|
||||||
|
|
||||||
|
ModifyCommandRequest request = new ModifyCommandRequest();
|
||||||
|
request.setBranch("master");
|
||||||
|
request.setCommitMessage("test commit");
|
||||||
|
request.addRequest(new ModifyCommandRequest.CreateFileRequest("a.txt", newFile, true));
|
||||||
|
request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det"));
|
||||||
|
|
||||||
|
command.execute(request);
|
||||||
|
|
||||||
|
TreeAssertions assertions = canonicalTreeParser -> assertThat(canonicalTreeParser.findFile("a.txt")).isTrue();
|
||||||
|
|
||||||
|
assertInTree(assertions);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertInTree(TreeAssertions assertions) throws IOException, GitAPIException {
|
private void assertInTree(TreeAssertions assertions) throws IOException, GitAPIException {
|
||||||
try (Git git = new Git(createContext().open())) {
|
try (Git git = new Git(createContext().open())) {
|
||||||
RevCommit lastCommit = getLastCommit(git);
|
RevCommit lastCommit = getLastCommit(git);
|
||||||
|
|||||||
Reference in New Issue
Block a user