Refactor to clean up main, add unit tests around command selection

This commit is contained in:
ferrreo 2023-01-19 13:34:17 +00:00
parent 00e1cbcc62
commit ad32b47827
3 changed files with 190 additions and 88 deletions

87
loader/loader.go Normal file
View File

@ -0,0 +1,87 @@
package loader
import (
"fmt"
"os"
"os/exec"
"pikman/alpine"
"pikman/arch"
"pikman/fedora"
"pikman/flatpak"
"pikman/ubuntu"
"strings"
)
type OSType = int
const (
Ubuntu OSType = iota
Arch
Fedora
Alpine
Flatpak
)
func ProcessCommand(command string, osType OSType, containerName string, packageName []string) error {
var err error
if osType != Ubuntu && osType != Flatpak && containerName != "" {
containerName = "--name " + containerName
} else {
containerName = ""
}
commandToExecute, err := getCommand(command, osType, containerName, packageName)
cmd := exec.Command("/bin/sh", "-c", commandToExecute)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
err = cmd.Run()
if err != nil {
return err
}
return nil
}
func getCommand(command string, osType OSType, containerName string, packageName []string) (string, error) {
switch osType {
case Arch:
cmd, ok := arch.Commands[command]
if ok {
return fmt.Sprintf("%s %s %s %s", arch.PackageManager, cmd, containerName, strings.Join(packageName, " ")), nil
} else {
return "", fmt.Errorf("%s: is not a valid command for Arch", command)
}
case Fedora:
cmd, ok := fedora.Commands[command]
if ok {
return fmt.Sprintf("%s %s %s %s", fedora.PackageManager, cmd, containerName, strings.Join(packageName, " ")), nil
} else {
return "", fmt.Errorf("%s: is not a valid command for Fedora", command)
}
case Flatpak:
cmd, ok := flatpak.Commands[command]
if ok {
return fmt.Sprintf("%s %s %s", flatpak.PackageManager, cmd, strings.Join(packageName, " ")), nil
} else {
return "", fmt.Errorf("%s: is not a valid command for Flatpak", command)
}
case Alpine:
cmd, ok := alpine.Commands[command]
if ok {
return fmt.Sprintf("%s %s %s %s", alpine.PackageManager, cmd, containerName, strings.Join(packageName, " ")), nil
} else {
return "", fmt.Errorf("%s: is not a valid command for Alpine", command)
}
case Ubuntu:
cmd, ok := ubuntu.Commands[command]
if ok {
return fmt.Sprintf("%s %s %s", ubuntu.PackageManager, cmd, strings.Join(packageName, " ")), nil
} else {
return "", fmt.Errorf("%s: is not a valid command for Ubuntu", command)
}
}
return "", fmt.Errorf("%s: was passed without a valid backend", command)
}

86
loader/loader_test.go Normal file
View File

@ -0,0 +1,86 @@
package loader
import "testing"
func Test_getCommand(t *testing.T) {
type args struct {
command string
osType OSType
containerName string
packageName []string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "Ubuntu single package",
args: args{
command: "install",
osType: Ubuntu,
containerName: "",
packageName: []string{"testPackage"},
},
want: "sudo -S nala install testPackage",
wantErr: false,
},
{
name: "Arch single package",
args: args{
command: "install",
osType: Arch,
containerName: "",
packageName: []string{"testPackage"},
},
want: "apx --aur install testPackage",
wantErr: false,
},
{
name: "Arch single package with container name",
args: args{
command: "install",
osType: Arch,
containerName: "--name testName",
packageName: []string{"testPackage"},
},
want: "apx --aur install --name testName testPackage",
wantErr: false,
},
{
name: "Ubuntu single package, container name not used",
args: args{
command: "install",
osType: Ubuntu,
containerName: "--name testName",
packageName: []string{"testPackage"},
},
want: "sudo -S nala install testPackage",
wantErr: false,
},
{
name: "Ubuntu invalid command should return nothing and error",
args: args{
command: "init",
osType: Ubuntu,
containerName: "",
packageName: []string{"testPackage"},
},
want: "",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := getCommand(tt.args.command, tt.args.osType, tt.args.containerName, tt.args.packageName)
if (err != nil) != tt.wantErr {
t.Errorf("getCommand() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("getCommand() got = %v, want %v", got, tt.want)
}
})
}
}

105
main.go
View File

