Skip to content

Commit 748c985

Browse files
committed
Use constants for base shell commands
1 parent ba2938f commit 748c985

File tree

4 files changed

+99
-82
lines changed

4 files changed

+99
-82
lines changed

src/main/java/cf/maybelambda/fedora/Main.java

Lines changed: 27 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@
1111
import java.util.Scanner;
1212

1313
public class Main {
14+
static List<String> CMD_RPM_IMPORT = asList("sudo", "rpm", "--import");
15+
static List<String> CMD_DNF_INST_REPOS = asList("sudo", "dnf", "install", "-y");
16+
static List<String> CMD_DNF_INST_PKGS = asList("sudo", "dnf", "--refresh", "install", "-y");
17+
static List<String> CMD_DNF_RM_PKGS = asList("sudo", "dnf", "remove", "-y", "--noautoremove");
18+
static List<String> CMD_DNF_MARK = asList("sudo", "dnf", "mark", "user", "flatpak");
19+
static List<String> CMD_DNF_AUTORM = asList("sudo", "dnf", "autoremove", "-y");
20+
static List<String> CMD_FLATPAK_REMOTE_ADD = asList("sudo", "flatpak", "remote-add", "--if-not-exists");
21+
static List<String> CMD_FLATPAK_INST = asList("flatpak", "install", "-y");
22+
static List<String> CMD_GETENT = asList("getent", "group");
23+
static List<String> CMD_ADD_GROUP = asList("sudo", "groupadd");
24+
static List<String> CMD_ADD_USER_TO_GROUP = asList("sudo", "usermod", "-aG");
25+
static List<String> CMD_SYSTEMCTL_ENABLE = asList("sudo", "systemctl", "enable", "--now", "cockpit.socket");
26+
1427
public static void main(String[] args) {
1528
run(args, new PostInstallUpdater());
1629
}
@@ -35,82 +48,50 @@ static void run(String[] args, PostInstallUpdater updater) {
3548

3649
if (confirm(scanner, "Install RPMFusion repos?")) {
3750
for (String key : ConfigManager.getRPMFusionGpgKeys()) {
38-
updater.runCommand(new String[]{"sudo", "rpm", "--import", key});
51+
updater.runCommand(CMD_RPM_IMPORT, asList(key));
3952
}
4053

4154
List<String> repos = ConfigManager.getRPMFusionRepos();
42-
String[] cmd = new String[repos.size() + 4];
43-
cmd[0] = "sudo";
44-
cmd[1] = "dnf";
45-
cmd[2] = "install";
46-
cmd[3] = "-y";
47-
for (int i = 0; i < repos.size(); i++) {
48-
cmd[4 + i] = repos.get(i);
49-
}
50-
updater.runCommand(cmd);
55+
updater.runCommand(CMD_DNF_INST_REPOS, repos);
5156
}
5257

5358
if (confirm(scanner, "Install additional packages with DNF?")) {
5459
List<String> filtered = promptForExclusions(dnfInstallPackages, scanner);
55-
String[] cmd = new String[filtered.size() + 5];
56-
cmd[0] = "sudo";
57-
cmd[1] = "dnf";
58-
cmd[2] = "--refresh";
59-
cmd[3] = "install";
60-
cmd[4] = "-y";
61-
for (int i = 0; i < filtered.size(); i++) {
62-
cmd[5 + i] = filtered.get(i);
63-
}
64-
updater.runCommand(cmd);
60+
updater.runCommand(CMD_DNF_INST_PKGS, filtered);
6561
}
6662

6763
if (confirm(scanner, "Remove all DNF packages marked for removal?")) {
6864
List<String> filtered = promptForExclusions(dnfRemovePackages, scanner);
69-
String[] cmd = new String[filtered.size() + 5];
70-
cmd[0] = "sudo";
71-
cmd[1] = "dnf";
72-
cmd[2] = "remove";
73-
cmd[3] = "-y";
74-
cmd[4] = "--noautoremove";
75-
for (int i = 0; i < filtered.size(); i++) {
76-
cmd[5 + i] = filtered.get(i);
77-
}
78-
updater.runCommand(cmd);
79-
updater.runCommand(new String[]{"sudo", "dnf", "mark", "user", "flatpak"});
80-
updater.runCommand(new String[]{"sudo", "dnf", "autoremove", "-y"});
65+
updater.runCommand(CMD_DNF_RM_PKGS, filtered);
66+
updater.runCommand(CMD_DNF_MARK, asList());
67+
updater.runCommand(CMD_DNF_AUTORM, asList());
8168
}
8269

8370
if (confirm(scanner, "Install Flatpak apps?")) {
8471
String name = ConfigManager.getFlatpakRemoteName();
8572
String url = ConfigManager.getFlatpakRemoteUrl();
86-
updater.runCommand(new String[]{"sudo", "flatpak", "remote-add", "--if-not-exists", name, url});
73+
updater.runCommand(CMD_FLATPAK_REMOTE_ADD, asList(name, url));
74+
8775
List<String> filtered = promptForExclusions(flatpakInstallPackages, scanner);
88-
String[] cmd = new String[filtered.size() + 4];
89-
cmd[0] = "flatpak";
90-
cmd[1] = "install";
91-
cmd[2] = "-y";
92-
cmd[3] = name;
93-
for (int i = 0; i < filtered.size(); i++) {
94-
cmd[4 + i] = filtered.get(i);
95-
}
96-
updater.runCommand(cmd);
76+
filtered.addFirst(name);
77+
updater.runCommand(CMD_FLATPAK_INST, filtered);
9778
}
9879

9980
if (confirm(scanner, "Ensure admin groups exist and add current user to them?")) {
10081
String user = System.getProperty("user.name");
10182
for (String group : ConfigManager.getAdminGroups()) {
102-
int exit = updater.runCommand(new String[]{"getent", "group", group});
83+
int exit = updater.runCommand(CMD_GETENT, asList(group));
10384
boolean groupExists = (exit == 0);
10485
if (!groupExists) {
10586
System.out.println("Group '" + group + "' does not exist. Creating...");
106-
updater.runCommand(new String[]{"sudo", "groupadd", group});
87+
updater.runCommand(CMD_ADD_GROUP, asList(group));
10788
}
108-
updater.runCommand(new String[]{"sudo", "usermod", "-aG", group, user});
89+
updater.runCommand(CMD_ADD_USER_TO_GROUP, asList(group, user));
10990
}
11091
}
11192

11293
if (confirm(scanner, "Enable and start cockpit.socket service?")) {
113-
updater.runCommand(new String[]{"sudo", "systemctl", "enable", "--now", "cockpit.socket"});
94+
updater.runCommand(CMD_SYSTEMCTL_ENABLE, asList());
11495
}
11596

11697
System.out.println(color("\n.o0×X×0o. All actions completed. Goodbye. .o0×X×0o.", GREEN));

src/main/java/cf/maybelambda/fedora/PostInstallUpdater.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import static cf.maybelambda.fedora.ConsoleIOHelper.BLUE;
44
import static cf.maybelambda.fedora.ConsoleIOHelper.YELLOW;
55
import static cf.maybelambda.fedora.ConsoleIOHelper.color;
6+
import static java.util.stream.Stream.concat;
67

78
import java.io.BufferedReader;
89
import java.io.IOException;
910
import java.io.InputStreamReader;
11+
import java.util.List;
1012
import java.util.NoSuchElementException;
1113

1214
public class PostInstallUpdater {
@@ -24,7 +26,8 @@ ProcessBuilder createProcessBuilder(String[] cmd) {
2426
return new ProcessBuilder(cmd);
2527
}
2628

27-
int runCommand(String[] command) {
29+
int runCommand(List<String> commandPrefix, List<String> args) {
30+
String[] command = concat(commandPrefix.stream(), args.stream()).toArray(String[]::new);
2831
System.out.println("Executing shell command: " + color(String.join(" ", command), BLUE));
2932
if (isDryRun()) {
3033
System.out.println(color("Dry-run: command not executed.", YELLOW));

src/test/java/cf/maybelambda/fedora/MainTests.java

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
package cf.maybelambda.fedora;
22

3+
import static cf.maybelambda.fedora.ConfigManager.getAdminGroups;
4+
import static cf.maybelambda.fedora.ConfigManager.getDnfInstallPackages;
5+
import static cf.maybelambda.fedora.ConfigManager.getDnfRemovePackages;
6+
import static cf.maybelambda.fedora.ConfigManager.getFlatpakInstallPackages;
7+
import static cf.maybelambda.fedora.ConfigManager.getFlatpakRemoteName;
8+
import static cf.maybelambda.fedora.ConfigManager.getFlatpakRemoteUrl;
9+
import static cf.maybelambda.fedora.ConfigManager.getRPMFusionGpgKeys;
10+
import static cf.maybelambda.fedora.ConfigManager.getRPMFusionRepos;
11+
import static cf.maybelambda.fedora.Main.CMD_ADD_USER_TO_GROUP;
12+
import static cf.maybelambda.fedora.Main.CMD_DNF_AUTORM;
13+
import static cf.maybelambda.fedora.Main.CMD_DNF_INST_PKGS;
14+
import static cf.maybelambda.fedora.Main.CMD_DNF_INST_REPOS;
15+
import static cf.maybelambda.fedora.Main.CMD_DNF_MARK;
16+
import static cf.maybelambda.fedora.Main.CMD_DNF_RM_PKGS;
17+
import static cf.maybelambda.fedora.Main.CMD_FLATPAK_INST;
18+
import static cf.maybelambda.fedora.Main.CMD_FLATPAK_REMOTE_ADD;
19+
import static cf.maybelambda.fedora.Main.CMD_GETENT;
20+
import static cf.maybelambda.fedora.Main.CMD_RPM_IMPORT;
21+
import static cf.maybelambda.fedora.Main.CMD_SYSTEMCTL_ENABLE;
22+
import static org.junit.jupiter.api.Assertions.assertEquals;
323
import static org.junit.jupiter.api.Assertions.assertTrue;
424
import static org.mockito.ArgumentMatchers.any;
525
import static org.mockito.Mockito.mock;
@@ -17,19 +37,6 @@
1737

1838
class MainTests {
1939
private PostInstallUpdater mockUpdater = mock(PostInstallUpdater.class);
20-
private static final List<String> EXPECTED_COMMAND_PARTS = List.of(
21-
"rpm --import",
22-
"dnf install -y repo1",
23-
"dnf --refresh install -y pkg1",
24-
"dnf remove -y --noautoremove pkg2",
25-
"dnf mark user flatpak",
26-
"dnf autoremove",
27-
"flatpak remote-add",
28-
"flatpak install -y flathub flatpak1",
29-
"getent group wheel",
30-
"usermod -aG wheel",
31-
"systemctl enable --now cockpit.socket"
32-
);
3340

3441
private void setupConfigManager(MockedStatic<ConfigManager> cfg) {
3542
cfg.when(ConfigManager::getDnfInstallPackages).thenReturn(List.of("pkg1"));
@@ -48,29 +55,54 @@ private void simulateUserInput() {
4855
System.setIn(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)));
4956
}
5057

51-
private void assertCommandSequence(List<String> actualCommands) {
52-
for (int i = 0; i < EXPECTED_COMMAND_PARTS.size(); i++) {
53-
assertTrue(actualCommands.get(i).contains(EXPECTED_COMMAND_PARTS.get(i)),
54-
"Command at index " + i + " should contain '" + EXPECTED_COMMAND_PARTS.get(i) + "'");
55-
}
56-
}
57-
5858
@Test
59-
void runExecutesAllActionsInExpectedOrder() {
60-
try (var cfg = mockStatic(ConfigManager.class)) {
59+
void runExecutesCommandStructureAndSequenceInCorrectOrdering() {
60+
try (MockedStatic<ConfigManager> cfg = mockStatic(ConfigManager.class)) {
6161
setupConfigManager(cfg);
6262
simulateUserInput();
63-
when(mockUpdater.runCommand(any(String[].class))).thenReturn(0);
64-
63+
when(mockUpdater.runCommand(any(List.class), any(List.class))).thenReturn(0);
64+
6565
Main.run(new String[]{}, mockUpdater);
66-
67-
ArgumentCaptor<String[]> captor = ArgumentCaptor.forClass(String[].class);
68-
Mockito.verify(mockUpdater, Mockito.atLeastOnce()).runCommand(captor.capture());
69-
List<String> joined = captor.getAllValues().stream()
70-
.map(arr -> String.join(" ", arr))
71-
.toList();
72-
73-
assertCommandSequence(joined);
66+
67+
ArgumentCaptor<List<String>> captorPrefix = ArgumentCaptor.forClass(List.class);
68+
ArgumentCaptor<List<String>> captorArgs = ArgumentCaptor.forClass(List.class);
69+
Mockito.verify(mockUpdater, Mockito.atLeastOnce()).runCommand(captorPrefix.capture(), captorArgs.capture());
70+
List<List<String>> prefixes = captorPrefix.getAllValues();
71+
List<List<String>> args = captorArgs.getAllValues();
72+
int i = 0;
73+
74+
assertEquals(CMD_RPM_IMPORT, prefixes.get(i));
75+
assertEquals(getRPMFusionGpgKeys(), args.get(i));
76+
i++;
77+
assertEquals(CMD_DNF_INST_REPOS, prefixes.get(i));
78+
assertEquals(getRPMFusionRepos(), args.get(i));
79+
i++;
80+
assertEquals(CMD_DNF_INST_PKGS, prefixes.get(i));
81+
assertEquals(getDnfInstallPackages(), args.get(i));
82+
i++;
83+
assertEquals(CMD_DNF_RM_PKGS, prefixes.get(i));
84+
assertEquals(getDnfRemovePackages(), args.get(i));
85+
i++;
86+
assertEquals(CMD_DNF_MARK, prefixes.get(i));
87+
assertTrue(args.get(i).isEmpty());
88+
i++;
89+
assertEquals(CMD_DNF_AUTORM, prefixes.get(i));
90+
assertTrue(args.get(i).isEmpty());
91+
i++;
92+
assertEquals(CMD_FLATPAK_REMOTE_ADD, prefixes.get(i));
93+
assertEquals(List.of(getFlatpakRemoteName(), getFlatpakRemoteUrl()), args.get(i));
94+
i++;
95+
assertEquals(CMD_FLATPAK_INST, prefixes.get(i));
96+
assertEquals(List.of(getFlatpakRemoteName(), getFlatpakInstallPackages().getFirst()), args.get(i));
97+
i++;
98+
assertEquals(CMD_GETENT, prefixes.get(i));
99+
assertEquals(getAdminGroups(), args.get(i));
100+
i++;
101+
assertEquals(CMD_ADD_USER_TO_GROUP, prefixes.get(i));
102+
assertTrue(args.get(i).containsAll(getAdminGroups()));
103+
i++;
104+
assertEquals(CMD_SYSTEMCTL_ENABLE, prefixes.get(i));
105+
assertTrue(args.get(i).isEmpty());
74106
}
75107
}
76108

src/test/java/cf/maybelambda/fedora/PostInstallUpdaterTests.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package cf.maybelambda.fedora;
22

3+
import static java.util.Arrays.asList;
34
import static org.junit.jupiter.api.Assertions.assertEquals;
45
import static org.mockito.ArgumentMatchers.any;
56
import static org.mockito.Mockito.mock;
@@ -32,7 +33,7 @@ void runCommandReturnsStatusCodeOfCommandExecuted() throws Exception {
3233
when(mockBuilder.redirectErrorStream(true)).thenReturn(mockBuilder);
3334
Mockito.doReturn(mockBuilder).when(updater).createProcessBuilder(any(String[].class));
3435

35-
int exitCode = updater.runCommand(new String[]{"echo", "test"});
36+
int exitCode = updater.runCommand(asList("echo"), asList("test"));
3637

3738
assertEquals(0, exitCode);
3839
}
@@ -42,7 +43,7 @@ void runCommandReturnsStatusMinusOneOnIOException() throws Exception {
4243
when(mockBuilder.start()).thenThrow(new IOException("Simulated I/O error"));
4344
Mockito.doReturn(mockBuilder).when(updater).createProcessBuilder(any(String[].class));
4445

45-
int exitCode = updater.runCommand(new String[]{"failing", "cmd"});
46+
int exitCode = updater.runCommand(asList("failing"), asList("cmd"));
4647

4748
assertEquals(-1, exitCode);
4849
}
@@ -53,7 +54,7 @@ void runCommandSkipsExecutionInDryRunMode() {
5354
Mockito.doThrow(new AssertionError("Should not create ProcessBuilder in dry-run mode"))
5455
.when(updater).createProcessBuilder(any(String[].class));
5556

56-
int exitCode = updater.runCommand(new String[]{"fake", "cmd"});
57+
int exitCode = updater.runCommand(asList("fake"), asList("cmd"));
5758

5859
assertEquals(0, exitCode);
5960
}

0 commit comments

Comments
 (0)