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 extends TopLevelItem> 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;
}
}
}