diff --git a/pom.xml b/pom.xml index 4177744..85ea340 100644 --- a/pom.xml +++ b/pom.xml @@ -96,6 +96,11 @@ io.jenkins.plugins ionicons-api + + org.jenkins-ci.plugins + jobConfigHistory + true + io.jenkins configuration-as-code diff --git a/src/main/java/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink.java b/src/main/java/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink.java index 22718d2..a7b7150 100644 --- a/src/main/java/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink.java +++ b/src/main/java/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink.java @@ -93,7 +93,8 @@ public void doRestore( final StaplerResponse2 rsp, @QueryParameter("restoreBackupFrom") final String restoreBackupFrom, @QueryParameter("restoreNextBuildNumber") final String restoreNextBuildNumber, - @QueryParameter("restorePlugins") final String restorePlugins) + @QueryParameter("restorePlugins") final String restorePlugins, + @QueryParameter("restoreConfigHistory") final String restoreConfigHistory) throws IOException { LOGGER.info("Starting restore operation."); @@ -113,7 +114,8 @@ public void doRestore( ThinBackupPluginImpl.get().getExpandedBackupPath(), restoreFromDate, "on".equals(restoreNextBuildNumber), - "on".equals(restorePlugins)); + "on".equals(restorePlugins), + "on".equals(restoreConfigHistory)); hudsonRestore.restore(); LOGGER.info("Restore finished."); diff --git a/src/main/java/org/jvnet/hudson/plugins/thinbackup/backup/HudsonBackup.java b/src/main/java/org/jvnet/hudson/plugins/thinbackup/backup/HudsonBackup.java index 7f547db..1da7a33 100644 --- a/src/main/java/org/jvnet/hudson/plugins/thinbackup/backup/HudsonBackup.java +++ b/src/main/java/org/jvnet/hudson/plugins/thinbackup/backup/HudsonBackup.java @@ -18,11 +18,13 @@ import com.google.common.base.Throwables; import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Plugin; import hudson.PluginWrapper; import hudson.model.ItemGroup; import hudson.model.Job; import hudson.model.Run; import hudson.model.TopLevelItem; +import hudson.plugins.jobConfigHistory.JobConfigHistory; import hudson.util.RunList; import java.io.File; import java.io.FileNotFoundException; @@ -31,6 +33,7 @@ import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; +import java.nio.file.Paths; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -69,7 +72,6 @@ public class HudsonBackup { public static final String JOBS_DIR_NAME = "jobs"; public static final String USERS_DIR_NAME = "users"; public static final String ARCHIVE_DIR_NAME = "archive"; - public static final String CONFIG_HISTORY_DIR_NAME = "config-history"; public static final String USERSCONTENTS_DIR_NAME = "userContent"; public static final String NEXT_BUILD_NUMBER_FILE_NAME = "nextBuildNumber"; public static final String PLUGINS_DIR_NAME = "plugins"; @@ -87,7 +89,7 @@ public class HudsonBackup { public static final String COMPLETED_BACKUP_FILE = "backup-completed.info"; private final ThinBackupPluginImpl plugin; - private final File hudsonHome; + private final File jenkinsHome; private final File backupRoot; private final File backupDirectory; private final BackupType backupType; @@ -108,7 +110,7 @@ public HudsonBackup( ItemGroup hudson) { this.hudson = hudson; this.plugin = plugin; - this.hudsonHome = plugin.getJenkinsHome(); + this.jenkinsHome = plugin.getJenkinsHome(); final String excludedFilesRegex = plugin.getExcludedFilesRegex(); if ((excludedFilesRegex != null) && !excludedFilesRegex.trim().isEmpty()) { @@ -170,7 +172,7 @@ public void backup() throws IOException { LOGGER.fine(MessageFormat.format("Performing {0} backup.", backupType)); - if (!hudsonHome.exists() || !hudsonHome.isDirectory()) { + if (!jenkinsHome.exists() || !jenkinsHome.isDirectory()) { final String msg = "No Hudson directory found. Backup cannot be performed."; LOGGER.severe(msg); throw new FileNotFoundException(msg); @@ -194,7 +196,15 @@ public void backup() throws IOException { } if (plugin.isBackupConfigHistory()) { - backupRootFolder(CONFIG_HISTORY_DIR_NAME); + final Plugin configHistoryPlugin = Jenkins.get().getPlugin("jobConfigHistory"); + if (configHistoryPlugin != null && configHistoryPlugin.getWrapper().isActive()) { + final JobConfigHistory descriptor = + (JobConfigHistory) Jenkins.get().getDescriptor(JobConfigHistory.class); + if (descriptor != null) { + final File configuredHistoryRootDir = descriptor.getConfiguredHistoryRootDir(); + backupConfigHistoryFolder(configuredHistoryRootDir.toString()); + } + } } if (plugin.isBackupPluginArchives()) { @@ -272,7 +282,7 @@ private void backupGlobalXmls() throws IOException { getExcludedFilesFilter()); try { FileUtils.copyDirectory( - hudsonHome, backupDirectory, ExistsAndReadableFileFilter.wrapperFilter(suffixFileFilter)); + jenkinsHome, backupDirectory, ExistsAndReadableFileFilter.wrapperFilter(suffixFileFilter)); } catch (IOException e) { if (plugin.isFailFast()) { throw e; @@ -286,7 +296,7 @@ private void backupGlobalXmls() throws IOException { private void backupJobs() throws IOException { LOGGER.fine("Backing up job specific configuration files..."); - final File jobsDirectory = new File(hudsonHome.getAbsolutePath(), JOBS_DIR_NAME); + final File jobsDirectory = new File(jenkinsHome.getAbsolutePath(), JOBS_DIR_NAME); final File jobsBackupDirectory = new File(backupDirectory.getAbsolutePath(), JOBS_DIR_NAME); backupJobsDirectory(jobsDirectory, jobsBackupDirectory); @@ -415,7 +425,8 @@ private void backupAdditionalFiles() throws IOException { FileFilterUtils.and(getFileAgeDiffFilter(), getExcludedFilesFilter()))); try { - FileUtils.copyDirectory(hudsonHome, backupDirectory, ExistsAndReadableFileFilter.wrapperFilter(filter)); + FileUtils.copyDirectory( + jenkinsHome, backupDirectory, ExistsAndReadableFileFilter.wrapperFilter(filter)); } catch (IOException e) { if (plugin.isFailFast()) { throw e; @@ -465,7 +476,7 @@ private File createBackupDirectory(File jobBackupdirectory, File jobDirectory, F */ private List findAllConfigurations(File dir) throws UncheckedIOException { Collection listFiles = - FileUtils.listFiles(dir, FileFilterUtils.nameFileFilter(CONFIG_XML), TrueFileFilter.INSTANCE); + FileUtils.listFiles(dir, FileFilterUtils.nameFileFilter(CONFIG_XML), TrueFileFilter.TRUE); List confs = new ArrayList<>(); for (File file : listFiles) { @@ -583,7 +594,7 @@ private void backupBuildArchive(final File buildSrcDir, final File buildDestDir) private void backupRootFolder(String folderName) throws IOException { try { - backupRootFolder(folderName, TrueFileFilter.INSTANCE); + backupRootFolder(folderName, TrueFileFilter.TRUE); } catch (IOException e) { if (plugin.isFailFast()) { throw e; @@ -594,8 +605,24 @@ private void backupRootFolder(String folderName) throws IOException { } } + private void backupConfigHistoryFolder(String folderName) throws IOException { + final File srcDirectory = new File(folderName); + if (srcDirectory.exists() && srcDirectory.isDirectory()) { + LOGGER.log(Level.FINE, "Backing up {0}...", folderName); + Path pathAbsolute = Paths.get(folderName); + Path pathBase = Paths.get(jenkinsHome.getAbsolutePath()); + Path pathRelative = pathBase.relativize(pathAbsolute); + final File destDirectory = new File(backupDirectory.getAbsolutePath(), String.valueOf(pathRelative)); + IOFileFilter filter = + FileFilterUtils.and(TrueFileFilter.TRUE, getFileAgeDiffFilter(), getExcludedFilesFilter()); + filter = FileFilterUtils.or(filter, DirectoryFileFilter.DIRECTORY); + FileUtils.copyDirectory(srcDirectory, destDirectory, ExistsAndReadableFileFilter.wrapperFilter(filter)); + LOGGER.log(Level.FINE, "DONE backing up {0}.", folderName); + } + } + private void backupRootFolder(String folderName, IOFileFilter fileFilter) throws IOException { - final File srcDirectory = new File(hudsonHome.getAbsolutePath(), folderName); + final File srcDirectory = new File(jenkinsHome.getAbsolutePath(), folderName); if (srcDirectory.exists() && srcDirectory.isDirectory()) { LOGGER.log(Level.FINE, "Backing up {0}...", folderName); final File destDirectory = new File(backupDirectory.getAbsolutePath(), folderName); diff --git a/src/main/java/org/jvnet/hudson/plugins/thinbackup/restore/HudsonRestore.java b/src/main/java/org/jvnet/hudson/plugins/thinbackup/restore/HudsonRestore.java index ef82401..25d4571 100644 --- a/src/main/java/org/jvnet/hudson/plugins/thinbackup/restore/HudsonRestore.java +++ b/src/main/java/org/jvnet/hudson/plugins/thinbackup/restore/HudsonRestore.java @@ -62,10 +62,11 @@ public class HudsonRestore { private static final Logger LOGGER = Logger.getLogger("hudson.plugins.thinbackup"); private final String backupPath; - private final File hudsonHome; + private final File jenkinsHome; private final Date restoreFromDate; private final boolean restoreNextBuildNumber; private final boolean restorePlugins; + private final boolean restoreConfigHistory; private final Map> availablePluginLocations; public HudsonRestore( @@ -73,13 +74,15 @@ public HudsonRestore( final String backupPath, final Date restoreFromDate, final boolean restoreNextBuildNumber, - final boolean restorePlugins) { - this.hudsonHome = hudsonConfigurationPath; + final boolean restorePlugins, + final boolean restoreConfigHistory) { + this.jenkinsHome = hudsonConfigurationPath; this.backupPath = backupPath; this.restoreFromDate = restoreFromDate; this.restoreNextBuildNumber = restoreNextBuildNumber; this.restorePlugins = restorePlugins; this.availablePluginLocations = new HashMap<>(); + this.restoreConfigHistory = restoreConfigHistory; } public void restore() { @@ -168,6 +171,8 @@ private boolean restoreFromZipFile() throws IOException { private void restore(final File toRestore) throws IOException { final IOFileFilter nextBuildNumberFileFilter = FileFilterUtils.nameFileFilter("nextBuildNumber"); + final IOFileFilter configHistoryFileFilter = + FileFilterUtils.notFileFilter(FileFilterUtils.prefixFileFilter("config-history")); final IOFileFilter noBackupCompletedFile = FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter(COMPLETED_BACKUP_FILE)); IOFileFilter restoreNextBuildNumberFilter; @@ -176,7 +181,7 @@ private void restore(final File toRestore) throws IOException { restoreNextBuildNumberFilter = noBackupCompletedFile; final Collection restore = - FileUtils.listFiles(toRestore, nextBuildNumberFileFilter, TrueFileFilter.INSTANCE); + FileUtils.listFiles(toRestore, nextBuildNumberFileFilter, TrueFileFilter.TRUE); final Map nextBuildNumbers = new HashMap<>(); for (final File file : restore) { try (BufferedReader reader = new BufferedReader(new FileReader(file, StandardCharsets.UTF_8))) { @@ -185,7 +190,7 @@ private void restore(final File toRestore) throws IOException { } final Collection current = - FileUtils.listFiles(hudsonHome, nextBuildNumberFileFilter, TrueFileFilter.INSTANCE); + FileUtils.listFiles(jenkinsHome, nextBuildNumberFileFilter, TrueFileFilter.TRUE); for (final File file : current) { try (BufferedReader reader = new BufferedReader(new FileReader(file, StandardCharsets.UTF_8))) { final int currentBuildNumber = Integer.parseInt(reader.readLine()); @@ -201,7 +206,11 @@ private void restore(final File toRestore) throws IOException { FileFilterUtils.notFileFilter(nextBuildNumberFileFilter), noBackupCompletedFile); } - FileUtils.copyDirectory(toRestore, this.hudsonHome, restoreNextBuildNumberFilter, true); + if (!restoreConfigHistory) { + restoreNextBuildNumberFilter = FileFilterUtils.and(restoreNextBuildNumberFilter, configHistoryFileFilter); + } + + FileUtils.copyDirectory(toRestore, this.jenkinsHome, restoreNextBuildNumberFilter, true); if (restorePlugins) { restorePlugins(toRestore); diff --git a/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions.jelly b/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions.jelly index 15b228e..1555866 100644 --- a/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions.jelly +++ b/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions.jelly @@ -46,6 +46,10 @@ + + + + diff --git a/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions.properties b/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions.properties index a5b4f84..17c3bb3 100644 --- a/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions.properties +++ b/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions.properties @@ -3,3 +3,4 @@ restore_configuration = Restore Configuration restore_next_build_number = Restore next build number file (if found in backup) restore_options = Restore options restore_plugins = Restore plugins +restore_config_history = Restore config-history (if found in backup) diff --git a/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions_de.properties b/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions_de.properties index ff7c126..f2685b5 100644 --- a/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions_de.properties +++ b/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupMgmtLink/restoreOptions_de.properties @@ -1,5 +1,6 @@ restore_backup_from = Backup wiederherstellen von: restore_configuration = Restore Konfiguration -restore_next_build_number = Nächste Build Nummer Datein wiederherstellen (falls im Backup vorhanden) +restore_next_build_number = Nächste Build Nummer Dateien wiederherstellen (falls im Backup vorhanden) restore_options = Restore Optionen restore_plugins = Plugins wiederherstellen +restore_config_history = Config-history wiederherstellen (falls im Backup vorhanden) diff --git a/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupPluginImpl/help-backupConfigHistory.html b/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupPluginImpl/help-backupConfigHistory.html index 448b4fd..0111c69 100644 --- a/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupPluginImpl/help-backupConfigHistory.html +++ b/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupPluginImpl/help-backupConfigHistory.html @@ -24,6 +24,6 @@

- If this option is enabled, the directory config-history will also be backed up. + If this option is enabled, the directory which is configured within the config-history plugin will also be backed up (only if plugin is installed).

diff --git a/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupPluginImpl/help-backupConfigHistory_de.html b/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupPluginImpl/help-backupConfigHistory_de.html index 452bc0f..20afc91 100644 --- a/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupPluginImpl/help-backupConfigHistory_de.html +++ b/src/main/resources/org/jvnet/hudson/plugins/thinbackup/ThinBackupPluginImpl/help-backupConfigHistory_de.html @@ -24,6 +24,6 @@

- Falls diese Option aktiviert ist, wird das Verzeichnis config-history zum Backup hinzugefügt. + Falls diese Option aktiviert ist, wird das Verzeichnis, welches im config-history konfiguriert ist, zum Backup hinzugefügt (nur wenn das Plugin installiert ist).

diff --git a/src/main/webapp/help/help-restoreConfigHistory.html b/src/main/webapp/help/help-restoreConfigHistory.html new file mode 100644 index 0000000..5811b82 --- /dev/null +++ b/src/main/webapp/help/help-restoreConfigHistory.html @@ -0,0 +1,30 @@ + + +
+

+ If this option is enabled, the config-history gets restored.
+ This will only work, if the config-history plugin is installed, otherwise it cannot read the config folder. +

+
diff --git a/src/main/webapp/help/help-restoreConfigHistory_de.html b/src/main/webapp/help/help-restoreConfigHistory_de.html new file mode 100644 index 0000000..3c5cb87 --- /dev/null +++ b/src/main/webapp/help/help-restoreConfigHistory_de.html @@ -0,0 +1,30 @@ + + +
+

+ Falls diese Option aktiviert ist, wird die config-history aus dem Backup wiederhergestellt.
+ Es wird nur funktionieren, falls das config-history Plugin installiert ist, sonst kann der Konfigurationsordner nicht ausgelesen werden. +

+
diff --git a/src/test/java/org/jvnet/hudson/plugins/thinbackup/backup/TestBackupWithCloudBeesFolder.java b/src/test/java/org/jvnet/hudson/plugins/thinbackup/backup/TestBackupWithCloudBeesFolder.java index 7d0f86d..6bcbc64 100644 --- a/src/test/java/org/jvnet/hudson/plugins/thinbackup/backup/TestBackupWithCloudBeesFolder.java +++ b/src/test/java/org/jvnet/hudson/plugins/thinbackup/backup/TestBackupWithCloudBeesFolder.java @@ -22,7 +22,7 @@ import org.jvnet.hudson.test.junit.jupiter.WithJenkins; @WithJenkins -class TestBackupWithCloudBeesFolder { +class TestBackupWithFolder { @TempDir private File tmpFolder; diff --git a/src/test/java/org/jvnet/hudson/plugins/thinbackup/restore/TestRestore.java b/src/test/java/org/jvnet/hudson/plugins/thinbackup/restore/TestRestore.java index d29144d..48c7577 100644 --- a/src/test/java/org/jvnet/hudson/plugins/thinbackup/restore/TestRestore.java +++ b/src/test/java/org/jvnet/hudson/plugins/thinbackup/restore/TestRestore.java @@ -16,6 +16,7 @@ import java.util.Date; import java.util.List; import java.util.logging.Level; +import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.jvnet.hudson.plugins.thinbackup.ThinBackupPeriodicWork; @@ -32,6 +33,64 @@ class TestRestore { @TempDir private File tmpFolder; + @Test + void testRestoreWithConfigHistory(JenkinsRule r) throws Exception { + // create to test afterward + File backupDir = newFolder(tmpFolder, "junit"); + + final ThinBackupPluginImpl thinBackupPlugin = ThinBackupPluginImpl.get(); + thinBackupPlugin.setBackupPath(backupDir.getAbsolutePath()); + thinBackupPlugin.setBackupBuildResults(true); + thinBackupPlugin.setBackupNextBuildNumber(true); + thinBackupPlugin.setBackupConfigHistory(true); + final File rootDir = r.jenkins.getRootDir(); + final Date date = new Date(); + + // create 2 jobs + final FreeStyleProject test = r.createFreeStyleProject("test"); + final FreeStyleProject test2 = r.createFreeStyleProject("test2"); + + // adjust description to create config history + test.setDescription("new test"); + test2.setDescription("new test2"); + + // run backup + final HudsonBackup backup = + new HudsonBackup(thinBackupPlugin, ThinBackupPeriodicWork.BackupType.FULL, date, r.jenkins); + backup.backup(); + + // delete jobs + test.delete(); + test2.delete(); + + // delete config-history + final File configHistory = new File(rootDir, "config-history"); + FileUtils.deleteDirectory(configHistory); + + // check that files are gone + final File jobs = new File(rootDir, "jobs"); + String[] jobList = jobs.list(); + assertEquals(0, jobList.length); + + // now do the restore without config-history + HudsonRestore hudsonRestore = + new HudsonRestore(rootDir, backupDir.getAbsolutePath(), date, false, false, false); + hudsonRestore.restore(); + + // verify jobs are back + jobList = jobs.list(); + assertEquals(2, jobList.length); + + // verify config-history is missing + assertFalse(configHistory.exists()); + + // restore from backup INCLUDING config-history + hudsonRestore = new HudsonRestore(rootDir, backupDir.getAbsolutePath(), date, false, false, true); + hudsonRestore.restore(); + + assertTrue(configHistory.exists()); + } + @Test void testRestoreFromFolder(JenkinsRule r) throws Exception { // create to test afterward @@ -72,7 +131,8 @@ void testRestoreFromFolder(JenkinsRule r) throws Exception { assertEquals(0, jobList.length); // now do the restore without build number - HudsonRestore hudsonRestore = new HudsonRestore(rootDir, backupDir.getAbsolutePath(), date, false, false); + HudsonRestore hudsonRestore = + new HudsonRestore(rootDir, backupDir.getAbsolutePath(), date, false, false, false); hudsonRestore.restore(); // verify jobs are back @@ -83,7 +143,7 @@ void testRestoreFromFolder(JenkinsRule r) throws Exception { assertFalse(new File(test2rootDir, "nextBuildNumber").exists()); // restore from backup INCLUDING build number - hudsonRestore = new HudsonRestore(rootDir, backupDir.getAbsolutePath(), date, true, false); + hudsonRestore = new HudsonRestore(rootDir, backupDir.getAbsolutePath(), date, true, false, false); hudsonRestore.restore(); assertTrue(new File(test2rootDir, "nextBuildNumber").exists()); @@ -146,7 +206,7 @@ void testRestoreFromZip(JenkinsRule r) throws Exception { // now do the restore without build number HudsonRestore hudsonRestore = - new HudsonRestore(rootDir, backupDir.getAbsolutePath(), restoreFromDate, false, false); + new HudsonRestore(rootDir, backupDir.getAbsolutePath(), restoreFromDate, false, false, false); hudsonRestore.restore(); // verify jobs are back @@ -157,7 +217,7 @@ void testRestoreFromZip(JenkinsRule r) throws Exception { assertFalse(new File(test2rootDir, "nextBuildNumber").exists()); // restore from backup INCLUDING build number - hudsonRestore = new HudsonRestore(rootDir, backupDir.getAbsolutePath(), restoreFromDate, true, false); + hudsonRestore = new HudsonRestore(rootDir, backupDir.getAbsolutePath(), restoreFromDate, true, false, false); hudsonRestore.restore(); assertTrue(new File(test2rootDir, "nextBuildNumber").exists()); @@ -166,7 +226,7 @@ void testRestoreFromZip(JenkinsRule r) throws Exception { @Test void testLogsForRestoringWithoutBackupPath(JenkinsRule r) { try (LogRecorder l = new LogRecorder().capture(3).record("hudson.plugins.thinbackup", Level.SEVERE)) { - final HudsonRestore hudsonRestore = new HudsonRestore(null, null, null, false, false); + final HudsonRestore hudsonRestore = new HudsonRestore(null, null, null, false, false, false); hudsonRestore.restore(); assertThat( l, recorded(Level.SEVERE, containsString("Backup path not specified for restoration. Aborting."))); @@ -176,7 +236,7 @@ void testLogsForRestoringWithoutBackupPath(JenkinsRule r) { @Test void testLogsForRestoringWithoutRestoreFromDate(JenkinsRule r) { try (LogRecorder l = new LogRecorder().capture(3).record("hudson.plugins.thinbackup", Level.SEVERE)) { - final HudsonRestore hudsonRestore = new HudsonRestore(null, "/var/backup", null, false, false); + final HudsonRestore hudsonRestore = new HudsonRestore(null, "/var/backup", null, false, false, false); hudsonRestore.restore(); assertThat( l,