package org.paylogic.jenkins.advancedscm.backends;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.plugins.mercurial.MercurialSCM;
import lombok.extern.java.Log;
import org.paylogic.jenkins.advancedscm.Branch;
import org.paylogic.jenkins.advancedscm.backends.helpers.AdvancedHgExe;
import org.paylogic.jenkins.advancedscm.exceptions.*;
import org.paylogic.jenkins.upmerge.releasebranch.ReleaseBranch;
import org.paylogic.jenkins.upmerge.releasebranch.ReleaseBranchImpl;
import org.paylogic.jenkins.upmerge.releasebranch.ReleaseBranchInvalidException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
/**
* Mercurial Implementation of AdvancedSCMManager
*/
@Log
public class MercurialBackend extends BaseBackend {
private String hgExe;
private AdvancedHgExe advancedHgExe;
private AbstractBuild build;
private PrintStream l;
/**
* Please do not instantiate objects of this class yourself, use SCMManagerFactory.
*/
public MercurialBackend(AbstractBuild build, Launcher launcher, BuildListener listener, MercurialSCM scm) throws IOException, InterruptedException {
this.build = build;
this.l = listener.getLogger();
this.advancedHgExe = new AdvancedHgExe(scm, launcher, build, listener);
this.repoPath = this.advancedHgExe.getFilePath();
}
public List<Branch> getBranches(boolean all) {
String rawBranches = "";
String[] args = new String[] {};
if (all) {
args = new String[]{"-c"};
}
try {
rawBranches = this.advancedHgExe.branches(args);
} catch (Exception e) {
l.append(e.toString());
return new ArrayList<Branch>();
}
List<Branch> list = new ArrayList<Branch>();
for (String line: rawBranches.split("\n")) {
// line should contain: <branchName> <revision>:<hash> (yes, with lots of whitespace)
String[] seperatedByWhitespace = line.split("\\s+");
String branchName = seperatedByWhitespace[0];
String[] seperatedByColon = seperatedByWhitespace[1].split(":");
int revision = Integer.parseInt(seperatedByColon[0]);
String hash = seperatedByColon[1];
list.add(new Branch(branchName, revision, hash));
}
return list;
}
public String getBranch() throws AdvancedSCMException {
String branchName = "";
try {
branchName = this.advancedHgExe.branch();
} catch (Exception e) {
throw new AdvancedSCMException(e.toString());
}
return branchName;
}
public void update(String revision) throws AdvancedSCMException{
String output = "";
try {
output = this.advancedHgExe.update(revision);
} catch (Exception e) {
log.log(Level.SEVERE, "Exception occured during update of workspace.", e);
l.append(e.toString());
throw new AdvancedSCMException(e.getMessage());
}
if (output.contains("abort: unknown revision")) {
throw new UnknownRevisionException(output);
} else if (output.contains("abort:")) {
throw new AdvancedSCMException(output);
}
}
public void updateClean(String revision) throws AdvancedSCMException{
String output = "";
try {
output = this.advancedHgExe.updateClean(revision);
} catch (Exception e) {
log.log(Level.SEVERE, "Exception occurred during update of workspace.", e);
l.append(e.toString());
throw new AdvancedSCMException(e.getMessage());
}
if (output.contains("abort: unknown revision")) {
throw new UnknownRevisionException(output);
} else if (output.contains("abort:")) {
throw new AdvancedSCMException(output);
}
clean();
}
public void stripLocal() throws AdvancedSCMException {
try {
String[] out = this.advancedHgExe.out();
if (out.length > 0) {
String output = "";
try {
output = this.advancedHgExe.strip(out);
} catch (Exception e) {
log.log(Level.SEVERE, "Exception occurred during strip.", e);
l.append(e.toString());
throw new AdvancedSCMException(e.getMessage());
}
if (output.contains("abort:")) {
throw new AdvancedSCMException(output);
}
}
} catch (Exception e) {
throw new AdvancedSCMException(e.getMessage());
}
}
public void clean() throws AdvancedSCMException{
String output = "";
try {
output = this.advancedHgExe.clean();
} catch (Exception e) {
log.log(Level.SEVERE, "Exception occured during cleaning of workspace.", e);
l.append(e.toString());
throw new AdvancedSCMException(e.getMessage());
}
if (output.contains("abort:")) {
throw new AdvancedSCMException(output);
}
}
public void closeBranch(String branch, String message, String username) throws AdvancedSCMException {
String output = "";
update(branch);
try {
output = this.advancedHgExe.commit(message, username, "--close-branch");
} catch (Exception e) {
log.log(Level.SEVERE, "Exception occured while trying to close branch commit.");
l.append(e.toString());
throw new AdvancedSCMException(e.getMessage());
}
if (output.contains("abort:")) {
throw new AdvancedSCMException(output);
}
}
public void mergeWorkspaceWith(String revision, String updateTo) throws AdvancedSCMException {
if (updateTo != null) {
this.update(updateTo);
}
String output = "";
try {
output = this.advancedHgExe.merge(revision);
} catch (Exception e) {
log.log(Level.SEVERE, "Exception occurred during merge of workspace with " + revision + ".", e);
l.append(e.toString());
if (output.contains("conflicts during merge") || e.toString().contains("conflicts during merge")) {
log.log(Level.INFO, "Throwing MergeConflictException.");
throw new MergeConflictException(output);
} else {
throw new AdvancedSCMException(e.getMessage());
}
}
if (output.contains("abort: merging") && output.contains("has no effect")) {
throw new MergeWontHaveEffectException(output);
} else if (output.contains("abort:")) {
throw new AdvancedSCMException(output);
}
}
public void mergeHeads(String message, String username) throws AdvancedSCMException {
String output = "";
try {
output = this.advancedHgExe.merge("");
} catch (Exception e) {
log.log(Level.SEVERE, "Exception occurred during merge of the heads.", e);
l.append(e.toString());
if (output.contains("conflicts during merge") || e.toString().contains("conflicts during merge")) {
log.log(Level.INFO, "Throwing MergeConflictException.");
throw new MergeConflictException(output);
} else {
throw new AdvancedSCMException(e.getMessage());
}
}
commit(message, username);
}
public void commit(String message, String username) throws AdvancedSCMException {
String output = "";
try {
output = this.advancedHgExe.commit(message, username);
} catch (Exception e) {
log.log(Level.SEVERE, "Exception occurred during commit.", e);
l.append(e.toString());
throw new AdvancedSCMException(e.getMessage());
}
if (output.contains("abort:")) {
throw new AdvancedSCMException(output);
}
}
public void push(String... branchNames) throws AdvancedSCMException {
String output = "";
try {
output = this.advancedHgExe.push(branchNames);
} catch (Exception e) {
log.log(Level.SEVERE, "Execption during push :(", e);
l.append(e.toString());
throw new AdvancedSCMException(e.getMessage());
}
if (output.contains("abort: push creates new remote head")) {
throw new PushCreatesNewRemoteHeadException(output);
} else if (output.contains("abort:")) {
throw new AdvancedSCMException(output);
}
}
public void pull() throws AdvancedSCMException {
this.pull("");
}
public void pull(String remote) throws AdvancedSCMException {
this.pull(remote, "");
}
public void pull(String remote, String branch) throws AdvancedSCMException {
String output = "";
try {
if (remote == null || remote.isEmpty()) {
output = this.advancedHgExe.pullChanges();
}
else if (branch.isEmpty()) {
remote = this.advancedHgExe.pullChanges(remote);
}
else {
remote = this.advancedHgExe.pullChanges(remote, branch);
}
} catch (Exception e) {
log.log(Level.SEVERE, "Error during Mercurial command exceution");
l.append(e.toString());
throw new AdvancedSCMException(e.getMessage());
}
if (output.contains("abort:")) {
throw new AdvancedSCMException(output);
}
}
public ReleaseBranch getReleaseBranch(String branch) throws ReleaseBranchInvalidException {
return new ReleaseBranchImpl(branch, "default");
}
public ReleaseBranch createReleaseBranch(
String branch, String releaseFilePath, String releaseFileContent, String message, String username)
throws AdvancedSCMException
{
try {
this.update("default");
this.advancedHgExe.branch(branch);
if (releaseFilePath != null && !releaseFilePath.isEmpty()
&& releaseFileContent != null && !releaseFileContent.isEmpty()) {
this.createFile(releaseFilePath, releaseFileContent);
this.advancedHgExe.add(releaseFilePath, releaseFileContent);
}
this.advancedHgExe.commit(message, username);
return getReleaseBranch(branch);
} catch (Exception e) {
throw new AdvancedSCMException(e.getMessage());
}
}
}