diff options
| author | huker667 <huker@tuta.io> | 2026-07-15 14:33:08 +0300 |
|---|---|---|
| committer | huker667 <huker@tuta.io> | 2026-07-15 14:33:08 +0300 |
| commit | 22359129afeef78e0fcd56e62586819c06950846 (patch) | |
| tree | ac83fef674adb3e5527b9e5ee53246d43fb8be1b /package | |
| parent | d64b4f39839e112d096b9809fdb35e873a1b40fd (diff) | |
| download | qulay-22359129afeef78e0fcd56e62586819c06950846.tar.gz qulay-22359129afeef78e0fcd56e62586819c06950846.tar.bz2 qulay-22359129afeef78e0fcd56e62586819c06950846.zip | |
init commit da
Diffstat (limited to 'package')
| -rw-r--r-- | package/package.go | 255 |
1 files changed, 233 insertions, 22 deletions
diff --git a/package/package.go b/package/package.go index 826b2ad..79d6e04 100644 --- a/package/package.go +++ b/package/package.go @@ -16,11 +16,19 @@ import ( "qulay/database" "qulay/helpers" + "net/http" + "time" + "io" + "context" + + "github.com/codeclysm/extract/v3" "codeberg.org/UzbekLinux/uzbekdb-go" ) var _name string = filepath.Base(os.Args[0]) +var installing = map[string]bool{} + type Package struct { Name string Repo string @@ -34,28 +42,36 @@ func randomTempDir(destDir string) string { return tempDirPath } -func readDepends(path string) []string { - dependsPath := filepath.Join(path, "depends") - dependsPath2 := filepath.Join(path, "depends.uz") - f, err := os.Open(dependsPath) +func readPackage(path string) ([]string, string, string, string, string) { + pkgPath := filepath.Join(path, "pkg") + + f, err := os.Open(pkgPath) if err != nil { - f, err = os.Open(dependsPath2) - if err != nil { - return []string{} - } + return []string{}, "", "", "", "" } defer f.Close() var depends []string + var taip = "" + var url = "" + var afterScript = "" + var removeScript = "" + scanner := bufio.NewScanner(f) for scanner.Scan() { - depends = append(depends, scanner.Text()) + line := scanner.Text() + if strings.HasPrefix(line, "deps: ") { + depends = append(depends, strings.Fields(strings.TrimPrefix(line, "deps: "))...) + } else if strings.HasPrefix(line, "type: ") { + taip = strings.TrimPrefix(line, "type: ") + } else if strings.HasPrefix(line, "url: ") { + url = strings.TrimPrefix(line, "url: ") + } else if strings.HasPrefix(line, "after: ") { + afterScript = strings.TrimPrefix(line, "after: ") + } else if strings.HasPrefix(line, "remove: ") { + removeScript = strings.TrimPrefix(line, "remove: ") + } } - return depends -} - -func isNewFormat(path string) bool { - _, err := os.Stat(filepath.Join(path, "data")) - return !os.IsNotExist(err) + return depends, taip, url, afterScript, removeScript } func GetPackages(destDir string) []Package { @@ -157,13 +173,24 @@ func Install(name string, args []string, destDir string) error { } pkgPath := filepath.Join(destDir, paths.ReposDir, pkg.Repo, "packages", pkg.Name) - depends := readDepends(pkgPath) + depends, taip, url, afterScript, _ := readPackage(pkgPath) + + key := pkg.Repo + "/" + pkg.Name + + if installing[key] { + return nil + } + installing[key] = true + defer func() { + installing[key] = false + }() + if !disableDeps { if len(depends) != 0 { - fmt.Println(helpers.ToString(len(depends)) + " depends for " + pkg.Repo + "/" + pkg.Name + ":") + fmt.Println(helpers.ToString(len(depends)) + " deps for " + pkg.Repo + "/" + pkg.Name + ":") for i, n := range depends { if n == pkg.Name || n == pkg.Repo+"/"+pkg.Name { - return errors.New("broken depends in package " + n) + return errors.New("broken deps in package " + n) } depPkgs := FindPackages(n, destDir) @@ -176,11 +203,13 @@ func Install(name string, args []string, destDir string) error { } } } + if slices.Contains(args, ":a") { if !helpers.Ask("install " + pkg.Repo + "/" + pkg.Name + " with version " + helpers.ToString(pkg.Data[1])) { return errors.New("canceled by user") } } + if !disableDeps { for _, dep := range depends { depPkg, err := getPackage(dep, destDir) @@ -199,7 +228,107 @@ func Install(name string, args []string, destDir string) error { } } - if !isNewFormat(pkgPath) { + fmt.Println(":: installing " + pkg.Name + " from repo " + pkg.Repo) + + if taip == "arch" { + destArchivePath := filepath.Join(destDir, "tmp", pkg.Name + pkg.Repo + ".tar.zst") + fullDestPath := filepath.Join(pkgPath, "arch") + + os.MkdirAll(fullDestPath, 0755) + os.MkdirAll(filepath.Dir(destArchivePath), 0755) + + client := &http.Client{ + Timeout: 10 * time.Second, + } + + resp, err := client.Get(url) + if err != nil { + fmt.Println("!! failed to download", url, err) + return err + } + defer resp.Body.Close() + + f, err := os.Create(destArchivePath) + if err != nil { + fmt.Println("!! failed to create file", err) + return err + } + defer f.Close() + + _, err = io.Copy(f, resp.Body) + f.Close() + if err != nil { + fmt.Println("!! failed to copy", err) + return err + } + + fmt.Println(":: downloaded", url, "to", destArchivePath) + + _ = os.RemoveAll(fullDestPath) + + file, err := os.Open(destArchivePath) + if err != nil { + fmt.Println("!! failed to open archive file", destArchivePath, err) + return err + } + + defer file.Close() + + err = extract.Zstd(context.TODO(), file, fullDestPath, nil) + if err != nil { + fmt.Println("!! failed to extract", err) + return err + } + + fmt.Println(":: removing govnofiles from package...") + + _ = os.Remove(filepath.Join(fullDestPath, ".BUILDINFO")) + _ = os.Remove(filepath.Join(fullDestPath, ".MTREE")) + _ = os.Remove(filepath.Join(fullDestPath, ".PKGINFO")) + _ = os.Remove(filepath.Join(fullDestPath, ".INSTALL")) + + fmt.Println(":: copying files to / ...") + + err = helpers.CopyDir(fullDestPath, filepath.Join(destDir, "/")) + if err != nil { + fmt.Println("!! failed to copy files to /:", err) + } else { + fmt.Println(":: successfully copied to /") + } + + outputFilePath := filepath.Join(pkgPath, "files") + outputFile, err := os.Create(outputFilePath) + if err != nil { + fmt.Println("!! failed to create files list:", err) + return err + } + defer outputFile.Close() + + err = filepath.WalkDir(fullDestPath, func(path string, d os.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + return nil + } + + relPath, err := filepath.Rel(fullDestPath, path) + if err != nil { + return err + } + + formattedPath := "/" + filepath.ToSlash(relPath) + + _, err = outputFile.WriteString(formattedPath + "\n") + return err + }) + + if err != nil { + fmt.Println("!! failed to index files:", err) + return err + } + } else if taip == "script" { cmd := exec.Command("sh", "install.sh") cmd.Dir = pkgPath cmd.Env = append(os.Environ(), "DESTDIR="+destDir) @@ -209,6 +338,49 @@ func Install(name string, args []string, destDir string) error { if err != nil { return err } + } else if taip == "binary" { + client := &http.Client{ + Timeout: 10 * time.Second, + } + + resp, err := client.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + + outPath := filepath.Join(destDir, "/usr/bin", pkg.Name) + + f, err := os.Create(outPath) + if err != nil { + return err + } + + _, err = io.Copy(f, resp.Body) + f.Close() + if err != nil { + return err + } + + err = os.Chmod(outPath, 0755) + if err != nil { + return err + } + } else { + return errors.New("package err maybe old format") + } + + if afterScript != "" { + fmt.Println(":: running after installation script " + afterScript + " ...") + cmd := exec.Command("sh", afterScript) + cmd.Dir = pkgPath + cmd.Env = append(os.Environ(), "DESTDIR="+destDir) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Run() + if err != nil { + return err + } } err = database.RegPackage(pkg.Repo+"/"+pkg.Name, helpers.ToString(pkg.Data[1]), destDir) @@ -234,18 +406,57 @@ func Remove(name string, args []string, destDir string) error { pkgPath := filepath.Join(destDir, paths.ReposDir, pkg.Repo, "packages", pkg.Name) - if !isNewFormat(pkgPath) { - cmd := exec.Command("sh", "remove.sh") + _, _, _, _, removeScript := readPackage(pkgPath) + + if removeScript != "" { + fmt.Println(":: running remove script " + removeScript + " ...") + cmd := exec.Command("sh", removeScript) cmd.Dir = pkgPath cmd.Env = os.Environ() cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - err := cmd.Run() + err = cmd.Run() if err != nil { return err } } + if _, err := os.Stat("files"); err == nil { + f, _ := os.Open("files") + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + file := scanner.Text() + + if file == "" { + continue + } + + path := filepath.Join(destDir, file) + + if _, err := os.Stat(path); err == nil { + fmt.Printf("removing %s\n", path) + + if err := os.RemoveAll(path); err != nil { + fmt.Fprintf(os.Stderr, "failed to remove %s: %v\n", path, err) + } + } else if !os.IsNotExist(err) { + fmt.Fprintf(os.Stderr, "failed to stat %s: %v\n", path, err) + } + } + + if err := scanner.Err(); err != nil { + fmt.Fprintf(os.Stderr, "failed to read files: %v\n", err) + } + } + + if removeScript == "" { + if _, err := os.Stat("files"); os.IsNotExist(err) { + return errors.New("failed to remove package file (no remove script and paths file)") + } + } + err = database.UnRegPackage(pkg.Repo+"/"+pkg.Name, destDir) if err != nil { return err |