diff --git a/download/download.go b/download/download.go index 3d7edbf..d9d9c09 100644 --- a/download/download.go +++ b/download/download.go @@ -227,6 +227,11 @@ func extractFile(ctx context.Context, input io.Reader, hash hash.Hash, format ar return err } defer fr.Close() + fi, err := f.Stat() + if err != nil { + return err + } + fm := fi.Mode() path := filepath.Join(opts.Destination, f.NameInArchive) @@ -241,7 +246,7 @@ func extractFile(ctx context.Context, input io.Reader, hash hash.Hash, format ar return err } } else { - outFl, err := os.Create(path) + outFl, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fm.Perm()) if err != nil { return err } diff --git a/helpers.go b/helpers.go index 02a6f6a..13c8f7d 100644 --- a/helpers.go +++ b/helpers.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "io" "os" @@ -10,6 +11,8 @@ import ( "mvdan.cc/sh/v3/interp" ) +var ErrNoPipe = errors.New("command requires data to be piped in") + var helpers = shutils.ExecFuncs{ "install-binary": installHelperCmd("/usr/bin", 0o755), "install-systemd-user": installHelperCmd("/usr/lib/systemd/user", 0o644), @@ -18,6 +21,7 @@ var helpers = shutils.ExecFuncs{ "install-license": installHelperCmd("/usr/share/licenses", 0o644), "install-manual": installHelperCmd("/usr/share/man/man1", 0o644), "install-desktop": installHelperCmd("/usr/share/applications", 0o644), + "install-completion": installCompletionCmd, } func installHelperCmd(prefix string, perms os.FileMode) shutils.ExecFunc { @@ -42,6 +46,49 @@ func installHelperCmd(prefix string, perms os.FileMode) shutils.ExecFunc { } } +func installCompletionCmd(hc interp.HandlerContext, cmd string, args []string) error { + // If the command's stdin is the same as the system's, + // that means nothing was piped in. In this case, return an error. + if hc.Stdin == os.Stdin { + return fmt.Errorf("install-completion: %w", ErrNoPipe) + } + + if len(args) < 2 { + return shutils.InsufficientArgsError(cmd, 2, len(args)) + } + + shell := args[0] + name := args[1] + + var prefix string + switch shell { + case "bash": + prefix = "/usr/share/bash-completion/completion" + case "zsh": + prefix = "/usr/share/zsh/site-functions" + name = "_" + name + case "fish": + prefix = "/usr/share/fish/vendor_completions.d" + name += ".fish" + } + + path := filepath.Join(hc.Env.Get("pkgdir").Str, prefix, name) + + err := os.MkdirAll(filepath.Dir(path), 0o755) + if err != nil { + return err + } + + dst, err := os.OpenFile(path, os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0o644) + if err != nil { + return err + } + defer dst.Close() + + _, err = io.Copy(dst, hc.Stdin) + return err +} + func helperInstall(from, to string, perms os.FileMode) error { err := os.MkdirAll(filepath.Dir(to), 0o755) if err != nil {