diff --git a/src/bpm-package/main.go b/src/bpm-package/main.go index 538f98d..fadfee0 100644 --- a/src/bpm-package/main.go +++ b/src/bpm-package/main.go @@ -2,6 +2,7 @@ package main import ( bpmutilsshared "bpm-utils-shared" + "bytes" "fmt" "io" "log" @@ -22,6 +23,7 @@ var skipCheck = flag.BoolP("skip-checks", "s", false, "Skip 'check' function whi var installDepends = flag.BoolP("depends", "d", false, "Install package dependencies for compilation") var installPackage = flag.BoolP("install", "i", false, "Install compiled BPM package after compilation finishes") var moveToBinaryDir = flag.BoolP("move", "m", false, "Move output packages to the current repository's binary directory") +var updateChecksums = flag.BoolP("update-checksums", "u", false, "Update the checksums for all download entries") var yesAll = flag.BoolP("yes", "y", false, "Accept all confirmation prompts") func main() { @@ -74,22 +76,47 @@ func createArchive() string { } } - // Read pkg.info file into basic struct - pkgInfo := struct { - Name string `yaml:"name"` - Version string `yaml:"version"` - Revision int `yaml:"revision"` - Arch string `yaml:"architecture"` - }{ - Revision: 1, - } - data, err := os.ReadFile("pkg.info") + // Read pkg.info file + pkgInfo, err := bpmutilsshared.ReadPacakgeInfoFromFile("pkg.info") if err != nil { - log.Fatalf("Error: could not read pkg.info file") + log.Fatalf("Error: could not read package info: %s", err) } - err = yaml.Unmarshal(data, &pkgInfo) - if err != nil { - log.Fatalf("Error: could not unmarshal pkg.info file") + + // Update checksums + if *updateChecksums { + for i, download := range pkgInfo.Downloads { + if download.Checksum == "skip" { + continue + } + + download.Checksum, err = download.CalculateChecksum(pkgInfo) + if err != nil { + log.Fatalf("Could not calculate checksum for download entry %d: %s", i+1, err) + } + + pkgInfo.Downloads[i] = download + } + + // Save yaml back to file + var data bytes.Buffer + encoder := yaml.NewEncoder(&data) + encoder.SetIndent(2) + encoder.Encode(pkgInfo) + if err != nil { + log.Fatalf("Could not marshal package info: %s", err) + } + + // Stat pkg.info + stat, err := os.Stat("pkg.info") + if err != nil { + log.Fatalf("Could not stat pkg.info: %s", err) + } + + // Write package info back to file + err = os.WriteFile("pkg.info", data.Bytes(), stat.Mode().Perm()) + if err != nil { + log.Fatalf("Could not write package info to pkg.info: %s", err) + } } // Remove old BPM archives in current directory diff --git a/src/bpm-utils-shared/package.go b/src/bpm-utils-shared/package.go index f7886fe..82f9469 100644 --- a/src/bpm-utils-shared/package.go +++ b/src/bpm-utils-shared/package.go @@ -1,29 +1,44 @@ package bpm_utils_shared import ( + "fmt" "os" "os/exec" + "strings" "gopkg.in/yaml.v3" ) type PackageInfo struct { - Name string `yaml:"name,omitempty"` - Description string `yaml:"description,omitempty"` - Version string `yaml:"version,omitempty"` - Revision int `yaml:"revision,omitempty"` - Url string `yaml:"url,omitempty"` - License string `yaml:"license,omitempty"` - Arch string `yaml:"architecture,omitempty"` - Type string `yaml:"type,omitempty"` - Keep []string `yaml:"keep,omitempty"` - Depends []string `yaml:"depends,omitempty"` - MakeDepends []string `yaml:"make_depends,omitempty"` - OptionalDepends []string `yaml:"optional_depends,omitempty"` - Conflicts []string `yaml:"conflicts,omitempty"` - Replaces []string `yaml:"replaces,omitempty"` - Provides []string `yaml:"provides,omitempty"` - SplitPackages []*PackageInfo `yaml:"split_packages,omitempty"` + Name string `yaml:"name"` + Description string `yaml:"description"` + Version string `yaml:"version"` + Revision int `yaml:"revision,omitempty"` + Url string `yaml:"url,omitempty"` + License string `yaml:"license,omitempty"` + Arch string `yaml:"architecture,omitempty"` + OutputArch string `yaml:"output_architecture,omitempty"` + Type string `yaml:"type,omitempty"` + Keep []string `yaml:"keep,omitempty"` + Depends []string `yaml:"depends,omitempty"` + OptionalDepends []string `yaml:"optional_depends,omitempty"` + MakeDepends []string `yaml:"make_depends,omitempty"` + Conflicts []string `yaml:"conflicts,omitempty"` + Replaces []string `yaml:"replaces,omitempty"` + Provides []string `yaml:"provides,omitempty"` + Downloads []PackageDownload `yaml:"downloads,omitempty"` + SplitPackages []*PackageInfo `yaml:"split_packages,omitempty"` +} + +type PackageDownload struct { + Url string `yaml:"url"` + Type string `yaml:"type,omitempty"` + NoExtract bool `yaml:"no_extract,omitempty"` + ExtractToBPMSource bool `yaml:"extract_to_bpm_source,omitempty"` + ExtractStripComponents int `yaml:"extract_strip_components,omitempty"` + GitBranch string `yaml:"git_branch,omitempty"` + Filepath string `yaml:"filepath,omitempty,omitempty"` + Checksum string `yaml:"checksum,omitempty"` } func ReadPacakgeInfo(path string) (*PackageInfo, error) { @@ -42,6 +57,7 @@ func ReadPacakgeInfo(path string) (*PackageInfo, error) { Url: "", License: "", Arch: "", + OutputArch: "", Type: "", Keep: make([]string, 0), Depends: make([]string, 0), @@ -50,6 +66,7 @@ func ReadPacakgeInfo(path string) (*PackageInfo, error) { Conflicts: make([]string, 0), Replaces: make([]string, 0), Provides: make([]string, 0), + Downloads: make([]PackageDownload, 0), SplitPackages: make([]*PackageInfo, 0), } @@ -77,14 +94,16 @@ func ReadPacakgeInfoFromFile(path string) (*PackageInfo, error) { Url: "", License: "", Arch: "", + OutputArch: "", Type: "", Keep: make([]string, 0), Depends: make([]string, 0), - MakeDepends: make([]string, 0), OptionalDepends: make([]string, 0), + MakeDepends: make([]string, 0), Conflicts: make([]string, 0), Replaces: make([]string, 0), Provides: make([]string, 0), + Downloads: make([]PackageDownload, 0), SplitPackages: make([]*PackageInfo, 0), } @@ -96,3 +115,64 @@ func ReadPacakgeInfoFromFile(path string) (*PackageInfo, error) { return pkgInfo, nil } + +func (pkgDownload *PackageDownload) CalculateChecksum(pkgInfo *PackageInfo) (string, error) { + switch pkgDownload.Type { + case "", "file": + fmt.Println("Downloading and calculating checksum for file...") + + // Replace variables in download url + downloadUrl := pkgDownload.Url + downloadUrl = os.Expand(downloadUrl, func(s string) string { + switch s { + case "BPM_PKG_VERSION": + return pkgInfo.Version + case "BPM_PKG_NAME": + return pkgInfo.Name + default: + return "" + } + }) + + cmd := exec.Command("sh", "-c", fmt.Sprintf("curl -s -L %s | sha256sum | awk '{print $1}'", downloadUrl)) + cmd.Stderr = os.Stderr + + checksum, err := cmd.Output() + if err != nil { + return "", err + } + + return strings.TrimSpace(string(checksum)), err + case "git": + fmt.Println("Calculating checksum for git branch...") + + // Replace variables in git branch + gitBranch := pkgDownload.GitBranch + gitBranch = os.Expand(gitBranch, func(s string) string { + switch s { + case "BPM_PKG_VERSION": + return pkgInfo.Version + case "BPM_PKG_NAME": + return pkgInfo.Name + default: + return "" + } + }) + + if pkgDownload.GitBranch == "" { + return "", fmt.Errorf("'git_branch' field cannot be empty") + } + + cmd := exec.Command("sh", "-c", fmt.Sprintf("git ls-remote --refs %s | grep 'refs/.*/%s$' | awk '{print $1}'", pkgDownload.Url, gitBranch)) + cmd.Stderr = os.Stderr + + checksum, err := cmd.Output() + if err != nil { + return "", err + } + + return strings.TrimSpace(string(checksum)), err + default: + return "", fmt.Errorf("unknown download type (%s)", pkgDownload.Type) + } +}