Skip to content
Permalink
Browse files
[JENKINS-41171] All OrganizationFolder instances should be single origin
  • Loading branch information
stephenc committed Jan 24, 2017
1 parent 94118e6 commit 0c563150d2889a0fd035b04182f9b5bbad9ee61e
@@ -55,6 +55,12 @@

private static final Logger LOGGER = Logger.getLogger(CustomOrganizationFolderDescriptor.class.getName());

// JENKINS-41171 disabling generic organization folders in favour of single blend.
// Leaving the code path as it is tested and otherwise we would need to write migration tests if we need
// multi navigator support in the future. NOTE: Blue Ocean as of Jan 2017 has hard-coded the assumption
// that there is one and only one SCMNavigator in an OrganizationFolder
static final boolean SHOW_GENERIC = false;

public final SCMNavigatorDescriptor delegate;

CustomOrganizationFolderDescriptor(SCMNavigatorDescriptor delegate) {
@@ -194,6 +200,9 @@ public boolean filter(Object context, Descriptor descriptor) {
LOGGER.log(Level.FINER, "filtering {0}", descriptor.getId());
if (descriptor instanceof OrganizationFolder.DescriptorImpl
&& (context instanceof View || context instanceof ViewGroup)) {
if (!SHOW_GENERIC) {
return false;
}
if (ExtensionList.lookup(MultiBranchProjectFactoryDescriptor.class).isEmpty()) {
// if we have no factories, so do not display
return false;
@@ -251,6 +251,15 @@ public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOExcep
return super.getItem(NameEncoder.encode(projectName));
}

/**
* Returns {@code true} if this is a single origin {@link OrganizationFolder}.
*
* @return {@code true} if this is a single origin {@link OrganizationFolder}.
*/
public boolean isSingleOrigin() {
// JENKINS-41171 we expect everything except for rare legacy instances to be single origin.
return navigators.size() == 1;
}

public DescribableList<SCMNavigator,SCMNavigatorDescriptor> getNavigators() {
return navigators;
@@ -45,7 +45,7 @@ OrganizationFolder.OrganizationScan.displayName=Scan {0}
OrganizationFolder.DefaultPronoun=Organization
OrganizationFolder.DefaultProject=Multibranch
OrganizationFolder.DisplayName={0} Folder
OrganizationFolder.Description=Creates a set of {0} projects for {1} matching a defined criteria from a {2}
OrganizationFolder.Description=Creates a set of {0} projects for {1} matching a defined criteria combining projects from more than one {2}
OrganizationFolder.OrJoin2={0} or {1}
OrganizationFolder.OrJoinN.First={0}, {1}
OrganizationFolder.OrJoinN.Middle={0}, {1}
@@ -23,11 +23,28 @@
~ THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<f:section title="${%Project Sources}">
<f:entry field="navigators" title="${%Repository Sources}">
<f:repeatableHeteroProperty field="navigators" hasHeader="true" />
</f:entry>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler">
<f:section title="${%Projects}">
<j:choose>
<j:when test="${instance.singleOrigin}">
<f:entry title="${instance.navigators.get(0).descriptor.displayName}">
<table name="navigators" width="100%">
<j:scope>
<j:set var="instance" value="${instance.navigators.get(0)}"/>
<j:set var="descriptor" value="${instance.descriptor}"/>
<f:class-entry descriptor="${descriptor}"/>
<st:include from="${descriptor}" page="${descriptor.configPage}"/>
</j:scope>
</table>
</f:entry>
</j:when>
<j:otherwise>
<f:entry field="navigators" title="${%Repository Sources}">
<div class="warning">${%deprecated}</div>
<f:repeatableHeteroProperty field="navigators" hasHeader="true"/>
</f:entry>
</j:otherwise>
</j:choose>
<f:entry field="projectFactories" title="${%Project Recognizers}">
<f:repeatableHeteroProperty field="projectFactories" hasHeader="true" />
</f:entry>
@@ -0,0 +1,26 @@
#
# The MIT License
#
# Copyright (c) 2017, CloudBees, Inc.
#
# 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.
#
deprecated=This organization folder has a legacy configuration and does not have a single repository source. The \
ability to have an organization folders with multiple repository sources may be removed in a future release \
of the Branch API plugin.
@@ -49,11 +49,13 @@
import org.jvnet.hudson.test.LoggerRule;
import org.jvnet.hudson.test.TestExtension;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeThat;

public class CustomOrganizationFolderDescriptorTest {

@@ -134,6 +136,7 @@ public void dynamicLoadReversed() throws Exception {
@SuppressWarnings("deprecation") // ExtensionList.add simulating dynamic installation
@Test
public void dynamicLoad2() throws Exception {
assumeThat(CustomOrganizationFolderDescriptor.SHOW_GENERIC, is(true));
assertEquals(Collections.emptyList(), newItemTypes());
ExtensionList.lookup(SCMNavigatorDescriptor.class).add(new SomeNavigatorNoFactoryInstalledDescriptor());
ExtensionList.lookup(MultiBranchProjectFactoryDescriptor.class).add(new SomeNavigatorSomeFactoryInstalledDescriptor2());
@@ -142,6 +145,19 @@ public void dynamicLoad2() throws Exception {
newItemTypes(), containsInAnyOrder("MockNavigator", "MockNavigator", "Organization Folder"));
}

@Issue("JENKINS-41171")
@SuppressWarnings("deprecation") // ExtensionList.add simulating dynamic installation
@Test
public void dynamicLoad3() throws Exception {
assumeThat(CustomOrganizationFolderDescriptor.SHOW_GENERIC, is(false));
assertEquals(Collections.emptyList(), newItemTypes());
ExtensionList.lookup(SCMNavigatorDescriptor.class).add(new SomeNavigatorNoFactoryInstalledDescriptor());
ExtensionList.lookup(MultiBranchProjectFactoryDescriptor.class).add(new SomeNavigatorSomeFactoryInstalledDescriptor2());
ExtensionList.lookup(SCMNavigatorDescriptor.class).add(new SomeNavigatorSomeFactoryInstalledDescriptor1());
assertThat("When there is more than one navigator then the generic organization folder makes sense to show",
newItemTypes(), containsInAnyOrder("MockNavigator", "MockNavigator"));
}

@Issue("JENKINS-31949")
@Test
public void insideFolder() throws Exception {

0 comments on commit 0c56315

Please sign in to comment.