package database import ( "fmt" "os" // "archive/tar" "bufio" "context" "net/http" "path" "path/filepath" "sync" "time" // "net/url" "io" "strings" "qulay/config" "codeberg.org/UzbekLinux/uzbekdb-go" "github.com/codeclysm/extract/v3" // "github.com/klauspost/compress/zstd" ) var _name string = filepath.Base(os.Args[0]) func GetReposUrls(destDir string) []string { f, err := os.Open(filepath.Join(destDir, paths.ReposUrlsFile)) if err != nil { return []string{} } defer f.Close() var urls []string scanner := bufio.NewScanner(f) for scanner.Scan() { urls = append(urls, scanner.Text()) } return urls } func DownloadRepos(urls []string, destDir string) { var wg sync.WaitGroup var links []string for _, link := range urls { link = strings.TrimSpace(link) if link == "" { continue } links = append(links, link) } wg.Add(len(links)) for _, link := range links { go func(link string) { defer wg.Done() archiveName := path.Base(link) repoName := strings.TrimSuffix(archiveName, ".tar.zst") destArchivePath := filepath.Join(destDir, "tmp", archiveName) destNArchivePath := filepath.Join(destDir, "tmp") destPath := filepath.Join(destDir, paths.ReposDir) fullDestPath := filepath.Join(destDir, paths.ReposDir, repoName) os.MkdirAll(destNArchivePath, 0755) client := &http.Client{ Timeout: 10 * time.Second, } resp, err := client.Get(link) if err != nil { fmt.Println("!! failed to download", link, err) return } defer resp.Body.Close() f, err := os.Create(destArchivePath) if err != nil { fmt.Println("!! failed to create file", err) return } defer f.Close() _, err = io.Copy(f, resp.Body) if err != nil { fmt.Println("!! failed to copy", err) return } fmt.Println(":: downloaded", archiveName, "to", destArchivePath) err = os.RemoveAll(fullDestPath) fmt.Println(":: removing old repo", fullDestPath) if err != nil { fmt.Println("w! failed to delete old repo", fullDestPath, err) } file, err := os.Open(destArchivePath) if err != nil { fmt.Println("!! failed to open archive file", destArchivePath, err) return } err = extract.Zstd(context.TODO(), file, destPath, nil) if err != nil { fmt.Println("!! failed to extract", err) return } }(link) } wg.Wait() fmt.Println(":: repo updating ended") } func ReadInstalled(destDir string) map[interface{}][]interface{} { installedFullPath := filepath.Join(destDir, paths.InstalledFile) file, err := os.OpenFile(installedFullPath, os.O_RDONLY, 0644) if err != nil { return map[interface{}][]interface{}{} } defer file.Close() text, err := io.ReadAll(file) if err != nil { return map[interface{}][]interface{}{} } data := uzbekdb.Loads(string(text), "map") if data == nil { return map[interface{}][]interface{}{} } return data.(map[interface{}][]interface{}) } func WriteInstalled(data map[interface{}][]interface{}, destDir string) error { installedFullPath := filepath.Join(destDir, paths.InstalledFile) file, err := os.OpenFile(installedFullPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { return err } defer file.Close() _, err = file.WriteString(uzbekdb.Dumps(data)) return err } func IsInstalled(name string, destDir string) bool { data := ReadInstalled(destDir) if !strings.Contains(name, "/") { return false } _, ok := data[name] return ok } func GetPackageVersion(name string, destDir string) string { data := ReadInstalled(destDir) alo, _ := data[name] if len(alo) > 0 { return alo[0].(string) } else { return "" } } func RegPackage(name string, version string, destDir string) error { data := ReadInstalled(destDir) val, installed := data[name] if installed && len(val) > 0 { currentVersion := fmt.Sprintf("%v", val[0]) if currentVersion != version { data[name][0] = version } } else { data[name] = []interface{}{version} } return WriteInstalled(data, destDir) } func UnRegPackage(name string, destDir string) error { data := ReadInstalled(destDir) _, ok := data[name] if !ok { return fmt.Errorf("cant unregister '%s': package is not installed", name) } delete(data, name) return WriteInstalled(data, destDir) } func PurgeRepository(name string, destDir string) error { dirPath := filepath.Join(destDir, paths.ReposDir, name) err := os.RemoveAll(dirPath) if err != nil { return err } return nil } // func Ensure(args, destDir) error { // // }