package com.codicesoftware.plugins.bamboo40;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.atlassian.bamboo.commit.*;
import com.atlassian.bamboo.repository.AbstractRepository;
import com.atlassian.bamboo.repository.Repository;
import com.atlassian.bamboo.repository.RepositoryException;
import com.atlassian.bamboo.repository.BranchDetectionCapableRepository;
import com.atlassian.bamboo.utils.error.ErrorCollection;
import com.atlassian.bamboo.v2.build.BuildRepositoryChanges;
import com.atlassian.bamboo.v2.build.BuildContext;
import com.atlassian.bamboo.v2.build.BuildRepositoryChangesImpl;
import com.atlassian.bamboo.v2.build.repository.CustomSourceDirectoryAwareRepository;
import com.atlassian.bamboo.ww2.actions.build.admin.create.BuildConfiguration;
import com.atlassian.bamboo.plan.branch.VcsBranch;
import com.atlassian.bamboo.plan.branch.VcsBranchImpl;
import com.codicesoftware.plastic.commontypes.BranchInfo;
import com.codicesoftware.plastic.query.QueryCommands;
import com.codicesoftware.plastic.query.WhereClauseBuilder;
import com.codicesoftware.plastic.core.PlasticException;
import com.codicesoftware.plugins.bamboo40.changesproviders.ChangesProviderFactory;
import com.codicesoftware.plugins.bamboo40.changesproviders.IChangesProvider;
public class PlasticRepository extends AbstractRepository implements CustomSourceDirectoryAwareRepository, BranchDetectionCapableRepository {
private static final long serialVersionUID = -2933468731569230963L;
private static final Logger log = Logger.getLogger(PlasticRepository.class);
public final PlasticRepositoryData repositoryData = new PlasticRepositoryData();
private static PlasticClient plasticClient = null;
@NotNull
private VcsBranch vcsBranch;
public PlasticRepository()
{
if(plasticClient == null) {
plasticClient = new PlasticClient();
}
}
//must be implemented (AbstractRepository)
public String getHost() {
return "localhost";
}
@NotNull
public String getName() {
return Constants.NAME;
}
public boolean isRepositoryDifferent(@NotNull Repository repository) {
if (repository instanceof PlasticRepository) {
PlasticRepository repo = (PlasticRepository)repository;
boolean result = !new EqualsBuilder()
.append(this.repositoryData.repository, repo.repositoryData.repository)
.append(this.repositoryData.repositoryserver, repo.repositoryData.repositoryserver)
.append(this.repositoryData.branch, repo.repositoryData.branch)
.isEquals();
log.debug("isRepositoryDifferent: " + result);
return result;
}
return true;
}
@SuppressWarnings("unchecked")
@NotNull
public BuildRepositoryChanges collectChangesSinceLastBuild(@NotNull String planKey,
@Nullable String lastVcsRevisionKey) throws RepositoryException {
String lastCsetBuilt = lastVcsRevisionKey == null ? "-1" : lastVcsRevisionKey;
log.debug("collectChanges: last vcs key built: " + lastCsetBuilt);
IChangesProvider changesProvider = ChangesProviderFactory.get().getChangesProvider(repositoryData);
List<Commit> newerCommits = new ArrayList<Commit>();
String lastCsetOnRep = changesProvider.getChangesSinceLastBuilt(lastCsetBuilt, newerCommits);
log.debug(String.format(
"collectChanges: last changeset on rep:%s, number of commits:%s",
lastCsetBuilt,
newerCommits.size()));
return new BuildRepositoryChangesImpl(lastCsetOnRep, newerCommits);
}
@NotNull
public String retrieveSourceCode(@NotNull BuildContext buildContext, @Nullable String vcsRevisionKey, @NotNull File file)
throws RepositoryException {
return retrieveSourceCode(buildContext.getPlanKey(), vcsRevisionKey);
}
@NotNull
public String retrieveSourceCode(@NotNull BuildContext buildContext,
@Nullable String vcsRevisionKey) throws RepositoryException {
return retrieveSourceCode(buildContext.getPlanKey(), vcsRevisionKey);
}
@NotNull
public String retrieveSourceCode(@NotNull String planKey, @Nullable String vcsRevisionKey)
throws RepositoryException {
IChangesProvider changesProvider = ChangesProviderFactory.get().getChangesProvider(repositoryData);
return changesProvider.updateWorkspace(buildDirectoryManager.getBaseBuildWorkingDirectory(), planKey, vcsRevisionKey);
}
public void prepareConfigObject(@NotNull BuildConfiguration buildConfiguration) {
// Nothing to do here
}
@Override
public void addDefaultValues(@NotNull BuildConfiguration buildConfiguration)
{
super.addDefaultValues(buildConfiguration);
buildConfiguration.setProperty(Constants.PLASTIC_REPOSITORY, Constants.PLASTIC_DEFAULT_REPOSITORY_NAME);
buildConfiguration.setProperty(Constants.PLASTIC_REPOSITORYSERVER, Utils.getDefaultRepServer());
buildConfiguration.setProperty(Constants.PLASTIC_BRANCH_TO_TRACK, Constants.MAIN);
}
public void populateFromConfig(@NotNull HierarchicalConfiguration config){
super.populateFromConfig(config);
repositoryData.repository = config.getString(Constants.PLASTIC_REPOSITORY, Constants.PLASTIC_DEFAULT_REPOSITORY_NAME);
repositoryData.repositoryserver = config.getString(Constants.PLASTIC_REPOSITORYSERVER, Utils.getDefaultRepServer());
repositoryData.branch = config.getString(Constants.PLASTIC_BRANCH_TO_TRACK, Constants.MAIN);
vcsBranch = new VcsBranchImpl(StringUtils.defaultIfEmpty(repositoryData.branch, Constants.MAIN));
log.debug("populateFromConfig: "+ repositoryData.printValues());
}
@NotNull
public HierarchicalConfiguration toConfiguration() {
HierarchicalConfiguration config = super.toConfiguration();
config.setProperty(Constants.PLASTIC_REPOSITORY, repositoryData.repository);
config.setProperty(Constants.PLASTIC_REPOSITORYSERVER, repositoryData.repositoryserver);
config.setProperty(Constants.PLASTIC_BRANCH_TO_TRACK, repositoryData.branch);
log.debug("toConfiguration: "+ repositoryData.printValues());
return config;
}
@NotNull
public ErrorCollection validate(@NotNull BuildConfiguration buildConfiguration) {
ErrorCollection errorCollection = super.validate(buildConfiguration);
String repName = buildConfiguration.getString(Constants.PLASTIC_REPOSITORY);
String repServer = buildConfiguration.getString(Constants.PLASTIC_REPOSITORYSERVER);
String branch = buildConfiguration.getString(Constants.PLASTIC_BRANCH_TO_TRACK);
if (repName == null || repName.trim().length() == 0) {
errorCollection.addError(Constants.PLASTIC_REPOSITORY, "The repository name must be specified");
}
try {
BranchInfo brInfo;
if (branch.equals(Constants.BR_NAME))
brInfo = Utils.getBranchInfo(Constants.MAIN, repName, repServer);
else
brInfo = Utils.getBranchInfo(branch, repName, repServer);
if (brInfo == null)
throw new Exception("Branch not found:" + branch);
}
catch(Exception ex) {
errorCollection.addError(Constants.PLASTIC_BRANCH_TO_TRACK,
"The specified branch does not exist in the specified repository and server.");
}
return errorCollection;
}
/*BranchDetectionCapableRepository*/
public VcsBranch getVcsBranch() {
return vcsBranch;
}
public void setVcsBranch(@NotNull final VcsBranch branch) {
this.vcsBranch = branch;
this.repositoryData.branch = branch.getName();
}
@NotNull
public List<VcsBranch> getOpenBranches() throws RepositoryException {
BranchInfo currentMainTrackedBranch = Utils.getBranchInfo(
repositoryData.branch, repositoryData.repository, repositoryData.repositoryserver);
List<VcsBranch> openBranches = new ArrayList<VcsBranch>();
try {
WhereClauseBuilder whereBuilder = new WhereClauseBuilder();
whereBuilder.addClause("parent", "=", currentMainTrackedBranch.getFullBranchNameWithoutBranchPreffix());
BranchInfo[] branchesByName = QueryCommands.GetBranches(Utils.getRepositorySpec(repositoryData), whereBuilder.getWhereString());
log.debug("Getting open branches from branch"+ repositoryData.branch + ". Count: " + branchesByName.length);
for(BranchInfo br : branchesByName) {
openBranches.add(new VcsBranchImpl(br.getFullBranchNameWithoutBranchPreffix()));
}
} catch (PlasticException e) {
throw new RepositoryException(String.format(
"getOpenBranches: An error occurred when retrieving child branches of branch:%s",repositoryData.branch), e);
}
return openBranches;
}
public CommitContext getLastCommit() throws RepositoryException {
return null;
}
public CommitContext getFirstCommit() throws RepositoryException {
return null;
}
}