From c1a356b11a111f4dff30bfc47788c83601d48b0f Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Tue, 3 Dec 2024 17:32:28 -0500 Subject: [PATCH 1/2] Recover views after error in `Jenkins.load` --- core/src/main/java/jenkins/model/Jenkins.java | 14 +++++++++++--- .../src/test/java/jenkins/model/JenkinsTest.java | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java index bedbea0af7c4..312f7a804cde 100644 --- a/core/src/main/java/jenkins/model/Jenkins.java +++ b/core/src/main/java/jenkins/model/Jenkins.java @@ -3299,11 +3299,19 @@ public void load() throws IOException { if (cfg.exists()) { // reset some data that may not exist in the disk file // so that we can take a proper compensation action later. + String originalPrimaryView = primaryView; + List originalViews = new ArrayList<>(views); primaryView = null; views.clear(); - - // load from disk - cfg.unmarshal(Jenkins.this); + try { + // load from disk + cfg.unmarshal(Jenkins.this); + } catch (IOException | RuntimeException x) { + primaryView = originalPrimaryView; + views.clear(); + views.addAll(originalViews); + throw x; + } } // initialize views by inserting the default view if necessary // this is both for clean Jenkins and for backward compatibility. diff --git a/test/src/test/java/jenkins/model/JenkinsTest.java b/test/src/test/java/jenkins/model/JenkinsTest.java index 3f3f615a6c5f..8fdb761791a8 100644 --- a/test/src/test/java/jenkins/model/JenkinsTest.java +++ b/test/src/test/java/jenkins/model/JenkinsTest.java @@ -30,9 +30,11 @@ import static org.awaitility.Awaitility.await; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.arrayContaining; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isA; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -46,6 +48,7 @@ import hudson.XmlFile; import hudson.init.InitMilestone; import hudson.init.Initializer; +import hudson.model.AllView; import hudson.model.Computer; import hudson.model.Failure; import hudson.model.FreeStyleProject; @@ -101,6 +104,7 @@ import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.rules.TemporaryFolder; +import org.jvnet.hudson.reactor.ReactorException; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.JenkinsRule.WebClient; @@ -756,4 +760,16 @@ public String getUrlName() { return null; } } + + @Test + public void reloadViews() throws Exception { + assertThat(j.jenkins.getPrimaryView(), isA(AllView.class)); + assertThat(j.jenkins.getViews(), contains(isA(AllView.class))); + Files.writeString(j.jenkins.getConfigFile().getFile().toPath(), " Date: Tue, 3 Dec 2024 18:11:24 -0500 Subject: [PATCH 2/2] Prevent infinite recursion in `Jenkins/sidepanel.jelly` when `Jenkins.primaryView` is null --- .../main/resources/jenkins/model/Jenkins/sidepanel.jelly | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/resources/jenkins/model/Jenkins/sidepanel.jelly b/core/src/main/resources/jenkins/model/Jenkins/sidepanel.jelly index 9ddff73647d6..e413712d6e7c 100644 --- a/core/src/main/resources/jenkins/model/Jenkins/sidepanel.jelly +++ b/core/src/main/resources/jenkins/model/Jenkins/sidepanel.jelly @@ -23,4 +23,9 @@ THE SOFTWARE. --> - \ No newline at end of file + + + + + +