/*************************GO-LICENSE-START********************************* * Copyright 2014 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. *************************GO-LICENSE-END***********************************/ package com.thoughtworks.go.server.service.materials; import com.thoughtworks.go.config.materials.PluggableSCMMaterial; import com.thoughtworks.go.config.materials.SubprocessExecutionContext; import com.thoughtworks.go.domain.MaterialInstance; import com.thoughtworks.go.domain.config.Configuration; import com.thoughtworks.go.domain.config.ConfigurationProperty; import com.thoughtworks.go.domain.materials.Modification; import com.thoughtworks.go.domain.materials.Modifications; import com.thoughtworks.go.domain.materials.Revision; import com.thoughtworks.go.domain.materials.scm.PluggableSCMMaterialRevision; import com.thoughtworks.go.domain.scm.SCM; import com.thoughtworks.go.plugin.access.scm.SCMExtension; import com.thoughtworks.go.plugin.access.scm.SCMProperty; import com.thoughtworks.go.plugin.access.scm.SCMPropertyConfiguration; import com.thoughtworks.go.plugin.access.scm.material.MaterialPollResult; import com.thoughtworks.go.plugin.access.scm.revision.ModifiedAction; import com.thoughtworks.go.plugin.access.scm.revision.ModifiedFile; import com.thoughtworks.go.plugin.access.scm.revision.SCMRevision; import com.thoughtworks.go.plugin.api.response.Result; import com.thoughtworks.go.server.persistence.MaterialRepository; import com.thoughtworks.go.server.transaction.TransactionTemplate; import com.thoughtworks.go.util.json.JsonHelper; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import java.io.File; import java.util.List; import java.util.Map; public class PluggableSCMMaterialPoller implements MaterialPoller<PluggableSCMMaterial> { private MaterialRepository materialRepository; private SCMExtension scmExtension; private TransactionTemplate transactionTemplate; public PluggableSCMMaterialPoller(MaterialRepository materialRepository, SCMExtension scmExtension, TransactionTemplate transactionTemplate) { this.materialRepository = materialRepository; this.scmExtension = scmExtension; this.transactionTemplate = transactionTemplate; } @Override public List<Modification> latestModification(final PluggableSCMMaterial material, File baseDir, SubprocessExecutionContext execCtx) { SCMPropertyConfiguration scmPropertyConfiguration = buildSCMPropertyConfigurations(material.getScmConfig()); final MaterialInstance materialInstance = materialRepository.findMaterialInstance(material); MaterialPollResult pollResult = scmExtension.getLatestRevision(material.getPluginId(), scmPropertyConfiguration, materialInstance.getAdditionalDataMap(), baseDir.getAbsolutePath()); final Map<String, String> materialData = pollResult.getMaterialData(); if (materialInstance.requiresUpdate(materialData)) { updateAdditionalData(materialInstance.getId(), materialData); } SCMRevision scmRevision = pollResult.getLatestRevision(); return scmRevision == null ? new Modifications() : new Modifications(getModification(scmRevision)); } @Override public List<Modification> modificationsSince(final PluggableSCMMaterial material, File baseDir, final Revision revision, SubprocessExecutionContext execCtx) { SCMPropertyConfiguration scmPropertyConfiguration = buildSCMPropertyConfigurations(material.getScmConfig()); MaterialInstance materialInstance = materialRepository.findMaterialInstance(material); PluggableSCMMaterialRevision pluggableSCMMaterialRevision = (PluggableSCMMaterialRevision) revision; SCMRevision previouslyKnownRevision = new SCMRevision(pluggableSCMMaterialRevision.getRevision(), pluggableSCMMaterialRevision.getTimestamp(), null, null, pluggableSCMMaterialRevision.getData(), null); MaterialPollResult pollResult = scmExtension.latestModificationSince(material.getPluginId(), scmPropertyConfiguration, materialInstance.getAdditionalDataMap(), baseDir.getAbsolutePath(), previouslyKnownRevision); final Map<String, String> materialData = pollResult.getMaterialData(); if (materialInstance.requiresUpdate(materialData)) { updateAdditionalData(materialInstance.getId(), materialData); } List<SCMRevision> scmRevisions = pollResult.getRevisions(); return getModifications(scmRevisions); } @Override public void checkout(PluggableSCMMaterial material, File baseDir, Revision revision, SubprocessExecutionContext execCtx) { SCMPropertyConfiguration scmPropertyConfiguration = buildSCMPropertyConfigurations(material.getScmConfig()); MaterialInstance materialInstance = materialRepository.findMaterialInstance(material); PluggableSCMMaterialRevision pluggableSCMMaterialRevision = (PluggableSCMMaterialRevision) revision; SCMRevision scmRevision = new SCMRevision( pluggableSCMMaterialRevision.getRevision(), pluggableSCMMaterialRevision.getTimestamp(), null, null, pluggableSCMMaterialRevision.getData(), null); Result result = scmExtension.checkout(material.getPluginId(), scmPropertyConfiguration, baseDir.getAbsolutePath(), scmRevision); if(!result.isSuccessful()) throw new RuntimeException("Failed to perform checkout on pluggable SCM"); } private SCMPropertyConfiguration buildSCMPropertyConfigurations(SCM scmConfig) { SCMPropertyConfiguration scmPropertyConfiguration = new SCMPropertyConfiguration(); populateConfiguration(scmConfig.getConfiguration(), scmPropertyConfiguration); return scmPropertyConfiguration; } private void populateConfiguration(Configuration configuration, com.thoughtworks.go.plugin.api.config.Configuration pluginConfiguration) { for (ConfigurationProperty configurationProperty : configuration) { pluginConfiguration.add(new SCMProperty(configurationProperty.getConfigurationKey().getName(), configurationProperty.getValue())); } } private void updateAdditionalData(final long materialId, final Map<String, String> materialData) { transactionTemplate.execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus transactionStatus) { MaterialInstance materialInstance = materialRepository.find(materialId); String additionalData = (materialData == null || materialData.isEmpty()) ? null : JsonHelper.toJsonString(materialData); materialInstance.setAdditionalData(additionalData); materialRepository.saveOrUpdate(materialInstance); return materialInstance; } }); } private List<Modification> getModifications(List<SCMRevision> scmRevisions) { Modifications modifications = new Modifications(); if (scmRevisions == null || scmRevisions.isEmpty()) { return modifications; } for (SCMRevision scmRevision : scmRevisions) { modifications.add(getModification(scmRevision)); } return modifications; } private Modification getModification(SCMRevision scmRevision) { String additionalData = (scmRevision.getData() == null || scmRevision.getData().isEmpty()) ? null : JsonHelper.toJsonString(scmRevision.getData()); Modification modification = new Modification(scmRevision.getUser(), scmRevision.getRevisionComment(), null, scmRevision.getTimestamp(), scmRevision.getRevision(), additionalData); if (scmRevision.getModifiedFiles() != null && !scmRevision.getModifiedFiles().isEmpty()) { for (ModifiedFile modifiedFile : scmRevision.getModifiedFiles()) { modification.createModifiedFile(modifiedFile.getFileName(), null, convertAction(modifiedFile.getAction())); } } return modification; } private com.thoughtworks.go.domain.materials.ModifiedAction convertAction(ModifiedAction modifiedFile) { if (modifiedFile == ModifiedAction.added) { return com.thoughtworks.go.domain.materials.ModifiedAction.added; } else if (modifiedFile == ModifiedAction.modified) { return com.thoughtworks.go.domain.materials.ModifiedAction.modified; } else if (modifiedFile == ModifiedAction.deleted) { return com.thoughtworks.go.domain.materials.ModifiedAction.deleted; } return com.thoughtworks.go.domain.materials.ModifiedAction.unknown; } }