summaryrefslogtreecommitdiff
path: root/main.go
blob: 6433ba334b7976bf1dd430b70fe9546f9ebab649 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
package main

import (
	"fmt"
	"os"
	"path/filepath"
	paths "qulay/config"
	"qulay/database"
	"qulay/helpers"
	pkg "qulay/package"
	"slices"
	"strings"
)

var _name string = filepath.Base(os.Args[0])
var _cmds = []string{"h", "+", "-", "g", "s", "p", "u", "r", "q", "f", "v", "b", "o"}

const _version string = "1.0"
const _help string = `{_name}: Qulay Package Manager
Usage:
    {_name} h       -> help menu
    {_name} + pkg   -> download and install package (or .qpmp file path)
    {_name} - pkg   -> remove package
    {_name} b pkg   -> build package into .tar.zst (or .qpmp on :qpmp)
    {_name} g pkg   -> get package version
    {_name} s pkg   -> search packages by name
    {_name} p repo  -> purge local repo directory
    {_name} u       -> update all repositories
    {_name} r       -> get all repositories configs
    {_name} o       -> upgrade all installed packages
    {_name} q       -> get all installed packages
    {_name} f       -> get files path for destDir
    {_name} v       -> get {_name} version
Options:
    :a    -> ask before doing
    :nl   -> disable recording in databases and logs
    :nd   -> do not download deps
    :r    -> reinstall already installed deps
    :f    -> force install (ignore conflicts)
    :qpmp -> build a .qpmp archive instead of .tar.zst
Tags (for +, - , b and o):
    @all        -> apply to all packages
    repo/@all   -> apply to all packages in repo
    @inst       -> apply to installed (for b: built) packages
    repo/@inst  -> apply to installed (for b: built) packages in repo
    @notinst    -> apply to not installed (for b: not built) packages
    repo/@notinst-> apply to not installed (for b: not built) packages in repo
    @old        -> apply to installed/built packages outdated by version
    repo/@old   -> apply to outdated packages in repo
    o without tags applies @old automatically
Vars:
    DESTDIR  -> path where the package will be installed/removed`

func parseArgs(args []string) ([]string, []string, []string) {
	var cmds, oths, opts []string
	for _, arg := range args {
		if strings.HasPrefix(arg, ":") {
			opts = append(opts, arg)
		} else if slices.Contains(_cmds, arg) && len(cmds) < 1 {
			cmds = append(cmds, arg)
		} else {
			oths = append(oths, arg)
		}
	}
	return cmds, oths, opts
}

func printHelp() {
	r := strings.NewReplacer("{_name}", _name)
	fmt.Println(r.Replace(_help))
}