@ -1,17 +1,10 @@
package main package main
import ( import (
"fmt"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"log" "log"
"os" "os"
"os/exec" "pikman/loader"
"pikman/alpine"
"pikman/arch"
"pikman/fedora"
"pikman/flatpak"
"pikman/ubuntu"
"strings"
) )
type OSType = int type OSType = int
@ -96,7 +89,7 @@ func main() {
Name: "autoremove", Name: "autoremove",
Usage: "Remove all unused packages", Usage: "Remove all unused packages",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
@ -104,28 +97,28 @@ func main() {
Aliases: []string{"cl"}, Aliases: []string{"cl"},
Usage: "Clean the package manager cache", Usage: "Clean the package manager cache",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
Name: "enter", Name: "enter",
Usage: "Enter the container instance for select package manager", Usage: "Enter the container instance for select package manager",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
Name: "export", Name: "export",
Usage: "Export/Recreate a program's desktop entry from the container", Usage: "Export/Recreate a program's desktop entry from the container",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
Name: "init", Name: "init",
Usage: "Initialize a managed container", Usage: "Initialize a managed container",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
@ -133,7 +126,7 @@ func main() {
Aliases: []string{"i"}, Aliases: []string{"i"},
Usage: "Install the specified package(s)", Usage: "Install the specified package(s)",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
@ -141,28 +134,28 @@ func main() {
Aliases: []string{"l"}, Aliases: []string{"l"},
Usage: "List installed packages", Usage: "List installed packages",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
Name: "log", Name: "log",
Usage: "Show package manager logs", Usage: "Show package manager logs",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
Name: "purge", Name: "purge",
Usage: "Fully purge a package", Usage: "Fully purge a package",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
Name: "run", Name: "run",
Usage: "Run a command inside a managed container", Usage: "Run a command inside a managed container",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
@ -170,7 +163,7 @@ func main() {
Aliases: []string{"r"}, Aliases: []string{"r"},
Usage: "Remove an installed package", Usage: "Remove an installed package",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
@ -178,28 +171,28 @@ func main() {
Aliases: []string{"s"}, Aliases: []string{"s"},
Usage: "Search for a package", Usage: "Search for a package",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
Name: "show", Name: "show",
Usage: "Show details for a package", Usage: "Show details for a package",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
Name: "unexport", Name: "unexport",
Usage: "Unexport/Remove a program's desktop entry", Usage: "Unexport/Remove a program's desktop entry",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
Name: "update", Name: "update",
Usage: "Update the list of available packages", Usage: "Update the list of available packages",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
{ {
@ -207,7 +200,7 @@ func main() {
Usage: "Upgrade the system by installing/upgrading available packages", Usage: "Upgrade the system by installing/upgrading available packages",
Action: func(cCtx *cli.Context) error { Action: func(cCtx *cli.Context) error {
cCtx.Args().Tail() cCtx.Args().Tail()
return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) return loader.ProcessCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice())
}, },
}, },
}, },
@ -219,67 +212,3 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
} }
func processCommand(command string, osType OSType, containerName string, packageName []string) error {
var err error
if osType == Arch && containerName != "" {
containerName = "--name " + containerName
} else {
containerName = ""
}
commandToExecute, err := getCommand(command, osType, containerName, packageName)
cmd := exec.Command("/bin/sh", "-c", commandToExecute)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
err = cmd.Run()
if err != nil {
return err
}
return nil
}
func getCommand(command string, osType OSType, containerName string, packageName []string) (string, error) {
switch osType {
case Arch:
cmd, ok := arch.Commands[command]
if ok {
return fmt.Sprintf("%s %s %s %s", arch.PackageManager, cmd, containerName, strings.Join(packageName, " ")), nil
} else {
return "", fmt.Errorf("%s: is not a valid command for Arch", command)
}
case Fedora:
cmd, ok := fedora.Commands[command]
if ok {
return fmt.Sprintf("%s %s %s %s", fedora.PackageManager, cmd, containerName, strings.Join(packageName, " ")), nil
} else {
return "", fmt.Errorf("%s: is not a valid command for Fedora", command)
}
case Flatpak:
cmd, ok := flatpak.Commands[command]
if ok {
return fmt.Sprintf("%s %s %s", flatpak.PackageManager, cmd, strings.Join(packageName, " ")), nil
} else {
return "", fmt.Errorf("%s: is not a valid command for Flatpak", command)
}
case Alpine:
cmd, ok := alpine.Commands[command]
if ok {
return fmt.Sprintf("%s %s %s %s", alpine.PackageManager, cmd, containerName, strings.Join(packageName, " ")), nil
} else {
return "", fmt.Errorf("%s: is not a valid command for Alpine", command)
}
case Ubuntu:
cmd, ok := ubuntu.Commands[command]
if ok {
return fmt.Sprintf("%s %s %s", ubuntu.PackageManager, cmd, strings.Join(packageName, " ")), nil
} else {
return "", fmt.Errorf("%s: is not a valid command for Ubuntu", command)
}
}
return "", fmt.Errorf("%s: was passed without a valid backend", command)
}