Sort CLI commands alphabetically (#2020)

Sort CLI commands alphabetically to show them in consistent order.
This commit is contained in:
Eduard Heimbuch
2022-05-04 09:36:01 +02:00
committed by GitHub
parent 689b191ec3
commit 1c540e1fbd
4 changed files with 37 additions and 16 deletions

View File

@@ -0,0 +1,2 @@
- type: fixed
description: Sort CLI commands alphabetically ([#2020](https://github.com/scm-manager/scm-manager/pull/2020))

View File

@@ -26,10 +26,11 @@ package sonia.scm.cli;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Singleton
public class CommandRegistry {
@@ -41,17 +42,17 @@ public class CommandRegistry {
this.commandCollector = commandCollector;
}
public Set<RegisteredCommandNode> createCommandTree() {
Set<RegisteredCommandNode> rootCommands = new HashSet<>();
Set<RegisteredCommand> registeredCommands = commandCollector.collect();
public List<RegisteredCommandNode> createCommandTree() {
List<RegisteredCommandNode> rootCommands = new ArrayList<>();
List<RegisteredCommand> sortedCommands = collectSortedCommands();
Map<Class<?>, RegisteredCommandNode> commandNodes = new HashMap<>();
for (RegisteredCommand command : registeredCommands) {
for (RegisteredCommand command : sortedCommands) {
commandNodes.put(command.getCommand(), new RegisteredCommandNode(command.getName(), command.getCommand()));
}
for (RegisteredCommand command : registeredCommands) {
for (RegisteredCommand command : sortedCommands) {
RegisteredCommandNode node = commandNodes.get(command.getCommand());
if (command.getParent() == null) {
rootCommands.add(node);
@@ -66,4 +67,11 @@ public class CommandRegistry {
}
return rootCommands;
}
private List<RegisteredCommand> collectSortedCommands() {
return commandCollector.collect()
.stream()
.sorted((a, b) -> a.getName().compareToIgnoreCase(b.getName()))
.collect(Collectors.toList());
}
}

View File

@@ -24,6 +24,7 @@
package sonia.scm.cli;
import com.google.common.collect.ImmutableList;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.junit.jupiter.api.BeforeEach;
@@ -73,7 +74,7 @@ class CliProcessorTest {
@Test
void shouldExecutePingCommand() {
when(registry.createCommandTree()).thenReturn(Collections.singleton(new RegisteredCommandNode("ping", PingCommand.class)));
when(registry.createCommandTree()).thenReturn(ImmutableList.of(new RegisteredCommandNode("ping", PingCommand.class)));
Injector injector = Guice.createInjector();
CliProcessor cliProcessor = new CliProcessor(registry, injector, exceptionHandlerFactory);
@@ -84,7 +85,7 @@ class CliProcessorTest {
@Test
void shouldExecutePingCommandWithExitCode0() {
when(registry.createCommandTree()).thenReturn(Collections.singleton(new RegisteredCommandNode("ping", PingCommand.class)));
when(registry.createCommandTree()).thenReturn(ImmutableList.of(new RegisteredCommandNode("ping", PingCommand.class)));
Injector injector = Guice.createInjector();
CliProcessor cliProcessor = new CliProcessor(registry, injector, exceptionHandlerFactory);
@@ -164,7 +165,7 @@ class CliProcessorTest {
two.getChildren().add(three);
one.getChildren().add(two);
when(registry.createCommandTree()).thenReturn(Collections.singleton(one));
when(registry.createCommandTree()).thenReturn(ImmutableList.of(one));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
when(context.getStdout()).thenReturn(new PrintWriter(baos));

View File

@@ -31,10 +31,8 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Arrays;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
@@ -52,7 +50,7 @@ class CommandRegistryTest {
void shouldCreateTreeWithOnlyRootNodes() {
mockCommands(rc(Object.class), rc(String.class), rc(Integer.class));
Set<RegisteredCommandNode> commandTree = registry.createCommandTree();
List<RegisteredCommandNode> commandTree = registry.createCommandTree();
assertContainsCommands(commandTree, Object.class, String.class, Integer.class);
}
@@ -60,7 +58,7 @@ class CommandRegistryTest {
void shouldCreateTreeWithParents() {
mockCommands(rc(Object.class), rc(String.class, Object.class), rc(Integer.class, Object.class));
Set<RegisteredCommandNode> commandTree = registry.createCommandTree();
List<RegisteredCommandNode> commandTree = registry.createCommandTree();
assertContainsCommands(commandTree, Object.class);
assertContainsCommands(commandTree.iterator().next().getChildren(), Integer.class, String.class);
@@ -70,7 +68,7 @@ class CommandRegistryTest {
void shouldCreateTreeWithParentsSecondLevel() {
mockCommands(rc(Object.class), rc(String.class, Object.class), rc(Integer.class, String.class));
Set<RegisteredCommandNode> commandTree = registry.createCommandTree();
List<RegisteredCommandNode> commandTree = registry.createCommandTree();
assertContainsCommands(commandTree, Object.class);
RegisteredCommandNode rootNode = commandTree.iterator().next();
@@ -78,6 +76,18 @@ class CommandRegistryTest {
assertContainsCommands(rootNode.getChildren().get(0).getChildren(), Integer.class);
}
@Test
void shouldSortCommandsAlphabetically() {
mockCommands(rc(Object.class), rc(String.class, Object.class), rc(Float.class, Object.class), rc(Integer.class, Object.class));
List<RegisteredCommandNode> commandTree = registry.createCommandTree();
List<RegisteredCommandNode> subCommands = commandTree.get(0).getChildren();
assertThat(subCommands.get(0).getCommand()).isEqualTo(Float.class);
assertThat(subCommands.get(1).getCommand()).isEqualTo(Integer.class);
assertThat(subCommands.get(2).getCommand()).isEqualTo(String.class);
}
private void mockCommands(RegisteredCommand... commands) {
when(commandCollector.collect()).thenReturn(ImmutableSet.copyOf(commands));
}