From dc4043bb449313e4eeea43fc130a5f8cad1bba99 Mon Sep 17 00:00:00 2001 From: zilmTT Date: Mon, 24 Aug 2015 12:28:44 +0200 Subject: [PATCH 1/4] Fix wrong condition in getPathContents() If the deletion and adding path share some characters the contains() function succeed and removes the added path. It should be checked if they are equal. This fixes some rename issues we discovered in our environment. --- .../hudson/plugins/scm_sync_configuration/model/ChangeSet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } } From aabe49b8f023cad2d302528f3b13602e3be14924 Mon Sep 17 00:00:00 2001 From: zilmTT Date: Mon, 24 Aug 2015 12:32:41 +0200 Subject: [PATCH 2/4] Fix hierarchy deletion issues (JENKINS-26652) Before deleting the job hierarchy it is needed to check for changes on the files, e.g config.xml. While deleting a job it gets updated, this blocks the git -rm command from deleting this hierarchy. Commits should always come with proper messages, git command fails if the commit message is empty. Which put scm-sync in an dirty state if there are commits which cannot be pushed. --- .../scm_sync_configuration/SCMManipulator.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) 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..2ff009db 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/SCMManipulator.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/SCMManipulator.java @@ -9,6 +9,7 @@ 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; @@ -18,6 +19,7 @@ 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; @@ -124,7 +126,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; From dcd8be1193ce3891dcc228be32c52be1f773cf3a Mon Sep 17 00:00:00 2001 From: zilmTT Date: Mon, 24 Aug 2015 12:34:14 +0200 Subject: [PATCH 3/4] Add a basic filter for FileUtil.copy As i encountered some copy issues, e.g was not able to copy blank build/ dir, i implemented a basic filter for the FileUtil.copy function. This matches on any XML-File and on includes specified on ManualIncludes list from scm-sync-configuration. --- .../ScmSyncConfigurationBusiness.java | 26 ++++++++++++++++--- .../ScmSyncConfigurationPlugin.java | 3 +++ 2 files changed, 26 insertions(+), 3 deletions(-) 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..48085a8c 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 @@ -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()){ @@ -245,6 +256,15 @@ private void processCommitsQueue() { } } + public List getManualSynchronizationIncludes() { + return manualSynchronizationIncludes; + } + + public void setManualSynchronizationIncludes( + List manualSynchronizationIncludes) { + this.manualSynchronizationIncludes = manualSynchronizationIncludes; + } + private boolean writeScmContentOnlyIfItDiffers(Path pathRelativeToJenkinsRoot, byte[] content, File fileTranslatedInScm) throws LoggableException { boolean scmContentUpdated = false; 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..b4612674 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin.java @@ -164,6 +164,7 @@ public void loadData(ScmSyncConfigurationPOJO pojo){ this.displayStatus = pojo.isDisplayStatus(); this.commitMessagePattern = pojo.getCommitMessagePattern(); this.manualSynchronizationIncludes = pojo.getManualSynchronizationIncludes(); + this.business.setManualSynchronizationIncludes(manualSynchronizationIncludes); } protected void initialInit() throws Exception { @@ -228,6 +229,8 @@ public void configure(StaplerRequest req, JSONObject formData) 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 if(repoInitializationRequired){ From 16704b24a41986145e3b2b51330733b20b13d435 Mon Sep 17 00:00:00 2001 From: Marco Nenciarini Date: Thu, 3 Nov 2016 17:40:28 +0100 Subject: [PATCH 4/4] Avoid to delete unexistent paths [JENKINS-37500] Signed-off-by: Marco Nenciarini Signed-off-by: Giulio Calacoci --- .../plugins/scm_sync_configuration/model/ChangeSet.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 7514f3ac..2538a6fd 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 @@ -58,8 +58,10 @@ public void registerPath(String path) { public void registerPathForDeletion(String path){ // We should determine if path is a directory by watching scm path (and not hudson path) because in most of time, // when we are here, directory is already deleted in hudson hierarchy... - boolean isDirectory = new Path(path).getScmFile().isDirectory(); - pathsToDelete.add(new Path(path, isDirectory)); + if(new Path(path).getScmFile().exists()) { + boolean isDirectory = new Path(path).getScmFile().isDirectory(); + pathsToDelete.add(new Path(path, isDirectory)); + } } public boolean isEmpty(){