package se.bjurr.sbcc.commits;
import static com.google.common.base.Joiner.on;
import static se.bjurr.sbcc.data.SbccChangeSetBuilder.changeSetBuilder;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.atlassian.bitbucket.io.LineReader;
import com.atlassian.bitbucket.io.LineReaderOutputHandler;
import com.atlassian.bitbucket.scm.CommandOutputHandler;
import se.bjurr.sbcc.data.SbccChangeSet;
import se.bjurr.sbcc.data.SbccPerson;
import se.bjurr.sbcc.settings.SbccSettings;
public class RevListOutputHandler extends LineReaderOutputHandler
implements CommandOutputHandler<List<SbccChangeSet>> {
private static Logger logger = LoggerFactory.getLogger(RevListOutputHandler.class);
private static final String RAW_BODY = "%B";
private static final String NEW_LINE = "%n";
private static final String COMMITTER_EMAIL = "%cE";
private static final String COMMITTER_NAME = "%cN";
private static final String AUTHOR_EMAIL = "%aE";
private static final String AUTHOR_NAME = "%aN";
private static final String PARENT_HASH = "%P";
private static final String START_OF_TEXT = "%x02";
private static final String COMMIT_HASH = "%H";
private static final String END = "%x03END%x04";
/** https://git-scm.com/docs/git-rev-list */
public static final String FORMAT = //
COMMIT_HASH
+ START_OF_TEXT
+ // 0
PARENT_HASH
+ START_OF_TEXT
+ // 1
COMMITTER_NAME
+ START_OF_TEXT
+ // 2
COMMITTER_EMAIL
+ START_OF_TEXT
+ // 3
AUTHOR_NAME
+ START_OF_TEXT
+ // 4
AUTHOR_EMAIL
+ NEW_LINE
+ // 5
RAW_BODY
+ NEW_LINE
+ END; // 6
private static final String OUTPUT_END = "\u0003END\u0004";
private static final String OUTPUT_NEW_LINE = "\u0002";
private final List<SbccChangeSet> commits = new ArrayList<>();
private final SbccSettings settings;
public RevListOutputHandler(SbccSettings settings) {
super(Charset.forName("UTF-8"));
this.settings = settings;
}
@Nullable
@Override
public List<SbccChangeSet> getOutput() {
return commits;
}
@Override
protected void processReader(LineReader lineReader) throws IOException {
String line;
while ((line = lineReader.readLine()) != null) {
if (!line.startsWith("commit ")) {
throw new RuntimeException("unexpected line: " + line);
}
line = lineReader.readLine();
String[] commitData = line.split(OUTPUT_NEW_LINE);
try {
String ref = commitData[0];
boolean isMerge = commitData[1].contains(" ");
if (isMerge && settings.shouldExcludeMergeCommits()) {
while ((line = lineReader.readLine()) != null && !line.equals(OUTPUT_END)) {
// Read the rest of this object before continuing with next object
}
continue;
}
String committerName = commitData[2];
String committerEmail = commitData[3];
SbccPerson committer = new SbccPerson(committerName, committerEmail);
String authorName = commitData[4];
String authorEmail = commitData[5];
SbccPerson author = new SbccPerson(authorName, authorEmail);
String message = parseMessage(lineReader);
SbccChangeSet sbccChangeSet =
changeSetBuilder() //
.withCommitter(committer) //
.withAuthor(author) //
.withId(ref) //
.withMessage(message) //
.build();
commits.add(sbccChangeSet);
} catch (Exception e) {
logger.error("Unable to parse commit, commit data found:\n" + on('\n').join(commitData), e);
}
}
}
private String parseMessage(LineReader lineReader) throws IOException {
String message = "";
String line;
while ((line = lineReader.readLine()) != null && !line.equals(OUTPUT_END)) {
if (!message.isEmpty()) {
message += "\n";
}
message += line.trim();
}
return message.trim();
}
}