/* * Copyright 2016 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.thoughtworks.go.config.materials; import com.thoughtworks.go.config.CaseInsensitiveString; import com.thoughtworks.go.config.PipelineConfig; import com.thoughtworks.go.domain.MaterialRevision; import com.thoughtworks.go.domain.materials.*; import com.thoughtworks.go.util.command.EnvironmentVariableContext; import com.thoughtworks.go.util.command.InMemoryStreamConsumer; import com.thoughtworks.go.util.command.ProcessOutputStreamConsumer; import com.thoughtworks.go.util.command.UrlArgument; import org.apache.commons.lang.StringUtils; import java.io.File; import java.util.Map; import static com.thoughtworks.go.util.command.EnvironmentVariableContext.escapeEnvironmentVariable; /** * @understands a source control repository and its configuration */ public abstract class ScmMaterial extends AbstractMaterial { public static final String GO_REVISION = "GO_REVISION"; public static final String GO_TO_REVISION = "GO_TO_REVISION"; public static final String GO_FROM_REVISION = "GO_FROM_REVISION"; protected Filter filter; protected String folder; protected boolean autoUpdate = true; protected boolean invertFilter = false; public ScmMaterial(String typeName) { super(typeName); } @Override protected void appendPipelineUniqueCriteria(Map<String, Object> basicCriteria) { basicCriteria.put("dest", folder); } public File workingdir(File baseFolder) { if (getFolder() == null) { return baseFolder; } return new File(baseFolder, getFolder()); } public String updatingTarget() { return StringUtils.isEmpty(getFolder()) ? "files" : getFolder(); } public void toJson(Map json, Revision revision) { json.put("folder", getFolder() == null ? "" : getFolder()); json.put("scmType", getTypeForDisplay()); json.put("location", getLocation()); if (!CaseInsensitiveString.isBlank(getName())) { json.put("materialName", CaseInsensitiveString.str(getName())); } json.put("action", "Modified"); } //most of the material such as hg, git, p4 all print the file from the root without '/' //but subverion print it with '/', we standarize it here. look at the implementation of subversion as well. public boolean matches(String name, String regex) { if (regex.startsWith("/")) { regex = regex.substring(1); } return name.matches(regex); } public void checkout(File baseDir, Revision revision, SubprocessExecutionContext execCtx) { InMemoryStreamConsumer output = ProcessOutputStreamConsumer.inMemoryConsumer(); this.updateTo(output, baseDir, new RevisionContext(revision), execCtx); } public abstract String getUserName(); public abstract String getPassword(); public abstract String getEncryptedPassword(); public abstract boolean isCheckExternals(); public abstract String getUrl(); protected abstract UrlArgument getUrlArgument(); protected abstract String getLocation(); public void setFilter(Filter filter) { this.filter = filter; } public void emailContent(StringBuilder content, Modification modification) { content.append(getTypeForDisplay() + ": " + getLocation()).append('\n').append( String.format("revision: %s, modified by %s on %s", modification.getRevision(), modification.getUserName(), modification.getModifiedTime())) .append('\n') .append(modification.getComment()); } public String getDescription() { return getUriForDisplay(); } public String getUriForDisplay() { return getUrlArgument().forDisplay(); } public void populateEnvironmentContext(EnvironmentVariableContext environmentVariableContext, MaterialRevision materialRevision, File workingDir) { String toRevision = materialRevision.getRevision().getRevision(); String fromRevision = materialRevision.getOldestRevision().getRevision(); setGoRevisionVariables(environmentVariableContext, fromRevision, toRevision); } private void setGoRevisionVariables(EnvironmentVariableContext environmentVariableContext, String fromRevision, String toRevision) { setVariableWithName(environmentVariableContext, toRevision, GO_REVISION); setVariableWithName(environmentVariableContext, toRevision, GO_TO_REVISION); setVariableWithName(environmentVariableContext, fromRevision, GO_FROM_REVISION); } protected void setVariableWithName(EnvironmentVariableContext environmentVariableContext, String value, String propertyName) { if (!CaseInsensitiveString.isBlank(this.name)) { environmentVariableContext.setProperty(propertyName + "_" + escapeEnvironmentVariable(this.name.toUpper()), value, false); return; } String scrubbedFolder = escapeEnvironmentVariable(folder); if (!StringUtils.isEmpty(scrubbedFolder)) { environmentVariableContext.setProperty(propertyName + "_" + scrubbedFolder, value, false); } else { environmentVariableContext.setProperty(propertyName, value, false); } } public String getFolder() { return folder; } public String getDisplayName() { return name == null ? getUriForDisplay() : CaseInsensitiveString.str(name); } public boolean isAutoUpdate() { return autoUpdate; } public boolean getAutoUpdate() { return autoUpdate; } public void setAutoUpdate(boolean value) { autoUpdate = value; } public boolean isInvertFilter() { return invertFilter; } public boolean getInvertFilter() { return invertFilter; } public void setInvertFilter(boolean value) { invertFilter = value; } public final MatchedRevision createMatchedRevision(Modification modification, String searchString) { return new MatchedRevision(searchString, getShortRevision(modification.getRevision()), modification.getRevision(), modification.getUserName(), modification.getModifiedTime(), modification.getComment()); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } if (!super.equals(o)) { return false; } ScmMaterial that = (ScmMaterial) o; if (folder != null ? !folder.equals(that.folder) : that.folder != null) { return false; } return true; } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + (folder != null ? folder.hashCode() : 0); return result; } public static String changesetUrl(Modification modification, String baseUrl, final long id) { return baseUrl + "/api/materials/" + id + "/changeset/" + modification.getRevision() + ".xml"; } public Boolean isUsedInFetchArtifact(PipelineConfig pipelineConfig) { return false; } // TODO: Consider renaming this to dest since we use that word in the UI & Config public void setFolder(String folder) { this.folder = folder; } public Revision oldestRevision(Modifications modifications) { return Modification.oldestRevision(modifications); } @Override public boolean supportsDestinationFolder() { return true; } }