diff --git a/changelog.html b/changelog.html index a5e7efb2cd9a21e137e56caabdadfdf24b4a6074..9abb41e9921a22b375b2f1754c8f328420a7ccc3 100644 --- a/changelog.html +++ b/changelog.html @@ -82,6 +82,9 @@ Upcoming changes Core started relying on Java 1.6 as per the agreement in the dev list. If you have a serious objection against it, please let us know before we really start relying on 1.6 features. +
  • + CLI list-jobs command should list all nested jobs. + (pull request 793) diff --git a/core/src/main/java/hudson/model/View.java b/core/src/main/java/hudson/model/View.java index d6d4ef4a5b6906ff1a1631d818198c7d64fc091c..a4ac6d0c5bf3ff49a4b05753817649721fc5e18c 100644 --- a/core/src/main/java/hudson/model/View.java +++ b/core/src/main/java/hudson/model/View.java @@ -179,23 +179,24 @@ public abstract class View extends AbstractModelObject implements AccessControll /** * Gets all the items recursively contained in this collection in a read-only view. + *

    + * The default implementation recursively adds the items of all contained Views + * in case this view implements {@link ViewGroup}, which should be enough for most cases. + * * @since 1.520 */ public Collection getAllItems() { - final Collection items = new LinkedHashSet( - getItems() - ); - if (this instanceof ViewGroup) { + final Collection items = new LinkedHashSet(getItems()); - for(final View view: ((ViewGroup) this).getViews()) { - + for(View view: ((ViewGroup) this).getViews()) { items.addAll(view.getAllItems()); } + return Collections.unmodifiableCollection(items); + } else { + return getItems(); } - - return Collections.unmodifiableCollection(items); } /** diff --git a/core/src/test/java/hudson/model/ViewTest.java b/core/src/test/java/hudson/model/ViewTest.java index 85a44919471aa6d0c388bd002647e4749ff9fba2..0e7f78272ebbfaf42f5a082adc8f1cd7deb447ac 100644 --- a/core/src/test/java/hudson/model/ViewTest.java +++ b/core/src/test/java/hudson/model/ViewTest.java @@ -1,16 +1,23 @@ package hudson.model; +import hudson.model.Descriptor.FormException; import hudson.search.SearchIndex; import hudson.search.SearchIndexBuilder; import hudson.search.SearchItem; +import hudson.views.ViewsTabBar; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; +import javax.servlet.ServletException; + import org.junit.Assert; import org.junit.Test; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; import org.mockito.Mockito; public class ViewTest { @@ -73,26 +80,21 @@ public class ViewTest { @Test public void getAllItems() throws Exception { - final CompositeView rootView = Mockito.mock(CompositeView.class); final View leftView = Mockito.mock(View.class); final View rightView = Mockito.mock(View.class); + CompositeView rootView = new CompositeView("rootJob", leftView, rightView); - Mockito.when(rootView.getAllItems()).thenCallRealMethod(); Mockito.when(leftView.getAllItems()).thenCallRealMethod(); Mockito.when(rightView.getAllItems()).thenCallRealMethod(); - final TopLevelItem rootJob = Mockito.mock(TopLevelItem.class); - final TopLevelItem leftJob = Mockito.mock(TopLevelItem.class); - final TopLevelItem rightJob = Mockito.mock(TopLevelItem.class); - final TopLevelItem sharedJob = Mockito.mock(TopLevelItem.class); - - Mockito.when(rootJob.getDisplayName()).thenReturn("rootJob"); - Mockito.when(leftJob.getDisplayName()).thenReturn("leftJob"); - Mockito.when(rightJob.getDisplayName()).thenReturn("rightJob"); - Mockito.when(sharedJob.getDisplayName()).thenReturn("sharedJob"); + final TopLevelItem rootJob = createJob("rootJob"); + final TopLevelItem sharedJob = createJob("sharedJob"); + + rootView = rootView.withJobs(rootJob, sharedJob); + + final TopLevelItem leftJob = createJob("leftJob"); + final TopLevelItem rightJob = createJob("rightJob"); - Mockito.when(rootView.getViews()).thenReturn(Arrays.asList(leftView, rightView)); - Mockito.when(rootView.getItems()).thenReturn(Arrays.asList(rootJob, sharedJob)); Mockito.when(leftView.getItems()).thenReturn(Arrays.asList(leftJob, sharedJob)); Mockito.when(rightView.getItems()).thenReturn(Arrays.asList(rightJob)); @@ -101,10 +103,91 @@ public class ViewTest { Assert.assertArrayEquals(expected, rootView.getAllItems().toArray()); } - public static abstract class CompositeView extends View implements ViewGroup { + private TopLevelItem createJob(String jobName) { + final TopLevelItem rootJob = Mockito.mock(TopLevelItem.class); + Mockito.when(rootJob.getDisplayName()).thenReturn(jobName); + return rootJob; + } + + public static class CompositeView extends View implements ViewGroup { - protected CompositeView(final String name) { + private View[] views; + private TopLevelItem[] jobs; + + protected CompositeView(final String name, View... views) { super(name); + this.views = views; + } + + private CompositeView withJobs(TopLevelItem... jobs) { + this.jobs = jobs; + return this; + } + + @Override + public Collection getItems() { + return Arrays.asList(this.jobs); + } + + @Override + public Collection getViews() { + return Arrays.asList(this.views); + } + + @Override + public boolean canDelete(View view) { + return false; + } + + @Override + public void deleteView(View view) throws IOException { + } + + @Override + public View getView(String name) { + return null; + } + + @Override + public View getPrimaryView() { + return null; + } + + @Override + public void onViewRenamed(View view, String oldName, String newName) { + } + + @Override + public ViewsTabBar getViewsTabBar() { + return null; + } + + @Override + public ItemGroup getItemGroup() { + return null; + } + + @Override + public List getViewActions() { + return null; + } + + @Override + public boolean contains(TopLevelItem item) { + return false; + } + + @Override + public void onJobRenamed(Item item, String oldName, String newName) { + } + + @Override + protected void submit(StaplerRequest req) throws IOException, ServletException, FormException { + } + + @Override + public Item doCreateItem(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + return null; } } }