diff --git a/pom.xml b/pom.xml index 229aaf63..28f2cd41 100644 --- a/pom.xml +++ b/pom.xml @@ -1,15 +1,15 @@ 4.0.0 - org.jenkins-ci.plugins - plugin - 1.409 - ../pom.xml + org.jenkins-ci.plugins + plugin + 1.580.1 + scm-sync-configuration SCM Sync Configuration Plugin - 0.0.8.1-SNAPSHOT + 0.0.8.2hybris hpi http://wiki.jenkins-ci.org/display/JENKINS/SCM+Sync+configuration+plugin SCM Sync Configuration Jenkins plugin is aimed at 2 main features : First, keep sync'ed your config.xml (and other ressources) jenkins files with a SCM repository (backup), Secondly, track changes (and author) made on every file with commit messages. @@ -28,6 +28,7 @@ + 0.3.0.M1 UTF-8 1.4.8 @@ -65,29 +66,35 @@ maven-surefire-plugin - -XX:MaxPermSize=128m + -Xmx2048m -Xms512m -XX:MaxPermSize=512m + + + org.codehaus.plexus + plexus-maven-plugin + 1.3.8 + + + merge + + + src/main/resources/META-INF/plexus/components.xml + + + generate-resources + + merge-descriptors + + + + org.codehaus.plexus plexus-maven-plugin - - - merge - - - src/main/resources/META-INF/plexus/components.xml - - - generate-resources - - merge-descriptors - - - @@ -97,7 +104,7 @@ org.jenkins-ci.main maven-plugin - ${project.parent.version} + 2.8 @@ -125,23 +132,15 @@ org.apache.maven.scm maven-scm-manager-plexus - 1.9.1 - - - org.jenkins-ci.plugins @@ -190,11 +189,11 @@ jar test - - com.google.guava - guava - 12.0.1 - + + org.eclipse.sisu + org.eclipse.sisu.plexus + ${sisuInjectVersion} + diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/JenkinsFilesHelper.java b/src/main/java/hudson/plugins/scm_sync_configuration/JenkinsFilesHelper.java index a12de734..151d9b57 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/JenkinsFilesHelper.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/JenkinsFilesHelper.java @@ -1,13 +1,14 @@ package hudson.plugins.scm_sync_configuration; -import hudson.model.Hudson; + +import jenkins.model.Jenkins; import java.io.File; public class JenkinsFilesHelper { public static String buildPathRelativeToHudsonRoot(File file){ - File hudsonRoot = Hudson.getInstance().getRootDir(); + File hudsonRoot = Jenkins.getInstance().getRootDir(); if(!file.getAbsolutePath().startsWith(hudsonRoot.getAbsolutePath())){ throw new IllegalArgumentException("Err ! File ["+file.getAbsolutePath()+"] seems not to reside in ["+hudsonRoot.getAbsolutePath()+"] !"); } @@ -16,7 +17,7 @@ public static String buildPathRelativeToHudsonRoot(File file){ } public static File buildFileFromPathRelativeToHudsonRoot(String pathRelativeToHudsonRoot){ - File hudsonRoot = Hudson.getInstance().getRootDir(); + File hudsonRoot = Jenkins.getInstance().getRootDir(); return new File(hudsonRoot.getAbsolutePath()+File.separator+pathRelativeToHudsonRoot); } } diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/SCMManipulator.java b/src/main/java/hudson/plugins/scm_sync_configuration/SCMManipulator.java index 279cbfcb..1e150570 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/SCMManipulator.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/SCMManipulator.java @@ -2,9 +2,7 @@ import hudson.plugins.scm_sync_configuration.model.ScmContext; import hudson.plugins.scm_sync_configuration.scms.SCM; -import org.apache.maven.scm.ScmException; -import org.apache.maven.scm.ScmFile; -import org.apache.maven.scm.ScmFileSet; +import org.apache.maven.scm.*; import org.apache.maven.scm.command.add.AddScmResult; import org.apache.maven.scm.command.checkin.CheckInScmResult; import org.apache.maven.scm.command.checkout.CheckOutScmResult; @@ -35,6 +33,7 @@ public class SCMManipulator { private ScmManager scmManager; private ScmRepository scmRepository = null; private String scmSpecificFilename = null; + private String scmGitBranch; public SCMManipulator(ScmManager _scmManager) { this.scmManager = _scmManager; @@ -65,7 +64,8 @@ public boolean scmConfigurationSettledUp(ScmContext scmContext, boolean resetScm return false; } } - + + scmGitBranch = scmContext.getScmGitBranch(); return expectScmRepositoryInitiated(); } @@ -88,7 +88,12 @@ public boolean checkout(File checkoutDirectory){ // Checkouting sources LOGGER.fine("Checkouting SCM files into ["+checkoutDirectory.getAbsolutePath()+"] ..."); try { - CheckOutScmResult result = scmManager.checkOut(this.scmRepository, new ScmFileSet(checkoutDirectory)); + ScmBranch scmBranch = null; + if (scmGitBranch != null && scmGitBranch.length() > 0){ + scmBranch = new ScmBranch(scmGitBranch); + } + CheckOutScmResult result = scmManager.checkOut(this.scmRepository, new ScmFileSet(checkoutDirectory),scmBranch); + if(!result.isSuccess()){ LOGGER.severe("[checkout] Error during checkout : "+result.getProviderMessage()+" || "+result.getCommandOutput()); return checkoutOk; @@ -262,5 +267,4 @@ public boolean checkinFiles(File scmRoot, String commitMessage){ public String getScmSpecificFilename() { return scmSpecificFilename; } - } diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationBusiness.java b/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationBusiness.java index 8e43be65..75300462 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationBusiness.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationBusiness.java @@ -1,7 +1,6 @@ package hudson.plugins.scm_sync_configuration; import com.google.common.io.Files; -import hudson.model.Hudson; import hudson.model.User; import hudson.plugins.scm_sync_configuration.exceptions.LoggableException; import hudson.plugins.scm_sync_configuration.model.*; @@ -9,6 +8,7 @@ import hudson.plugins.scm_sync_configuration.utils.Checksums; import hudson.security.Permission; import hudson.util.DaemonThreadFactory; +import jenkins.model.Jenkins; import org.apache.commons.io.FileUtils; import org.apache.maven.scm.ScmException; import org.apache.maven.scm.manager.ScmManager; @@ -61,7 +61,7 @@ public void init(ScmContext scmContext) throws ComponentLookupException, PlexusC this.scmManipulator = new SCMManipulator(scmManager); this.checkoutScmDirectory = new File(getCheckoutScmDirectoryAbsolutePath()); this.checkoutSucceeded = false; - initializeRepository(scmContext, false); + initializeRepository(scmContext, true); } public void initializeRepository(ScmContext scmContext, boolean deleteCheckoutScmDir){ @@ -304,15 +304,37 @@ public boolean scmCheckoutDirectorySettledUp(ScmContext scmContext){ } public List reloadAllFilesFromScm() throws IOException, ScmException { + //removeSourceJobsDuringReload(); this.scmManipulator.update(new File(getCheckoutScmDirectoryAbsolutePath())); return syncDirectories(new File(getCheckoutScmDirectoryAbsolutePath() + File.separator), ""); } + /** + * + * @return + * @throws IOException + */ + public List removeSourceJobsDuringReload() throws IOException { + List l = new ArrayList(); + File jobsFolder = new File(Jenkins.getInstance().getRootDir().toString()+ "/jobs"); + LOGGER.info("Configuration reload - jobs removal. Cleaning up folder:"+jobsFolder); + + for(File f : jobsFolder.listFiles()){ + l.add(f); + if (f.isDirectory()) { + FileUtils.deleteDirectory(f); + } else { + FileUtils.forceDelete(f); + } + } + return l; + } + private List syncDirectories(File from, String relative) throws IOException { List l = new ArrayList(); for(File f : from.listFiles()) { String newRelative = relative + File.separator + f.getName(); - File jenkinsFile = new File(Hudson.getInstance().getRootDir() + newRelative); + File jenkinsFile = new File(Jenkins.getInstance().getRootDir() + newRelative); if (f.getName().equals(scmManipulator.getScmSpecificFilename())) { // nothing to do } @@ -351,20 +373,20 @@ private void signal(String operation, boolean result) { } public static String getCheckoutScmDirectoryAbsolutePath(){ - return Hudson.getInstance().getRootDir().getAbsolutePath()+WORKING_DIRECTORY_PATH+CHECKOUT_SCM_DIRECTORY; + return Jenkins.getInstance().getRootDir().getAbsolutePath()+WORKING_DIRECTORY_PATH+CHECKOUT_SCM_DIRECTORY; } public void purgeFailLogs() { - Hudson.getInstance().checkPermission(purgeFailLogPermission()); + Jenkins.getInstance().checkPermission(purgeFailLogPermission()); scmSyncConfigurationStatusManager.purgeFailLogs(); } public boolean canCurrentUserPurgeFailLogs() { - return Hudson.getInstance().hasPermission(purgeFailLogPermission()); + return Jenkins.getInstance().hasPermission(purgeFailLogPermission()); } private static Permission purgeFailLogPermission(){ // Only administrators should be able to purge logs - return Hudson.ADMINISTER; + return Jenkins.ADMINISTER; } } diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin.java b/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin.java index 95b9ed11..ff8fe848 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin.java @@ -5,7 +5,6 @@ import hudson.Plugin; import hudson.model.Descriptor; import hudson.model.Descriptor.FormException; -import hudson.model.Hudson; import hudson.model.Saveable; import hudson.model.User; import hudson.plugins.scm_sync_configuration.extensions.ScmSyncConfigurationFilter; @@ -21,6 +20,8 @@ import hudson.plugins.scm_sync_configuration.xstream.ScmSyncConfigurationXStreamConverter; import hudson.plugins.scm_sync_configuration.xstream.migration.ScmSyncConfigurationPOJO; import hudson.util.PluginServletFilter; +import jenkins.model.Jenkins; +import net.sf.json.JSONException; import net.sf.json.JSONObject; import org.acegisecurity.AccessDeniedException; import org.apache.maven.scm.ScmException; @@ -88,6 +89,7 @@ public static interface AtomicTransactionFactory { private transient Future latestCommitFuture; private String scmRepositoryUrl; + private String scmGitBranch; private SCM scm; private boolean noUserCommitMessage; private boolean displayStatus = true; @@ -97,6 +99,8 @@ public static interface AtomicTransactionFactory { private List filesModifiedByLastReload; private List manualSynchronizationIncludes; + private static final String SCM_SYNC_GIT_PREFX="scm:git:"; + public ScmSyncConfigurationPlugin(){ // By default, transactions should be asynchronous this(false); @@ -121,7 +125,7 @@ public List getManualSynchronizationIncludes(){ public void start() throws Exception { super.start(); - Hudson.XSTREAM.registerConverter(new ScmSyncConfigurationXStreamConverter()); + Jenkins.XSTREAM.registerConverter(new ScmSyncConfigurationXStreamConverter()); this.load(); @@ -140,6 +144,7 @@ public void start() throws Exception { public void loadData(ScmSyncConfigurationPOJO pojo){ this.scmRepositoryUrl = pojo.getScmRepositoryUrl(); + this.scmGitBranch = pojo.getScmGitBranch(); this.scm = pojo.getScm(); this.noUserCommitMessage = pojo.isNoUserCommitMessage(); this.displayStatus = pojo.isDisplayStatus(); @@ -174,6 +179,7 @@ public void configure(StaplerRequest req, JSONObject formData) this.displayStatus = formData.getBoolean("displayStatus"); this.commitMessagePattern = req.getParameter("commitMessagePattern"); + String oldGitBranch = this.scmGitBranch; String oldScmRepositoryUrl = this.scmRepositoryUrl; String scmType = req.getParameter("scm"); if(scmType != null){ @@ -182,8 +188,21 @@ public void configure(StaplerRequest req, JSONObject formData) this.scmRepositoryUrl = newScmRepositoryUrl; + String newScmGitBranch = null; + if ("hudson.plugins.scm_sync_configuration.scms.ScmSyncGitSCM".equals(scmType)){ + newScmGitBranch = formData.getJSONObject("scm").getString("scmGitBranch"); + } + + if (oldGitBranch == null) { + oldGitBranch = "master"; + } + if (newScmGitBranch == null){ + newScmGitBranch = "master"; + } + this.scmGitBranch = newScmGitBranch; + // If something changed, let's reinitialize repository in working directory ! - repoInitializationRequired = newScmRepositoryUrl != null && !newScmRepositoryUrl.equals(oldScmRepositoryUrl); + repoInitializationRequired = (newScmRepositoryUrl != null && !newScmRepositoryUrl.equals(oldScmRepositoryUrl)) || !newScmGitBranch.equals(oldGitBranch); configsResynchronizationRequired = repoInitializationRequired; repoCleaningRequired = newScmRepositoryUrl==null && oldScmRepositoryUrl!=null; } @@ -222,7 +241,14 @@ public void configure(StaplerRequest req, JSONObject formData) public void doReloadAllFilesFromScm(StaplerRequest req, StaplerResponse res) throws ServletException, IOException { try { - filesModifiedByLastReload = business.reloadAllFilesFromScm(); + String branchToReload = req.getParameter("scmBranchReload"); + String urlToReload = req.getParameter("urlRepoReload"); + LOGGER.info("Switching to URL:" + urlToReload + " branch:"+ branchToReload); + scmGitBranch = branchToReload; + scmRepositoryUrl = SCM_SYNC_GIT_PREFX + urlToReload; + business.removeSourceJobsDuringReload(); + init(); + filesModifiedByLastReload = business.reloadAllFilesFromScm(); req.getView(this, "/hudson/plugins/scm_sync_configuration/reload.jelly").forward(req, res); } catch(ScmException e) { @@ -265,13 +291,13 @@ public List getDefaultIncludes(){ private User getCurrentUser(){ User user = null; try { - user = Hudson.getInstance().getMe(); + user = Jenkins.getInstance().getMe(); }catch(AccessDeniedException e){} return user; } public static ScmSyncConfigurationPlugin getInstance(){ - return Hudson.getInstance().getPlugin(ScmSyncConfigurationPlugin.class); + return Jenkins.getInstance().getPlugin(ScmSyncConfigurationPlugin.class); } public ScmSyncStrategy getStrategyForSaveable(Saveable s, File f){ @@ -285,7 +311,7 @@ public ScmSyncStrategy getStrategyForSaveable(Saveable s, File f){ } public ScmContext createScmContext(){ - return new ScmContext(this.scm, this.scmRepositoryUrl, this.commitMessagePattern); + return new ScmContext(this.scm, this.scmRepositoryUrl, this.commitMessagePattern, this.scmGitBranch); } public boolean shouldDecorationOccursOnURL(String url){ @@ -347,7 +373,9 @@ public String getScmUrl(){ } } - public List getFilesModifiedByLastReload() { + public String getScmGitBranch() { return scmGitBranch; } + + public List getFilesModifiedByLastReload() { return filesModifiedByLastReload; } diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationStatusManager.java b/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationStatusManager.java index ed26afe2..d257cd10 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationStatusManager.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationStatusManager.java @@ -1,12 +1,11 @@ package hudson.plugins.scm_sync_configuration; -import hudson.model.Hudson; - import java.io.File; import java.io.IOException; import java.util.Date; import java.util.logging.Logger; +import jenkins.model.Jenkins; import org.codehaus.plexus.util.FileUtils; public class ScmSyncConfigurationStatusManager { @@ -21,8 +20,8 @@ public class ScmSyncConfigurationStatusManager { private File success; public ScmSyncConfigurationStatusManager() { - fail = new File(Hudson.getInstance().getRootDir().getAbsolutePath()+File.separator+LOG_FAIL_FILENAME); - success = new File(Hudson.getInstance().getRootDir().getAbsolutePath()+File.separator+LOG_SUCCESS_FILENAME); + fail = new File(Jenkins.getInstance().getRootDir().getAbsolutePath()+File.separator+LOG_FAIL_FILENAME); + success = new File(Jenkins.getInstance().getRootDir().getAbsolutePath()+File.separator+LOG_SUCCESS_FILENAME); } public String getLastFail() { diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/model/ScmContext.java b/src/main/java/hudson/plugins/scm_sync_configuration/model/ScmContext.java index b31f822e..ae3cab8a 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/model/ScmContext.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/model/ScmContext.java @@ -9,17 +9,23 @@ public class ScmContext { private String scmRepositoryUrl; private SCM scm; private String commitMessagePattern; + private String scmGitBranch; public ScmContext(SCM _scm, String _scmRepositoryUrl){ this(_scm, _scmRepositoryUrl, "[message]"); } public ScmContext(SCM _scm, String _scmRepositoryUrl, String _commitMessagePattern){ - this.scm = _scm; - this.scmRepositoryUrl = _scmRepositoryUrl; - this.commitMessagePattern = _commitMessagePattern; + this(_scm, _scmRepositoryUrl, _commitMessagePattern, null); } + public ScmContext(SCM _scm, String _scmRepositoryUrl, String _commitMessagePattern, String _scmGitBranch){ + this.scm = _scm; + this.scmRepositoryUrl = _scmRepositoryUrl; + this.commitMessagePattern = _commitMessagePattern; + this.scmGitBranch = _scmGitBranch; + } + public String getScmRepositoryUrl() { return scmRepositoryUrl; } @@ -28,6 +34,10 @@ public SCM getScm() { return scm; } + public String getScmGitBranch() { + return scmGitBranch; + } + public String getCommitMessagePattern(){ return commitMessagePattern; } diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/scms/SCM.java b/src/main/java/hudson/plugins/scm_sync_configuration/scms/SCM.java index f473948d..85f6a528 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/scms/SCM.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/scms/SCM.java @@ -1,12 +1,12 @@ package hudson.plugins.scm_sync_configuration.scms; import hudson.model.Descriptor; -import hudson.model.Hudson; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; +import jenkins.model.Jenkins; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.maven.scm.manager.NoSuchScmProviderException; import org.apache.maven.scm.manager.ScmManager; @@ -52,7 +52,7 @@ public String getSCMClassName() { } public Descriptor getSCMDescriptor(){ - return Hudson.getInstance().getDescriptorByName(getSCMClassName()); + return Jenkins.getInstance().getDescriptorByName(getSCMClassName()); } public String getRepositoryUrlHelpPath() { @@ -62,7 +62,8 @@ public String getRepositoryUrlHelpPath() { public ScmRepository getConfiguredRepository(ScmManager scmManager, String scmRepositoryURL) { SCMCredentialConfiguration credentials = extractScmCredentials( extractScmUrlFrom(scmRepositoryURL) ); - LOGGER.info("Creating SCM repository object for url : "+scmRepositoryURL); + LOGGER.info("" + + "Creating SCM repository object for url : "+scmRepositoryURL); ScmRepository repository = null; try { repository = scmManager.makeScmRepository( scmRepositoryURL ); diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/scms/customproviders/git/gitexe/ScmSyncGitExeScmProvider.java b/src/main/java/hudson/plugins/scm_sync_configuration/scms/customproviders/git/gitexe/ScmSyncGitExeScmProvider.java index 49e01232..1e000a59 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/scms/customproviders/git/gitexe/ScmSyncGitExeScmProvider.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/scms/customproviders/git/gitexe/ScmSyncGitExeScmProvider.java @@ -29,7 +29,7 @@ * checkin is originally made by passing pushUrl instead of a local reference (such as "origin") * Problem is passing pushUrl doesn't update current local reference once pushed => after push, * origin/ will not be updated to latest commit => on next push, there will be an - * error saying some pull is needed. + * error saying some ull is needed. * This workaround could be betterly handled when something like "checkinAndFetch" could be * implemented generically in maven-scm-api * (see http://maven.40175.n5.nabble.com/SCM-GitExe-no-fetch-after-push-td5745064.html) @@ -113,7 +113,11 @@ protected CheckInScmResult executeCheckInCommand( if( repo.isPushChanges() ) { Commandline cl = createSpecificPushCommandLine( getLogger(), repository, fileSet, version ); - + StringBuffer clOutput = new StringBuffer(); + String[] clTab = cl.getCommandline(); + for (int i = 0; i < clTab.length; i++) { + clOutput.append(clTab[i] + ", "); + } exitCode = GitCommandLineUtils.execute( cl, stdout, stderr, getLogger() ); if ( exitCode != 0 ) { diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/strategies/AbstractScmSyncStrategy.java b/src/main/java/hudson/plugins/scm_sync_configuration/strategies/AbstractScmSyncStrategy.java index c218c015..91e3e02c 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/strategies/AbstractScmSyncStrategy.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/strategies/AbstractScmSyncStrategy.java @@ -3,13 +3,13 @@ import com.google.common.base.Function; import com.google.common.collect.Collections2; import hudson.XmlFile; -import hudson.model.Hudson; import hudson.model.Item; import hudson.model.Saveable; import hudson.plugins.scm_sync_configuration.model.MessageWeight; import hudson.plugins.scm_sync_configuration.model.WeightedMessage; import hudson.plugins.scm_sync_configuration.strategies.model.ConfigurationEntityMatcher; import hudson.plugins.scm_sync_configuration.strategies.model.PageMatcher; +import jenkins.model.Jenkins; import javax.annotation.Nullable; import java.io.File; @@ -21,7 +21,7 @@ public abstract class AbstractScmSyncStrategy implements ScmSyncStrategy { private static final Function PATH_TO_FILE_IN_HUDSON = new Function() { public File apply(@Nullable String path) { - return new File(Hudson.getInstance().getRootDir()+File.separator+path); + return new File(Jenkins.getInstance().getRootDir()+File.separator+path); } }; @@ -54,7 +54,7 @@ public boolean isSaveableApplicable(Saveable saveable, File file) { } public PageMatcher getPageMatcherMatching(String url){ - String rootUrl = Hudson.getInstance().getRootUrlFromRequest(); + String rootUrl = Jenkins.getInstance().getRootUrlFromRequest(); String cleanedUrl = null; if(url.startsWith(rootUrl)){ cleanedUrl = url.substring(rootUrl.length()); @@ -70,7 +70,7 @@ public PageMatcher getPageMatcherMatching(String url){ } public List createInitializationSynchronizedFileset() { - File hudsonRoot = Hudson.getInstance().getRootDir(); + File hudsonRoot = Jenkins.getInstance().getRootDir(); String[] matchingFilePaths = createConfigEntityMatcher().matchingFilesFrom(hudsonRoot); return new ArrayList(Collections2.transform(Arrays.asList(matchingFilePaths), PATH_TO_FILE_IN_HUDSON)); } diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/strategies/model/PatternsEntityMatcher.java b/src/main/java/hudson/plugins/scm_sync_configuration/strategies/model/PatternsEntityMatcher.java index 3bccded2..15491119 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/strategies/model/PatternsEntityMatcher.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/strategies/model/PatternsEntityMatcher.java @@ -1,6 +1,5 @@ package hudson.plugins.scm_sync_configuration.strategies.model; -import hudson.model.Hudson; import hudson.model.Saveable; import hudson.plugins.scm_sync_configuration.JenkinsFilesHelper; import org.apache.tools.ant.DirectoryScanner; diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/xstream/ScmSyncConfigurationXStreamConverter.java b/src/main/java/hudson/plugins/scm_sync_configuration/xstream/ScmSyncConfigurationXStreamConverter.java index ef2aa16e..d2d5d5a5 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/xstream/ScmSyncConfigurationXStreamConverter.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/xstream/ScmSyncConfigurationXStreamConverter.java @@ -69,6 +69,11 @@ public void marshal(Object source, HierarchicalStreamWriter writer, writer.setValue(plugin.getScmRepositoryUrl()); writer.endNode(); } + if(plugin.getScmGitBranch() != null){ + writer.startNode(AbstractMigrator.SCM_GIT_BRANCH); + writer.setValue(plugin.getScmGitBranch()); + writer.endNode(); + } writer.startNode(AbstractMigrator.SCM_NO_USER_COMMIT_MESSAGE); writer.setValue(Boolean.toString(plugin.isNoUserCommitMessage())); diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/xstream/migration/AbstractMigrator.java b/src/main/java/hudson/plugins/scm_sync_configuration/xstream/migration/AbstractMigrator.java index 408473c3..2a3522f0 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/xstream/migration/AbstractMigrator.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/xstream/migration/AbstractMigrator.java @@ -18,6 +18,7 @@ public abstract class AbstractMigrator - - ${%Reload} + + + + + + + + + + + + + ${%Reload} + +
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/config.jelly b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/config.jelly index 2c74e408..c54fbc48 100644 --- a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/config.jelly +++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/config.jelly @@ -3,5 +3,7 @@ - + + + \ No newline at end of file diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/url-help.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/url-help.properties index 7b68062d..6933f03f 100644 --- a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/url-help.properties +++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/url-help.properties @@ -23,4 +23,5 @@ description.1=\ Specify the git repository URL to synchronize your configuration files with, such as "git@github.com:mycompany/jenkins-config.git" description.2=\ - Note that, for the moment, your MUST reference your Git repository root + Specify branch name in branch field. If you leave it empty, master branch will be used. \ + If you want to switch to new branch, just type it's name. If newly typed branch already contains any configuration, it will be merged with current one immediately after pressing "Save" button. diff --git a/src/main/webapp/help/reloadScmConfig-branch-help.html b/src/main/webapp/help/reloadScmConfig-branch-help.html new file mode 100644 index 00000000..f589250c --- /dev/null +++ b/src/main/webapp/help/reloadScmConfig-branch-help.html @@ -0,0 +1,4 @@ +
+ A branch of repository which is source of configuration for reloading.
+ Please read help at "Reload" button for further help. +
\ No newline at end of file diff --git a/src/main/webapp/help/reloadScmConfig-help.html b/src/main/webapp/help/reloadScmConfig-help.html index 39e70fa7..510de01e 100644 --- a/src/main/webapp/help/reloadScmConfig-help.html +++ b/src/main/webapp/help/reloadScmConfig-help.html @@ -29,6 +29,14 @@ Note that it should never happen since as soon as you activate scm sync config, every of your config file should be commited to the repository + + job XXX + Doesn't exist + + Beware! Job will be removed! Opposite to jenkins config files, all jobs are removed before reload
+ This is the only way to remove jobs that aren't stored in other branch or repo. After reload your Jenkins job configuration should be the same as in repository + + Doesn't exist XXX diff --git a/src/main/webapp/help/reloadScmConfig-url-help.html b/src/main/webapp/help/reloadScmConfig-url-help.html new file mode 100644 index 00000000..f425ee06 --- /dev/null +++ b/src/main/webapp/help/reloadScmConfig-url-help.html @@ -0,0 +1,4 @@ +
+ An URL of repository which is source of configuration for reloading. + Please read help at "Reload" button for further help. +
\ No newline at end of file diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/basic/ScmSyncConfigurationBasicTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/basic/ScmSyncConfigurationBasicTest.java index 0e15fc1e..e77912a8 100644 --- a/src/test/java/hudson/plugins/scm_sync_configuration/basic/ScmSyncConfigurationBasicTest.java +++ b/src/test/java/hudson/plugins/scm_sync_configuration/basic/ScmSyncConfigurationBasicTest.java @@ -5,12 +5,12 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertThat; -import hudson.model.Hudson; import hudson.plugins.scm_sync_configuration.util.ScmSyncConfigurationBaseTest; import hudson.plugins.test.utils.scms.ScmUnderTestSubversion; import java.io.File; +import jenkins.model.Jenkins; import org.junit.Test; public class ScmSyncConfigurationBasicTest extends ScmSyncConfigurationBaseTest { @@ -21,16 +21,16 @@ public ScmSyncConfigurationBasicTest() { @Test public void shouldRetrieveMockedHudsonInstanceCorrectly() throws Throwable { - Hudson hudsonInstance = Hudson.getInstance(); - assertThat(hudsonInstance, is(notNullValue())); - assertThat(hudsonInstance.toString().split("@")[0], is(not(equalTo("hudson.model.Hudson")))); + Jenkins jenkinsInstance = Jenkins.getInstance(); + assertThat(jenkinsInstance, is(notNullValue())); + assertThat(jenkinsInstance.toString().split("@")[0], is(not(equalTo("jenkins.model.Jenkins")))); } @Test public void shouldVerifyIfHudsonRootDirectoryExists() throws Throwable { - - Hudson hudsonInstance = Hudson.getInstance(); - File hudsonRootDir = hudsonInstance.getRootDir(); + + Jenkins jenkinsInstance = Jenkins.getInstance(); + File hudsonRootDir = jenkinsInstance.getRootDir(); assertThat(hudsonRootDir, is(not(equalTo(null)))); assertThat(hudsonRootDir.exists(), is(true)); } diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/data/CurrentVersionCompatibilityTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/data/CurrentVersionCompatibilityTest.java index c10904af..5c4ba7e7 100644 --- a/src/test/java/hudson/plugins/scm_sync_configuration/data/CurrentVersionCompatibilityTest.java +++ b/src/test/java/hudson/plugins/scm_sync_configuration/data/CurrentVersionCompatibilityTest.java @@ -17,6 +17,7 @@ import hudson.plugins.test.utils.PluginUtil; import hudson.plugins.test.utils.scms.ScmUnderTestSubversion; +import jenkins.model.Jenkins; import org.junit.Test; import org.powermock.core.classloader.annotations.PrepareForTest; diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsTest.java index bb4ebde4..2c31a2dc 100644 --- a/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsTest.java +++ b/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsTest.java @@ -383,6 +383,56 @@ private void assertStrategy(Class expectedStrategyCla } } + /** + * Test that checks if after reload, disk contains only jobs that were reloaded from SCM. Speaking in other way - + * if joba non existent in SCM were removed from the disk. + * @throws Throwable + */ + @Test + public void shouldReloadAllFilesRemoveNonExistentJobs() throws Throwable { + createSCMMock(); + + sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES); + + // Let's checkout current scm view ... and commit something in it ... + SCMManipulator scmManipulator = createMockedScmManipulator(); + File checkoutDirectoryForVerifications = createTmpDirectory(this.getClass().getSimpleName()+"_"+testName.getMethodName()+"__tmpHierarchyForCommit"); + scmManipulator.checkout(checkoutDirectoryForVerifications); + + verifyCurrentScmContentMatchesCurrentHudsonDir(true); + + + final String jobDir = checkoutDirectoryForVerifications.getAbsolutePath() + "/jobs/myJob"; + FileUtils.mkdir(jobDir); + final File addedJobFile = new File(jobDir + "/config.xml"); + FileUtils.fileWrite(addedJobFile.getAbsolutePath(), "titi"); + scmManipulator.addFile(checkoutDirectoryForVerifications, "jobs/myJob"); + File jobToRemove = new File(checkoutDirectoryForVerifications.getAbsolutePath() + "/jobs/fakeJob"); + FileUtils.deleteDirectory(jobToRemove); + scmManipulator.deleteHierarchy(jobToRemove); + scmManipulator.checkinFiles(checkoutDirectoryForVerifications, "external commit for add myJob file and remove fakeJob"); + + verifyCurrentScmContentMatchesCurrentHudsonDir(false); + + // Reload config + List removedJobs = sscBusiness.removeSourceJobsDuringReload(); + List syncedFiles = sscBusiness.reloadAllFilesFromScm(); + + verifyCurrentScmContentMatchesCurrentHudsonDir(true); + + assertThat(removedJobs.size(), is(1)); + assertThat(removedJobs.contains(new File(getCurrentHudsonRootDirectory().getAbsolutePath() + "/jobs/fakeJob")), is(true)); + + assertThat(syncedFiles.size(), is(1)); + assertThat(syncedFiles.contains(new File(getCurrentHudsonRootDirectory().getAbsolutePath() + "/jobs/myJob")), is(true)); + + assertThat(new File(getCurrentHudsonRootDirectory().getAbsolutePath() + "/jobs/fakeJob").exists(), is(false)); + assertThat(new File(getCurrentHudsonRootDirectory().getAbsolutePath() + "/jobs/myJob").exists(), is(true)); + + + assertStatusManagerIsOk(); + } + @Override protected String getHudsonRootBaseTemplate(){ if("shouldFileWhichHaveToBeInSCM".equals(testName.getMethodName())){ diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/util/ScmSyncConfigurationBaseTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/util/ScmSyncConfigurationBaseTest.java index 5de847fa..0fde8530 100644 --- a/src/test/java/hudson/plugins/scm_sync_configuration/util/ScmSyncConfigurationBaseTest.java +++ b/src/test/java/hudson/plugins/scm_sync_configuration/util/ScmSyncConfigurationBaseTest.java @@ -2,7 +2,6 @@ import hudson.Plugin; import hudson.PluginWrapper; -import hudson.model.Hudson; import hudson.model.User; import hudson.plugins.scm_sync_configuration.SCMManagerFactory; import hudson.plugins.scm_sync_configuration.SCMManipulator; @@ -16,6 +15,7 @@ import hudson.plugins.scm_sync_configuration.xstream.migration.ScmSyncConfigurationPOJO; import hudson.plugins.test.utils.DirectoryUtils; import hudson.plugins.test.utils.scms.ScmUnderTest; +import jenkins.model.Jenkins; import org.codehaus.plexus.PlexusContainerException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.util.FileUtils; @@ -46,7 +46,7 @@ @RunWith(PowerMockRunner.class) @PowerMockIgnore({ "org.tmatesoft.svn.*" }) -@PrepareForTest({Hudson.class, SCM.class, ScmSyncSubversionSCM.class, PluginWrapper.class}) +@PrepareForTest({SCM.class, ScmSyncSubversionSCM.class, PluginWrapper.class, Jenkins.class}) public abstract class ScmSyncConfigurationBaseTest { @Rule protected TestName testName = new TestName(); @@ -105,14 +105,14 @@ public void setup() throws Throwable { // Mocking Hudson singleton instance ... // Warning : this line will only work on Objenesis supported VMs : // http://code.google.com/p/objenesis/wiki/ListOfCurrentlySupportedVMs - Hudson hudsonMockedInstance = spy((Hudson) new ObjenesisStd().getInstantiatorOf(Hudson.class).newInstance()); - PowerMockito.doReturn(currentHudsonRootDirectory).when(hudsonMockedInstance).getRootDir(); - PowerMockito.doReturn(mockedUser).when(hudsonMockedInstance).getMe(); - PowerMockito.doReturn(scmSyncConfigPluginInstance).when(hudsonMockedInstance).getPlugin(ScmSyncConfigurationPlugin.class); - - PowerMockito.mockStatic(Hudson.class); - PowerMockito.doReturn(hudsonMockedInstance).when(Hudson.class); Hudson.getInstance(); - //when(Hudson.getInstance()).thenReturn(hudsonMockedInstance); + + Jenkins jenkinsMockInstance = spy((Jenkins) new ObjenesisStd().getInstantiatorOf(Jenkins.class).newInstance()); + PowerMockito.doReturn(currentHudsonRootDirectory).when(jenkinsMockInstance).getRootDir(); + PowerMockito.doReturn(mockedUser).when(jenkinsMockInstance).getMe(); + PowerMockito.doReturn(scmSyncConfigPluginInstance).when(jenkinsMockInstance).getPlugin(ScmSyncConfigurationPlugin.class); + + PowerMockito.mockStatic(Jenkins.class); + PowerMockito.doReturn(jenkinsMockInstance).when(Jenkins.class); Jenkins.getInstance(); } @After