mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-15 09:46:16 +01:00
First steps to implement create in modify command
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface ModifyCommand {
|
||||
|
||||
@@ -9,7 +10,7 @@ public interface ModifyCommand {
|
||||
interface Worker {
|
||||
void delete(String toBeDeleted);
|
||||
|
||||
void create(String toBeCreated, File file);
|
||||
void create(String toBeCreated, File file) throws IOException;
|
||||
|
||||
void modify(String path, File file);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import sonia.scm.Validateable;
|
||||
import sonia.scm.repository.Person;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -63,7 +64,7 @@ public class ModifyCommandRequest implements Resetable, Validateable {
|
||||
}
|
||||
|
||||
public interface PartialRequest {
|
||||
void execute(ModifyCommand.Worker worker);
|
||||
void execute(ModifyCommand.Worker worker) throws IOException;
|
||||
}
|
||||
|
||||
public static class DeleteFileRequest implements PartialRequest {
|
||||
@@ -121,7 +122,7 @@ public class ModifyCommandRequest implements Resetable, Validateable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ModifyCommand.Worker worker) {
|
||||
public void execute(ModifyCommand.Worker worker) throws IOException {
|
||||
worker.create(path, getContent());
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ class ModifyCommandBuilderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldExecuteDelete() {
|
||||
void shouldExecuteDelete() throws IOException {
|
||||
initCommand()
|
||||
.deleteFile("toBeDeleted")
|
||||
.execute();
|
||||
@@ -80,7 +80,7 @@ class ModifyCommandBuilderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldExecuteMove() {
|
||||
void shouldExecuteMove() throws IOException {
|
||||
initCommand()
|
||||
.moveFile("source", "target")
|
||||
.execute();
|
||||
@@ -157,9 +157,11 @@ class ModifyCommandBuilderTest {
|
||||
assertThat(contentCaptor).contains("content");
|
||||
}
|
||||
|
||||
private void executeRequest() {
|
||||
private void executeRequest() throws IOException {
|
||||
ModifyCommandRequest request = requestCaptor.getValue();
|
||||
request.getRequests().forEach(r -> r.execute(worker));
|
||||
for (ModifyCommandRequest.PartialRequest r : request.getRequests()) {
|
||||
r.execute(worker);
|
||||
}
|
||||
}
|
||||
|
||||
private ModifyCommandBuilder initCommand() {
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.api.errors.RefNotFoundException;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.GitWorkdirFactory;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
import sonia.scm.repository.Person;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.util.WorkingCopy;
|
||||
import sonia.scm.user.User;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
||||
import static sonia.scm.NotFoundException.notFound;
|
||||
|
||||
public class GitModifyCommand extends AbstractGitCommand implements ModifyCommand {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GitModifyCommand.class);
|
||||
|
||||
private final GitWorkdirFactory workdirFactory;
|
||||
|
||||
public GitModifyCommand(GitContext context, Repository repository, GitWorkdirFactory workdirFactory) {
|
||||
super(context, repository);
|
||||
this.workdirFactory = workdirFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(ModifyCommandRequest request) {
|
||||
try (WorkingCopy<org.eclipse.jgit.lib.Repository> workingCopy = workdirFactory.createWorkingCopy(context)) {
|
||||
org.eclipse.jgit.lib.Repository repository = workingCopy.getWorkingRepository();
|
||||
LOG.debug("cloned repository to folder {}", repository.getWorkTree());
|
||||
try {
|
||||
return new ModifyWorker(repository, request).execute();
|
||||
} catch (IOException e) {
|
||||
return throwInternalRepositoryException("could not apply modifications to cloned repository", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ModifyWorker implements Worker {
|
||||
|
||||
private final Git clone;
|
||||
private final File workDir;
|
||||
private final ModifyCommandRequest request;
|
||||
|
||||
ModifyWorker(org.eclipse.jgit.lib.Repository repository, ModifyCommandRequest request) {
|
||||
this.clone = new Git(repository);
|
||||
this.workDir = repository.getWorkTree();
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
String execute() throws IOException {
|
||||
checkOutBranch();
|
||||
for (ModifyCommandRequest.PartialRequest r: request.getRequests()) {
|
||||
r.execute(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(String toBeCreated, File file) throws IOException {
|
||||
Path targetFile = new File(workDir, toBeCreated).toPath();
|
||||
Files.createDirectories(targetFile.getParent());
|
||||
Files.copy(file.toPath(), targetFile);
|
||||
try {
|
||||
clone.add().addFilepattern(toBeCreated).call();
|
||||
} catch (GitAPIException e) {
|
||||
throwInternalRepositoryException("could not add new file to index", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String toBeDeleted) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modify(String path, File file) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(String sourcePath, String targetPath) {
|
||||
|
||||
}
|
||||
|
||||
private void checkOutBranch() throws IOException {
|
||||
String branch = request.getBranch();
|
||||
try {
|
||||
clone.checkout().setName(branch).call();
|
||||
} catch (RefNotFoundException e) {
|
||||
LOG.trace("could not checkout branch {} for modifications directly; trying to create local branch", branch, e);
|
||||
checkOutTargetAsNewLocalBranch();
|
||||
} catch (GitAPIException e) {
|
||||
throwInternalRepositoryException("could not checkout target branch for merge: " + branch, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkOutTargetAsNewLocalBranch() throws IOException {
|
||||
String branch = request.getBranch();
|
||||
try {
|
||||
ObjectId targetRevision = resolveRevision(branch);
|
||||
clone.checkout().setStartPoint(targetRevision.getName()).setName(branch).setCreateBranch(true).call();
|
||||
} catch (RefNotFoundException e) {
|
||||
LOG.debug("could not checkout branch {} for modifications as local branch", branch, e);
|
||||
throw notFound(entity("Branch", branch).in(context.getRepository()));
|
||||
} catch (GitAPIException e) {
|
||||
throw new InternalRepositoryException(context.getRepository(), "could not checkout branch for modifications as local branch: " + branch, e);
|
||||
}
|
||||
}
|
||||
|
||||
private ObjectId resolveRevision(String revision) throws IOException {
|
||||
ObjectId resolved = clone.getRepository().resolve(revision);
|
||||
if (resolved == null) {
|
||||
return resolveRevisionOrThrowNotFound(clone.getRepository(), "origin/" + revision);
|
||||
} else {
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
|
||||
private ObjectId resolveRevisionOrThrowNotFound(org.eclipse.jgit.lib.Repository repository, String revision) throws IOException {
|
||||
ObjectId resolved = repository.resolve(revision);
|
||||
if (resolved == null) {
|
||||
throw notFound(entity("Revision", revision).in(context.getRepository()));
|
||||
} else {
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
|
||||
private void doCommit() {
|
||||
String branch = request.getBranch();
|
||||
LOG.debug("modified branch {}", branch);
|
||||
Person authorToUse = determineAuthor();
|
||||
try {
|
||||
if (!clone.status().call().isClean()) {
|
||||
clone.commit()
|
||||
.setAuthor(authorToUse.getName(), authorToUse.getMail())
|
||||
.setMessage(request.getCommitMessage())
|
||||
.call();
|
||||
}
|
||||
} catch (GitAPIException e) {
|
||||
throw new InternalRepositoryException(context.getRepository(), "could not commit modifications on branch " + request.getBranch(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private Person determineAuthor() {
|
||||
if (request.getAuthor() == null) {
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
User user = subject.getPrincipals().oneByType(User.class);
|
||||
String name = user.getDisplayName();
|
||||
String email = user.getMail();
|
||||
LOG.debug("no author set; using logged in user: {} <{}>", name, email);
|
||||
return new Person(name, email);
|
||||
} else {
|
||||
return request.getAuthor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String throwInternalRepositoryException(String message, Exception e) {
|
||||
throw new InternalRepositoryException(context.getRepository(), message, e);
|
||||
}
|
||||
}
|
||||
@@ -268,6 +268,11 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider
|
||||
return new GitMergeCommand(context, repository, handler.getWorkdirFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModifyCommand getModifyCommand() {
|
||||
return new GitModifyCommand(context, repository, handler.getWorkdirFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Feature> getSupportedFeatures() {
|
||||
return FEATURES;
|
||||
|
||||
@@ -10,30 +10,17 @@ import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.transport.ScmTransportProtocol;
|
||||
import org.eclipse.jgit.transport.Transport;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.GitRepositoryHandler;
|
||||
import sonia.scm.repository.Person;
|
||||
import sonia.scm.repository.PreProcessorUtil;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.api.HookContextFactory;
|
||||
import sonia.scm.repository.api.MergeCommandResult;
|
||||
import sonia.scm.repository.api.MergeDryRunCommandResult;
|
||||
import sonia.scm.repository.util.WorkdirProvider;
|
||||
import sonia.scm.user.User;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.google.inject.util.Providers.of;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@SubjectAware(configuration = "classpath:sonia/scm/configuration/shiro.ini", username = "admin", password = "secret")
|
||||
public class GitMergeCommandTest extends AbstractGitCommandTestBase {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import sonia.scm.repository.util.WorkdirProvider;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
public class GitModifyCommandTest extends AbstractGitCommandTestBase {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
@Rule
|
||||
public BindTransportProtocolRule transportProtocolRule = new BindTransportProtocolRule();
|
||||
|
||||
@Test
|
||||
public void shouldCreateNewFile() throws IOException {
|
||||
File newFile = Files.write(temporaryFolder.newFile().toPath(), "new content".getBytes()).toFile();
|
||||
|
||||
GitModifyCommand command = new GitModifyCommand(createContext(), repository, new SimpleGitWorkdirFactory(new WorkdirProvider()));
|
||||
|
||||
ModifyCommandRequest request = new ModifyCommandRequest();
|
||||
request.setBranch("master");
|
||||
request.setCommitMessage("test commit");
|
||||
request.addRequest(new ModifyCommandRequest.CreateFileRequest("new/file", newFile));
|
||||
command.execute(request);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user