func main() {
	var args []string = os.Args[1:]
	cmds, oths, opts := parseArgs(args)

	destDir := os.Getenv("DESTDIR")
	if destDir == "" {
		destDir = "/"
	}

	absDestDir, err := filepath.Abs(destDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "!! failed to get absolute path of destDir: %v\n", err)
		os.Exit(1)
	}

	if len(args) == 0 || len(cmds) == 0 {
		printHelp()
		os.Exit(1)
	}

	// fmt.Println(cmds, oths, opts)
	if cmds[0] == "h" {
		printHelp()
	} else if cmds[0] == "+" {
		if len(oths) < 1 {
			fmt.Println("!! no package(s) received")
			os.Exit(1)
		}
		names, err := pkg.Expand("+", oths, absDestDir)
		if err != nil {
			fmt.Println("!!", err)
			os.Exit(1)
		}
		for _, n := range names {
			err := pkg.Install(n, opts, absDestDir)
			if err != nil {
				fmt.Println("!!", err)
				os.Exit(1)
			}
		}
	} else if cmds[0] == "-" {
		if len(oths) < 1 {
			fmt.Println("!! no package(s) received")
			os.Exit(1)
		}
		names, err := pkg.Expand("-", oths, absDestDir)
		if err != nil {
			fmt.Println("!!", err)
			os.Exit(1)
		}
		for _, n := range names {
			err := pkg.Remove(n, opts, absDestDir)
			if err != nil {
				fmt.Println("!!", err)
				os.Exit(1)
			}
		}
	} else if cmds[0] == "u" {
		database.DownloadRepos(absDestDir)
	} else if cmds[0] == "b" {
		if len(oths) < 1 {
			fmt.Println("!! no package(s) received")
			os.Exit(1)
		}
		names, err := pkg.Expand("b", oths, absDestDir)
		if err != nil {
			fmt.Println("!!", err)
			os.Exit(1)
		}
		for _, n := range names {
			err := pkg.Build(n, opts, absDestDir)
			if err != nil {
				fmt.Println("!!", err)
				os.Exit(1)
			}
		}
	} else if cmds[0] == "g" {
		if len(oths) < 1 {
			fmt.Println("!! no package(s) received")
			os.Exit(1)
		}
		for _, name := range oths {
			fmt.Println(database.GetPackageVersion(name, absDestDir))
		}
	} else if cmds[0] == "r" {
		for _, repo := range database.GetRepos(absDestDir) {
			fmt.Println(repo.Name, "url:", repo.URL)
		}
	} else if cmds[0] == "o" {
		if len(oths) < 1 {
			oths = []string{"@old"}
		}
		names, err := pkg.Expand("o", oths, absDestDir)
		if err != nil {
			fmt.Println("!!", err)
			os.Exit(1)
		}
		err = pkg.Upgrade(names, opts, absDestDir)
		if err != nil {
			fmt.Println("!!", err)
			os.Exit(1)
		}
	} else if cmds[0] == "q" {
		for name, version := range database.ReadInstalled(absDestDir) {
			if len(version) > 0 {
				fmt.Println(name, "-", version[0])
			}
		}
	} else if cmds[0] == "s" {
		if len(oths) < 1 {
			pkgs := pkg.GetPackages(absDestDir)
			for _, p := range pkgs {
				if database.IsInstalled(p.Repo+"/"+p.Name, absDestDir) {
					fmt.Printf("[+] %s/%s - %v - %v\n", p.Repo, p.Name, p.Version, p.Desc)
				} else {
					fmt.Printf("    %s/%s - %v - %v\n", p.Repo, p.Name, p.Version, p.Desc)
				}
			}
		} else {
			for _, n := range oths {
				pkgs := pkg.FindPackages(n, absDestDir)
				for _, p := range pkgs {
					if database.IsInstalled(p.Repo+"/"+p.Name, absDestDir) {
						fmt.Printf("[+] %s/%s - %v - %v\n", p.Repo, p.Name, p.Version, p.Desc)
					} else {
						fmt.Printf("    %s/%s - %v - %v\n", p.Repo, p.Name, p.Version, p.Desc)
					}
				}
			}
		}
	} else if cmds[0] == "p" {
		if slices.Contains(opts, ":a") {
			if !helpers.Ask("do you want purge repo(s)?") {
				os.Exit(1)
			}
		}
		if len(oths) >= 1 {
			for _, n := range oths {
				err := database.PurgeRepository(n, absDestDir)
				if err != nil {
					fmt.Println("!!", err)
					os.Exit(1)
				} else {
					fmt.Println(":: deleted", n, "repository in", paths.ReposDir)
				}
			}
		}
	} else if cmds[0] == "f" {
		fmt.Printf("dest dir: %v\n", destDir)
		fmt.Printf("abs dest dir: %v\n", absDestDir)
		fmt.Printf("is abs: %v\n", filepath.IsAbs(destDir))
		fmt.Printf("repos config dir: %v\n", filepath.Join(absDestDir, paths.ReposConfigDir))
		fmt.Printf("repos dir: %v\n", filepath.Join(absDestDir, paths.ReposDir))
		fmt.Printf("installed pkgs database: %v\n", filepath.Join(absDestDir, paths.InstalledFile))
		fmt.Printf("built pkgs dir: %v\n", filepath.Join(absDestDir, paths.BuiltDir))
		fmt.Printf("build config file: %v\n", filepath.Join(absDestDir, paths.BuildConfigFile))
	} else if cmds[0] == "v" {
		fmt.Println(_version)
	} else {
		fmt.Println("w! unknown command:", cmds[0])
		printHelp()
		os.Exit(1)
	}
}