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 24de088f..6ed7d4e5 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/SCMManipulator.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/SCMManipulator.java @@ -2,6 +2,16 @@ import hudson.plugins.scm_sync_configuration.model.ScmContext; import hudson.plugins.scm_sync_configuration.scms.SCM; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + import org.apache.maven.scm.ScmException; import org.apache.maven.scm.ScmFile; import org.apache.maven.scm.ScmFileSet; @@ -9,19 +19,12 @@ import org.apache.maven.scm.command.checkin.CheckInScmResult; import org.apache.maven.scm.command.checkout.CheckOutScmResult; import org.apache.maven.scm.command.remove.RemoveScmResult; +import org.apache.maven.scm.command.status.StatusScmResult; import org.apache.maven.scm.command.update.UpdateScmResult; import org.apache.maven.scm.manager.NoSuchScmProviderException; import org.apache.maven.scm.manager.ScmManager; import org.apache.maven.scm.repository.ScmRepository; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Class providing atomic scm commands and wrapping calls to maven scm api * with logging informations @@ -32,81 +35,81 @@ public class SCMManipulator { private static final Logger LOGGER = Logger.getLogger(SCMManipulator.class.getName()); private final ScmManager scmManager; - private ScmRepository scmRepository = null; - private String scmSpecificFilename = null; - - public SCMManipulator(ScmManager _scmManager) { - this.scmManager = _scmManager; - } - - /** - * Will check if everything is settled up (useful before a scm manipulation) - * @param scmContext - * @param resetScmRepository - * @return - */ - public boolean scmConfigurationSettledUp(ScmContext scmContext, boolean resetScmRepository){ - String scmRepositoryUrl = scmContext.getScmRepositoryUrl(); - SCM scm = scmContext.getScm(); - if(scmRepositoryUrl == null || scm == null){ - return false; - } - - if(resetScmRepository){ - LOGGER.info("Creating scmRepository connection data .."); - this.scmRepository = scm.getConfiguredRepository(this.scmManager, scmRepositoryUrl); - try { - this.scmSpecificFilename = this.scmManager.getProviderByRepository(this.scmRepository).getScmSpecificFilename(); - } - catch(NoSuchScmProviderException e) { - LOGGER.throwing(ScmManager.class.getName(), "getScmSpecificFilename", e); - LOGGER.severe("[getScmSpecificFilename] Error while getScmSpecificFilename : "+e.getMessage()); - return false; - } - } - - return expectScmRepositoryInitiated(); - } - - private boolean expectScmRepositoryInitiated(){ - boolean scmRepositoryInitiated = this.scmRepository != null; + private ScmRepository scmRepository = null; + private String scmSpecificFilename = null; + + public SCMManipulator(ScmManager _scmManager) { + this.scmManager = _scmManager; + } + + /** + * Will check if everything is settled up (useful before a scm manipulation) + * @param scmContext + * @param resetScmRepository + * @return + */ + public boolean scmConfigurationSettledUp(ScmContext scmContext, boolean resetScmRepository){ + String scmRepositoryUrl = scmContext.getScmRepositoryUrl(); + SCM scm = scmContext.getScm(); + if(scmRepositoryUrl == null || scm == null){ + return false; + } + + if(resetScmRepository){ + LOGGER.info("Creating scmRepository connection data .."); + this.scmRepository = scm.getConfiguredRepository(this.scmManager, scmRepositoryUrl); + try { + this.scmSpecificFilename = this.scmManager.getProviderByRepository(this.scmRepository).getScmSpecificFilename(); + } + catch(NoSuchScmProviderException e) { + LOGGER.throwing(ScmManager.class.getName(), "getScmSpecificFilename", e); + LOGGER.severe("[getScmSpecificFilename] Error while getScmSpecificFilename : "+e.getMessage()); + return false; + } + } + + return expectScmRepositoryInitiated(); + } + + private boolean expectScmRepositoryInitiated(){ + boolean scmRepositoryInitiated = this.scmRepository != null; if(!scmRepositoryInitiated) { LOGGER.warning("SCM Repository has not yet been initiated !"); } - return scmRepositoryInitiated; - } - - public UpdateScmResult update(File root) throws ScmException { - return this.scmManager.update(scmRepository, new ScmFileSet(root)); - } - public boolean checkout(File checkoutDirectory){ - boolean checkoutOk = false; - - if(!expectScmRepositoryInitiated()){ - return checkoutOk; - } - - // Checkouting sources + return scmRepositoryInitiated; + } + + public UpdateScmResult update(File root) throws ScmException { + return this.scmManager.update(scmRepository, new ScmFileSet(root)); + } + public boolean checkout(File checkoutDirectory){ + boolean checkoutOk = false; + + if(!expectScmRepositoryInitiated()){ + return checkoutOk; + } + + // Checkouting sources LOGGER.fine("Checking out SCM files into ["+checkoutDirectory.getAbsolutePath()+"] ..."); - try { - CheckOutScmResult result = scmManager.checkOut(this.scmRepository, new ScmFileSet(checkoutDirectory)); - if(!result.isSuccess()){ - LOGGER.severe("[checkout] Error during checkout : "+result.getProviderMessage()+" || "+result.getCommandOutput()); - return checkoutOk; - } - checkoutOk = true; - } catch (ScmException e) { - LOGGER.throwing(ScmManager.class.getName(), "checkOut", e); - LOGGER.severe("[checkout] Error during checkout : "+e.getMessage()); - return checkoutOk; - } - - if(checkoutOk){ + try { + CheckOutScmResult result = scmManager.checkOut(this.scmRepository, new ScmFileSet(checkoutDirectory)); + if(!result.isSuccess()){ + LOGGER.severe("[checkout] Error during checkout : "+result.getProviderMessage()+" || "+result.getCommandOutput()); + return checkoutOk; + } + checkoutOk = true; + } catch (ScmException e) { + LOGGER.throwing(ScmManager.class.getName(), "checkOut", e); + LOGGER.severe("[checkout] Error during checkout : "+e.getMessage()); + return checkoutOk; + } + + if(checkoutOk){ LOGGER.fine("Checked out SCM files into ["+checkoutDirectory.getAbsolutePath()+"] !"); - } + } - return checkoutOk; - } + return checkoutOk; + } public List deleteHierarchy(File hierarchyToDelete){ if(!expectScmRepositoryInitiated()){ @@ -124,7 +127,17 @@ public List deleteHierarchy(File hierarchyToDelete){ try { ScmFileSet deleteFileSet = new ScmFileSet(enclosingDirectory, hierarchyToDelete); - RemoveScmResult removeResult = this.scmManager.remove(this.scmRepository, deleteFileSet, ""); + StatusScmResult checkForChanges = this.scmManager.status(scmRepository, deleteFileSet); + LOGGER.fine("Checking for changes on SCM hierarchy ["+hierarchyToDelete.getAbsolutePath()+"] from SCM ..."); + for (ScmFile changedFile : checkForChanges.getChangedFiles()) { + //check in this change as it affect our hierarchy + LOGGER.fine("[checkForChanges] Found changed file "+changedFile.toString()+", try to check-in..."); + CheckInScmResult checkedInChangedFile = scmManager.checkIn(scmRepository, new ScmFileSet(enclosingDirectory.getParentFile(), new File(changedFile.getPath())), "Check-In changes for "+changedFile.getPath()); + if(!checkedInChangedFile.isSuccess()){ + LOGGER.severe("[checkForChanges] Failed to check-in changed file ["+changedFile.getPath()+"]: "+checkedInChangedFile.getProviderMessage()); + } + } + RemoveScmResult removeResult = this.scmManager.remove(this.scmRepository, deleteFileSet, "Delete hierarchy "+hierarchyToDelete.getPath()); if(!removeResult.isSuccess()){ LOGGER.severe("[deleteHierarchy] Problem during remove : "+removeResult.getProviderMessage()); return null; @@ -142,32 +155,32 @@ public List deleteHierarchy(File hierarchyToDelete){ } } - public List addFile(File scmRoot, String filePathRelativeToScmRoot){ - List synchronizedFiles = new ArrayList(); - - if(!expectScmRepositoryInitiated()){ - return synchronizedFiles; - } - - LOGGER.fine("Adding SCM file ["+filePathRelativeToScmRoot+"] ..."); - - try { - // Split every directory leading through modifiedFilePathRelativeToHudsonRoot - // and try add it in the scm - String[] pathChunks = filePathRelativeToScmRoot.split("\\\\|/"); - StringBuilder currentPath = new StringBuilder(); - for(int i=0; i addFile(File scmRoot, String filePathRelativeToScmRoot){ + List synchronizedFiles = new ArrayList(); + + if(!expectScmRepositoryInitiated()){ + return synchronizedFiles; + } + + LOGGER.fine("Adding SCM file ["+filePathRelativeToScmRoot+"] ..."); + + try { + // Split every directory leading through modifiedFilePathRelativeToHudsonRoot + // and try add it in the scm + String[] pathChunks = filePathRelativeToScmRoot.split("\\\\|/"); + StringBuilder currentPath = new StringBuilder(); + for(int i=0; i addFile(File scmRoot, String filePathRelativeToScmRoot){ LOGGER.severe("Error while adding SCM files in directory : " + addResult.getCommandOutput()); } } - } else { + } else { // If addResult.isSuccess() is false, it isn't an error if it is related to path chunks (except for latest one) : // if pathChunk is already synchronized, addResult.isSuccess() will be false. Level logLevel = (i==pathChunks.length-1)?Level.SEVERE:Level.FINE; LOGGER.log(logLevel, "Error while adding SCM file : " + addResult.getCommandOutput()); } - } + } } catch (IOException e) { LOGGER.throwing(ScmFileSet.class.getName(), "init<>", e); LOGGER.warning("[addFile] Error while creating ScmFileset : "+e.getMessage()); return synchronizedFiles; - } catch (ScmException e) { - LOGGER.throwing(ScmManager.class.getName(), "add", e); - LOGGER.warning("[addFile] Error while adding file : "+e.getMessage()); - return synchronizedFiles; - } + } catch (ScmException e) { + LOGGER.throwing(ScmManager.class.getName(), "add", e); + LOGGER.warning("[addFile] Error while adding file : "+e.getMessage()); + return synchronizedFiles; + } - if(!synchronizedFiles.isEmpty()){ - LOGGER.fine("Added SCM files : "+Arrays.toString(synchronizedFiles.toArray(new File[0]))+" !"); - } - - return synchronizedFiles; - } + if(!synchronizedFiles.isEmpty()){ + LOGGER.fine("Added SCM files : "+Arrays.toString(synchronizedFiles.toArray(new File[0]))+" !"); + } + + return synchronizedFiles; + } private List refineUpdatedFilesInScmResult(List updatedFiles){ List refinedUpdatedFiles = new ArrayList(); @@ -224,42 +237,42 @@ private List refineUpdatedFilesInScmResult(List updatedFiles){ return refinedUpdatedFiles; } - - public boolean checkinFiles(File scmRoot, String commitMessage){ - boolean checkinOk = false; - - if(!expectScmRepositoryInitiated()){ - return checkinOk; - } - - LOGGER.fine("Checking in SCM files ..."); - - ScmFileSet fileSet = new ScmFileSet(scmRoot); - - // Let's commit everything ! - try { - CheckInScmResult result = this.scmManager.checkIn(this.scmRepository, fileSet, commitMessage); - if(!result.isSuccess()){ - LOGGER.severe("[checkinFiles] Problem during SCM commit : "+result.getCommandOutput()); - return checkinOk; - } - checkinOk = true; - } catch (ScmException e) { - LOGGER.throwing(ScmManager.class.getName(), "checkIn", e); - LOGGER.severe("[checkinFiles] Error while checkin : "+e.getMessage()); - return checkinOk; - } - - - if(checkinOk){ - LOGGER.fine("Checked in SCM files !"); - } - - return checkinOk; - } - - public String getScmSpecificFilename() { - return scmSpecificFilename; - } - + + public boolean checkinFiles(File scmRoot, String commitMessage){ + boolean checkinOk = false; + + if(!expectScmRepositoryInitiated()){ + return checkinOk; + } + + LOGGER.fine("Checking in SCM files ..."); + + ScmFileSet fileSet = new ScmFileSet(scmRoot); + + // Let's commit everything ! + try { + CheckInScmResult result = this.scmManager.checkIn(this.scmRepository, fileSet, commitMessage); + if(!result.isSuccess()){ + LOGGER.severe("[checkinFiles] Problem during SCM commit : "+result.getCommandOutput()); + return checkinOk; + } + checkinOk = true; + } catch (ScmException e) { + LOGGER.throwing(ScmManager.class.getName(), "checkIn", e); + LOGGER.severe("[checkinFiles] Error while checkin : "+e.getMessage()); + return checkinOk; + } + + + if(checkinOk){ + LOGGER.fine("Checked in SCM files !"); + } + + return checkinOk; + } + + 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 a2feba7b..0aa58bcb 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationBusiness.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationBusiness.java @@ -39,6 +39,7 @@ public class ScmSyncConfigurationBusiness { private SCMManipulator scmManipulator; private File checkoutScmDirectory = null; private ScmSyncConfigurationStatusManager scmSyncConfigurationStatusManager = null; + private List manualSynchronizationIncludes = new ArrayList(); /** * Use of a size 1 thread pool frees us from worrying about accidental thread death and @@ -135,21 +136,21 @@ public Future queueChangeSet(final ScmContext scmContext, ChangeSet change if(scmManipulator == null || !scmManipulator.scmConfigurationSettledUp(scmContext, false)){ LOGGER.info("Queue of changeset "+changeset.toString()+" aborted (scm manipulator not settled !)"); return null; - } + } Commit commit = new Commit(changeset, user, userMessage, scmContext); LOGGER.finest("Queuing commit "+commit.toString()+" to SCM ..."); synchronized(commitsQueue) { - commitsQueue.add(commit); + commitsQueue.add(commit); - return writer.submit(new Callable() { + return writer.submit(new Callable() { @Override - public Void call() throws Exception { - processCommitsQueue(); - return null; - } - }); - } + public Void call() throws Exception { + processCommitsQueue(); + return null; + } + }); + } } private void processCommitsQueue() { @@ -187,8 +188,17 @@ private void processCommitsQueue() { String firstNonExistingParentScmPath = pathRelativeToJenkinsRoot.getFirstNonExistingParentScmPath(); try { - FileUtils.copyDirectory(JenkinsFilesHelper.buildFileFromPathRelativeToHudsonRoot(pathRelativeToJenkinsRoot.getPath()), - fileTranslatedInScm); + File buildFileFromPathRelativeToHudsonRoot = JenkinsFilesHelper.buildFileFromPathRelativeToHudsonRoot(pathRelativeToJenkinsRoot.getPath()); + FileUtils.copyDirectory(buildFileFromPathRelativeToHudsonRoot, fileTranslatedInScm, new FileFilter() { + @Override + public boolean accept(File pathname) { + if(pathname.getPath().endsWith(".xml") + || getManualSynchronizationIncludes().contains(pathname)){ + return true; + } + return false; + } + }); } catch (IOException e) { throw new LoggableException("Error while copying file hierarchy to SCM directory", FileUtils.class, "copyDirectory", e); } @@ -212,7 +222,8 @@ private void processCommitsQueue() { } for(Path path : commit.getChangeset().getPathsToDelete()){ List deletedFiles = deleteHierarchy(commit.getScmContext(), path); - updatedFiles.addAll(deletedFiles); + if(deletedFiles != null) + updatedFiles.addAll(deletedFiles); } if(updatedFiles.isEmpty()){ @@ -232,7 +243,7 @@ private void processCommitsQueue() { signal(logMessage, true); } } - // As soon as a commit doesn't goes well, we should abort commit queue processing... + // As soon as a commit doesn't goes well, we should abort commit queue processing... }catch(LoggableException e){ LOGGER.throwing(e.getClazz().getName(), e.getMethodName(), e); LOGGER.severe("Error while processing commit queue : "+e.getMessage()); @@ -240,13 +251,22 @@ private void processCommitsQueue() { } finally { // We should remove every checkedInCommits synchronized (commitsQueue) { - commitsQueue.removeAll(checkedInCommits); - } + commitsQueue.removeAll(checkedInCommits); } } + } + + public List getManualSynchronizationIncludes() { + return manualSynchronizationIncludes; + } + + public void setManualSynchronizationIncludes( + List manualSynchronizationIncludes) { + this.manualSynchronizationIncludes = manualSynchronizationIncludes; + } private boolean writeScmContentOnlyIfItDiffers(Path pathRelativeToJenkinsRoot, byte[] content, File fileTranslatedInScm) - throws LoggableException { + throws LoggableException { boolean scmContentUpdated = false; boolean contentDiffer = false; try { @@ -265,7 +285,7 @@ private boolean writeScmContentOnlyIfItDiffers(Path pathRelativeToJenkinsRoot, b } private void createScmContent(Path pathRelativeToJenkinsRoot, byte[] content, File fileTranslatedInScm) - throws LoggableException { + throws LoggableException { Stack directoriesToCreate = new Stack(); File directory = fileTranslatedInScm.getParentFile(); 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 ef1b7da9..9e80b558 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin.java @@ -60,13 +60,13 @@ public class ScmSyncConfigurationPlugin extends Plugin{ - public static final transient ScmSyncStrategy[] AVAILABLE_STRATEGIES = new ScmSyncStrategy[]{ - new JenkinsConfigScmSyncStrategy(), - new BasicPluginsConfigScmSyncStrategy(), - new JobConfigScmSyncStrategy(), - new UserConfigScmSyncStrategy(), - new ManualIncludesScmSyncStrategy() - }; + public static final transient ScmSyncStrategy[] AVAILABLE_STRATEGIES = new ScmSyncStrategy[]{ + new JenkinsConfigScmSyncStrategy(), + new BasicPluginsConfigScmSyncStrategy(), + new JobConfigScmSyncStrategy(), + new UserConfigScmSyncStrategy(), + new ManualIncludesScmSyncStrategy() + }; /** * Strategies that cannot be updated by user @@ -74,10 +74,10 @@ public class ScmSyncConfigurationPlugin extends Plugin{ public static final transient List DEFAULT_STRATEGIES = ImmutableList.copyOf( Collections2.filter(Arrays.asList(AVAILABLE_STRATEGIES), new Predicate() { @Override - public boolean apply(@Nullable ScmSyncStrategy scmSyncStrategy) { - return !( scmSyncStrategy instanceof ManualIncludesScmSyncStrategy ); - } - })); + public boolean apply(@Nullable ScmSyncStrategy scmSyncStrategy) { + return !( scmSyncStrategy instanceof ManualIncludesScmSyncStrategy ); + } + })); public void purgeFailLogs() { business.purgeFailLogs(); @@ -89,7 +89,7 @@ public static interface AtomicTransactionFactory { private static final Logger LOGGER = Logger.getLogger(ScmSyncConfigurationPlugin.class.getName()); - private transient ScmSyncConfigurationBusiness business; + private transient ScmSyncConfigurationBusiness business; /** * Flag allowing to process commit synchronously instead of asynchronously (default) @@ -105,10 +105,10 @@ public static interface AtomicTransactionFactory { */ private transient ThreadLocal transaction = new ThreadLocal(); - private String scmRepositoryUrl; - private SCM scm; - private boolean noUserCommitMessage; - private boolean displayStatus = true; + private String scmRepositoryUrl; + private SCM scm; + private boolean noUserCommitMessage; + private boolean displayStatus = true; // The [message] is a magic string that will be replaced with commit message // when commit occurs private String commitMessagePattern = "[message]"; @@ -120,51 +120,52 @@ public ScmSyncConfigurationPlugin(){ this(false); } - public ScmSyncConfigurationPlugin(boolean synchronousTransactions){ + public ScmSyncConfigurationPlugin(boolean synchronousTransactions){ this.synchronousTransactions = synchronousTransactions; - setBusiness(new ScmSyncConfigurationBusiness()); + setBusiness(new ScmSyncConfigurationBusiness()); try { PluginServletFilter.addFilter(new ScmSyncConfigurationFilter()); } catch (ServletException e) { throw new RuntimeException(e); } - } + } public List getManualSynchronizationIncludes(){ return manualSynchronizationIncludes; } - @Override - public void start() throws Exception { - super.start(); + @Override + public void start() throws Exception { + super.start(); Jenkins.XSTREAM.registerConverter(new ScmSyncConfigurationXStreamConverter()); - this.load(); + this.load(); - // If scm has not been read in scm-sync-configuration.xml, let's initialize it - // to the "no scm" SCM - if(this.scm == null){ - this.scm = SCM.valueOf(ScmSyncNoSCM.class); - this.scmRepositoryUrl = null; - } + // If scm has not been read in scm-sync-configuration.xml, let's initialize it + // to the "no scm" SCM + if(this.scm == null){ + this.scm = SCM.valueOf(ScmSyncNoSCM.class); + this.scmRepositoryUrl = null; + } - // SCMManagerFactory.start() must be called here instead of ScmSyncConfigurationItemListener.onLoaded() - // because, for some unknown reasons, we reach plexus bootstraping exceptions when - // calling Embedder.start() when everything is loaded (very strange...) - SCMManagerFactory.getInstance().start(); + // SCMManagerFactory.start() must be called here instead of ScmSyncConfigurationItemListener.onLoaded() + // because, for some unknown reasons, we reach plexus bootstraping exceptions when + // calling Embedder.start() when everything is loaded (very strange...) + SCMManagerFactory.getInstance().start(); initialInit(); - } + } - public void loadData(ScmSyncConfigurationPOJO pojo){ - this.scmRepositoryUrl = pojo.getScmRepositoryUrl(); - this.scm = pojo.getScm(); - this.noUserCommitMessage = pojo.isNoUserCommitMessage(); - this.displayStatus = pojo.isDisplayStatus(); + public void loadData(ScmSyncConfigurationPOJO pojo){ + this.scmRepositoryUrl = pojo.getScmRepositoryUrl(); + this.scm = pojo.getScm(); + this.noUserCommitMessage = pojo.isNoUserCommitMessage(); + this.displayStatus = pojo.isDisplayStatus(); this.commitMessagePattern = pojo.getCommitMessagePattern(); this.manualSynchronizationIncludes = pojo.getManualSynchronizationIncludes(); - } + this.business.setManualSynchronizationIncludes(manualSynchronizationIncludes); + } protected void initialInit() throws Exception { // We need to init() here in addition to ScmSyncConfigurationItemListener.onLoaded() to ensure that we do @@ -174,24 +175,24 @@ protected void initialInit() throws Exception { this.business.init(createScmContext()); } - public void init() { - try { - this.business.init(createScmContext()); - } catch (Exception e) { - throw new RuntimeException("Error during ScmSyncConfiguration initialisation !", e); - } - } + public void init() { + try { + this.business.init(createScmContext()); + } catch (Exception e) { + throw new RuntimeException("Error during ScmSyncConfiguration initialisation !", e); + } + } - @Override - public void stop() throws Exception { - SCMManagerFactory.getInstance().stop(); - super.stop(); - } + @Override + public void stop() throws Exception { + SCMManagerFactory.getInstance().stop(); + super.stop(); + } - @Override - public void configure(StaplerRequest req, JSONObject formData) - throws IOException, ServletException, FormException { - super.configure(req, formData); + @Override + public void configure(StaplerRequest req, JSONObject formData) + throws IOException, ServletException, FormException { + super.configure(req, formData); boolean repoInitializationRequired = false; boolean configsResynchronizationRequired = false; @@ -202,12 +203,12 @@ public void configure(StaplerRequest req, JSONObject formData) this.commitMessagePattern = req.getParameter("commitMessagePattern"); String oldScmRepositoryUrl = this.scmRepositoryUrl; - String scmType = req.getParameter("scm"); - if(scmType != null){ - this.scm = SCM.valueOf(scmType); - String newScmRepositoryUrl = this.scm.createScmUrlFromRequest(req); + String scmType = req.getParameter("scm"); + if(scmType != null){ + this.scm = SCM.valueOf(scmType); + String newScmRepositoryUrl = this.scm.createScmUrlFromRequest(req); - this.scmRepositoryUrl = newScmRepositoryUrl; + this.scmRepositoryUrl = newScmRepositoryUrl; // If something changed, let's reinitialize repository in working directory ! repoInitializationRequired = newScmRepositoryUrl != null && !newScmRepositoryUrl.equals(oldScmRepositoryUrl); @@ -227,6 +228,8 @@ public void configure(StaplerRequest req, JSONObject formData) } else { this.manualSynchronizationIncludes = new ArrayList(); } + + this.business.setManualSynchronizationIncludes(manualSynchronizationIncludes); // Repo initialization should be made _before_ plugin save, in order to let scm-sync-configuration.xml // file synchronizable @@ -243,8 +246,8 @@ public void configure(StaplerRequest req, JSONObject formData) // Persisting plugin data // Note that save() is made _after_ the synchronizeAllConfigs() because, otherwise, scm-sync-configuration.xml // file would be commited _before_ every other jenkins configuration file, which doesn't seem "natural" - this.save(); - } + this.save(); + } public Iterable collectAllFilesForScm() { return Iterables.concat(Iterables.transform(Lists.newArrayList(AVAILABLE_STRATEGIES), new Function>() { @@ -272,29 +275,29 @@ public void reloadAllFilesFromScm() throws ServletException, IOException { } } - public void doReloadAllFilesFromScm(StaplerRequest req, StaplerResponse res) throws ServletException, IOException { - try { - filesModifiedByLastReload = business.reloadAllFilesFromScm(); - req.getView(this, "/hudson/plugins/scm_sync_configuration/reload.jelly").forward(req, res); - } - catch(ScmException e) { - throw new ServletException("Unable to reload SCM " + scm.getTitle() + ":" + getScmUrl(), e); - } - } - - public void doSubmitComment(StaplerRequest req, StaplerResponse res) throws ServletException, IOException { - // TODO: complexify this in order to pass a strategy identifier in the session key - ScmSyncConfigurationDataProvider.provideComment(req.getParameter("comment")); - if(Boolean.valueOf(req.getParameter("dontBotherMe")).booleanValue()){ - ScmSyncConfigurationDataProvider.provideBotherTimeout(req.getParameter("botherType"), - Integer.valueOf(req.getParameter("botherTime")), req.getParameter("currentURL")); - } - } - - // TODO: do retrieve help file with an action ! - public void doHelpForRepositoryUrl(StaplerRequest req, StaplerResponse res) throws ServletException, IOException{ - req.getView(this, SCM.valueOf(req.getParameter("scm")).getRepositoryUrlHelpPath()).forward(req, res); - } + public void doReloadAllFilesFromScm(StaplerRequest req, StaplerResponse res) throws ServletException, IOException { + try { + filesModifiedByLastReload = business.reloadAllFilesFromScm(); + req.getView(this, "/hudson/plugins/scm_sync_configuration/reload.jelly").forward(req, res); + } + catch(ScmException e) { + throw new ServletException("Unable to reload SCM " + scm.getTitle() + ":" + getScmUrl(), e); + } + } + + public void doSubmitComment(StaplerRequest req, StaplerResponse res) throws ServletException, IOException { + // TODO: complexify this in order to pass a strategy identifier in the session key + ScmSyncConfigurationDataProvider.provideComment(req.getParameter("comment")); + if(Boolean.valueOf(req.getParameter("dontBotherMe")).booleanValue()){ + ScmSyncConfigurationDataProvider.provideBotherTimeout(req.getParameter("botherType"), + Integer.valueOf(req.getParameter("botherTime")), req.getParameter("currentURL")); + } + } + + // TODO: do retrieve help file with an action ! + public void doHelpForRepositoryUrl(StaplerRequest req, StaplerResponse res) throws ServletException, IOException{ + req.getView(this, SCM.valueOf(req.getParameter("scm")).getRepositoryUrlHelpPath()).forward(req, res); + } // Help url for manualSynchronizationIncludes field is a jelly script and not a html file // because we need default includes list to be displayed in it ! @@ -319,27 +322,27 @@ public List getDefaultIncludes(){ return includes; } - private User getCurrentUser(){ - User user = null; - try { + private User getCurrentUser(){ + User user = null; + try { user = Jenkins.getInstance().getMe(); - }catch(AccessDeniedException e){} - return user; - } + }catch(AccessDeniedException e){} + return user; + } - public static ScmSyncConfigurationPlugin getInstance(){ + public static ScmSyncConfigurationPlugin getInstance(){ return Jenkins.getInstance().getPlugin(ScmSyncConfigurationPlugin.class); - } - - public ScmSyncStrategy getStrategyForSaveable(Saveable s, File f){ - for(ScmSyncStrategy strat : AVAILABLE_STRATEGIES){ - if(strat.isSaveableApplicable(s, f)){ - return strat; - } - } - // Strategy not found ! - return null; - } + } + + public ScmSyncStrategy getStrategyForSaveable(Saveable s, File f){ + for(ScmSyncStrategy strat : AVAILABLE_STRATEGIES){ + if(strat.isSaveableApplicable(s, f)){ + return strat; + } + } + // Strategy not found ! + return null; + } /** * Tries to find at least one strategy that would have applied to a deleted item. @@ -358,84 +361,84 @@ public ScmSyncStrategy getStrategyForDeletedSaveable(Saveable s, String pathRela return null; } - public ScmContext createScmContext(){ - return new ScmContext(this.scm, this.scmRepositoryUrl, this.commitMessagePattern); - } + public ScmContext createScmContext(){ + return new ScmContext(this.scm, this.scmRepositoryUrl, this.commitMessagePattern); + } - public boolean shouldDecorationOccursOnURL(String url){ - // Removing comment from session here... - ScmSyncConfigurationDataProvider.retrieveComment(true); + public boolean shouldDecorationOccursOnURL(String url){ + // Removing comment from session here... + ScmSyncConfigurationDataProvider.retrieveComment(true); - // Displaying commit message popup is based on following tests : - // Zero : never ask for a commit message - // First : no botherTimeout should match with current url - // Second : a strategy should exist, matching current url - // Third : SCM Sync should be settled up - return !noUserCommitMessage && ScmSyncConfigurationDataProvider.retrieveBotherTimeoutMatchingUrl(url) == null + // Displaying commit message popup is based on following tests : + // Zero : never ask for a commit message + // First : no botherTimeout should match with current url + // Second : a strategy should exist, matching current url + // Third : SCM Sync should be settled up + return !noUserCommitMessage && ScmSyncConfigurationDataProvider.retrieveBotherTimeoutMatchingUrl(url) == null && getStrategyForURL(url) != null && this.business.scmCheckoutDirectorySettledUp(createScmContext()); - } - - public ScmSyncStrategy getStrategyForURL(String url){ - for(ScmSyncStrategy strat : AVAILABLE_STRATEGIES){ - if(strat.isCurrentUrlApplicable(url)){ - return strat; - } - } - // Strategy not found ! - return null; - } - - public boolean isNoUserCommitMessage() { - return noUserCommitMessage; - } - - public SCM[] getScms(){ - return SCM.values(); - } - - public void setBusiness(ScmSyncConfigurationBusiness business) { - this.business = business; - } - - public ScmSyncConfigurationStatusManager getScmSyncConfigurationStatusManager() { - return business.getScmSyncConfigurationStatusManager(); - } - - public String getScmRepositoryUrl() { - return scmRepositoryUrl; - } - - public boolean isScmSelected(SCM _scm){ - return this.scm == _scm; - } - - public SCM getSCM(){ - return this.scm; - } - - public String getScmUrl(){ - if(this.scm != null){ - return this.scm.extractScmUrlFrom(this.scmRepositoryUrl); - } else { - return null; - } - } - - public List getFilesModifiedByLastReload() { - return filesModifiedByLastReload; - } - - public boolean isDisplayStatus() { - return displayStatus; - } + } + + public ScmSyncStrategy getStrategyForURL(String url){ + for(ScmSyncStrategy strat : AVAILABLE_STRATEGIES){ + if(strat.isCurrentUrlApplicable(url)){ + return strat; + } + } + // Strategy not found ! + return null; + } + + public boolean isNoUserCommitMessage() { + return noUserCommitMessage; + } + + public SCM[] getScms(){ + return SCM.values(); + } + + public void setBusiness(ScmSyncConfigurationBusiness business) { + this.business = business; + } + + public ScmSyncConfigurationStatusManager getScmSyncConfigurationStatusManager() { + return business.getScmSyncConfigurationStatusManager(); + } + + public String getScmRepositoryUrl() { + return scmRepositoryUrl; + } + + public boolean isScmSelected(SCM _scm){ + return this.scm == _scm; + } + + public SCM getSCM(){ + return this.scm; + } + + public String getScmUrl(){ + if(this.scm != null){ + return this.scm.extractScmUrlFrom(this.scmRepositoryUrl); + } else { + return null; + } + } + + public List getFilesModifiedByLastReload() { + return filesModifiedByLastReload; + } + + public boolean isDisplayStatus() { + return displayStatus; + } public String getCommitMessagePattern() { return commitMessagePattern; } - public Descriptor getDescriptorForSCM(String scmName){ - return SCM.valueOf(scmName).getSCMDescriptor(); - } + public Descriptor getDescriptorForSCM(String scmName){ + return SCM.valueOf(scmName).getSCMDescriptor(); + } public void startThreadedTransaction(){ this.setTransaction(new ThreadedTransaction(synchronousTransactions)); @@ -466,7 +469,7 @@ protected void setTransaction(ScmTransaction transactionToRegister){ LOGGER.warning("Existing threaded transaction will be overriden !"); } transaction.set(transactionToRegister); - } + } public boolean currentUserCannotPurgeFailLogs() { return !business.canCurrentUserPurgeFailLogs(); @@ -483,7 +486,7 @@ public boolean currentUserCannotPurgeFailLogs() { public FormValidation doCheckGitUrl(@QueryParameter String value) { if (Strings.isNullOrEmpty(value)) { return FormValidation.error(Messages.ScmSyncConfigurationsPlugin_gitRepoUrlEmpty()); - } + } String trimmed = value.trim(); // Plain file paths are valid URIs, except maybe on windows if starting with a drive letter if (!isValidUrl (trimmed)) { @@ -495,7 +498,7 @@ public FormValidation doCheckGitUrl(@QueryParameter String value) { if (trimmed.indexOf("://") < 0 && trimmed.indexOf(':') > 0) { if (!isValidUrl("ssh://" + trimmed.replaceFirst(":", "/"))) { return FormValidation.error(Messages.ScmSyncConfigurationsPlugin_gitRepoUrlInvalid()); - } +} } else { return FormValidation.error(Messages.ScmSyncConfigurationsPlugin_gitRepoUrlInvalid()); } diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/model/ChangeSet.java b/src/main/java/hudson/plugins/scm_sync_configuration/model/ChangeSet.java index d2927b29..7514f3ac 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/model/ChangeSet.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/model/ChangeSet.java @@ -75,7 +75,7 @@ public Map getPathContents(){ for(Path pathToAdd : filteredPathContents.keySet()){ for(Path pathToDelete : pathsToDelete){ // Removing paths being both in pathsToDelete and pathContents - if(pathToDelete.contains(pathToAdd)){ + if(pathToDelete.equals(pathToAdd)){ filteredPaths.add(pathToAdd); } }