diff --git a/app/app_run.go b/app/app_run.go index 2ebe623..eab95f3 100644 --- a/app/app_run.go +++ b/app/app_run.go @@ -7,7 +7,6 @@ import ( "github.com/permafrost-dev/zeget/lib/assets" . "github.com/permafrost-dev/zeget/lib/assets" "github.com/permafrost-dev/zeget/lib/detectors" - "github.com/permafrost-dev/zeget/lib/registry" "github.com/permafrost-dev/zeget/lib/reporters" "github.com/permafrost-dev/zeget/lib/utilities" . "github.com/permafrost-dev/zeget/lib/utilities" @@ -40,22 +39,8 @@ func (app *Application) Run() *ReturnStatus { finder := app.getFinder() findResult := app.getFindResult(finder) - if len(app.Opts.Filters) > 0 { - var temp []assets.Asset = []assets.Asset{} - - for _, filter := range app.Opts.Filters { - for _, a := range findResult.Assets { - if filter.Apply(a) { - temp = append(temp, a) - } - } - } - findResult.Assets = temp - - if len(findResult.Assets) == 0 { - findResult.Error = fmt.Errorf("no assets found matching filters") - return NewReturnStatus(FatalError, findResult.Error, fmt.Sprintf("error: %v", findResult.Error)) - } + if result := app.ProcessFilters(&finder, &findResult); result != nil { + return result } app.cacheTarget(&finder, &findResult) @@ -94,75 +79,31 @@ func (app *Application) Run() *ReturnStatus { } } - asset := detected.Asset + assetWrapper.Asset = &detected.Asset if len(detected.Candidates) != 0 { - asset, err = app.selectFromMultipleAssets(detected.Candidates, err) // manually select which asset to download + assetWrapper.Asset, err = app.selectFromMultipleAssets(detected.Candidates, err) // manually select which asset to download if err != nil { return NewReturnStatus(FatalError, err, fmt.Sprintf("error: %v", err)) } - // convert the selected asset to an array of filters, then save them to file for future use - app.Cache.Data.GetRepositoryEntryByKey(app.Target, &app.Cache).Filters = asset.Filters - app.Cache.SaveToFile() - } - - assetWrapper.Asset = &asset - - app.WriteLine("› " + "downloading " + assetWrapper.Asset.DownloadURL + "...") // print the URL - - body, err := app.downloadAsset(assetWrapper.Asset, &findResult) // download with progress bar and get the response body - if err != nil { - return NewReturnStatus(FatalError, err, fmt.Sprintf("error: %v", err)) - } - app.VerifyChecksums(assetWrapper, body) - - if app.Opts.Sha256 || app.Opts.Hash { - reporters.NewAssetSha256HashReporter(assetWrapper.Asset, app.Output).Report(string(body)) + cacheItem.Filters = assetWrapper.Asset.Filters } - tagDownloaded := utilities.SetIf(app.Opts.Tag != "", "latest", app.Opts.Tag) - app.Cache.Data.GetRepositoryEntryByKey(app.Target, &app.Cache).UpdateDownloadedAt(tagDownloaded) - - extractor, err := app.getExtractor(assetWrapper.Asset, finder.Tool) - if err != nil { - return NewReturnStatus(FatalError, err, fmt.Sprintf("error: %v", err)) + body, result := app.DownloadAndVerify(assetWrapper, &findResult) + if result != nil { + return result } - bin, bins, err := extractor.Extract(body, app.Opts.All) // get extraction candidates - // if err != nil && len(bins) == 0 { - // return NewReturnStatus(FatalError, err, fmt.Sprintf("error: %v", err)) - // } - if err != nil && len(bins) != 0 && !app.Opts.All { - var e error - bin, e = app.selectFromMultipleCandidates(bin, bins, err) - if e != nil { - return NewReturnStatus(FatalError, e, fmt.Sprintf("error: %v", e)) - } + extractedCount, result := app.ExtractDownloadedAsset(assetWrapper, body, &finder) + if result != nil { + return result } - extractedCount := app.ExtractBins(bin, app.wrapBins(bins, bin), app.Opts.All) - - ref, _ := utilities.ParseRepositoryReference(app.Target) - - hash := registry.CalculateFileHash(string(body)) - app.Cache.Data.GetRepositoryEntryByKey(app.Target, &app.Cache).UpdateTag(asset.DownloadURL, tagDownloaded) - app.Cache.Data.GetRepositoryEntryByKey(app.Target, &app.Cache).UpdateHash(hash) - - realTag := utilities.ParseVersionTagFromURL(asset.DownloadURL, tagDownloaded) - - app.Registry.AddOrUpdatePackage(registry.PackageData{ - Source: "github", - Repo: ref.Name, Owner: ref.Owner, - InstalledAt: time.Now().Format(time.RFC3339), - AssetFilters: asset.Filters, - Asset: asset.Name, - Binary: bin.String(), - URL: asset.DownloadURL, - BinaryHash: hash, - Tag: realTag, - }) - app.Registry.Save() + cacheItem.LastDownloadAt = time.Now().Local() + cacheItem.LastDownloadTag = utilities.ParseVersionTagFromURL(assetWrapper.Asset.DownloadURL, app.Opts.Tag) + cacheItem.LastDownloadHash = utilities.CalculateStringHash(string(body)) + cacheItem.Save() if app.Opts.Verbose { reporters.NewMessageReporter(app.Output, "number of extracted files: %d\n", extractedCount).Report() diff --git a/app/application.go b/app/application.go index 0ed0eb3..7337cad 100644 --- a/app/application.go +++ b/app/application.go @@ -15,6 +15,7 @@ import ( "github.com/jessevdk/go-flags" . "github.com/permafrost-dev/zeget/lib/appflags" + "github.com/permafrost-dev/zeget/lib/assets" . "github.com/permafrost-dev/zeget/lib/assets" "github.com/permafrost-dev/zeget/lib/data" "github.com/permafrost-dev/zeget/lib/download" @@ -25,6 +26,7 @@ import ( . "github.com/permafrost-dev/zeget/lib/globals" "github.com/permafrost-dev/zeget/lib/home" "github.com/permafrost-dev/zeget/lib/registry" + "github.com/permafrost-dev/zeget/lib/reporters" "github.com/permafrost-dev/zeget/lib/utilities" . "github.com/permafrost-dev/zeget/lib/utilities" "github.com/permafrost-dev/zeget/lib/verifiers" @@ -174,9 +176,9 @@ func (app *Application) targetToProject(target string) error { } // if multiple candidates are returned, the user must select manually which one to download -func (app *Application) selectFromMultipleAssets(candidates []Asset, err error) (Asset, error) { +func (app *Application) selectFromMultipleAssets(candidates []Asset, err error) (*Asset, error) { if app.cli.NoInteraction || app.Opts.NoInteraction { - return Asset{}, fmt.Errorf("error: multiple candidates found, cannot select automatically (user interaction disabled)") + return &Asset{}, fmt.Errorf("error: multiple candidates found, cannot select automatically (user interaction disabled)") } app.WriteErrorLine("%v: please select manually", err) @@ -188,7 +190,7 @@ func (app *Application) selectFromMultipleAssets(candidates []Asset, err error) choice, err := app.userSelect(choices) if err != nil { - return Asset{}, fmt.Errorf("error: %v", err) + return &Asset{}, fmt.Errorf("error: %v", err) } choiceStr := fmt.Sprintf("%s", choices[choice-1]) @@ -196,7 +198,7 @@ func (app *Application) selectFromMultipleAssets(candidates []Asset, err error) result := candidates[choice-1] result.Filters = utilities.FilenameToAssetFilters(choiceStr) - return result, nil + return &result, nil } @@ -633,3 +635,62 @@ func (app *Application) downloadConfigRepositories() error { return nil } + +func (app *Application) ProcessFilters(finder *finders.ValidFinder, findResult *finders.FindResult) *ReturnStatus { + if len(app.Opts.Filters) > 0 { + var temp []assets.Asset = []assets.Asset{} + + for _, filter := range app.Opts.Filters { + for _, a := range findResult.Assets { + if filter.Apply(a) { + temp = append(temp, a) + } + } + } + findResult.Assets = temp + + if len(findResult.Assets) == 0 { + findResult.Error = fmt.Errorf("no assets found matching filters") + return NewReturnStatus(FatalError, findResult.Error, fmt.Sprintf("error: %v", findResult.Error)) + } + } + + return nil +} + +func (app *Application) DownloadAndVerify(assetWrapper *AssetWrapper, findResult *finders.FindResult) ([]byte, *ReturnStatus) { + app.WriteLine("› " + "downloading " + assetWrapper.Asset.DownloadURL + "...") // print the URL + + body, err := app.downloadAsset(assetWrapper.Asset, findResult) // download with progress bar and get the response body + if err != nil { + return nil, NewReturnStatus(FatalError, err, fmt.Sprintf("error: %v", err)) + } + + app.VerifyChecksums(assetWrapper, body) + + if app.Opts.Sha256 || app.Opts.Hash { + reporters.NewAssetSha256HashReporter(assetWrapper.Asset, app.Output).Report(string(body)) + } + + return body, nil +} + +func (app *Application) ExtractDownloadedAsset(assetWrapper *AssetWrapper, body []byte, finder *finders.ValidFinder) (int, *ReturnStatus) { + extractor, err := app.getExtractor(assetWrapper.Asset, finder.Tool) + if err != nil { + return -1, NewReturnStatus(FatalError, err, fmt.Sprintf("error: %v", err)) + } + + bin, bins, err := extractor.Extract(body, app.Opts.All) // get extraction candidates + if err != nil && len(bins) != 0 && !app.Opts.All { + var e error + bin, e = app.selectFromMultipleCandidates(bin, bins, err) + if e != nil { + return -1, NewReturnStatus(FatalError, e, fmt.Sprintf("error: %v", e)) + } + } + + extractedCount := app.ExtractBins(bin, app.wrapBins(bins, bin), app.Opts.All) + + return extractedCount, nil +} diff --git a/lib/data/types.go b/lib/data/types.go index 300dcf2..003809b 100644 --- a/lib/data/types.go +++ b/lib/data/types.go @@ -36,6 +36,10 @@ type ApplicationData struct { Repositories map[string]*RepositoryCacheEntry `json:"repositories"` } +func (rce *RepositoryCacheEntry) Save() error { + return rce.owner.SaveToFile() +} + func (ad *ApplicationData) HasRepositoryEntryByKey(key string) bool { _, found := ad.Repositories[key] return found diff --git a/lib/registry/registry.go b/lib/registry/registry.go index 59b15f5..0136e91 100644 --- a/lib/registry/registry.go +++ b/lib/registry/registry.go @@ -1,8 +1,6 @@ package registry import ( - "crypto/sha256" - "encoding/hex" "encoding/json" "os" "path/filepath" @@ -199,11 +197,3 @@ func DeleteAssetAndBinary(stewPkgPath, stewBinPath, asset, binary string) error } return nil } - -func CalculateFileHash(body string) string { - hasher := sha256.New() - - hasher.Write([]byte(body)) - - return hex.EncodeToString(hasher.Sum(nil)) -} diff --git a/lib/utilities/helpers.go b/lib/utilities/helpers.go index 4379166..39c0242 100644 --- a/lib/utilities/helpers.go +++ b/lib/utilities/helpers.go @@ -1,6 +1,8 @@ package utilities import ( + "crypto/sha256" + "encoding/hex" "errors" "fmt" "io/fs" @@ -283,13 +285,18 @@ func ExtractToolNameFromURL(url string) string { func ParseVersionTagFromURL(url string, currentTag string) string { // parse version from url like "https://github.com/sharkdp/fd/releases/download/v10.2.0/fd-v10.2.0-x86_64-unknown-linux-gnu.tar.gz": - // Regular expression to find the version pattern. re := regexp.MustCompile(`releases\/download\/(v?[\d\.]+)`) - matches := re.FindStringSubmatch(url) - - if len(matches) > 1 { + if matches := re.FindStringSubmatch(url); len(matches) > 1 { return matches[1] } - return currentTag + return SetIf(currentTag != "", "latest", currentTag) +} + +func CalculateStringHash(body string) string { + hasher := sha256.New() + + hasher.Write([]byte(body)) + + return hex.EncodeToString(hasher.Sum(nil)) }