diff --git a/pom.xml b/pom.xml index 54c7ef89..e0fc945e 100644 --- a/pom.xml +++ b/pom.xml @@ -145,7 +145,8 @@ org.jenkins-ci.plugins subversion 1.39 - + + com.google.code.maven-scm-provider-svnjava @@ -159,6 +160,11 @@ 1.6 + + org.apache.maven.scm + maven-scm-provider-hg + 1.8 + 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 f2af3515..b15ba70f 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/SCMManipulator.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/SCMManipulator.java @@ -106,14 +106,16 @@ public boolean checkout(File checkoutDirectory){ return checkoutOk; } - public List deleteHierarchy(File hierarchyToDelete){ + public List deleteHierarchy(File hierarchyToDelete, String hierarchyPath){ if(!expectScmRepositoryInitiated()){ return null; } - File enclosingDirectory = hierarchyToDelete.getParentFile(); - - LOGGER.fine("Deleting SCM hierarchy ["+hierarchyToDelete.getAbsolutePath()+"] from SCM ..."); + String absolutePath = hierarchyToDelete.getAbsolutePath(); + String basePath = absolutePath.substring(0, absolutePath.lastIndexOf(hierarchyPath)); + File enclosingDirectory = new File(basePath); + + LOGGER.fine("Deleting SCM hierarchy ["+absolutePath+"] from SCM ..."); File commitFile = hierarchyToDelete; while(! commitFile.isDirectory()) { 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 a4112e7f..eda658e6 100644 --- a/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationBusiness.java +++ b/src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationBusiness.java @@ -110,7 +110,7 @@ public List deleteHierarchy(ScmContext scmContext, Path hierarchyPath){ File rootHierarchyTranslatedInScm = hierarchyPath.getScmFile(); - List filesToCommit = scmManipulator.deleteHierarchy(rootHierarchyTranslatedInScm); + List filesToCommit = scmManipulator.deleteHierarchy(rootHierarchyTranslatedInScm, hierarchyPath.getPath()); // Once done, we should delete path in scm if it is a directory if(hierarchyPath.isDirectory()){ 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..722de775 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 @@ -25,6 +25,7 @@ public abstract class SCM { add(new ScmSyncNoSCM()); add(new ScmSyncSubversionSCM()); add(new ScmSyncGitSCM()); + add(new ScmSyncHgSCM()); } }; transient protected String title; diff --git a/src/main/java/hudson/plugins/scm_sync_configuration/scms/ScmSyncHgSCM.java b/src/main/java/hudson/plugins/scm_sync_configuration/scms/ScmSyncHgSCM.java new file mode 100644 index 00000000..1de33a4b --- /dev/null +++ b/src/main/java/hudson/plugins/scm_sync_configuration/scms/ScmSyncHgSCM.java @@ -0,0 +1,31 @@ +package hudson.plugins.scm_sync_configuration.scms; + +import org.kohsuke.stapler.StaplerRequest; + +public class ScmSyncHgSCM extends SCM { + + private static final String SCM_URL_PREFIX="scm:hg:"; + + ScmSyncHgSCM(){ + super("Mercurial", "hg/config.jelly", "hudson.plugins.mercurial.MercurialSCM", "/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/url-help.jelly"); + } + + public String createScmUrlFromRequest(StaplerRequest req) { + String repoURL = req.getParameter("hgRepositoryUrl"); + if(repoURL == null){ + return null; + } + else { + return SCM_URL_PREFIX+repoURL; + } + } + + public String extractScmUrlFrom(String scmUrl) { + return scmUrl.substring(SCM_URL_PREFIX.length()); + } + + public SCMCredentialConfiguration extractScmCredentials(String scmUrl) { + return null; + } + +} diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/config.jelly b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/config.jelly new file mode 100644 index 00000000..e089d694 --- /dev/null +++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/config.jelly @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/config_fr.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/config_fr.properties new file mode 100644 index 00000000..7c14cc25 --- /dev/null +++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/config_fr.properties @@ -0,0 +1 @@ +Repository\ URL=URL du repository diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/url-help.jelly b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/url-help.jelly new file mode 100644 index 00000000..e5c23d37 --- /dev/null +++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/url-help.jelly @@ -0,0 +1,32 @@ + + + + +
+ ${%description.1}
+ ${%description.2} +
+
+
\ No newline at end of file diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/url-help.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/url-help.properties new file mode 100644 index 00000000..8c1247f1 --- /dev/null +++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/url-help.properties @@ -0,0 +1,26 @@ +# The MIT License +# +# Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +description.1=\ + Specify the hg repository URL to synchronize your configuration files with, such as "hg@bitbucket.org:mycompany/jenkins-config" +description.2=\ + Note that, for the moment, your MUST reference your Hg repository root diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/url-help_fr.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/url-help_fr.properties new file mode 100644 index 00000000..d90cd208 --- /dev/null +++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/hg/url-help_fr.properties @@ -0,0 +1,26 @@ +# The MIT License +# +# Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Eric Lefevre-Ardant +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +description.1=\ + Spécifier l''url du repository Hg vers lequel synchroniser vos fichiers de configuration, tel que "hg@bitbucket.org/mycompany/jenkins-config" +description.2=\ + A noter qu''il est pour le moment obligatoire de référencer la racine du repository diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsHgTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsHgTest.java new file mode 100644 index 00000000..b6cdab06 --- /dev/null +++ b/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsHgTest.java @@ -0,0 +1,16 @@ +package hudson.plugins.scm_sync_configuration.repository; + +import hudson.plugins.test.utils.scms.ScmUnderTestHg; +import org.junit.Ignore; + +public class HudsonExtensionsHgTest extends HudsonExtensionsTest { + + public HudsonExtensionsHgTest() { + super(new ScmUnderTestHg()); + } + + @Ignore("Should be re-activated once maven-scm-api 1.9 is released (see JENKINS-15128)") + public void shouldJobRenameBeCorrectlyImpactedOnSCM() throws Throwable { + super.shouldJobRenameBeCorrectlyImpactedOnSCM(); + } +} 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 67bb10e0..ec86139b 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 @@ -294,7 +294,7 @@ public void shouldReloadAllFilesUpdateScmAndReloadAllFiles() throws Throwable { final File configJobFile = new File(checkoutDirectoryForVerifications.getAbsolutePath() + "/jobs/fakeJob/config.xml"); FileUtils.fileAppend(configJobFile.getAbsolutePath(), "titi"); - scmManipulator.checkinFiles(checkoutDirectoryForVerifications, "external commit on jonb file"); + scmManipulator.checkinFiles(checkoutDirectoryForVerifications, "external commit on job file"); verifyCurrentScmContentMatchesCurrentHudsonDir(false); @@ -303,6 +303,7 @@ public void shouldReloadAllFilesUpdateScmAndReloadAllFiles() throws Throwable { verifyCurrentScmContentMatchesCurrentHudsonDir(true); + assertAndRemoveHgSpecificFile(syncedFiles); assertThat(syncedFiles.size(), is(2)); assertThat(syncedFiles.contains(new File(getCurrentHudsonRootDirectory().getAbsolutePath() + "/config.xml")), is(true)); assertThat(syncedFiles.contains(new File(getCurrentHudsonRootDirectory().getAbsolutePath() + "/jobs/fakeJob/config.xml")), is(true)); @@ -345,6 +346,7 @@ public void shouldReloadAllFilesUpdateScmAndReloadAllFilesWithFileAdd() throws T verifyCurrentScmContentMatchesCurrentHudsonDir(true); + assertAndRemoveHgSpecificFile(syncedFiles); assertThat(syncedFiles.size(), is(2)); assertThat(syncedFiles.contains(new File(getCurrentHudsonRootDirectory().getAbsolutePath() + "/myConfigFile.xml")), is(true)); assertThat(syncedFiles.contains(new File(getCurrentHudsonRootDirectory().getAbsolutePath() + "/jobs/myJob")), is(true)); @@ -378,4 +380,13 @@ private void assertStrategy(Class expectedStrategyCla } } + private void assertAndRemoveHgSpecificFile(List syncedFiles) { + // HG Support: If we encounter the dummy file used to initialise HG repo then we know + // we are dealing with a HG repo, so remove it so other tests can pass. + if(this instanceof HudsonExtensionsHgTest) { + File file = new File(getCurrentHudsonRootDirectory().getAbsolutePath() + "/hg_dummy.txt"); + assertThat(syncedFiles.contains(file), is(true)); + syncedFiles.remove(syncedFiles.indexOf(file)); + } + } } diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositoryHgTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositoryHgTest.java new file mode 100644 index 00000000..174b865a --- /dev/null +++ b/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositoryHgTest.java @@ -0,0 +1,13 @@ +package hudson.plugins.scm_sync_configuration.repository; + +import hudson.plugins.test.utils.scms.ScmUnderTestHg; + + + +public class InitRepositoryHgTest extends InitRepositoryTest { + + public InitRepositoryHgTest() { + super(new ScmUnderTestHg()); + } + +} diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositoryTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositoryTest.java index 75107891..cb6b20bf 100644 --- a/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositoryTest.java +++ b/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositoryTest.java @@ -60,7 +60,14 @@ public void shouldResetCheckoutConfigurationDirectoryWhenAsked() throws Throwabl // Reseting the repository, without cleanup sscBusiness.initializeRepository(scmContext, false); - assertThat(fileWhichShouldBeDeletedAfterReset.exists(), is(true)); + if (this instanceof InitRepositoryHgTest) { + // HG Support: HG behaves differently and always destroys files that aren't yet in source control. + // Note: Should this be allowed in the first place? If a reset is requested why should it + // allow untracked files to linger around? + assertThat(fileWhichShouldBeDeletedAfterReset.exists(), is(false)); + } else { + assertThat(fileWhichShouldBeDeletedAfterReset.exists(), is(true)); + } // Reseting the repository with cleanup sscBusiness.initializeRepository(scmContext, true); 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..5f053715 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 @@ -203,6 +203,8 @@ protected static List getSpecialSCMDirectoryExcludePattern(){ return new ArrayList(){{ add(Pattern.compile("\\.svn")); add(Pattern.compile("\\.git.*")); + add(Pattern.compile("\\.hg.*")); + add(Pattern.compile("hg_dummy.txt")); add(Pattern.compile("scm-sync-configuration\\..*\\.log")); add(Pattern.compile("scm-sync-configuration")); }}; diff --git a/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTestHg.java b/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTestHg.java new file mode 100644 index 00000000..689281de --- /dev/null +++ b/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTestHg.java @@ -0,0 +1,51 @@ +package hudson.plugins.test.utils.scms; + +import hudson.plugins.scm_sync_configuration.scms.SCM; +import hudson.plugins.scm_sync_configuration.scms.ScmSyncHgSCM; + +import java.io.File; + +import org.codehaus.plexus.util.FileUtils; + +public class ScmUnderTestHg implements ScmUnderTest { + + public void initRepo(File path) throws Exception { + // HG support: Unlike Git, Mercurial does not appear to support "bare" repositories. + // So we have to initialise the repository by committing a dummy file. + + final String dummyFileName = "hg_dummy.txt"; + File dummyFile = new File(path, dummyFileName); + FileUtils.fileWrite(dummyFile.getAbsolutePath(), "This is a dummy file"); + + ProcessBuilder[] commands = new ProcessBuilder[] { + new ProcessBuilder("hg", "init"), + new ProcessBuilder("hg", "add", dummyFileName), + new ProcessBuilder("hg", "commit", "-m", "\"initial commit\"") + }; + + for (ProcessBuilder pb : commands) { + pb.directory(path); + Process p = pb.start(); + if (p.waitFor() != 0) { + throw new Exception("Unable to init hg repo in " + path.getAbsolutePath()); + } + } + } + + public String createUrl(String url) { + return "scm:hg:" + url; + } + + public Class getClazz() { + return ScmSyncHgSCM.class; + } + + public boolean useCredentials() { + return false; + } + + public String getSuffixForTestFiles() { + return ".hg"; + } + +} diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.hg/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.hg/config.xml new file mode 100644 index 00000000..824eae41 --- /dev/null +++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.hg/config.xml @@ -0,0 +1,31 @@ + + + 1.339 + 2 + NORMAL + true + + + true + + Welcome ! + + + + 5 + 0 + + + + All + false + false + + + All + 0 + + + + + \ No newline at end of file diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.hg/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.hg/hudson.tasks.Shell.xml new file mode 100644 index 00000000..8b953697 --- /dev/null +++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.hg/hudson.tasks.Shell.xml @@ -0,0 +1,5 @@ + + + + /bin/bash + \ No newline at end of file diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.hg/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.hg/scm-sync-configuration.xml new file mode 100644 index 00000000..a83018f2 --- /dev/null +++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.hg/scm-sync-configuration.xml @@ -0,0 +1,5 @@ + + + scm:svn:https://myrepo/synchronizedDirectory/ + + \ No newline at end of file