From abcc91ecb92a32a09f0b2c14a5faceedde92e001 Mon Sep 17 00:00:00 2001 From: ferrreo Date: Wed, 18 Jan 2023 17:42:08 +0000 Subject: [PATCH] Initial version --- .gitignore | 1 + alpine/commands.go | 21 ++++ arch/commands.go | 21 ++++ fedora/commands.go | 21 ++++ flatpak/commands.go | 15 +++ go.mod | 11 ++ go.sum | 8 ++ main.go | 285 ++++++++++++++++++++++++++++++++++++++++++++ ubuntu/commands.go | 16 +++ 9 files changed, 399 insertions(+) create mode 100644 alpine/commands.go create mode 100644 arch/commands.go create mode 100644 fedora/commands.go create mode 100644 flatpak/commands.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 ubuntu/commands.go diff --git a/.gitignore b/.gitignore index 66fd13c..d1baad6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ # Dependency directories (remove the comment below to include it) # vendor/ +.idea \ No newline at end of file diff --git a/alpine/commands.go b/alpine/commands.go new file mode 100644 index 0000000..7db693a --- /dev/null +++ b/alpine/commands.go @@ -0,0 +1,21 @@ +package alpine + +var PackageManager = "apx " + +var Commands = map[string]string{ + "autoremove": "--apk autoremove", + "clean": "--apk clean", + "export": "--apk export", + "init": "--apk init", + "install": "--apk install", + "list": "--apk list", + "log": "--apk log", + "purge": "--apk purge", + "run": "--apk run", + "remove": "--apk remove", + "enter": "--apk enter", + "search": "--apk search", + "show": "--apk show", + "update": "--apk update", + "upgrade": "--apk upgrade", +} diff --git a/arch/commands.go b/arch/commands.go new file mode 100644 index 0000000..087972b --- /dev/null +++ b/arch/commands.go @@ -0,0 +1,21 @@ +package arch + +var PackageManager = "apx " + +var Commands = map[string]string{ + "autoremove": "--aur autoremove", + "clean": "--aur clean", + "export": "--aur export", + "init": "--aur init", + "install": "--aur install", + "list": "--aur list", + "log": "--aur log", + "purge": "--aur purge", + "run": "--aur run", + "remove": "--aur remove", + "enter": "--aur enter", + "search": "--aur search", + "show": "--aur show", + "update": "--aur update", + "upgrade": "--aur upgrade", +} diff --git a/fedora/commands.go b/fedora/commands.go new file mode 100644 index 0000000..d1a7042 --- /dev/null +++ b/fedora/commands.go @@ -0,0 +1,21 @@ +package fedora + +var PackageManager = "apx " + +var Commands = map[string]string{ + "autoremove": "--dnf autoremove", + "clean": "--dnf clean", + "export": "--dnf export", + "init": "--dnf init", + "install": "--dnf install", + "list": "--dnf list", + "log": "--dnf log", + "purge": "--dnf purge", + "run": "--dnf run", + "remove": "--dnf remove", + "enter": "--dnf enter", + "search": "--dnf search", + "show": "--dnf show", + "update": "--dnf update", + "upgrade": "--dnf upgrade", +} diff --git a/flatpak/commands.go b/flatpak/commands.go new file mode 100644 index 0000000..445bc98 --- /dev/null +++ b/flatpak/commands.go @@ -0,0 +1,15 @@ +package flatpak + +var PackageManager = "flatpak " + +var Commands = map[string]string{ + "install": "install", + "list": "list", + "log": "history", + "run": "run", + "remove": "uninstall", + "enter": "enter", + "search": "search", + "show": "info", + "update": "update", +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d2f2436 --- /dev/null +++ b/go.mod @@ -0,0 +1,11 @@ +module pikman + +go 1.19 + +require github.com/urfave/cli/v2 v2.23.7 + +require ( + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..0b6ea42 --- /dev/null +++ b/go.sum @@ -0,0 +1,8 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY= +github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= diff --git a/main.go b/main.go new file mode 100644 index 0000000..e6460a1 --- /dev/null +++ b/main.go @@ -0,0 +1,285 @@ +package main + +import ( + "fmt" + "github.com/urfave/cli/v2" + "log" + "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 main() { + + osType := Ubuntu + containerName := "" + + cli.VersionFlag = &cli.BoolFlag{ + Name: "version", + Aliases: []string{"v"}, + Usage: "Version number", + } + + app := &cli.App{ + Name: "pikman", + Usage: "One package manager to rule them all", + Version: "v0.11", + EnableBashCompletion: true, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "arch", + Aliases: []string{"aur"}, + Usage: "Install Arch packages (including from the AUR)", + Action: func(cCtx *cli.Context, b bool) error { + if b { + osType = Arch + } + return nil + }, + }, + &cli.BoolFlag{ + Name: "fedora", + Aliases: []string{"dnf"}, + Usage: "Install Fedora packages", + Action: func(cCtx *cli.Context, b bool) error { + if b { + osType = Fedora + } + return nil + }, + }, + &cli.BoolFlag{ + Name: "alpine", + Aliases: []string{"apk"}, + Usage: "Install Alpine packages", + Action: func(cCtx *cli.Context, b bool) error { + if b { + osType = Alpine + } + return nil + }, + }, + &cli.BoolFlag{ + Name: "flatpak", + Aliases: []string{"fl"}, + Usage: "Install Flatpak packages", + Action: func(cCtx *cli.Context, b bool) error { + if b { + osType = Flatpak + } + return nil + }, + }, + &cli.StringFlag{ + Name: "name", + Usage: "Name of the managed container", + Destination: &containerName, + }, + }, + Commands: []*cli.Command{ + { + Name: "autoremove", + Usage: "Remove all unused packages", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "clean", + Aliases: []string{"cl"}, + Usage: "Clean the package manager cache", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "enter", + Usage: "Enter the container instance for select package manager", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "export", + Usage: "Export/Recreate a program's desktop entry from the container", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "init", + Usage: "Initialize a managed container", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "install", + Aliases: []string{"i"}, + Usage: "Install the specified package(s)", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "list", + Aliases: []string{"l"}, + Usage: "List installed packages", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "log", + Usage: "Show package manager logs", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "purge", + Usage: "Fully purge a package", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "run", + Usage: "Run a command inside a managed container", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "remove", + Aliases: []string{"r"}, + Usage: "Remove an installed package", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "search", + Aliases: []string{"s"}, + Usage: "Search for a package", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "show", + Usage: "Show details for a package", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "unexport", + Usage: "Unexport/Remove a program's desktop entry", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "update", + Usage: "Update the list of available packages", + Action: func(cCtx *cli.Context) error { + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + { + Name: "upgrade", + Usage: "Upgrade the system by installing/upgrading available packages", + Action: func(cCtx *cli.Context) error { + cCtx.Args().Tail() + return processCommand(cCtx.Command.FullName(), osType, containerName, cCtx.Args().Slice()) + }, + }, + }, + } + + app.Suggest = true + + if err := app.Run(os.Args); err != nil { + 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 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 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 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 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 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) +} diff --git a/ubuntu/commands.go b/ubuntu/commands.go new file mode 100644 index 0000000..dbf2cf0 --- /dev/null +++ b/ubuntu/commands.go @@ -0,0 +1,16 @@ +package ubuntu + +var PackageManager = "sudo -S apt " + +var Commands = map[string]string{ + "autoremove": "autoremove", + "clean": "clean", + "install": "install", + "list": "list", + "purge": "purge", + "remove": "remove", + "search": "search", + "show": "show", + "update": "update", + "upgrade": "upgrade", +}