Merge branch 'develop' into feature/browse_commit_with_limit

This commit is contained in:
René Pfeuffer
2020-03-09 08:40:29 +01:00
154 changed files with 7158 additions and 233 deletions

View File

@@ -51,7 +51,7 @@ public class GitConfigResource {
@GET
@Path("")
@Produces(GitVndMediaType.GIT_CONFIG)
@Operation(summary = "Git configuration", description = "Returns the global git configuration.", tags = "Git")
@Operation(summary = "Git configuration", description = "Returns the global git configuration.", tags = "Git", operationId = "git_get_config")
@ApiResponse(
responseCode = "200",
description = "success",
@@ -91,11 +91,8 @@ public class GitConfigResource {
@PUT
@Path("")
@Consumes(GitVndMediaType.GIT_CONFIG)
@Operation(summary = "Modify git configuration", description = "Modifies the global git configuration.", tags = "Git")
@ApiResponse(
responseCode = "204",
description = "update success"
)
@Operation(summary = "Modify git configuration", description = "Modifies the global git configuration.", tags = "Git", operationId = "git_put_config")
@ApiResponse(responseCode = "204", description = "update success")
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
@ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"configuration:write:git\" privilege")
@ApiResponse(

View File

@@ -4,54 +4,34 @@ import com.google.common.io.ByteStreams;
import org.eclipse.jgit.attributes.FilterCommand;
import org.eclipse.jgit.attributes.FilterCommandRegistry;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.SCMContextProvider;
import sonia.scm.plugin.Extension;
import javax.inject.Inject;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.regex.Pattern;
import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
@Extension
public class GitLfsFilterContextListener implements ServletContextListener {
public static final String GITCONFIG = "[filter \"lfs\"]\n" +
"clean = git-lfs clean -- %f\n" +
"smudge = git-lfs smudge -- %f\n" +
"process = git-lfs filter-process\n" +
"required = true\n";
public static final Pattern COMMAND_NAME_PATTERN = Pattern.compile("git-lfs (smudge|clean) -- .*");
private static final Logger LOG = LoggerFactory.getLogger(GitLfsFilterContextListener.class);
private final SCMContextProvider contextProvider;
@Inject
public GitLfsFilterContextListener(SCMContextProvider contextProvider) {
this.contextProvider = contextProvider;
}
@Override
public void contextInitialized(ServletContextEvent sce) {
Path gitconfig = contextProvider.getBaseDirectory().toPath().resolve("gitconfig");
try {
Files.write(gitconfig, GITCONFIG.getBytes(Charset.defaultCharset()), TRUNCATE_EXISTING, CREATE);
FS.DETECTED.setGitSystemConfig(gitconfig.toFile());
LOG.info("wrote git config file: {}", gitconfig);
} catch (IOException e) {
LOG.error("could not write git config in path {}; git lfs support may not work correctly", gitconfig, e);
SystemReader.getInstance().getSystemConfig().setString("filter", "lfs", "clean", "git-lfs clean -- %f");
SystemReader.getInstance().getSystemConfig().setString("filter", "lfs", "smudge", "git-lfs smudge -- %f");
SystemReader.getInstance().getSystemConfig().setString("filter", "lfs", "process", "git-lfs filter-process");
SystemReader.getInstance().getSystemConfig().setString("filter", "lfs", "required", "true");
} catch (Exception e) {
LOG.error("could not set git config; git lfs support may not work correctly", e);
}
FilterCommandRegistry.register(COMMAND_NAME_PATTERN, NoOpFilterCommand::new);
}

View File

@@ -88,7 +88,14 @@ abstract class GitMergeStrategy extends AbstractGitCommand.GitCloneWorker<MergeC
}
MergeCommandResult analyseFailure(MergeResult result) {
logger.info("could not merge branch {} into {} due to conflict in paths {}", branchToMerge, targetBranch, result.getConflicts().keySet());
logger.info("could not merge branch {} into {} with merge status '{}' due to ...", branchToMerge, targetBranch, result.getMergeStatus());
logger.info("... conflicts: {}", result.getConflicts());
logger.info("... checkout conflicts: {}", result.getCheckoutConflicts());
logger.info("... failing paths: {}", result.getFailingPaths());
logger.info("... message: {}", result);
if (result.getConflicts() == null) {
throw new UnexpectedMergeResultException(getRepository(), result);
}
return MergeCommandResult.failure(targetRevision.name(), revisionToMerge.name(), result.getConflicts().keySet());
}
}

View File

@@ -0,0 +1,27 @@
package sonia.scm.repository.spi;
import org.eclipse.jgit.api.MergeResult;
import sonia.scm.ContextEntry;
import sonia.scm.ExceptionWithContext;
import sonia.scm.repository.Repository;
class UnexpectedMergeResultException extends ExceptionWithContext {
public static final String CODE = "4GRrgkSC01";
public UnexpectedMergeResultException(Repository repository, MergeResult result) {
super(ContextEntry.ContextBuilder.entity(repository).build(), createMessage(result));
}
private static String createMessage(MergeResult result) {
return "unexpected merge result: " + result
+ "\nconflicts: " + result.getConflicts()
+ "\ncheckout conflicts: " + result.getCheckoutConflicts()
+ "\nfailing paths: " + result.getFailingPaths();
}
@Override
public String getCode() {
return CODE;
}
}

View File

@@ -39,8 +39,8 @@ import com.google.common.collect.ImmutableSet;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdSubclassMap;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.transport.BaseReceivePack;
import org.eclipse.jgit.transport.BaseReceivePack.PackParserListener;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.ReceivePack.PackParserListener;
import org.eclipse.jgit.transport.PackParser;
import org.slf4j.Logger;
@@ -76,7 +76,7 @@ public class CollectingPackParserListener implements PackParserListener
*
* @return listener
*/
public static CollectingPackParserListener get(BaseReceivePack pack)
public static CollectingPackParserListener get(ReceivePack pack)
{
PackParserListener listener = pack.getPackParserListener();
@@ -101,7 +101,7 @@ public class CollectingPackParserListener implements PackParserListener
*
* @param pack receive pack
*/
public static void set(BaseReceivePack pack)
public static void set(ReceivePack pack)
{
logger.trace("apply collecting listener to receive pack");
pack.setPackParserListener(new CollectingPackParserListener());

View File

@@ -113,5 +113,4 @@ public class AbstractGitCommandTestBase extends ZippedRepositoryTestBase
/** Field description */
private GitContext context;
private ScmTransportProtocol scmTransportProtocol;
}

View File

@@ -12,16 +12,23 @@ import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Rule;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import sonia.scm.NoChangesMadeException;
import sonia.scm.NotFoundException;
import sonia.scm.repository.GitWorkdirFactory;
import sonia.scm.repository.Person;
import sonia.scm.repository.api.MergeCommandResult;
import sonia.scm.repository.api.MergeStrategy;
import sonia.scm.repository.util.WorkdirProvider;
import sonia.scm.user.User;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import static org.assertj.core.api.Assertions.assertThat;
@@ -163,11 +170,34 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase {
assertThat(mergeCommandResult.getFilesWithConflict()).containsExactly("a.txt");
}
@Test
public void shouldHandleUnexpectedMergeResults() {
GitMergeCommand command = createCommand(git -> {
try {
FileWriter fw = new FileWriter(new File(git.getRepository().getWorkTree(), "b.txt"), true);
BufferedWriter bw = new BufferedWriter(fw);
bw.write("change");
bw.newLine();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
});
MergeCommandRequest request = new MergeCommandRequest();
request.setBranchToMerge("mergeable");
request.setTargetBranch("master");
request.setMergeStrategy(MergeStrategy.MERGE_COMMIT);
request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det"));
request.setMessageTemplate("simple");
Assertions.assertThrows(UnexpectedMergeResultException.class, () -> command.merge(request));
}
@Test
public void shouldTakeAuthorFromSubjectIfNotSet() throws IOException, GitAPIException {
SimplePrincipalCollection principals = new SimplePrincipalCollection();
principals.add("admin", REALM);
principals.add( new User("dirk", "Dirk Gently", "dirk@holistic.det"), REALM);
principals.add(new User("dirk", "Dirk Gently", "dirk@holistic.det"), REALM);
shiro.setSubject(
new Subject.Builder()
.principals(principals)
@@ -364,6 +394,20 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase {
}
private GitMergeCommand createCommand() {
return new GitMergeCommand(createContext(), repository, new SimpleGitWorkdirFactory(new WorkdirProvider()));
return createCommand(git -> {
});
}
private GitMergeCommand createCommand(Consumer<Git> interceptor) {
return new GitMergeCommand(createContext(), repository, new SimpleGitWorkdirFactory(new WorkdirProvider())) {
@Override
<R, W extends GitCloneWorker<R>> R inClone(Function<Git, W> workerSupplier, GitWorkdirFactory workdirFactory, String initialBranch) {
Function<Git, W> interceptedWorkerSupplier = git -> {
interceptor.accept(git);
return workerSupplier.apply(git);
};
return super.inClone(interceptedWorkerSupplier, workdirFactory, initialBranch);
}
};
}
}

View File

@@ -5,8 +5,8 @@ import com.github.sdorra.shiro.SubjectAware;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.After;
import org.junit.Before;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -38,14 +38,14 @@ public class GitModifyCommand_LFSTest extends AbstractGitCommandTestBase {
private final LfsBlobStoreFactory lfsBlobStoreFactory = mock(LfsBlobStoreFactory.class);
@Before
public void registerFilter() {
new GitLfsFilterContextListener(contextProvider).contextInitialized(null);
@BeforeClass
public static void registerFilter() {
new GitLfsFilterContextListener().contextInitialized(null);
}
@After
public void unregisterFilter() {
new GitLfsFilterContextListener(contextProvider).contextDestroyed(null);
@AfterClass
public static void unregisterFilter() {
new GitLfsFilterContextListener().contextDestroyed(null);
}
@Test