From 47c4b91fe437f3c93f47b7acccddab369ac89b24 Mon Sep 17 00:00:00 2001 From: Bishal Prasad Date: Fri, 1 Jul 2022 00:22:03 +0530 Subject: [PATCH] Refactor input params as Options (#9) * some minor code refactor * unsaved changes * Minor cleanup Co-authored-by: t-dedah --- .gitignore | 3 +- cmd/delete.go | 27 +++++++---- cmd/list.go | 25 ++++------ internal/utils.go | 52 ++++----------------- types/{model.go => api_models.go} | 10 ---- types/options.go | 78 +++++++++++++++++++++++++++++++ 6 files changed, 115 insertions(+), 80 deletions(-) rename types/{model.go => api_models.go} (86%) create mode 100644 types/options.go diff --git a/.gitignore b/.gitignore index 84264c0..17a6723 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store -gh-actions-cache \ No newline at end of file +gh-actions-cache +.vscode \ No newline at end of file diff --git a/cmd/delete.go b/cmd/delete.go index 9337a1d..4979e4a 100644 --- a/cmd/delete.go +++ b/cmd/delete.go @@ -14,7 +14,7 @@ import ( func NewCmdDelete() *cobra.Command { COMMAND = "delete" - f := types.InputFlags{} + f := types.DeleteOptions{} var deleteCmd = &cobra.Command{ Use: "delete", @@ -24,7 +24,8 @@ func NewCmdDelete() *cobra.Command { fmt.Printf("accepts 1 arg(s), received %d\n", len(args)) return } - key := args[0] + + f.Key = args[0] repo, err := internal.GetRepo(f.Repo) if err != nil { @@ -32,13 +33,14 @@ func NewCmdDelete() *cobra.Command { return } artifactCache := service.NewArtifactCache(repo, COMMAND, VERSION) - queryParams := internal.GenerateQueryParams(f.Branch, 100, key, "", "", 1) + queryParams := url.Values{} + f.GenerateBaseQueryParams(queryParams) if !f.Confirm { - var matchedCaches = getCacheListWithExactMatch(queryParams, key, artifactCache) + var matchedCaches = getCacheListWithExactMatch(f, artifactCache) matchedCachesLen := len(matchedCaches) if matchedCachesLen == 0 { - fmt.Printf("Cache with input key '%s' does not exist\n", key) + fmt.Printf("Cache with input key '%s' does not exist\n", f.Key) return } fmt.Printf("You're going to delete %s", internal.PrintSingularOrPlural(matchedCachesLen, "cache entry\n\n", "cache entries\n\n")) @@ -59,9 +61,9 @@ func NewCmdDelete() *cobra.Command { if f.Confirm { cachesDeleted := artifactCache.DeleteCaches(queryParams) if cachesDeleted > 0 { - fmt.Printf("%s Deleted %s with key '%s'\n", internal.RedTick(), internal.PrintSingularOrPlural(cachesDeleted, "cache entry", "cache entries"), key) + fmt.Printf("%s Deleted %s with key '%s'\n", internal.RedTick(), internal.PrintSingularOrPlural(cachesDeleted, "cache entry", "cache entries"), f.Key) } else { - fmt.Printf("Cache with input key '%s' does not exist\n", key) + fmt.Printf("Cache with input key '%s' does not exist\n", f.Key) } } }, @@ -97,11 +99,16 @@ EXAMPLES: ` } -func getCacheListWithExactMatch(queryParams url.Values, key string, artifactCache service.ArtifactCacheService) []types.ActionsCache { - caches := artifactCache.ListAllCaches(queryParams, key) +func getCacheListWithExactMatch(f types.DeleteOptions, artifactCache service.ArtifactCacheService) []types.ActionsCache { + listOption := types.ListOptions{BaseOptions: types.BaseOptions{Repo: f.Repo, Branch: f.Branch, Key: f.Key}, Limit: 100, Order: "", Sort: ""} + queryParams := url.Values{} + + listOption.GenerateBaseQueryParams(queryParams) + caches := artifactCache.ListAllCaches(queryParams, f.Key) + var exactMatchedKeys []types.ActionsCache for _, cache := range caches { - if strings.EqualFold(key, cache.Key) { + if strings.EqualFold(f.Key, cache.Key) { exactMatchedKeys = append(exactMatchedKeys, cache) } } diff --git a/cmd/list.go b/cmd/list.go index 25e3735..502d30b 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" "log" + "net/url" "github.com/actions/gh-actions-cache/internal" "github.com/actions/gh-actions-cache/service" @@ -13,7 +14,7 @@ import ( func NewCmdList() *cobra.Command { COMMAND = "list" - f := types.InputFlags{} + f := types.ListOptions{} var listCmd = &cobra.Command{ Use: "list", @@ -30,7 +31,10 @@ func NewCmdList() *cobra.Command { log.Fatal(err) } - validateInputs(f) + err = f.Validate() + if err != nil { + log.Fatal(err) + } artifactCache := service.NewArtifactCache(repo, COMMAND, VERSION) @@ -39,7 +43,8 @@ func NewCmdList() *cobra.Command { fmt.Printf("Total caches size %s\n\n", internal.FormatCacheSize(totalCacheSize)) } - queryParams := internal.GenerateQueryParams(f.Branch, f.Limit, f.Key, f.Order, f.Sort, 1) + queryParams := url.Values{} + f.GenerateQueryParams(queryParams) listCacheResponse := artifactCache.ListCaches(queryParams) totalCaches := listCacheResponse.TotalCount @@ -68,20 +73,6 @@ func displayedEntriesCount(totalCaches int, limit int) int { return limit } -func validateInputs(input types.InputFlags) { - if input.Order != "" && input.Order != "asc" && input.Order != "desc" { - log.Fatal(fmt.Errorf(fmt.Sprintf("%s is not a valid value for order flag. Allowed values: asc/desc", input.Order))) - } - - if input.Sort != "" && input.Sort != "last-used" && input.Sort != "size" && input.Sort != "created-at" { - log.Fatal(fmt.Errorf(fmt.Sprintf("%s is not a valid value for sort flag. Allowed values: last-used/size/created-at", input.Sort))) - } - - if input.Limit < 1 || input.Limit > 100 { - log.Fatal(fmt.Errorf(fmt.Sprintf("%d is not a valid value for limit flag. Allowed values: 1-100", input.Limit))) - } -} - func getListHelp() string { return ` gh-actions-cache: Works with GitHub Actions Cache. diff --git a/internal/utils.go b/internal/utils.go index 0656a72..19e9b21 100644 --- a/internal/utils.go +++ b/internal/utils.go @@ -3,9 +3,7 @@ package internal import ( "fmt" "math" - "net/url" "os" - "strconv" "strings" "unicode/utf8" @@ -19,40 +17,8 @@ import ( const MB_IN_BYTES = 1024 * 1024 const GB_IN_BYTES = 1024 * 1024 * 1024 - -var SORT_INPUT_TO_QUERY_MAP = map[string]string{ - "created-at": "created_at", - "last-used": "last_accessed_at", - "size": "size_in_bytes", -} - -func GenerateQueryParams(branch string, limit int, key string, order string, sort string, page int) url.Values { - query := url.Values{} - if branch != "" { - if strings.HasPrefix(branch, "refs/") { - query.Add("ref", branch) - } else { - query.Add("ref", fmt.Sprintf("refs/heads/%s", branch)) - } - } - if limit != 30 { - query.Add("per_page", strconv.Itoa(limit)) - } - if key != "" { - query.Add("key", key) - } - if order != "" { - query.Add("direction", order) - } - if sort != "" { - query.Add("sort", SORT_INPUT_TO_QUERY_MAP[sort]) - } - if page > 1 { - query.Add("page", strconv.Itoa(page)) - } - - return query -} +const SIZE_COLUMN_WIDTH = 15 +const LAST_ACCESSED_AT_COLUMN_WIDTH = 20 func GetRepo(r string) (ghRepo.Repository, error) { if r != "" { @@ -79,13 +45,15 @@ func FormatCacheSize(size_in_bytes float64) string { } func PrettyPrintCacheList(caches []types.ActionsCache) { - fd := os.Stdin.Fd() + fd := os.Stdout.Fd() ws, _ := term.GetWinsize(fd) width := math.Min(float64(ws.Width), 180) - keyWidth := int(math.Floor(0.30 * width)) - sizeWidth := int(math.Floor(0.12 * width)) - refWidth := int(math.Floor(0.20 * width)) - timeWidth := int(math.Floor(0.20 * width)) + + sizeWidth := SIZE_COLUMN_WIDTH // hard-coded size as the content is scoped + timeWidth := LAST_ACCESSED_AT_COLUMN_WIDTH // hard-coded size as the content is scoped + keyWidth := int(math.Floor(0.75 * (width - 15 - 20))) + refWidth := int(math.Floor(0.25 * (width - 15 - 20))) + for _, cache := range caches { var formattedRow string = getFormattedCacheInfo(cache, keyWidth, sizeWidth, refWidth, timeWidth) fmt.Println(formattedRow) @@ -105,7 +73,7 @@ func PrettyPrintTrimmedCacheList(caches []types.ActionsCache) { func lastAccessedTime(lastAccessedAt string) string { lastAccessed, _ := goment.New(lastAccessedAt) - return fmt.Sprintf("Used %s", lastAccessed.FromNow()) + return fmt.Sprintf(" %s", lastAccessed.FromNow()) } func trimOrPad(value string, maxSize int) string { diff --git a/types/model.go b/types/api_models.go similarity index 86% rename from types/model.go rename to types/api_models.go index 1d30a66..653a8f5 100644 --- a/types/model.go +++ b/types/api_models.go @@ -25,13 +25,3 @@ type ActionsCache struct { CreatedAt string `json:"created_at"` SizeInBytes float64 `json:"size_in_bytes"` } - -type InputFlags struct { - Repo string - Branch string - Limit int - Key string - Order string - Sort string - Confirm bool -} diff --git a/types/options.go b/types/options.go new file mode 100644 index 0000000..8e90472 --- /dev/null +++ b/types/options.go @@ -0,0 +1,78 @@ +package types + +import ( + "fmt" + "net/url" + "strconv" + "strings" +) + +var SORT_INPUT_TO_QUERY_MAP = map[string]string{ + "created-at": "created_at", + "last-used": "last_accessed_at", + "size": "size_in_bytes", +} + +type BaseOptions struct { + Repo string + Branch string + Key string +} + +type ListOptions struct { + BaseOptions + Limit int + Order string + Sort string +} + +type DeleteOptions struct { + BaseOptions + Confirm bool +} + +func (o *ListOptions) Validate() error { + if o.Order != "" && o.Order != "asc" && o.Order != "desc" { + return fmt.Errorf(fmt.Sprintf("%s is not a valid value for order flag. Allowed values: asc/desc", o.Order)) + } + + if o.Sort != "" && o.Sort != "last-used" && o.Sort != "size" && o.Sort != "created-at" { + return fmt.Errorf(fmt.Sprintf("%s is not a valid value for sort flag. Allowed values: last-used/size/created-at", o.Sort)) + } + + if o.Limit < 1 || o.Limit > 100 { + return fmt.Errorf(fmt.Sprintf("%d is not a valid value for limit flag. Allowed values: 1-100", o.Limit)) + } + + return nil +} + +func (o *BaseOptions) GenerateBaseQueryParams(query url.Values) { + if o.Branch != "" { + if strings.HasPrefix(o.Branch, "refs/") { + query.Add("ref", o.Branch) + } else { + query.Add("ref", fmt.Sprintf("refs/heads/%s", o.Branch)) + } + } + + if o.Key != "" { + query.Add("key", o.Key) + } +} + +func (o *ListOptions) GenerateQueryParams(query url.Values) { + if o.Limit != 30 { + query.Add("per_page", strconv.Itoa(o.Limit)) + } + + if o.Order != "" { + query.Add("direction", o.Order) + } + + if o.Sort != "" { + query.Add("sort", SORT_INPUT_TO_QUERY_MAP[o.Sort]) + } + + o.GenerateBaseQueryParams(query) +}