Skip to content

Commit

Permalink
Add blank commit/duplicate branch guards to Git CLI delegate
Browse files Browse the repository at this point in the history
  • Loading branch information
fbiville committed Jan 12, 2022
1 parent f2a4076 commit aee2e76
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 18 deletions.
36 changes: 36 additions & 0 deletions src/main/java/com/neo4j/sandbox/git/CommandIOException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.neo4j.sandbox.git;

import java.io.IOException;

class CommandIOException extends IOException {

private final String stdout;
private final String stderr;

public CommandIOException(String faultyCommand, int status, String stdout, String stderr) {
super(String.format("Expected Git operation %s to succeed but got exit status %d. See error below%n%s",
faultyCommand, status, combinedOutputs(stdout, stderr)));

this.stdout = stdout;
this.stderr = stderr;
}

public boolean commandOutputContains(String msg) {
return this.stdout.contains(msg) || this.stderr.contains(msg);
}

private static String combinedOutputs(String stdout, String stderr) {
StringBuilder builder = new StringBuilder();
builder.append(String.format("=====%n"));
builder.append(String.format("Error stream%n"));
builder.append(String.format("=====%n"));
builder.append(stderr);
builder.append("\n");
builder.append(String.format("=====%n"));
builder.append(String.format("Output stream%n"));
builder.append(String.format("=====%n"));
builder.append(stdout);
builder.append("\n");
return builder.toString();
}
}
38 changes: 20 additions & 18 deletions src/main/java/com/neo4j/sandbox/git/GitCli.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.TimeUnit;

// @Service
public class GitCli implements GitOperations {

private static final Logger LOGGER = LoggerFactory.getLogger(GitCli.class);

private static final String GIT_LOCALE = "en_US";

@Override
public void clone(Path cloneLocation, String repositoryUri, String token) throws IOException {
File workingDirectory = cloneLocation.toFile();
Expand All @@ -25,6 +27,9 @@ public void clone(Path cloneLocation, String repositoryUri, String token) throws

@Override
public void checkoutNewBranch(Path cloneLocation, String branchName) throws IOException {
if (branchExists(cloneLocation, branchName)) {
throw new DuplicateBranchException();
}
executeCommand(cloneLocation.toFile(), "git", "checkout", "-b", branchName);
}

Expand All @@ -34,7 +39,10 @@ public void commitAll(Path cloneLocation, String message) throws IOException {
executeCommand(workingDirectory, "git", "add", "--all");
try {
executeCommand(workingDirectory, "git", "commit", "-m", message);
} catch (IOException e) {
} catch (CommandIOException e) {
if (e.commandOutputContains("nothing to commit")) {
throw new BlankCommitException(e);
}
throw new CommitException(e);
}
}
Expand All @@ -57,14 +65,22 @@ public String currentBranch(Path cloneLocation) throws IOException {
return stdout.substring(stdout.lastIndexOf("/") + 1);
}

private static void executeCommand(File workingDirectory, String... commands) throws IOException {
private boolean branchExists(Path cloneLocation, String branchName) throws IOException {
String remoteUrl = executeCommand(cloneLocation.toFile(), "git", "remote", "get-url", "origin");
String output = executeCommand(cloneLocation.toFile(), "git", "ls-remote", "--heads", remoteUrl.trim(), branchName);
return !output.isBlank();
}

private static String executeCommand(File workingDirectory, String... commands) throws IOException {
Process process = runProcess(workingDirectory, commands);
assertSuccessfulExitCode(process, commands);
return stdout(process);
}

private static Process runProcess(File workingDirectory, String... commands) throws IOException {
String command = String.join(" ", commands);
ProcessBuilder processBuilder = new ProcessBuilder(commands);
processBuilder.environment().put("LC_ALL", GIT_LOCALE);
processBuilder.directory(workingDirectory);
Process process = processBuilder.start();
waitForProcess(command, process);
Expand All @@ -76,10 +92,7 @@ private static void assertSuccessfulExitCode(Process process, String[] commands)
String command = String.join(" ", commands);
LOGGER.trace("Git command {} exited with status code {}", command, exitStatus);
if (exitStatus != 0) {
String error = combinedOutputs(process);
throw new IOException(
String.format("Expected Git operation %s to succeed but got exit status %d. See error below%n%s",
command, exitStatus, error));
throw new CommandIOException(command, exitStatus, stdout(process), stderr(process));
}
}

Expand All @@ -93,17 +106,6 @@ private static void waitForProcess(String command, Process process) throws IOExc
}
}

private static String combinedOutputs(Process process) throws IOException {
StringBuilder builder = new StringBuilder();
builder.append(String.format("Error stream%n"));
builder.append(stderr(process));
builder.append("\n");
builder.append(String.format("Output stream%n"));
builder.append(stdout(process));
builder.append("\n");
return builder.toString();
}

private static String stdout(Process process) throws IOException {
return new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
}
Expand Down

0 comments on commit aee2e76

Please sign in to comment.