aboutsummaryrefslogtreecommitdiff
path: root/cmd/slackware.com/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/slackware.com/main.go')
-rw-r--r--cmd/slackware.com/main.go271
1 files changed, 271 insertions, 0 deletions
diff --git a/cmd/slackware.com/main.go b/cmd/slackware.com/main.go
new file mode 100644
index 0000000..54f171a
--- /dev/null
+++ b/cmd/slackware.com/main.go
@@ -0,0 +1,271 @@
+package main
+
+import (
+ "errors"
+ "fmt"
+ "net/url"
+ "os"
+ "path"
+ "slackware_com/internal/slackware_com"
+ "sort"
+ "strconv"
+
+ "github.com/pborman/getopt/v2"
+ "golang.org/x/exp/maps"
+)
+
+type Flags struct {
+ // local directory for downloads
+ Quiet bool
+ // remote root slackware package location
+ SlackwareMirror string
+}
+
+var DefaultFlags = Flags{
+ Quiet: false,
+ SlackwareMirror: "https://mirrors.kernel.org/slackware/slackware64-15.0",
+}
+
+func applyEnvVars(flags *Flags) error {
+ var err error
+ if v, ok := os.LookupEnv("QUIET"); ok {
+ flags.Quiet, err = strconv.ParseBool(v)
+ }
+ if v, ok := os.LookupEnv("SLACKWARE_MIRROR"); ok {
+ flags.SlackwareMirror = v
+ }
+
+ return err
+}
+
+func applyCommandFlags(flags *Flags) {
+ getopt.FlagLong(&flags.Quiet, "quiet", 0, "be quiet")
+ getopt.FlagLong(&flags.SlackwareMirror, "slackware-mirror", 0, "/")
+ getopt.Parse()
+}
+
+func ParseFlags() *Flags {
+ flags := DefaultFlags
+
+ applyEnvVars(&flags)
+ applyCommandFlags(&flags)
+
+ return &flags
+}
+
+type SubCommand struct {
+ Description string
+ Command func(globalOpts *Flags, args []string) error
+}
+
+func Unimplemented(globalOpts *Flags, args []string) error {
+ return errors.New("not implemented")
+}
+
+var subcommands = map[string]SubCommand{
+ "changelog": {
+ Description: "show changes described in the Changelog since the last update",
+ Command: func(globalOpts *Flags, args []string) error {
+ mirrorUrl, err := url.Parse(globalOpts.SlackwareMirror)
+ if err != nil {
+ return err
+ }
+
+ mirror, err := slackware_com.OpenMirror(mirrorUrl)
+ if err != nil {
+ return err
+ }
+
+ registry, err := slackware_com.NewPackageStore(slackware_com.PkgToolsPath)
+ if err != nil {
+ return err
+ }
+ installed, err := registry.GetInstalledPackages()
+ if err != nil {
+ return err
+ }
+
+ lastInstall := slackware_com.GetLastInstallTime(
+ mirror.ChangeLog,
+ installed,
+ mirror.Checksums.Files(),
+ )
+
+ firstEntry := true
+ for _, entry := range mirror.ChangeLog.Entries {
+ if !entry.Time.After(lastInstall) {
+ continue
+ }
+
+ if !firstEntry {
+ fmt.Println(slackware_com.Break)
+ firstEntry = false
+ }
+ fmt.Println(entry.String())
+ }
+
+ return nil
+ },
+ },
+ "download": {
+ Description: "download the given packages",
+ Command: func(globalOpts *Flags, args []string) error {
+ if len(args) <= 0 {
+ return errors.New("not enough arguments")
+ }
+
+ mirrorUrl, err := url.Parse(globalOpts.SlackwareMirror)
+ if err != nil {
+ return err
+ }
+
+ mirror, err := slackware_com.OpenMirror(mirrorUrl)
+ if err != nil {
+ return err
+ }
+
+ var pkgPaths []string
+ for _, pattern := range args {
+ pkgPath, ok := mirror.FindPackage(slackware_com.PackageNamePattern(pattern))
+ if !ok {
+ return fmt.Errorf("could not find '%s' at '%s'", pattern, mirrorUrl.String())
+ }
+
+ pkgPaths = append(pkgPaths, pkgPath)
+ }
+
+ for _, pkgPath := range pkgPaths {
+ fileName := path.Base(pkgPath)
+
+ tempFileName := fmt.Sprintf("%s.part", fileName)
+ f, err := os.Create(tempFileName)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ err = mirror.DownloadAndVerify(f, pkgPath)
+ if err != nil {
+ return fmt.Errorf("downloading '%s': %w", pkgPath, err)
+ }
+
+ err = os.Rename(tempFileName, fileName)
+ if err != nil {
+ return err
+ }
+ fmt.Println(fileName)
+ }
+
+ return nil
+ },
+ },
+ "list": {
+ Description: "list Slackware mirrors",
+ Command: Unimplemented,
+ },
+ "sync": {
+ Description: "update knowledge about mirror's content",
+ Command: Unimplemented,
+ },
+ "updates": {
+ Description: "print all new and updated packages on mirror",
+ Command: func(globalOpts *Flags, args []string) error {
+ mirrorUrl, err := url.Parse(globalOpts.SlackwareMirror)
+ if err != nil {
+ return err
+ }
+
+ mirror, err := slackware_com.OpenMirror(mirrorUrl)
+ if err != nil {
+ return err
+ }
+
+ registry, err := slackware_com.NewPackageStore(slackware_com.PkgToolsPath)
+ if err != nil {
+ return err
+ }
+
+ installed, err := registry.GetInstalledPackages()
+ if err != nil {
+ return err
+ }
+
+ isInstalled := make(map[string]bool)
+ for _, pkg := range installed {
+ isInstalled[pkg.Application] = true
+ }
+
+ lastInstall := slackware_com.GetLastInstallTime(
+ mirror.ChangeLog,
+ installed,
+ mirror.Checksums.Files(),
+ )
+
+ var packages []slackware_com.PackageName
+ for _, entry := range mirror.ChangeLog.Entries {
+ if !entry.Time.After(lastInstall) {
+ continue
+ }
+
+ for _, item := range entry.Items {
+ pathUpdate, ok := item.(slackware_com.PathUpdate)
+ if !ok {
+ continue
+ }
+
+ // TODO: fix me
+ pkg, err := slackware_com.NewPackageNameFromPath(pathUpdate.GetPath())
+ if err != nil {
+ continue
+ }
+ if !isInstalled[pkg.Application] {
+ continue
+ }
+
+ packages = append(packages, pkg)
+ }
+ }
+
+ for _, pkg := range packages {
+ fmt.Println(pkg.AppplicationVersion())
+ }
+
+ return err
+ },
+ },
+}
+
+func printHelp(commands map[string]SubCommand) {
+ fmt.Printf("%s is an unofficial command line interface to Slackware's website.\n", os.Args[0])
+ fmt.Println()
+ fmt.Println("The commands are:")
+ fmt.Println()
+ cmdNames := maps.Keys(commands)
+ sort.Strings(cmdNames)
+ for _, name := range cmdNames {
+ fmt.Printf("\t%s\n", name)
+ fmt.Printf("\t\t - %s\n", subcommands[name].Description)
+ }
+}
+
+func main() {
+ userCommand := ""
+ args := os.Args
+ if len(args) > 1 {
+ userCommand = os.Args[1]
+ args = args[2:]
+ }
+
+ cmd, ok := subcommands[userCommand]
+ if !ok {
+ printHelp(subcommands)
+ os.Exit(-1)
+ }
+
+ flags := ParseFlags()
+ err := cmd.Command(flags, args)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s\n", err)
+ os.Exit(-1)
+ }
+}