31
"github.com/go-git/go-git/v5"
32
"github.com/go-git/go-git/v5/plumbing/object"
33
"golang.org/x/exp/slices"
34
"plemya-x.ru/alr/internal/shutils/handlers"
35
"mvdan.cc/sh/v3/interp"
39
ErrNoPipe = errors.New("command requires data to be piped in")
40
ErrNoDetectManNum = errors.New("manual number cannot be detected from the filename")
44
var Helpers = handlers.ExecFuncs{
45
"install-binary": installHelperCmd("/usr/bin", 0o755),
46
"install-systemd-user": installHelperCmd("/usr/lib/systemd/user", 0o644),
47
"install-systemd": installHelperCmd("/usr/lib/systemd/system", 0o644),
48
"install-config": installHelperCmd("/etc", 0o644),
49
"install-license": installHelperCmd("/usr/share/licenses", 0o644),
50
"install-desktop": installHelperCmd("/usr/share/applications", 0o644),
51
"install-icon": installHelperCmd("/usr/share/pixmaps", 0o644),
52
"install-manual": installManualCmd,
53
"install-completion": installCompletionCmd,
54
"install-library": installLibraryCmd,
55
"git-version": gitVersionCmd,
60
var Restricted = handlers.ExecFuncs{
61
"git-version": gitVersionCmd,
64
func installHelperCmd(prefix string, perms os.FileMode) handlers.ExecFunc {
65
return func(hc interp.HandlerContext, cmd string, args []string) error {
67
return handlers.InsufficientArgsError(cmd, 1, len(args))
70
from := resolvePath(hc, args[0])
73
to = filepath.Join(hc.Env.Get("pkgdir").Str, prefix, args[1])
75
to = filepath.Join(hc.Env.Get("pkgdir").Str, prefix, filepath.Base(from))
78
err := helperInstall(from, to, perms)
80
return fmt.Errorf("%s: %w", cmd, err)
86
func installManualCmd(hc interp.HandlerContext, cmd string, args []string) error {
88
return handlers.InsufficientArgsError(cmd, 1, len(args))
91
from := resolvePath(hc, args[0])
92
number := filepath.Base(from)
96
number = strings.TrimSuffix(number, ".gz")
97
number = strings.TrimPrefix(filepath.Ext(number), ".")
100
if _, err := strconv.Atoi(number); err != nil {
101
return fmt.Errorf("install-manual: %w", ErrNoDetectManNum)
104
prefix := "/usr/share/man/man" + number
105
to := filepath.Join(hc.Env.Get("pkgdir").Str, prefix, filepath.Base(from))
107
return helperInstall(from, to, 0o644)
110
func installCompletionCmd(hc interp.HandlerContext, cmd string, args []string) error {
113
if hc.Stdin == os.Stdin {
114
return fmt.Errorf("install-completion: %w", ErrNoPipe)
118
return handlers.InsufficientArgsError(cmd, 2, len(args))
127
prefix = "/usr/share/bash-completion/completions"
129
prefix = "/usr/share/zsh/site-functions"
132
prefix = "/usr/share/fish/vendor_completions.d"
136
path := filepath.Join(hc.Env.Get("pkgdir").Str, prefix, name)
138
err := os.MkdirAll(filepath.Dir(path), 0o755)
143
dst, err := os.OpenFile(path, os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0o644)
149
_, err = io.Copy(dst, hc.Stdin)
153
func installLibraryCmd(hc interp.HandlerContext, cmd string, args []string) error {
154
prefix := getLibPrefix(hc)
155
fn := installHelperCmd(prefix, 0o755)
156
return fn(hc, cmd, args)
160
var multiarchTupleMap = map[string]string{
161
"386": "i386-linux-gnu",
162
"amd64": "x86_64-linux-gnu",
163
"arm5": "arm-linux-gnueabi",
164
"arm6": "arm-linux-gnueabihf",
165
"arm7": "arm-linux-gnueabihf",
166
"arm64": "aarch64-linux-gnu",
167
"mips": "mips-linux-gnu",
168
"mipsle": "mipsel-linux-gnu",
169
"mips64": "mips64-linux-gnuabi64",
170
"mips64le": "mips64el-linux-gnuabi64",
171
"ppc64": "powerpc64-linux-gnu",
172
"ppc64le": "powerpc64le-linux-gnu",
173
"s390x": "s390x-linux-gnu",
174
"riscv64": "riscv64-linux-gnu",
175
"loong64": "loongarch64-linux-gnu",
180
var usrLibDistros = []string{
188
func getLibPrefix(hc interp.HandlerContext) string {
189
if dir, ok := os.LookupEnv("ALR_LIB_DIR"); ok {
195
distroID := hc.Env.Get("DISTRO_ID").Str
196
distroLike := strings.Split(hc.Env.Get("DISTRO_ID_LIKE").Str, " ")
198
for _, usrLibDistro := range usrLibDistros {
199
if distroID == usrLibDistro || slices.Contains(distroLike, usrLibDistro) {
204
wordSize := unsafe.Sizeof(uintptr(0))
209
architecture := hc.Env.Get("ARCH").Str
211
if distroID == "debian" || slices.Contains(distroLike, "debian") ||
212
distroID == "ubuntu" || slices.Contains(distroLike, "ubuntu") {
214
tuple, ok := multiarchTupleMap[architecture]
216
out = filepath.Join("/usr/lib", tuple)
223
func gitVersionCmd(hc interp.HandlerContext, cmd string, args []string) error {
226
path = resolvePath(hc, args[0])
229
r, err := git.PlainOpen(path)
231
return fmt.Errorf("git-version: %w", err)
235
commits, err := r.Log(&git.LogOptions{})
237
return fmt.Errorf("git-version: %w", err)
240
commits.ForEach(func(*object.Commit) error {
245
HEAD, err := r.Head()
247
return fmt.Errorf("git-version: %w", err)
250
hash := HEAD.Hash().String()
252
fmt.Fprintf(hc.Stdout, "%d.%s\n", revNum, hash[:7])
257
func helperInstall(from, to string, perms os.FileMode) error {
258
err := os.MkdirAll(filepath.Dir(to), 0o755)
263
src, err := os.Open(from)
269
dst, err := os.OpenFile(to, os.O_TRUNC|os.O_CREATE|os.O_RDWR, perms)
275
_, err = io.Copy(dst, src)
279
func resolvePath(hc interp.HandlerContext, path string) string {
280
if !filepath.IsAbs(path) {
281
return filepath.Join(hc.Dir, path)