+
+
+
+ ${%Reload}
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/config_fr.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/config_fr.properties
new file mode 100644
index 00000000..0433f211
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/config_fr.properties
@@ -0,0 +1,15 @@
+SCM\ Sync\ configuration=SCM Sync Configuration
+SCM=SCM
+Never\ bother\ me\ with\ commit\ messages=Ne jamais me d\u00E9ranger avec des messages de commit
+Display\ SCM\ Sync\ Status=Afficher le statut du SCM Sync
+Commit\ message\ pattern=Mod\u00E8le de message de commit
+Manual\ synchronization\ includes=Chemins synchronis\u00E9s manuellement
+Add\ new\ include=Ajouter un nouveau chemin
+Include=Chemin
+Delete\ include=Supprimer le chemin
+Reload\ config\ from\ SCM=Recharger la configuration depuis le SCM
+WARNING\ \:\ the\ Jenkins\ config\ will\ be\ reloaded\ from\ SCM=Attention : la configuration Jenkins va \u00EAtre recharg\u00E9e depuis le SCM
+Only\ file\ modifications\ are\ handled=Seules les modifications de fichier sont g\u00E9r\u00E9es
+File\ added\ or\ removed\ will\ not\ be\ handled=Les fichiers ajout\u00E9s ou supprim\u00E9s ne seront pas g\u00E9r\u00E9s
+Continue=Continuer
+Reload=Recharger
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/help/manualSynchronizationIncludes.jelly b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/help/manualSynchronizationIncludes.jelly
new file mode 100644
index 00000000..71ef9cee
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/help/manualSynchronizationIncludes.jelly
@@ -0,0 +1,25 @@
+
+
+ ${%List of ant-like includes allowing to specify additional files to synchronize with the repository}.
+ ${%Includes should be case sensitive paths starting from your JENKINS_HOME directory, without / in the beginning; Use of wildcards} (${%* and **}) ${%is allowed}.
+ ${%You can have a look at} ${%community shared includes in Jenkins wiki}, ${%feel free to share your owns on this page} !
+ ${%Before creating new includes, you should be aware of some things} :
+
+
+ ${%Avoid includes for big and updated-often files} : ${%otherwise, your jenkins instance will spend its CPU time to commit your file}
+
+
+ ${%In order to be noticed at the right time, your files must be represented in Jenkins by a} Saveable,
+ ${%most of them are, but who knows}...
+
+
+ ${%Following includes are brought "out of the box" by scm-sync-configuration default includes} :
+
+
+
${include}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/help/manualSynchronizationIncludes_fr.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/help/manualSynchronizationIncludes_fr.properties
new file mode 100644
index 00000000..ec375ad7
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/help/manualSynchronizationIncludes_fr.properties
@@ -0,0 +1,13 @@
+List\ of\ ant-like\ includes\ allowing\ to\ specify\ additional\ files\ to\ synchronize\ with\ the\ repository=Liste de chemin \u00E0 la Ant, permettant de sp\u00E9cifier des fichiers suppl\u00E9mentaires qui seront synchronis\u00E9s avec le repository
+Includes\ should\ be\ case\ sensitive\ paths\ starting\ from\ your\ JENKINS_HOME\ directory,\ without\ /\ in\ the\ beginning;\ Use\ of\ wildcards=Les chemins doivent \u00EAtre sensibles \u00E0 la casse, bas\u00E9s depuis votre r\u00E9pertoire JENKINS_HOME, et ne d\u00E9marrant pas par un /; L''utilisation des wildcards
+*\ and\ **=* et **
+is\ allowed=est autoris\u00E9
+You\ can\ have\ a\ look\ at=Vous pouvez jeter un oeil aux
+community\ shared\ includes\ in\ Jenkins\ wiki=chemin partag\u00E9s par la communaut\u00E9 dans le wiki Jenkins
+feel\ free\ to\ share\ your\ owns\ on\ this\ page=n''h\u00E9sitez pas \u00E0 partager les v\u00F4tres sur cette page
+Before\ creating\ new\ includes,\ you\ should\ be\ aware\ of\ some\ things=Avant de cr\u00E9er de nouveaux chemins, vous devriez \u00EAtre conscient de certaines contraintes
+Avoid\ includes\ for\ big\ and\ updated-often\ files=Evitez les chemins pour les gros fichiers ainsi que ceux mis \u00E0 jour souvent
+otherwise,\ your\ jenkins\ instance\ will\ spend\ its\ CPU\ time\ to\ commit\ your\ file=autrement, votre instance Jenkins va passer son temps CPU \u00E0 commiter votre fichier
+In\ order\ to\ be\ noticed\ at\ the\ right\ time,\ your\ files\ must\ be\ represented\ in\ Jenkins\ by\ a=Afin d''\u00EAtre notifi\u00E9 au bon moment, vos fichiers doivent correspondre, dans Jenkins, \u00E0 un
+most\ of\ them\ are,\ but\ who\ knows=la plupart le sont, mais qui sait
+Following\ includes\ are\ brought\ "out\ of\ the\ box"\ by\ scm-sync-configuration\ default\ includes=Les chemins suivants sont fournis par d\u00E9faut par le plugin scm-sync-configuration
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
new file mode 100644
index 00000000..8b8aae9f
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/config.jelly
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/config_fr.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/config_fr.properties
new file mode 100644
index 00000000..7c14cc25
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/config_fr.properties
@@ -0,0 +1 @@
+Repository\ URL=URL du repository
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/url-help.jelly b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/url-help.jelly
new file mode 100644
index 00000000..e5c23d37
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/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/git/url-help.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/url-help.properties
new file mode 100644
index 00000000..888432f3
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/url-help.properties
@@ -0,0 +1,24 @@
+# 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 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, you MUST reference your Git repository root
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/url-help_fr.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/url-help_fr.properties
new file mode 100644
index 00000000..36fd76bf
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/git/url-help_fr.properties
@@ -0,0 +1,24 @@
+# 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\u00E9cifiez l''url du repository Git vers lequel synchroniser vos fichiers de configuration, tel que "git@github.com\:mycompany/jenkins-config.git"
+description.2=A noter qu''il est pour le moment obligatoire de r\u00E9f\u00E9rencer la racine du repository
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/none/config.jelly b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/none/config.jelly
new file mode 100644
index 00000000..92945348
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/none/config.jelly
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/config.jelly b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/config.jelly
new file mode 100644
index 00000000..4fdfb427
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/config.jelly
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/config_fr.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/config_fr.properties
new file mode 100644
index 00000000..314af8a5
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/config_fr.properties
@@ -0,0 +1 @@
+Repository\ URL=URL du repository
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/url-help.jelly b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/url-help.jelly
new file mode 100644
index 00000000..28acfe2b
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/url-help.jelly
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/url-help.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/url-help.properties
new file mode 100644
index 00000000..69924a3e
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/url-help.properties
@@ -0,0 +1,25 @@
+# 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 subversion repository URL to synchronize your configuration files with, such as "http\://yourcompany.com/repos/hudson-config/"
+description.2=When you enter a URL, Jenkins automatically checks if it can access the repository If access requires authentication, it will ask you the necessary credentials. If you already have a working credential but would like to change it for other reasons, click this link and specify different credentials.
+description.3=Each time you enter a new repository URL, Jenkins will first synchronize all your configuration files with the repository. This process can take a while, depending on the amount of configuration files to synchronize.
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/url-help_fr.properties b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/url-help_fr.properties
new file mode 100644
index 00000000..aa9f0669
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin/scms/svn/url-help_fr.properties
@@ -0,0 +1,25 @@
+# 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\u00E9cifiez l''URL du repository Subversion avec lequel synchronier vos fichiers de configuration, par exemple "http\://yourcompany.com/repos/hudson-config/"
+description.2=Quand vous entrez une URL, Jenkins v\u00E9rifie automatiquement s''il peut s''y connecter. Si l''acc\u00E8s n\u00E9cessite une authentification, il vous demandera les informations n\u00E9cessaires. Si vous disposez d\u00E9j\u00E0 d''informations d''identification qui marchent mais que vous voulez en changer, cliquez sur ce lien et renseignez des valeurs diff\u00E9rentes.
+description.3=A chaque fois que vous entrerez une nouvelle URL de repository, Jenkins commencera par synchroniser tous vos fichier de configuration avec le repository. Ce processus peut prendre plusieurs minutes, en fonction du nombre de fichier de configuration \u00E0 synchroniser.
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/extensions/ScmSyncConfigurationPageDecorator/footer.jelly b/src/main/resources/hudson/plugins/scm_sync_configuration/extensions/ScmSyncConfigurationPageDecorator/footer.jelly
new file mode 100644
index 00000000..a27be1d2
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/extensions/ScmSyncConfigurationPageDecorator/footer.jelly
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SCM Sync status :
+ ${msg}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/hudson/plugins/scm_sync_configuration/reload.jelly b/src/main/resources/hudson/plugins/scm_sync_configuration/reload.jelly
new file mode 100644
index 00000000..49d20bf4
--- /dev/null
+++ b/src/main/resources/hudson/plugins/scm_sync_configuration/reload.jelly
@@ -0,0 +1,20 @@
+
+
+
+
+
Please reload Jenkins config from disk by clicking here
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/index.jelly b/src/main/resources/index.jelly
new file mode 100644
index 00000000..4708b457
--- /dev/null
+++ b/src/main/resources/index.jelly
@@ -0,0 +1,3 @@
+
+ This plugin allows you to synchronize your hudson configuration files with an SCM, allowing you to specify a commit message every time a config file is modified.
+
\ No newline at end of file
diff --git a/src/main/webapp/help/commitMessagePattern-help.html b/src/main/webapp/help/commitMessagePattern-help.html
new file mode 100644
index 00000000..bf04ad80
--- /dev/null
+++ b/src/main/webapp/help/commitMessagePattern-help.html
@@ -0,0 +1,12 @@
+
+ Pattern of the message which will be commited.
+ For example, if you need to add a prefix/suffix to every of your commit messages,
+ you can do it by changing this message pattern.
+ You can use following "special" strings in the pattern :
+
+
`[message]` : Will be replaced by the generated commit message
+
+
+ For instance, defining a commit message pattern of "ISSUE-1234: [message]" will make following commit message :
+ ISSUE-1234: Modification on file with following comment : Synchronization init
+
\ No newline at end of file
diff --git a/src/main/webapp/help/commitMessagePattern-help_fr.html b/src/main/webapp/help/commitMessagePattern-help_fr.html
new file mode 100644
index 00000000..a838397b
--- /dev/null
+++ b/src/main/webapp/help/commitMessagePattern-help_fr.html
@@ -0,0 +1,12 @@
+
+ Patron du message qui sera commité.
+ Par exemple, si vous avez besoin d'ajouter un préfixe/suffixe à l'ensemble de vos messages de commit,
+ vous pouvez le faire en changeant ce patron de message.
+ Vous pouvez utiliser les chaînes "spéciales" suivantes dans le patron :
+
+
`[message]` : Sera remplacé par le message généré pour le commit
+
+
+ Par exemple, en définissant un patron de commit à "ISSUE-1234: [message]", cela génèrera le message de commit suivant :
+ ISSUE-1234: Modification on file with following comment : Synchronization init
+
\ No newline at end of file
diff --git a/src/main/webapp/help/displayStatus-help.html b/src/main/webapp/help/displayStatus-help.html
new file mode 100644
index 00000000..9d9fee48
--- /dev/null
+++ b/src/main/webapp/help/displayStatus-help.html
@@ -0,0 +1,5 @@
+
+ Displays a SCM Sync Configuration status health on the bottom of your Jenkins pages.
+ It is generally useful to activate this in order to be aware of a synchronization problem
+ (due, for instance, to repository credentials change)
+
\ No newline at end of file
diff --git a/src/main/webapp/help/displayStatus-help_fr.html b/src/main/webapp/help/displayStatus-help_fr.html
new file mode 100644
index 00000000..32c9addd
--- /dev/null
+++ b/src/main/webapp/help/displayStatus-help_fr.html
@@ -0,0 +1,5 @@
+
+ Affiche un état de la dernière synchronisation avec le SCM en bas de chaque page de Jenkins.
+ Il est généralement utile d'activer cela afin d'être alerté d'un problème de synchronisation
+ (dû, par exemple, à un changement de credentials)
+
\ No newline at end of file
diff --git a/src/main/webapp/help/noUserCommitMessage-help.html b/src/main/webapp/help/noUserCommitMessage-help.html
new file mode 100644
index 00000000..478c128f
--- /dev/null
+++ b/src/main/webapp/help/noUserCommitMessage-help.html
@@ -0,0 +1,5 @@
+
+ If unchecked, everytime you change a synchronized configuration file via Jenkins UI, a
+ prompt will be displayed allowing to specify a commit message for your modifications.
+ By checking this checkbox, you will never be prompted for such a commit message.
+
\ No newline at end of file
diff --git a/src/main/webapp/help/noUserCommitMessage-help_fr.html b/src/main/webapp/help/noUserCommitMessage-help_fr.html
new file mode 100644
index 00000000..519afd92
--- /dev/null
+++ b/src/main/webapp/help/noUserCommitMessage-help_fr.html
@@ -0,0 +1,5 @@
+
+ Lorsque décoché, à chaque fois que vous modifierez un fichier de configuration synchronisé
+ via l'UI de Jenkins, vous pourrez saisir un message de commit représentant vos modifications.
+ En cochant cette case à cocher, vous n'aurez plus besoin de saisir ce message de commit.
+
\ No newline at end of file
diff --git a/src/main/webapp/help/reloadScmConfig-help.html b/src/main/webapp/help/reloadScmConfig-help.html
new file mode 100644
index 00000000..39e70fa7
--- /dev/null
+++ b/src/main/webapp/help/reloadScmConfig-help.html
@@ -0,0 +1,41 @@
+
+ Beware : Some of your Jenkins config files can be overriden by this reload.
+ That is to say, if you want to get your repository configuration files back, you can do it by clicking this link.
+ Following strategies will be applied :
+
+
+
+
Local (jenkins) file
+
Repository file
+
Action
+
+
+
+
+
XXX
+
XXX (same as Jenkins one)
+
Nothing
+
+
+
XXX
+
YYY (different as Jenkins one)
+
YYY will override XXX
+
+
+
XXX
+
Doesn't exist
+
+ Nothing (Jenkins file won't be removed)
+ 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
+
+
+
+
Doesn't exist
+
XXX
+
+ XXX will be imported from repository
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/webapp/help/reloadScmConfig-help_fr.html b/src/main/webapp/help/reloadScmConfig-help_fr.html
new file mode 100644
index 00000000..321700ab
--- /dev/null
+++ b/src/main/webapp/help/reloadScmConfig-help_fr.html
@@ -0,0 +1,41 @@
+
+ Attention : Certaines de vos configurations Jenkins peuvent être écrasées par ce rechargement.
+ En cliquant sur ce lien, vous rapatrierez la configuration de votre repository dans Jenkins.
+ Les stratégies suivantes seront appliquées :
+
+
+
+
Fichier local (jenkins)
+
Fichier du repository
+
Action
+
+
+
+
+
XXX
+
XXX (même contenu que celui de Jenkins)
+
Rien
+
+
+
XXX
+
YYY (contenu différent de celui de Jenkins)
+
YYY écrasera XXX
+
+
+
XXX
+
N'existe pas
+
+ Rien (le fichier de Jenkins ne sera pas supprimé)
+ Notez que ce cas ne devrait jamais arriver puisque dès que vous activez le plugin scm sync config, tous vos fichiers de configuration sont commités dans le repository
+
+
+
+
N'existe pas
+
XXX
+
+ XXX sera importé depuis le repository
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/webapp/help/scm-help.html b/src/main/webapp/help/scm-help.html
new file mode 100644
index 00000000..e439fd89
--- /dev/null
+++ b/src/main/webapp/help/scm-help.html
@@ -0,0 +1,5 @@
+
+ Specify the repository where you want to sync jenkins config files to.
+ If you select "None", SCM Sync configuration plugin won't be activated.
+ Note that repository path must already exist in your repository (plugin won't create it for you).
+
\ No newline at end of file
diff --git a/src/main/webapp/help/scm-help_fr.html b/src/main/webapp/help/scm-help_fr.html
new file mode 100644
index 00000000..8cad01f1
--- /dev/null
+++ b/src/main/webapp/help/scm-help_fr.html
@@ -0,0 +1,5 @@
+
+ Spécifier le repository où vous souhaitez synchroniser les fichiers de configuration de Jenkins.
+ Si vous sélectionnez "None", le plugin SCM Sync configuration ne sera pas activé.
+ Notez que le chemin du repository doit exister dans votre repository (le plugin ne le créera pas pour vous).
+
\ No newline at end of file
diff --git a/src/main/webapp/scripts/scm-sync-configuration/scm-sync-configuration-page-handler.js b/src/main/webapp/scripts/scm-sync-configuration/scm-sync-configuration-page-handler.js
new file mode 100644
index 00000000..4213b655
--- /dev/null
+++ b/src/main/webapp/scripts/scm-sync-configuration/scm-sync-configuration-page-handler.js
@@ -0,0 +1,169 @@
+function retrieveTargetFormOnPage(){
+ return $$(YAHOO.scmSyncConfiguration.targetFormSelector)[0];
+}
+function decorateOnsubmitForm(){
+ try {
+ var form = retrieveTargetFormOnPage();
+ if(form != null){
+ form.observe("submit", function(evt){
+ var dontStopEvent = YAHOO.scmSyncConfiguration.commentPopupValidated || enterCommitComment();
+ if(!dontStopEvent){
+ Event.stop(evt);
+ }
+ });
+ } else {
+ unexpectedError("Cannot retrieve target form on current page !");
+ }
+ }catch(ex){ unexpectedError("Exception: "+logProps(ex)); }
+ form = null; // memory leak prevention
+}
+
+function unexpectedError(message){
+ alertMsg = 'Something went wrong with the scm-sync-configuration plugin !\n';
+ alertMsg += 'Please report a JIRA with as much informations as possible (browser, os, current url, error message etc.).\n';
+ alertMsg += 'Error message : '+message;
+ alert(alertMsg);
+}
+
+/**
+ * Log l'ensemble des propriétés de l'objet javascript fourni
+ */
+function logProps(obj){
+ str = '';
+ if(obj == null){
+ return "unknown object (null) !";
+ } else {
+ for(prop in obj)
+ {
+ str += '['+prop+'='+obj[prop]+'],';
+ }
+ return "Object : "+obj+" :: "+str;
+ }
+}
+
+function ajaxCall(callType, param, successCallback){
+ ajaxCall(callType, param, successCallback, false);
+}
+
+function ajaxCall(callType, param, successCallback, skipLoading){
+
+ if(!skipLoading){
+ YAHOO.namespace("scm.sync.configuration.wait");
+ YAHOO.scm.sync.configuration.wait.modalPopup =
+ new YAHOO.widget.Panel("wait",
+ { width:"240px",
+ fixedcenter:true,
+ close:false,
+ draggable:false,
+ zindex:4,
+ modal:true
+ }
+ );
+
+ YAHOO.scm.sync.configuration.wait.modalPopup.setHeader("--- Waiting ---");
+ YAHOO.scm.sync.configuration.wait.modalPopup.setBody("--- Waiting ---");
+ YAHOO.scm.sync.configuration.wait.modalPopup.render(document.body);
+ }
+
+ var ajaxCallParams = {
+ onSuccess: function(ret) {
+ successCallback.call(null, ret);
+ if(!skipLoading){
+ YAHOO.scm.sync.configuration.wait.modalPopup.hide();
+ }
+ },/* For unknown reasons, an exception is thrown after the onSuccess process .. :(
+ onException: function(transport, ex) {
+ alert('exception : '+ex);
+ if(!skipLoading){
+ YAHOO.scm.sync.configuration.wait.modalPopup.hide();
+ }
+ throw ex;
+ },*/
+ onFailure: function(transport) {
+ alert('failure : '+Object.toJSON(transport));
+ if(!skipLoading){
+ YAHOO.scm.sync.configuration.wait.modalPopup.hide();
+ }
+ }
+ };
+
+ if(callType == 'form'){
+ $(param).request(ajaxCallParams);
+ } else {
+ new Ajax.Request(param, ajaxCallParams);
+ }
+}
+
+function enterCommitComment(form){
+ YAHOO.namespace("scm.sync.configuration");
+ YAHOO.scm.sync.configuration._buttons = [];
+ YAHOO.scm.sync.configuration.handleSubmit = function() {
+ ajaxCall('form', 'commentForm', function(ret){
+ YAHOO.scmSyncConfiguration.commentPopupValidated = true;
+ YAHOO.scm.sync.configuration.modalPopup.hide();
+ retrieveTargetFormOnPage().submit();
+ }, true);
+ }
+ YAHOO.scm.sync.configuration.handleCancel = function() {
+ YAHOO.scm.sync.configuration.modalPopup.hide();
+ }
+
+ YAHOO.scm.sync.configuration.modalPopup =
+ new YAHOO.widget.Panel("buildStatConfigForm",
+ { width:"720px",
+ fixedcenter:true,
+ close:false,
+ draggable:false,
+ zindex:4,
+ modal:true
+ }
+ );
+
+ var currentContext = createTemplateContext();
+ var popupContentTemplate = new Template(getTemplateContent('popupContentTemplate'));
+ content = popupContentTemplate.evaluate(currentContext);
+
+ YAHOO.scm.sync.configuration.modalPopup.setHeader("Commit comment");
+ YAHOO.scm.sync.configuration.modalPopup.setBody(content);
+ YAHOO.scm.sync.configuration.modalPopup.setFooter('');
+ YAHOO.scm.sync.configuration.modalPopup.showEvent.subscribe(function() {
+ if (this._buttons.length == 0) {
+ this._buttons[0] = new YAHOO.widget.Button({
+ type: 'button',
+ label: "Submit comment",
+ container: 'panelFooter'
+ });
+ this._buttons[0].on('click', YAHOO.scm.sync.configuration.handleSubmit);
+ this._buttons[1] = new YAHOO.widget.Button({
+ type: 'button',
+ label: "Cancel",
+ container: 'panelFooter'
+ });
+ this._buttons[1].on('click', YAHOO.scm.sync.configuration.handleCancel);
+
+ // Ugly part here ... I dunno why, but directly calling focus() doesn't work
+ // since rendered buttons will steal the textarea's focus
+ // The only workaround found is to delay the textarea focus !
+ setTimeout(function(){ $$("#commentForm #comment")[0].focus(); }, 300);
+ }
+ }, YAHOO.scm.sync.configuration, true);
+ YAHOO.scm.sync.configuration.modalPopup.render(document.body);
+
+ return false;
+}
+
+// For some unknown reasons, on firefox, some #{XXX} template variables are replaced by #%7BXXX%7D :(
+function getTemplateContent(templateId){
+ var content = $(templateId).innerHTML;
+ content = content.replace(new RegExp("%7B", "g"), "{");
+ content = content.replace(new RegExp("%7D", "g"), "}");
+ return content;
+}
+
+function createTemplateContext(){
+ // Creating context for creation
+ var currentContext = {
+ rootURL: rootURL
+ };
+ return currentContext;
+}
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
new file mode 100644
index 00000000..725876d0
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/basic/ScmSyncConfigurationBasicTest.java
@@ -0,0 +1,62 @@
+package hudson.plugins.scm_sync_configuration.basic;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import hudson.model.Hudson;
+import hudson.plugins.scm_sync_configuration.JenkinsFilesHelper;
+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 {
+
+ public ScmSyncConfigurationBasicTest() {
+ super(new ScmUnderTestSubversion());
+ }
+
+ @Test
+ public void shouldRetrieveMockedHudsonInstanceCorrectly() throws Throwable {
+ Jenkins jenkins = Jenkins.getInstance();
+ assertNotNull("Jenkins instance must not be null", jenkins);
+ assertFalse("Expected a mocked Jenkins instance", jenkins.getClass().equals(Jenkins.class) || jenkins.getClass().equals(Hudson.class));
+ }
+
+ @Test
+ public void shouldVerifyIfHudsonRootDirectoryExists() throws Throwable {
+ Jenkins jenkins = Jenkins.getInstance();
+ File jenkinsRootDir = jenkins.getRootDir();
+ assertNotNull("Jenkins instance must not be null", jenkinsRootDir);
+ assertTrue("$JENKINS_HOME must be an existing directory", jenkinsRootDir.isDirectory());
+ }
+
+ @Test
+ public void testPathesOutsideJenkisRoot () throws Exception {
+ Jenkins jenkins = Jenkins.getInstance();
+ File rootDirectory = jenkins.getRootDir().getAbsoluteFile();
+ File parentDirectory = rootDirectory.getParentFile();
+ assertNull("File outside $JENKINS_HOME should return null", JenkinsFilesHelper.buildPathRelativeToHudsonRoot(parentDirectory));
+ assertNull("File outside $JENKINS_HOME should return null", JenkinsFilesHelper.buildPathRelativeToHudsonRoot(new File(parentDirectory, "foo.txt")));
+ }
+
+ @Test
+ public void testPathesInsideJenkisRoot () throws Exception {
+ Jenkins jenkins = Jenkins.getInstance();
+ File rootDirectory = jenkins.getRootDir().getAbsoluteFile();
+ File pathUnderTest = new File(rootDirectory, "config.xml");
+ String result = JenkinsFilesHelper.buildPathRelativeToHudsonRoot(pathUnderTest);
+ assertNotNull("File inside $JENKINS_HOME must not return null path", result);
+ assertEquals("Path " + pathUnderTest + " should resolve properly", result, "config.xml");
+ pathUnderTest = new File(new File (rootDirectory, "someDir"), "foo.txt");
+ result = JenkinsFilesHelper.buildPathRelativeToHudsonRoot(pathUnderTest);
+ assertNotNull("File inside $JENKINS_HOME must not return null path", result);
+ assertEquals("Path " + pathUnderTest + " should resolve properly", result, "someDir/foo.txt");
+ }
+}
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
new file mode 100644
index 00000000..c10904af
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/data/CurrentVersionCompatibilityTest.java
@@ -0,0 +1,62 @@
+package hudson.plugins.scm_sync_configuration.data;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.notNull;
+import static org.powermock.api.mockito.PowerMockito.doNothing;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import hudson.XmlFile;
+import hudson.model.Saveable;
+import hudson.model.listeners.SaveableListener;
+import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationPlugin;
+import hudson.plugins.scm_sync_configuration.scms.SCM;
+import hudson.plugins.scm_sync_configuration.scms.ScmSyncSubversionSCM;
+import hudson.plugins.scm_sync_configuration.util.ScmSyncConfigurationPluginBaseTest;
+import hudson.plugins.test.utils.PluginUtil;
+import hudson.plugins.test.utils.scms.ScmUnderTestSubversion;
+
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+
+@PrepareForTest(SaveableListener.class)
+public class CurrentVersionCompatibilityTest extends ScmSyncConfigurationPluginBaseTest {
+
+ public CurrentVersionCompatibilityTest() {
+ super(new ScmUnderTestSubversion());
+ }
+
+ protected String getHudsonRootBaseTemplate() {
+ // Use default template directory...
+ return super.getHudsonRootBaseTemplate();
+ }
+
+ @Test
+ public void shouldCurrentVersionPluginConfigurationFileLoadCorrectly() throws Throwable {
+ ScmSyncConfigurationPlugin plugin = ScmSyncConfigurationPlugin.getInstance();
+ assertThat(plugin.getSCM(), is(notNullValue()));
+ assertThat(plugin.getSCM().getId(), is(equalTo(ScmSyncSubversionSCM.class.getName())));
+ }
+
+ @Test
+ public void shouldCurrentVersionPluginConfigurationMigrationBeIdemPotent() throws Throwable {
+ ScmSyncConfigurationPlugin plugin = ScmSyncConfigurationPlugin.getInstance();
+
+ // Plugin has been loaded : let's record scm & repository url
+ String expectedRepositoryUrl = plugin.getScmRepositoryUrl();
+ SCM expectedScm = plugin.getSCM();
+
+ // Persisting data
+ mockStatic(SaveableListener.class);
+ doNothing().when(SaveableListener.class); SaveableListener.fireOnChange((Saveable)notNull(), (XmlFile)notNull());
+ plugin.save();
+
+ // Then reloading it...
+ PluginUtil.loadPlugin(plugin);
+
+ // Verifying repositoryUrl & SCM
+ assertThat(plugin.getSCM().getId(), is(equalTo(expectedScm.getId())));
+ assertThat(plugin.getScmRepositoryUrl(), is(equalTo(expectedRepositoryUrl)));
+ }
+}
diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/data/V0_0_2CompatibilityTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/data/V0_0_2CompatibilityTest.java
new file mode 100644
index 00000000..3f17f3f1
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/data/V0_0_2CompatibilityTest.java
@@ -0,0 +1,79 @@
+package hudson.plugins.scm_sync_configuration.data;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.notNull;
+import static org.powermock.api.mockito.PowerMockito.doNothing;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import hudson.XmlFile;
+import hudson.model.Saveable;
+import hudson.model.listeners.SaveableListener;
+import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationPlugin;
+import hudson.plugins.scm_sync_configuration.scms.SCM;
+import hudson.plugins.scm_sync_configuration.scms.ScmSyncNoSCM;
+import hudson.plugins.scm_sync_configuration.scms.ScmSyncSubversionSCM;
+import hudson.plugins.scm_sync_configuration.util.ScmSyncConfigurationPluginBaseTest;
+import hudson.plugins.test.utils.PluginUtil;
+import hudson.plugins.test.utils.scms.ScmUnderTestSubversion;
+
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+
+@PrepareForTest(SaveableListener.class)
+public class V0_0_2CompatibilityTest extends ScmSyncConfigurationPluginBaseTest {
+
+ public V0_0_2CompatibilityTest() {
+ super(new ScmUnderTestSubversion());
+ }
+
+ protected String getHudsonRootBaseTemplate() {
+ if("should0_0_2_pluginConfigurationFileShouldLoadCorrectly".equals(testName.getMethodName())){
+ return "hudsonRoot0.0.2BaseTemplate/";
+ } else if("should0_0_2_pluginConfigurationMigrationBeIdemPotent".equals(testName.getMethodName())){
+ return "hudsonRoot0.0.2BaseTemplate/";
+ } else if("should0_0_2_pluginEmptyConfigurationFileShouldLoadCorrectly".equals(testName.getMethodName())){
+ return "hudsonRoot0.0.2WithEmptyConfTemplate/";
+ } else {
+ throw new IllegalArgumentException("Unsupported test name : "+testName);
+ }
+ }
+
+ @Test
+ // JENKINS-8453 related
+ public void should0_0_2_pluginConfigurationFileShouldLoadCorrectly() throws Throwable {
+ ScmSyncConfigurationPlugin plugin = ScmSyncConfigurationPlugin.getInstance();
+ assertThat(plugin.getSCM(), is(notNullValue()));
+ assertThat(plugin.getSCM().getId(), is(equalTo(ScmSyncSubversionSCM.class.getName())));
+ assertThat(plugin.getScmRepositoryUrl(), is(equalTo("scm:svn:https://myrepo/synchronizedDirectory/")));
+ }
+
+ @Test
+ public void should0_0_2_pluginConfigurationMigrationBeIdemPotent() throws Throwable {
+ ScmSyncConfigurationPlugin plugin = ScmSyncConfigurationPlugin.getInstance();
+
+ // Plugin has been loaded : let's record scm & repository url
+ String expectedRepositoryUrl = plugin.getScmRepositoryUrl();
+ SCM expectedScm = plugin.getSCM();
+
+ // Persisting data
+ mockStatic(SaveableListener.class);
+ doNothing().when(SaveableListener.class); SaveableListener.fireOnChange((Saveable)notNull(), (XmlFile)notNull());
+ plugin.save();
+
+ // Then reloading it...
+ PluginUtil.loadPlugin(plugin);
+
+ // Verifying repositoryUrl & SCM
+ assertThat(plugin.getSCM().getId(), is(equalTo(expectedScm.getId())));
+ assertThat(plugin.getScmRepositoryUrl(), is(equalTo(expectedRepositoryUrl)));
+ }
+
+ @Test
+ public void should0_0_2_pluginEmptyConfigurationFileShouldLoadCorrectly() throws Throwable {
+ ScmSyncConfigurationPlugin plugin = ScmSyncConfigurationPlugin.getInstance();
+ assertThat(plugin.getSCM(), is(notNullValue()));
+ assertThat(plugin.getSCM().getId(), is(equalTo(ScmSyncNoSCM.class.getName())));
+ }
+}
diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/data/V0_0_3CompatibilityTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/data/V0_0_3CompatibilityTest.java
new file mode 100644
index 00000000..bb8b2c20
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/data/V0_0_3CompatibilityTest.java
@@ -0,0 +1,62 @@
+package hudson.plugins.scm_sync_configuration.data;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.notNull;
+import static org.powermock.api.mockito.PowerMockito.doNothing;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import hudson.XmlFile;
+import hudson.model.Saveable;
+import hudson.model.listeners.SaveableListener;
+import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationPlugin;
+import hudson.plugins.scm_sync_configuration.scms.SCM;
+import hudson.plugins.scm_sync_configuration.scms.ScmSyncSubversionSCM;
+import hudson.plugins.scm_sync_configuration.util.ScmSyncConfigurationPluginBaseTest;
+import hudson.plugins.test.utils.PluginUtil;
+import hudson.plugins.test.utils.scms.ScmUnderTestSubversion;
+
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+
+@PrepareForTest(SaveableListener.class)
+public class V0_0_3CompatibilityTest extends ScmSyncConfigurationPluginBaseTest {
+
+ public V0_0_3CompatibilityTest() {
+ super(new ScmUnderTestSubversion());
+ }
+
+ protected String getHudsonRootBaseTemplate() {
+ return "hudsonRoot0.0.3BaseTemplate/";
+ }
+
+ @Test
+ // JENKINS-8453 related
+ public void should0_0_3_pluginConfigurationFileShouldLoadCorrectly() throws Throwable {
+ ScmSyncConfigurationPlugin plugin = ScmSyncConfigurationPlugin.getInstance();
+ assertThat(plugin.getSCM(), is(notNullValue()));
+ assertThat(plugin.getSCM().getId(), is(equalTo(ScmSyncSubversionSCM.class.getName())));
+ }
+
+ @Test
+ public void should0_0_3_pluginConfigurationMigrationBeIdemPotent() throws Throwable {
+ ScmSyncConfigurationPlugin plugin = ScmSyncConfigurationPlugin.getInstance();
+
+ // Plugin has been loaded : let's record scm & repository url
+ String expectedRepositoryUrl = plugin.getScmRepositoryUrl();
+ SCM expectedScm = plugin.getSCM();
+
+ // Persisting data
+ mockStatic(SaveableListener.class);
+ doNothing().when(SaveableListener.class); SaveableListener.fireOnChange((Saveable)notNull(), (XmlFile)notNull());
+ plugin.save();
+
+ // Then reloading it...
+ PluginUtil.loadPlugin(plugin);
+
+ // Verifying repositoryUrl & SCM
+ assertThat(plugin.getSCM().getId(), is(equalTo(expectedScm.getId())));
+ assertThat(plugin.getScmRepositoryUrl(), is(equalTo(expectedRepositoryUrl)));
+ }
+}
diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/data/V0_0_4CompatibilityTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/data/V0_0_4CompatibilityTest.java
new file mode 100644
index 00000000..8c5af912
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/data/V0_0_4CompatibilityTest.java
@@ -0,0 +1,30 @@
+package hudson.plugins.scm_sync_configuration.data;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationPlugin;
+import hudson.plugins.scm_sync_configuration.scms.ScmSyncNoSCM;
+import hudson.plugins.scm_sync_configuration.util.ScmSyncConfigurationPluginBaseTest;
+import hudson.plugins.test.utils.scms.ScmUnderTestSubversion;
+
+import org.junit.Test;
+
+public class V0_0_4CompatibilityTest extends ScmSyncConfigurationPluginBaseTest {
+
+ public V0_0_4CompatibilityTest() {
+ super(new ScmUnderTestSubversion());
+ }
+
+ protected String getHudsonRootBaseTemplate() {
+ return "hudsonRoot0.0.4WithEmptyConfTemplate/";
+ }
+
+ @Test
+ public void should0_0_4_pluginEmptyConfigurationFileShouldLoadCorrectly() throws Throwable {
+ ScmSyncConfigurationPlugin plugin = ScmSyncConfigurationPlugin.getInstance();
+ assertThat(plugin.getSCM(), is(notNullValue()));
+ assertThat(plugin.getSCM().getId(), is(equalTo(ScmSyncNoSCM.class.getName())));
+ }
+}
diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsGitTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsGitTest.java
new file mode 100644
index 00000000..89474b78
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsGitTest.java
@@ -0,0 +1,11 @@
+package hudson.plugins.scm_sync_configuration.repository;
+
+import hudson.plugins.test.utils.scms.ScmUnderTestGit;
+
+public class HudsonExtensionsGitTest extends HudsonExtensionsTest {
+
+ public HudsonExtensionsGitTest() {
+ super(new ScmUnderTestGit());
+ }
+
+}
diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsSubversionTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsSubversionTest.java
new file mode 100644
index 00000000..401c0c80
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsSubversionTest.java
@@ -0,0 +1,96 @@
+package hudson.plugins.scm_sync_configuration.repository;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+
+import org.codehaus.plexus.util.FileUtils;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import hudson.model.Item;
+import hudson.model.Job;
+import hudson.plugins.scm_sync_configuration.SCMManipulator;
+import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationPlugin;
+import hudson.plugins.test.utils.scms.ScmUnderTestSubversion;
+
+
+public class HudsonExtensionsSubversionTest extends HudsonExtensionsTest {
+
+ public HudsonExtensionsSubversionTest() {
+ super(new ScmUnderTestSubversion());
+ }
+
+ @Test
+ public void shouldJobDeleteDoesntPerformAnyScmUpdate() throws Throwable {
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ 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);
+ final File hello1 = new File(checkoutDirectoryForVerifications.getAbsolutePath()+"/jobs/hello.txt");
+ final File hello2 = new File(checkoutDirectoryForVerifications.getAbsolutePath()+"/hello2.txt");
+ FileUtils.fileAppend(hello1.getAbsolutePath(), "hello world !");
+ FileUtils.fileAppend(hello2.getAbsolutePath(), "hello world 2 !");
+ scmManipulator.addFile(checkoutDirectoryForVerifications, "jobs/hello.txt");
+ scmManipulator.addFile(checkoutDirectoryForVerifications, "hello2.txt");
+ assertTrue("External check-in should succeed", scmManipulator.checkinFiles(checkoutDirectoryForVerifications, "external commit"));
+
+ // Deleting fakeJob
+ Item mockedItem = Mockito.mock(Job.class);
+ File mockedItemRootDir = new File(getCurrentHudsonRootDirectory() + "/jobs/fakeJob/" );
+ when(mockedItem.getRootDir()).thenReturn(mockedItemRootDir);
+
+ sscItemListener.onDeleted(mockedItem);
+
+ // Assert no hello file is present in current hudson root
+ assertThat(new File(this.getCurrentScmSyncConfigurationCheckoutDirectory()+"/jobs/hello.txt").exists(), is(false));
+ assertThat(new File(this.getCurrentScmSyncConfigurationCheckoutDirectory()+"/hello2.txt").exists(), is(false));
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void shouldJobRenameDoesntPerformAnyScmUpdate() throws Throwable {
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ 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);
+ final File hello1 = new File(checkoutDirectoryForVerifications.getAbsolutePath()+"/jobs/hello.txt");
+ final File hello2 = new File(checkoutDirectoryForVerifications.getAbsolutePath()+"/hello2.txt");
+ FileUtils.fileAppend(hello1.getAbsolutePath(), "hello world !");
+ FileUtils.fileAppend(hello2.getAbsolutePath(), "hello world 2 !");
+ scmManipulator.addFile(checkoutDirectoryForVerifications, "jobs/hello.txt");
+ scmManipulator.addFile(checkoutDirectoryForVerifications, "hello2.txt");
+ scmManipulator.checkinFiles(checkoutDirectoryForVerifications, "external commit");
+
+ // Renaming fakeJob to newFakeJob
+ Item mockedItem = Mockito.mock(Job.class);
+ File mockedItemRootDir = new File(getCurrentHudsonRootDirectory() + "/jobs/newFakeJob/" );
+ when(mockedItem.getRootDir()).thenReturn(mockedItemRootDir);
+
+ sscItemListener.onLocationChanged(mockedItem, "fakeJob", "newFakeJob");
+
+ // Assert no hello file is present in current hudson root
+ assertThat(new File(this.getCurrentScmSyncConfigurationCheckoutDirectory()+"/jobs/hello.txt").exists(), is(false));
+ assertThat(new File(this.getCurrentScmSyncConfigurationCheckoutDirectory()+"/hello2.txt").exists(), is(false));
+
+ assertStatusManagerIsOk();
+ }
+
+
+}
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
new file mode 100644
index 00000000..c884c0f9
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/repository/HudsonExtensionsTest.java
@@ -0,0 +1,469 @@
+package hudson.plugins.scm_sync_configuration.repository;
+
+import hudson.XmlFile;
+import hudson.model.Item;
+import hudson.model.AbstractItem;
+import hudson.model.Job;
+import hudson.model.Saveable;
+import hudson.plugins.scm_sync_configuration.SCMManipulator;
+import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationPlugin;
+import hudson.plugins.scm_sync_configuration.extensions.ScmSyncConfigurationItemListener;
+import hudson.plugins.scm_sync_configuration.extensions.ScmSyncConfigurationSaveableListener;
+import hudson.plugins.scm_sync_configuration.strategies.ScmSyncStrategy;
+import hudson.plugins.scm_sync_configuration.strategies.impl.BasicPluginsConfigScmSyncStrategy;
+import hudson.plugins.scm_sync_configuration.strategies.impl.JenkinsConfigScmSyncStrategy;
+import hudson.plugins.scm_sync_configuration.strategies.impl.JobConfigScmSyncStrategy;
+import hudson.plugins.scm_sync_configuration.util.ScmSyncConfigurationPluginBaseTest;
+import hudson.plugins.test.utils.scms.ScmUnderTest;
+
+import org.codehaus.plexus.util.FileUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.springframework.core.io.ClassPathResource;
+
+import java.io.File;
+import java.util.List;
+
+import jenkins.model.Jenkins;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.when;
+
+public abstract class HudsonExtensionsTest extends ScmSyncConfigurationPluginBaseTest {
+
+ protected ScmSyncConfigurationItemListener sscItemListener;
+ protected ScmSyncConfigurationSaveableListener sscConfigurationSaveableListener;
+
+ protected HudsonExtensionsTest(ScmUnderTest scmUnderTest) {
+ super(scmUnderTest);
+ }
+
+ @Before
+ public void initObjectsUnderTests() throws Throwable{
+ this.sscItemListener = new ScmSyncConfigurationItemListener();
+ this.sscConfigurationSaveableListener = new ScmSyncConfigurationSaveableListener();
+ }
+
+ @Test
+ public void shouldJobRenameBeCorrectlyImpactedOnSCM() throws Throwable {
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES);
+
+ // Renaming fakeJob to newFakeJob
+ Item mockedItem = Mockito.mock(Job.class);
+ File mockedItemRootDir = new File(getCurrentHudsonRootDirectory() + "/jobs/newFakeJob/" );
+ when(mockedItem.getRootDir()).thenReturn(mockedItemRootDir);
+ when(mockedItem.getName()).thenReturn("newFakeJob");
+ when(mockedItem.getParent()).thenReturn(null);
+ // We should duplicate files in fakeJob to newFakeJob
+ File oldJobDirectory = new File(getCurrentHudsonRootDirectory() + "/jobs/fakeJob/");
+ FileUtils.copyDirectory(oldJobDirectory, mockedItemRootDir);
+
+ sscItemListener.onLocationChanged(mockedItem, "fakeJob", "newFakeJob");
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/HudsonExtensionsTest.shouldJobRenameBeCorrectlyImpactedOnSCM/");
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void shouldJobAddBeCorrectlyImpactedOnSCM() throws Throwable {
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES);
+
+ File jobDirectory = new File(getCurrentHudsonRootDirectory() + "/jobs/newFakeJob/" );
+ File configFile = new File(jobDirectory.getAbsolutePath() + File.separator + "config.xml");
+ jobDirectory.mkdir();
+ FileUtils.copyFile(new ClassPathResource("expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/jobs/newFakeJob/config.xml").getFile(), configFile);
+
+ // Creating fake new job
+ Item mockedItem = Mockito.mock(Job.class);
+ when(mockedItem.getRootDir()).thenReturn(jobDirectory);
+
+ sscItemListener.onCreated(mockedItem);
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/");
+
+ sscConfigurationSaveableListener.onChange(mockedItem, new XmlFile(configFile));
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/");
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void shouldJobModificationBeCorrectlyImpactedOnSCM() throws Throwable {
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES);
+
+ File jobDirectory = new File(getCurrentHudsonRootDirectory() + "/jobs/fakeJob/" );
+ File configFile = new File(jobDirectory.getAbsolutePath() + File.separator + "config.xml");
+
+ // Creating fake new job
+ Item mockedItem = Mockito.mock(Job.class);
+ when(mockedItem.getRootDir()).thenReturn(jobDirectory);
+
+ sscItemListener.onCreated(mockedItem);
+
+ sscConfigurationSaveableListener.onChange(mockedItem, new XmlFile(configFile));
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/");
+
+ FileUtils.copyFile(new ClassPathResource("expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/jobs/fakeJob/config.xml").getFile(), configFile);
+
+ sscConfigurationSaveableListener.onChange(mockedItem, new XmlFile(configFile));
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/");
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void shouldConfigModificationBeCorrectlyImpactedOnSCM() throws Throwable {
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES);
+
+ File configFile = new File(getCurrentHudsonRootDirectory() + "/hudson.tasks.Shell.xml" );
+
+ // Creating fake new plugin config
+ Item mockedItem = Mockito.mock(Item.class);
+
+ sscConfigurationSaveableListener.onChange(mockedItem, new XmlFile(configFile));
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/");
+
+ FileUtils.copyFile(new ClassPathResource("expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/hudson.tasks.Shell.xml").getFile(), configFile);
+
+ sscConfigurationSaveableListener.onChange(mockedItem, new XmlFile(configFile));
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/");
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void shouldJobDeleteBeCorrectlyImpactedOnSCM() throws Throwable {
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES);
+
+ // Deleting fakeJob
+ Item mockedItem = Mockito.mock(Job.class);
+ File mockedItemRootDir = new File(getCurrentHudsonRootDirectory() + "/jobs/fakeJob/" );
+ when(mockedItem.getRootDir()).thenReturn(mockedItemRootDir);
+
+ sscItemListener.onDeleted(mockedItem);
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM" + getSuffixForTestFiles() + "/");
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM() throws Throwable {
+ String newFakeJob = "expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/jobs/newFakeJob";
+ FileUtils.copyDirectoryStructure(new ClassPathResource(newFakeJob).getFile(), new File(getCurrentHudsonRootDirectory() + File.separator + "jobs" + File.separator + "newFakeJob"));
+
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES);
+
+ // Deleting fakeJob
+ Item mockedItem = Mockito.mock(Job.class);
+ File mockedItemRootDir = new File(getCurrentHudsonRootDirectory() + "/jobs/fakeJob/" );
+ when(mockedItem.getRootDir()).thenReturn(mockedItemRootDir);
+
+ sscItemListener.onDeleted(mockedItem);
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/");
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void shouldReloadAllFilesUpdateScmAndReloadAllFiles() throws Throwable {
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ 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 File configFile = new File(checkoutDirectoryForVerifications.getAbsolutePath() + "/config.xml");
+ FileUtils.fileAppend(configFile.getAbsolutePath(), "toto");
+ scmManipulator.checkinFiles(checkoutDirectoryForVerifications, "external commit on config file");
+
+ final File configJobFile = new File(checkoutDirectoryForVerifications.getAbsolutePath() + "/jobs/fakeJob/config.xml");
+ FileUtils.fileAppend(configJobFile.getAbsolutePath(), "titi");
+ scmManipulator.checkinFiles(checkoutDirectoryForVerifications, "external commit on jonb file");
+
+ verifyCurrentScmContentMatchesCurrentHudsonDir(false);
+
+ // Reload config
+ List syncedFiles = sscBusiness.reloadAllFilesFromScm();
+
+ verifyCurrentScmContentMatchesCurrentHudsonDir(true);
+
+ 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));
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void shouldReloadAllFilesUpdateScmAndReloadAllFilesWithFileAdd() throws Throwable {
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ 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);
+
+ // Verifying there isn't any difference between hudson and scm repo once every file are synchronized
+ verifyCurrentScmContentMatchesCurrentHudsonDir(true);
+
+ final File addedFile = new File(checkoutDirectoryForVerifications.getAbsolutePath() + "/myConfigFile.xml");
+ FileUtils.fileWrite(addedFile.getAbsolutePath(), "toto");
+ scmManipulator.addFile(checkoutDirectoryForVerifications, "myConfigFile.xml");
+ scmManipulator.checkinFiles(checkoutDirectoryForVerifications, "external commit for add file");
+
+ 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");
+ scmManipulator.checkinFiles(checkoutDirectoryForVerifications, "external commit for add job file");
+
+ verifyCurrentScmContentMatchesCurrentHudsonDir(false);
+
+ // Reload config
+ List syncedFiles = sscBusiness.reloadAllFilesFromScm();
+
+ verifyCurrentScmContentMatchesCurrentHudsonDir(true);
+
+ 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));
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void testJobNameStartingWithDash() throws Exception {
+ createSCMMock();
+ sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES);
+
+ File jobDirectory = new File(getCurrentHudsonRootDirectory(), "jobs/-newFakeJob/" );
+ File configFile = new File(jobDirectory, "config.xml");
+ jobDirectory.mkdir();
+ FileUtils.copyFile(new ClassPathResource("expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/jobs/-newFakeJob/config.xml").getFile(), configFile);
+
+ // Creating fake new job
+ Item mockedItem = Mockito.mock(Job.class);
+ when(mockedItem.getName()).thenReturn("-newFakeJob");
+ when(mockedItem.getRootDir()).thenReturn(jobDirectory);
+
+ sscItemListener.onCreated(mockedItem);
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/");
+
+ sscConfigurationSaveableListener.onChange(mockedItem, new XmlFile(configFile));
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/");
+
+ assertStatusManagerIsOk();
+
+ // Now delete it again
+ assertTrue("Config file deletion", configFile.delete());
+ assertTrue("Job dir deletion", jobDirectory.delete());
+
+ sscItemListener.onDeleted(mockedItem);
+
+ verifyCurrentScmContentMatchesHierarchy("hudsonRootBaseTemplate/");
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void testJobNameWithBlanks() throws Exception {
+ createSCMMock();
+ sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES);
+
+ File jobDirectory = new File(getCurrentHudsonRootDirectory(), "jobs/new fake Job/" );
+ File configFile = new File(jobDirectory, "config.xml");
+ jobDirectory.mkdir();
+ FileUtils.copyFile(new ClassPathResource("expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/jobs/new fake Job/config.xml").getFile(), configFile);
+
+ // Creating fake new job
+ Item mockedItem = Mockito.mock(Job.class);
+ when(mockedItem.getName()).thenReturn("new fake Job");
+ when(mockedItem.getRootDir()).thenReturn(jobDirectory);
+
+ sscItemListener.onCreated(mockedItem);
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/");
+
+ sscConfigurationSaveableListener.onChange(mockedItem, new XmlFile(configFile));
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/");
+
+ assertStatusManagerIsOk();
+
+ // Now delete it again
+ assertTrue("Config file deletion", configFile.delete());
+ assertTrue("Job dir deletion", jobDirectory.delete());
+
+ sscItemListener.onDeleted(mockedItem);
+
+ verifyCurrentScmContentMatchesHierarchy("hudsonRootBaseTemplate/");
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void testJobRenameWithBlanksAndDash() throws Exception {
+ createSCMMock();
+ sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES);
+
+ File jobDirectory = new File(getCurrentHudsonRootDirectory(), "jobs/-newFakeJob/" );
+ File configFile = new File(jobDirectory, "config.xml");
+ jobDirectory.mkdir();
+ FileUtils.copyFile(new ClassPathResource("expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/jobs/-newFakeJob/config.xml").getFile(), configFile);
+
+ // Creating fake new job
+ Item mockedItem = Mockito.mock(Job.class);
+ when(mockedItem.getName()).thenReturn("-newFakeJob");
+ when(mockedItem.getRootDir()).thenReturn(jobDirectory);
+
+ sscItemListener.onCreated(mockedItem);
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/");
+
+ sscConfigurationSaveableListener.onChange(mockedItem, new XmlFile(configFile));
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/");
+
+ assertStatusManagerIsOk();
+
+ // Now fake a rename
+ assertTrue("Config file deletion", configFile.delete());
+ assertTrue("Job dir deletion", jobDirectory.delete());
+ jobDirectory = new File(getCurrentHudsonRootDirectory(), "jobs/new fake Job/" );
+ configFile = new File(jobDirectory, "config.xml");
+ jobDirectory.mkdir();
+ FileUtils.copyFile(new ClassPathResource("expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/jobs/new fake Job/config.xml").getFile(), configFile);
+
+ Item mockedRenamedItem = Mockito.mock(Job.class);
+ when(mockedRenamedItem.getName()).thenReturn("new fake Job");
+ when(mockedRenamedItem.getRootDir()).thenReturn(jobDirectory);
+
+ sscItemListener.onLocationChanged(mockedRenamedItem, "-newFakeJob", "new fake Job");
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/");
+
+ assertStatusManagerIsOk();
+
+ // And while we're at it: let's rename it back
+ assertTrue("Config file deletion", configFile.delete());
+ assertTrue("Job dir deletion", jobDirectory.delete());
+ jobDirectory = new File(getCurrentHudsonRootDirectory(), "jobs/-newFakeJob/" );
+ configFile = new File(jobDirectory, "config.xml");
+ jobDirectory.mkdir();
+ FileUtils.copyFile(new ClassPathResource("expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/jobs/-newFakeJob/config.xml").getFile(), configFile);
+
+ sscItemListener.onLocationChanged(mockedItem, "new fake Job", "-newFakeJob");
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/");
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void shouldFileWhichHaveToBeInSCM() throws Throwable {
+ // IMPORTANT NOTE :
+ // For every tested files in this test, file path should exist in
+ // HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/ directory
+
+ assertStrategy(JenkinsConfigScmSyncStrategy.class, Mockito.mock(Saveable.class), "config.xml");
+ assertStrategy(BasicPluginsConfigScmSyncStrategy.class, Mockito.mock(Saveable.class), "hudson.scm.SubversionSCM.xml");
+ assertStrategy(null, Mockito.mock(Saveable.class), "hudson.config.xml2");
+ assertStrategy(null, Mockito.mock(Saveable.class), "nodeMonitors.xml");
+ assertStrategy(null, Mockito.mock(Saveable.class), "toto" + File.separator + "hudson.config.xml");
+
+ assertStrategy(null, Mockito.mock(Job.class), "toto" + File.separator + "config.xml");
+ assertStrategy(null, Mockito.mock(Job.class), "jobs" + File.separator + "config.xml");
+ assertStrategy(null, Mockito.mock(Saveable.class), "jobs" + File.separator + "myJob" + File.separator + "config.xml");
+ assertStrategy(JobConfigScmSyncStrategy.class, Mockito.mock(Job.class), "jobs" + File.separator + "myJob" + File.separator + "config.xml");
+ assertStrategy(JobConfigScmSyncStrategy.class, Mockito.mock(Job.class), "jobs" + File.separator + "myFolder" + File.separator + "jobs" + File.separator + "myJob" + File.separator + "config.xml");
+ assertStrategy(JobConfigScmSyncStrategy.class, Mockito.mock(AbstractItem.class), "jobs" + File.separator + "myFolder" + File.separator + "config.xml");
+ assertStrategy(null, Mockito.mock(Job.class), "jobs" + File.separator + "myJob" + File.separator + "config2.xml");
+ }
+
+ private void assertStrategy(Class extends ScmSyncStrategy> expectedStrategyClass, Saveable saveableInstance, String targetPath) {
+ ScmSyncStrategy strategy = ScmSyncConfigurationPlugin.getInstance().getStrategyForSaveable(saveableInstance, new File(getCurrentHudsonRootDirectory() + File.separator + targetPath));
+ if (expectedStrategyClass == null) {
+ assertThat(strategy, nullValue());
+ }
+ else {
+ assertThat(strategy, notNullValue());
+ assertThat(strategy, instanceOf(expectedStrategyClass));
+ }
+ }
+
+ @Override
+ protected String getHudsonRootBaseTemplate(){
+ if("shouldFileWhichHaveToBeInSCM".equals(testName.getMethodName())){
+ return "HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/";
+ }
+
+ return "hudsonRootBaseTemplate/";
+ }
+
+ @Test
+ public void testPageMatchers() throws Exception {
+ assertStrategy(JobConfigScmSyncStrategy.class, Jenkins.getInstance().getRootUrl() + "job/jobName/configure");
+ assertStrategy(JobConfigScmSyncStrategy.class, Jenkins.getInstance().getRootUrl() + "job/folderName/job/jobName/configure");
+ assertStrategy(null, Jenkins.getInstance().getRootUrl() + "job/folderName/job/configure");
+ assertStrategy(null, Jenkins.getInstance().getRootUrl() + "job/folderName/job/someThing/configure/foo");
+ }
+
+ private void assertStrategy(Class extends ScmSyncStrategy> expectedStrategyClass, String url) {
+ ScmSyncStrategy strategy = ScmSyncConfigurationPlugin.getInstance().getStrategyForURL(url);
+ if (expectedStrategyClass == null) {
+ assertThat(strategy, nullValue());
+ }
+ else {
+ assertThat(strategy, notNullValue());
+ assertThat(strategy, instanceOf(expectedStrategyClass));
+ }
+ }
+
+}
diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositoryGitTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositoryGitTest.java
new file mode 100644
index 00000000..bd02e59b
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositoryGitTest.java
@@ -0,0 +1,13 @@
+package hudson.plugins.scm_sync_configuration.repository;
+
+import hudson.plugins.test.utils.scms.ScmUnderTestGit;
+
+
+
+public class InitRepositoryGitTest extends InitRepositoryTest {
+
+ public InitRepositoryGitTest() {
+ super(new ScmUnderTestGit());
+ }
+
+}
diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositorySubversionTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositorySubversionTest.java
new file mode 100644
index 00000000..39191115
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositorySubversionTest.java
@@ -0,0 +1,11 @@
+package hudson.plugins.scm_sync_configuration.repository;
+
+import hudson.plugins.test.utils.scms.ScmUnderTestSubversion;
+
+public class InitRepositorySubversionTest extends InitRepositoryTest {
+
+ public InitRepositorySubversionTest() {
+ super(new ScmUnderTestSubversion());
+ }
+
+}
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
new file mode 100644
index 00000000..434a0cd0
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/repository/InitRepositoryTest.java
@@ -0,0 +1,94 @@
+package hudson.plugins.scm_sync_configuration.repository;
+
+import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationPlugin;
+import hudson.plugins.scm_sync_configuration.model.ScmContext;
+import hudson.plugins.scm_sync_configuration.scms.SCM;
+import hudson.plugins.scm_sync_configuration.util.ScmSyncConfigurationPluginBaseTest;
+import hudson.plugins.test.utils.scms.ScmUnderTest;
+import org.codehaus.plexus.util.FileUtils;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+
+import java.io.File;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+@PrepareForTest(SCM.class)
+public abstract class InitRepositoryTest extends ScmSyncConfigurationPluginBaseTest {
+
+ protected InitRepositoryTest(ScmUnderTest scmUnderTest) {
+ super(scmUnderTest);
+ }
+
+ @Test
+ public void shouldNotInitializeAnyRepositoryWhenScmContextIsEmpty() throws Throwable {
+ ScmContext emptyContext = new ScmContext(null, null);
+ sscBusiness.init(emptyContext);
+ assertThat(sscBusiness.scmCheckoutDirectorySettledUp(emptyContext), is(false));
+
+ emptyContext = new ScmContext(null, getSCMRepositoryURL());
+ sscBusiness.init(emptyContext);
+ assertThat(sscBusiness.scmCheckoutDirectorySettledUp(emptyContext), is(false));
+
+ createSCMMock(null);
+ assertThat(sscBusiness.scmCheckoutDirectorySettledUp(emptyContext), is(false));
+
+ assertStatusManagerIsNull();
+ }
+
+ @Test
+ @Ignore("Not yet implemented ! (it is difficult because svn list/log has not yet been implemented in svnjava impl")
+ public void shouldInitializeLocalRepositoryWhenScmContextIsCorrentAndEvenIfScmDirectoryDoesntExist() throws Throwable {
+ createSCMMock();
+ assertThat(sscBusiness.scmCheckoutDirectorySettledUp(scmContext), is(true));
+ }
+
+ @Test
+ public void shouldResetCheckoutConfigurationDirectoryWhenAsked() throws Throwable {
+ // Initializing the repository...
+ createSCMMock();
+
+ // After init, local checked out repository should exist
+ assertThat(getCurrentScmSyncConfigurationCheckoutDirectory().exists(), is(true));
+
+ // Populating checkoutConfiguration directory ..
+ File fileWhichShouldBeDeletedAfterReset = new File(getCurrentScmSyncConfigurationCheckoutDirectory().getAbsolutePath()+"/hello.txt");
+ assertThat(fileWhichShouldBeDeletedAfterReset.createNewFile(), is(true));
+ FileUtils.fileWrite(fileWhichShouldBeDeletedAfterReset.getAbsolutePath(), "Hello world !");
+
+ // Reseting the repository, without cleanup
+ sscBusiness.initializeRepository(scmContext, false);
+ assertThat(fileWhichShouldBeDeletedAfterReset.exists(), is(true));
+
+ // Reseting the repository with cleanup
+ sscBusiness.initializeRepository(scmContext, true);
+ assertThat(fileWhichShouldBeDeletedAfterReset.exists(), is(false));
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void shouldSynchronizeHudsonFiles() throws Throwable {
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES);
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/");
+
+ assertStatusManagerIsOk();
+ }
+
+ @Test
+ public void shouldInitializeLocalRepositoryWhenScmContextIsCorrect()
+ throws Throwable {
+ createSCMMock();
+ assertThat(sscBusiness.scmCheckoutDirectorySettledUp(scmContext), is(true));
+
+ assertStatusManagerIsOk();
+ }
+
+}
diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/strategies/impl/JobConfigScmSyncStrategyTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/strategies/impl/JobConfigScmSyncStrategyTest.java
new file mode 100644
index 00000000..153223bc
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/strategies/impl/JobConfigScmSyncStrategyTest.java
@@ -0,0 +1,63 @@
+package hudson.plugins.scm_sync_configuration.strategies.impl;
+
+import hudson.XmlFile;
+import hudson.model.Job;
+import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationPlugin;
+import hudson.plugins.scm_sync_configuration.extensions.ScmSyncConfigurationSaveableListener;
+import hudson.plugins.scm_sync_configuration.util.ScmSyncConfigurationPluginBaseTest;
+import hudson.plugins.test.utils.scms.ScmUnderTestSubversion;
+import org.codehaus.plexus.PlexusContainerException;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.mockito.Mockito.when;
+
+/**
+ * @author fcamblor
+ */
+public class JobConfigScmSyncStrategyTest extends ScmSyncConfigurationPluginBaseTest {
+
+ private ScmSyncConfigurationSaveableListener sscConfigurationSaveableListener;
+
+ public JobConfigScmSyncStrategyTest() {
+ super(new ScmUnderTestSubversion());
+ }
+
+ @Before
+ public void initObjectsUnderTests() throws Throwable{
+ this.sscConfigurationSaveableListener = new ScmSyncConfigurationSaveableListener();
+ }
+
+ @Override
+ protected String getHudsonRootBaseTemplate(){
+ return "jobConfigStrategyTemplate/";
+ }
+
+ // Reproducing JENKINS-17545
+ @Test
+ public void shouldConfigInSubmodulesNotSynced() throws ComponentLookupException, PlexusContainerException, IOException {
+ // Initializing the repository...
+ createSCMMock();
+
+ // Synchronizing hudson config files
+ sscBusiness.synchronizeAllConfigs(ScmSyncConfigurationPlugin.AVAILABLE_STRATEGIES);
+
+ File subModuleConfigFile = new File(getCurrentHudsonRootDirectory() + "/jobs/fakeJob/modules/submodule/config.xml" );
+
+ // Creating fake new item
+ Job,?> mockedItem = Mockito.mock(Job.class);
+ when(mockedItem.getRootDir()).thenReturn(subModuleConfigFile.getParentFile());
+
+ sscConfigurationSaveableListener.onChange(mockedItem, new XmlFile(subModuleConfigFile));
+
+ verifyCurrentScmContentMatchesHierarchy("expected-scm-hierarchies/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/");
+
+ assertStatusManagerIsOk();
+ }
+
+}
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
new file mode 100644
index 00000000..2bef1afe
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/util/ScmSyncConfigurationBaseTest.java
@@ -0,0 +1,252 @@
+package hudson.plugins.scm_sync_configuration.util;
+
+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;
+import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationBusiness;
+import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationPlugin;
+import hudson.plugins.scm_sync_configuration.model.ScmContext;
+import hudson.plugins.scm_sync_configuration.scms.SCM;
+import hudson.plugins.scm_sync_configuration.scms.SCMCredentialConfiguration;
+import hudson.plugins.scm_sync_configuration.scms.ScmSyncSubversionSCM;
+import hudson.plugins.scm_sync_configuration.xstream.migration.DefaultSSCPOJO;
+import hudson.plugins.scm_sync_configuration.xstream.migration.ScmSyncConfigurationPOJO;
+import hudson.plugins.test.utils.DirectoryUtils;
+import hudson.plugins.test.utils.scms.ScmUnderTest;
+
+import org.codehaus.plexus.PlexusContainerException;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.util.FileUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.objenesis.ObjenesisStd;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.springframework.core.io.ClassPathResource;
+
+import com.google.common.collect.Lists;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import jenkins.model.Jenkins;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockIgnore({ "org.tmatesoft.svn.*" })
+@PrepareForTest({Hudson.class, Jenkins.class, SCM.class, ScmSyncSubversionSCM.class, PluginWrapper.class})
+public abstract class ScmSyncConfigurationBaseTest {
+
+ @Rule protected TestName testName = new TestName();
+
+ private static final String TEST_URL = "https://jenkins.example.org/";
+
+ private File currentTestDirectory = null;
+ private File curentLocalRepository = null;
+ private File currentHudsonRootDirectory = null;
+ protected ScmSyncConfigurationBusiness sscBusiness = null;
+ protected ScmContext scmContext = null;
+
+ private final ScmUnderTest scmUnderTest;
+
+ protected ScmSyncConfigurationBaseTest(ScmUnderTest scmUnderTest) {
+ this.scmUnderTest = scmUnderTest;
+ this.scmContext = null;
+ }
+
+ @SuppressWarnings("deprecation") // We need to mock Hudson.getInstance()
+ @Before
+ public void setup() throws Throwable {
+ // Instantiating ScmSyncConfigurationPlugin instance for unit tests by using
+ // synchronous transactions (instead of an asynchronous ones)
+ // => this way, every commit will be processed synchronously !
+ ScmSyncConfigurationPlugin scmSyncConfigPluginInstance = new ScmSyncConfigurationPlugin(true) {
+ @Override
+ public void initialInit() throws Exception {
+ // No-op. We *must not* initialize here in tests because the tests provide their own setup.
+ }
+ };
+
+ // Mocking PluginWrapper attached to current ScmSyncConfigurationPlugin instance
+ PluginWrapper pluginWrapper = PowerMockito.mock(PluginWrapper.class);
+ when(pluginWrapper.getShortName()).thenReturn("scm-sync-configuration");
+ // Setting field on current plugin instance
+ Field wrapperField = Plugin.class.getDeclaredField("wrapper");
+ boolean wrapperFieldAccessibility = wrapperField.isAccessible();
+ wrapperField.setAccessible(true);
+ wrapperField.set(scmSyncConfigPluginInstance, pluginWrapper);
+ wrapperField.setAccessible(wrapperFieldAccessibility);
+
+ Field businessField = ScmSyncConfigurationPlugin.class.getDeclaredField("business");
+ businessField.setAccessible(true);
+ sscBusiness = (ScmSyncConfigurationBusiness) businessField.get(scmSyncConfigPluginInstance);
+
+ // Mocking Hudson root directory
+ currentTestDirectory = createTmpDirectory("SCMSyncConfigTestsRoot");
+ currentHudsonRootDirectory = new File(currentTestDirectory.getAbsolutePath()+"/hudsonRootDir/");
+ if(!(currentHudsonRootDirectory.mkdir())) { throw new IOException("Could not create hudson root directory: " + currentHudsonRootDirectory.getAbsolutePath()); }
+ FileUtils.copyDirectoryStructure(new ClassPathResource(getHudsonRootBaseTemplate()).getFile(), currentHudsonRootDirectory);
+
+ //EnvVars env = Computer.currentComputer().getEnvironment();
+ //env.put("HUDSON_HOME", tmpHudsonRoot.getPath() );
+
+ // Creating local repository...
+ curentLocalRepository = new File(currentTestDirectory.getAbsolutePath()+"/localRepo/");
+ if(!(curentLocalRepository.mkdir())) { throw new IOException("Could not create local repo directory: " + curentLocalRepository.getAbsolutePath()); }
+ scmUnderTest.initRepo(curentLocalRepository);
+
+ // Mocking user
+ User mockedUser = Mockito.mock(User.class);
+ when(mockedUser.getId()).thenReturn("fcamblor");
+
+ // 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.doReturn(TEST_URL).when(hudsonMockedInstance).getRootUrl();
+ PowerMockito.doReturn(TEST_URL).when(hudsonMockedInstance).getRootUrlFromRequest();
+
+ PowerMockito.mockStatic(Jenkins.class);
+ PowerMockito.doReturn(hudsonMockedInstance).when(Jenkins.class); Jenkins.getInstance();
+ PowerMockito.mockStatic(Hudson.class);
+ PowerMockito.doReturn(hudsonMockedInstance).when(Hudson.class); Hudson.getInstance();
+ //when(Hudson.getInstance()).thenReturn(hudsonMockedInstance);
+ }
+
+ @After
+ public void teardown() throws Throwable {
+ // Deleting current test directory
+ FileUtils.deleteDirectory(currentTestDirectory);
+ }
+
+ // Overridable
+ protected String getHudsonRootBaseTemplate(){
+ return "hudsonRootBaseTemplate/";
+ }
+
+ protected static File createTmpDirectory(String directoryPrefix) throws IOException {
+ final File temp = File.createTempFile(directoryPrefix, Long.toString(System.nanoTime()));
+ if(!(temp.delete())) { throw new IOException("Could not delete temp file: " + temp.getAbsolutePath()); }
+ if(!(temp.mkdir())) { throw new IOException("Could not create temp directory: " + temp.getAbsolutePath()); }
+ return (temp);
+ }
+
+ protected SCM createSCMMock(){
+ return createSCMMock(getSCMRepositoryURL());
+ }
+
+ protected SCM createSCMMock(String url){
+ SCM mockedSCM = spy(SCM.valueOf(getSCMClass().getName()));
+
+ if(scmUnderTest.useCredentials()){
+ SCMCredentialConfiguration mockedCredential = new SCMCredentialConfiguration("toto");
+ PowerMockito.doReturn(mockedCredential).when(mockedSCM).extractScmCredentials((String)Mockito.notNull());
+ }
+
+ scmContext = new ScmContext(mockedSCM, url);
+ ScmSyncConfigurationPOJO config = new DefaultSSCPOJO();
+ config.setScm(scmContext.getScm());
+ config.setScmRepositoryUrl(scmContext.getScmRepositoryUrl());
+ ScmSyncConfigurationPlugin.getInstance().loadData(config);
+ ScmSyncConfigurationPlugin.getInstance().init();
+
+ return mockedSCM;
+ }
+
+ protected SCMManipulator createMockedScmManipulator() throws ComponentLookupException, PlexusContainerException{
+ // Settling up scm context
+ SCMManipulator scmManipulator = new SCMManipulator(SCMManagerFactory.getInstance().createScmManager());
+ boolean configSettledUp = scmManipulator.scmConfigurationSettledUp(scmContext, true);
+ assertThat(configSettledUp, is(true));
+
+ return scmManipulator;
+ }
+
+ protected void verifyCurrentScmContentMatchesCurrentHudsonDir(boolean match) throws ComponentLookupException, PlexusContainerException, IOException{
+ verifyCurrentScmContentMatchesHierarchy(getCurrentHudsonRootDirectory(), match);
+ }
+
+ protected void verifyCurrentScmContentMatchesHierarchy(String hierarchyPath, boolean match) throws ComponentLookupException, PlexusContainerException, IOException{
+ verifyCurrentScmContentMatchesHierarchy(new ClassPathResource(hierarchyPath).getFile(), match);
+ }
+
+ protected void verifyCurrentScmContentMatchesHierarchy(File hierarchy, boolean match) throws ComponentLookupException, PlexusContainerException, IOException{
+ SCMManipulator scmManipulator = createMockedScmManipulator();
+
+ // Checkouting scm in temp directory
+ File checkoutDirectoryForVerifications = createTmpDirectory(this.getClass().getSimpleName()+"_"+testName.getMethodName()+"__verifyCurrentScmContentMatchesHierarchy");
+ scmManipulator.checkout(checkoutDirectoryForVerifications);
+ List diffs = DirectoryUtils.diffDirectories(checkoutDirectoryForVerifications, hierarchy,
+ getSpecialSCMDirectoryExcludePattern(), true);
+
+ FileUtils.deleteDirectory(checkoutDirectoryForVerifications);
+
+ if(match){
+ assertTrue("Directories doesn't match : "+diffs, diffs.isEmpty());
+ } else {
+ assertFalse("Directories should _not_ match !", diffs.isEmpty());
+ }
+ }
+
+ protected void verifyCurrentScmContentMatchesHierarchy(String hierarchyPath) throws ComponentLookupException, PlexusContainerException, IOException{
+ verifyCurrentScmContentMatchesHierarchy(hierarchyPath, true);
+ }
+
+ // Overridable in a near future (when dealing with multiple scms ...)
+ protected String getSCMRepositoryURL(){
+ return scmUnderTest.createUrl(this.getCurentLocalRepository().getAbsolutePath());
+ }
+
+ protected static List getSpecialSCMDirectoryExcludePattern(){
+ return Lists.newArrayList(
+ Pattern.compile("\\.svn"),
+ Pattern.compile("\\.git.*"),
+ Pattern.compile("scm-sync-configuration\\..*\\.log"),
+ Pattern.compile("scm-sync-configuration")
+ );
+ }
+
+ protected String getSuffixForTestFiles() {
+ return scmUnderTest.getSuffixForTestFiles();
+ }
+
+ // Overridable in a near future (when dealing with multiple scms ...)
+ protected Class extends SCM> getSCMClass(){
+ return scmUnderTest.getClazz();
+ }
+
+ protected File getCurrentTestDirectory() {
+ return currentTestDirectory;
+ }
+
+ protected File getCurentLocalRepository() {
+ return curentLocalRepository;
+ }
+
+ public File getCurrentHudsonRootDirectory() {
+ return currentHudsonRootDirectory;
+ }
+
+ public File getCurrentScmSyncConfigurationCheckoutDirectory(){
+ return new File(currentHudsonRootDirectory.getAbsolutePath()+"/scm-sync-configuration/checkoutConfiguration/");
+ }
+
+}
diff --git a/src/test/java/hudson/plugins/scm_sync_configuration/util/ScmSyncConfigurationPluginBaseTest.java b/src/test/java/hudson/plugins/scm_sync_configuration/util/ScmSyncConfigurationPluginBaseTest.java
new file mode 100644
index 00000000..e00a9447
--- /dev/null
+++ b/src/test/java/hudson/plugins/scm_sync_configuration/util/ScmSyncConfigurationPluginBaseTest.java
@@ -0,0 +1,41 @@
+package hudson.plugins.scm_sync_configuration.util;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationPlugin;
+import hudson.plugins.test.utils.scms.ScmUnderTest;
+
+// Class will start current ScmSyncConfigurationPlugin instance
+public abstract class ScmSyncConfigurationPluginBaseTest extends
+ ScmSyncConfigurationBaseTest {
+
+ protected ScmSyncConfigurationPluginBaseTest(ScmUnderTest scmUnderTest) {
+ super(scmUnderTest);
+ }
+
+ public void setup() throws Throwable {
+ super.setup();
+
+ // Let's start the plugin...
+ ScmSyncConfigurationPlugin.getInstance().start();
+ }
+
+ public void teardown() throws Throwable {
+ // Stopping current plugin
+ ScmSyncConfigurationPlugin.getInstance().stop();
+
+ super.teardown();
+ }
+
+ protected void assertStatusManagerIsOk() {
+ assertThat(sscBusiness.getScmSyncConfigurationStatusManager().getLastFail(), nullValue());
+ assertThat(sscBusiness.getScmSyncConfigurationStatusManager().getLastSuccess(), notNullValue());
+ }
+
+ protected void assertStatusManagerIsNull() {
+ assertThat(sscBusiness.getScmSyncConfigurationStatusManager().getLastFail(), nullValue());
+ assertThat(sscBusiness.getScmSyncConfigurationStatusManager().getLastSuccess(), nullValue());
+ }
+
+}
diff --git a/src/test/java/hudson/plugins/test/utils/DirectoryUtils.java b/src/test/java/hudson/plugins/test/utils/DirectoryUtils.java
new file mode 100644
index 00000000..b0a5e3cb
--- /dev/null
+++ b/src/test/java/hudson/plugins/test/utils/DirectoryUtils.java
@@ -0,0 +1,92 @@
+package hudson.plugins.test.utils;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import org.apache.commons.io.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+public class DirectoryUtils {
+
+ private static final Logger LOGGER = Logger.getLogger(DirectoryUtils.class.getName());
+
+ private static class FileComparator implements Comparator{
+ public int compare(File o1, File o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ }
+ private static final FileComparator FILE_COMPARATOR = new FileComparator();
+
+ public static List diffDirectories(File dir1, File dir2, final List excludePatterns, boolean recursive){
+ List diffs = new ArrayList();
+
+ if(!dir1.isDirectory() || !dir2.isDirectory()){
+ throw new IllegalArgumentException("dir1 & dir2 should be directories !");
+ }
+
+ Predicate patternMatcherOnFilenamePredicate = new Predicate() {
+ public boolean apply(File f) {
+ for(Pattern pattern : excludePatterns) {
+ if (pattern.matcher(f.getName()).matches()) {
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+
+ List dir1Files = new ArrayList( Arrays.asList(dir1.listFiles()) );
+ List dir2Files = new ArrayList( Arrays.asList(dir2.listFiles()) );
+
+ Collections.sort(dir1Files, FILE_COMPARATOR);
+ Collections.sort(dir2Files, FILE_COMPARATOR);
+
+ Collection dir1FilesCollec = dir1Files;
+ Collection dir2FilesCollec = dir2Files;
+ if(excludePatterns != null){
+ dir1FilesCollec = Collections2.filter(dir1Files, patternMatcherOnFilenamePredicate);
+ dir2FilesCollec = Collections2.filter(dir2Files, patternMatcherOnFilenamePredicate);
+ }
+
+ if(dir1FilesCollec.size() != dir2FilesCollec.size()){
+ diffs.add(String.format("Number of files in %s (%s) and %s (%s) differ !", dir1, dir1FilesCollec.size(), dir2, dir2FilesCollec.size()));
+ return diffs;
+ }
+
+
+ Iterator dir1FileIter=dir1FilesCollec.iterator();
+ Iterator dir2FileIter=dir2FilesCollec.iterator();
+ for(int i=0; i content with <"+f2.getAbsolutePath()+"> content");
+ diffs.add("Error occured when comparing <"+f1.getAbsolutePath()+"> content with <"+f2.getAbsolutePath()+"> content");
+ }
+ }
+ if(recursive && f1.isDirectory()){
+ diffs.addAll(diffDirectories(f1, f2, excludePatterns, recursive));
+ }
+ }
+
+ return diffs;
+ }
+
+}
diff --git a/src/test/java/hudson/plugins/test/utils/PluginUtil.java b/src/test/java/hudson/plugins/test/utils/PluginUtil.java
new file mode 100644
index 00000000..d6716028
--- /dev/null
+++ b/src/test/java/hudson/plugins/test/utils/PluginUtil.java
@@ -0,0 +1,19 @@
+package hudson.plugins.test.utils;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import hudson.Plugin;
+
+public class PluginUtil {
+
+ public static void loadPlugin(Plugin plugin)
+ throws SecurityException, NoSuchMethodException, IllegalArgumentException,
+ IllegalAccessException, InvocationTargetException {
+ Method loadMethod = Plugin.class.getDeclaredMethod("load");
+ boolean loadMethodAccessibility = loadMethod.isAccessible();
+ loadMethod.setAccessible(true);
+ loadMethod.invoke(plugin);
+ loadMethod.setAccessible(loadMethodAccessibility);
+ }
+}
diff --git a/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTest.java b/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTest.java
new file mode 100644
index 00000000..4e88afee
--- /dev/null
+++ b/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTest.java
@@ -0,0 +1,19 @@
+package hudson.plugins.test.utils.scms;
+
+import hudson.plugins.scm_sync_configuration.scms.SCM;
+
+import java.io.File;
+
+public interface ScmUnderTest {
+
+ void initRepo(File path) throws Exception;
+
+ String createUrl(String url);
+
+ Class extends SCM> getClazz();
+
+ boolean useCredentials();
+
+ String getSuffixForTestFiles();
+
+}
diff --git a/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTestGit.java b/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTestGit.java
new file mode 100644
index 00000000..99b91c6e
--- /dev/null
+++ b/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTestGit.java
@@ -0,0 +1,35 @@
+package hudson.plugins.test.utils.scms;
+
+import hudson.plugins.scm_sync_configuration.scms.SCM;
+import hudson.plugins.scm_sync_configuration.scms.ScmSyncGitSCM;
+
+import java.io.File;
+
+public class ScmUnderTestGit implements ScmUnderTest {
+
+ public void initRepo(File path) throws Exception {
+ ProcessBuilder pb = new ProcessBuilder("git", "init", "--bare");
+ pb.directory(path);
+ Process p = pb.start();
+ if (p.waitFor() != 0) {
+ throw new Exception("Unable to init git repo in " + path.getAbsolutePath());
+ }
+ }
+
+ public String createUrl(String url) {
+ return "scm:git:" + url;
+ }
+
+ public Class extends SCM> getClazz() {
+ return ScmSyncGitSCM.class;
+ }
+
+ public boolean useCredentials() {
+ return false;
+ }
+
+ public String getSuffixForTestFiles() {
+ return ".git";
+ }
+
+}
diff --git a/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTestSubversion.java b/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTestSubversion.java
new file mode 100644
index 00000000..337dd9bd
--- /dev/null
+++ b/src/test/java/hudson/plugins/test/utils/scms/ScmUnderTestSubversion.java
@@ -0,0 +1,32 @@
+package hudson.plugins.test.utils.scms;
+
+import hudson.plugins.scm_sync_configuration.scms.SCM;
+import hudson.plugins.scm_sync_configuration.scms.ScmSyncSubversionSCM;
+
+import java.io.File;
+
+import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
+
+public class ScmUnderTestSubversion implements ScmUnderTest {
+
+ public void initRepo(File path) throws Exception {
+ SVNRepositoryFactory.createLocalRepository(path, true , false);
+ }
+
+ public String createUrl(String url) {
+ return "scm:svn:file://" + url;
+ }
+
+ public Class extends SCM> getClazz() {
+ return ScmSyncSubversionSCM.class;
+ }
+
+ public boolean useCredentials() {
+ return true;
+ }
+
+ public String getSuffixForTestFiles() {
+ return ".subversion";
+ }
+
+}
diff --git a/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/config.xml b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/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/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/hudson.config.xml2 b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/hudson.config.xml2
new file mode 100644
index 00000000..e69de29b
diff --git a/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/hudson.scm.SubversionSCM.xml b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/hudson.scm.SubversionSCM.xml
new file mode 100644
index 00000000..e69de29b
diff --git a/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/config.xml b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myFolder/config.xml b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myFolder/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myFolder/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myFolder/jobs/myJob/config.xml b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myFolder/jobs/myJob/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myFolder/jobs/myJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myJob/config.xml b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myJob/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myJob/config2.xml b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myJob/config2.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/jobs/myJob/config2.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/nodeMonitors.xml b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/nodeMonitors.xml
new file mode 100644
index 00000000..e69de29b
diff --git a/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/scm-sync-configuration.xml b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/toto/config.xml b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/toto/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/toto/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/toto/hudson.config.xml b/src/test/resources/HudsonExtensionsTest.shouldFileWhichHaveToBeInSCM/toto/hudson.config.xml
new file mode 100644
index 00000000..e69de29b
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/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.shouldConfigModificationBeCorrectlyImpactedOnSCM/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/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.shouldConfigModificationBeCorrectlyImpactedOnSCM/jobs/fakeJob/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/jobs/fakeJob/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/jobs/fakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldConfigModificationBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/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.shouldJobAddBeCorrectlyImpactedOnSCM/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/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.shouldJobAddBeCorrectlyImpactedOnSCM/jobs/fakeJob/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/jobs/fakeJob/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/jobs/fakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/jobs/newFakeJob/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/jobs/newFakeJob/config.xml
new file mode 100644
index 00000000..fe28eac3
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/jobs/newFakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ true
+ false
+
+ false
+ true
+ false
+ true
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobAddBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.git/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.git/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.git/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.git/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.git/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.git/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.git/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.git/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.git/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.subversion/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.subversion/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.subversion/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.subversion/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.subversion/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.subversion/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.subversion/jobs/.gitkeep b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.subversion/jobs/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.subversion/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.subversion/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteBeCorrectlyImpactedOnSCM.subversion/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/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.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/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.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/jobs/.gitkeep b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/jobs/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/jobs/newFakeJob/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/jobs/newFakeJob/config.xml
new file mode 100644
index 00000000..4d80eade
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/jobs/newFakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+ MySecondJobs
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobDeleteWithTwoJobsBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/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.shouldJobModificationBeCorrectlyImpactedOnSCM/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/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.shouldJobModificationBeCorrectlyImpactedOnSCM/jobs/fakeJob/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/jobs/fakeJob/config.xml
new file mode 100644
index 00000000..c28432c2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/jobs/fakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+ My desc
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobModificationBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobRenameBeCorrectlyImpactedOnSCM/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobRenameBeCorrectlyImpactedOnSCM/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobRenameBeCorrectlyImpactedOnSCM/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.shouldJobRenameBeCorrectlyImpactedOnSCM/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobRenameBeCorrectlyImpactedOnSCM/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobRenameBeCorrectlyImpactedOnSCM/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.shouldJobRenameBeCorrectlyImpactedOnSCM/jobs/newFakeJob/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobRenameBeCorrectlyImpactedOnSCM/jobs/newFakeJob/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobRenameBeCorrectlyImpactedOnSCM/jobs/newFakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobRenameBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobRenameBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.shouldJobRenameBeCorrectlyImpactedOnSCM/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/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.testAddJobNameStartingWithDash/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/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.testAddJobNameStartingWithDash/jobs/-newFakeJob/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/jobs/-newFakeJob/config.xml
new file mode 100644
index 00000000..fe28eac3
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/jobs/-newFakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ true
+ false
+
+ false
+ true
+ false
+ true
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/jobs/fakeJob/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/jobs/fakeJob/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/jobs/fakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameStartingWithDash/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/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.testAddJobNameWithBlanks/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/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.testAddJobNameWithBlanks/jobs/fakeJob/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/jobs/fakeJob/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/jobs/fakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/jobs/new fake Job/config.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/jobs/new fake Job/config.xml
new file mode 100644
index 00000000..fe28eac3
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/jobs/new fake Job/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ true
+ false
+
+ false
+ true
+ false
+ true
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/HudsonExtensionsTest.testAddJobNameWithBlanks/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/config.xml b/src/test/resources/expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/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/InitRepositoryTest.shouldSynchronizeHudsonFiles/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/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/InitRepositoryTest.shouldSynchronizeHudsonFiles/jobs/fakeJob/config.xml b/src/test/resources/expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/jobs/fakeJob/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/jobs/fakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/InitRepositoryTest.shouldSynchronizeHudsonFiles/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/config.xml b/src/test/resources/expected-scm-hierarchies/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/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/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/hudson.tasks.Shell.xml b/src/test/resources/expected-scm-hierarchies/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/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/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/jobs/fakeJob/config.xml b/src/test/resources/expected-scm-hierarchies/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/jobs/fakeJob/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/jobs/fakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/expected-scm-hierarchies/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/scm-sync-configuration.xml b/src/test/resources/expected-scm-hierarchies/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/expected-scm-hierarchies/JobConfigScmSyncStrategyTest.shouldConfigInSubmodulesNotSynced/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/hudsonRoot0.0.2BaseTemplate/config.xml b/src/test/resources/hudsonRoot0.0.2BaseTemplate/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/hudsonRoot0.0.2BaseTemplate/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/hudsonRoot0.0.2BaseTemplate/scm-sync-configuration.xml b/src/test/resources/hudsonRoot0.0.2BaseTemplate/scm-sync-configuration.xml
new file mode 100644
index 00000000..fe8f5c52
--- /dev/null
+++ b/src/test/resources/hudsonRoot0.0.2BaseTemplate/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+ SUBVERSION
+
diff --git a/src/test/resources/hudsonRoot0.0.2WithEmptyConfTemplate/config.xml b/src/test/resources/hudsonRoot0.0.2WithEmptyConfTemplate/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/hudsonRoot0.0.2WithEmptyConfTemplate/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/hudsonRoot0.0.2WithEmptyConfTemplate/scm-sync-configuration.xml b/src/test/resources/hudsonRoot0.0.2WithEmptyConfTemplate/scm-sync-configuration.xml
new file mode 100644
index 00000000..3df67d29
--- /dev/null
+++ b/src/test/resources/hudsonRoot0.0.2WithEmptyConfTemplate/scm-sync-configuration.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/src/test/resources/hudsonRoot0.0.3BaseTemplate/config.xml b/src/test/resources/hudsonRoot0.0.3BaseTemplate/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/hudsonRoot0.0.3BaseTemplate/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/hudsonRoot0.0.3BaseTemplate/scm-sync-configuration.xml b/src/test/resources/hudsonRoot0.0.3BaseTemplate/scm-sync-configuration.xml
new file mode 100644
index 00000000..fbb42631
--- /dev/null
+++ b/src/test/resources/hudsonRoot0.0.3BaseTemplate/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/hudsonRoot0.0.4WithEmptyConfTemplate/config.xml b/src/test/resources/hudsonRoot0.0.4WithEmptyConfTemplate/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/hudsonRoot0.0.4WithEmptyConfTemplate/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/hudsonRoot0.0.4WithEmptyConfTemplate/scm-sync-configuration.xml b/src/test/resources/hudsonRoot0.0.4WithEmptyConfTemplate/scm-sync-configuration.xml
new file mode 100644
index 00000000..b6dc2541
--- /dev/null
+++ b/src/test/resources/hudsonRoot0.0.4WithEmptyConfTemplate/scm-sync-configuration.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/src/test/resources/hudsonRootBaseTemplate/config.xml b/src/test/resources/hudsonRootBaseTemplate/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/hudsonRootBaseTemplate/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/hudsonRootBaseTemplate/hudson.tasks.Shell.xml b/src/test/resources/hudsonRootBaseTemplate/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/hudsonRootBaseTemplate/hudson.tasks.Shell.xml
@@ -0,0 +1,5 @@
+
+
+
+ /bin/bash
+
\ No newline at end of file
diff --git a/src/test/resources/hudsonRootBaseTemplate/jobs/fakeJob/config.xml b/src/test/resources/hudsonRootBaseTemplate/jobs/fakeJob/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/hudsonRootBaseTemplate/jobs/fakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/hudsonRootBaseTemplate/scm-sync-configuration.xml b/src/test/resources/hudsonRootBaseTemplate/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/hudsonRootBaseTemplate/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file
diff --git a/src/test/resources/jobConfigStrategyTemplate/config.xml b/src/test/resources/jobConfigStrategyTemplate/config.xml
new file mode 100644
index 00000000..824eae41
--- /dev/null
+++ b/src/test/resources/jobConfigStrategyTemplate/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/jobConfigStrategyTemplate/hudson.tasks.Shell.xml b/src/test/resources/jobConfigStrategyTemplate/hudson.tasks.Shell.xml
new file mode 100644
index 00000000..8b953697
--- /dev/null
+++ b/src/test/resources/jobConfigStrategyTemplate/hudson.tasks.Shell.xml
@@ -0,0 +1,5 @@
+
+
+
+ /bin/bash
+
\ No newline at end of file
diff --git a/src/test/resources/jobConfigStrategyTemplate/jobs/fakeJob/config.xml b/src/test/resources/jobConfigStrategyTemplate/jobs/fakeJob/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/jobConfigStrategyTemplate/jobs/fakeJob/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/jobConfigStrategyTemplate/jobs/fakeJob/modules/submodule/config.xml b/src/test/resources/jobConfigStrategyTemplate/jobs/fakeJob/modules/submodule/config.xml
new file mode 100644
index 00000000..f1972d75
--- /dev/null
+++ b/src/test/resources/jobConfigStrategyTemplate/jobs/fakeJob/modules/submodule/config.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+
+ false
+ true
+ false
+ false
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/jobConfigStrategyTemplate/scm-sync-configuration.xml b/src/test/resources/jobConfigStrategyTemplate/scm-sync-configuration.xml
new file mode 100644
index 00000000..a83018f2
--- /dev/null
+++ b/src/test/resources/jobConfigStrategyTemplate/scm-sync-configuration.xml
@@ -0,0 +1,5 @@
+
+
+ scm:svn:https://myrepo/synchronizedDirectory/
+
+
\ No newline at end of file