wip
This commit is contained in:
		@@ -6,6 +6,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var aliasCmd = &cobra.Command{
 | 
					var aliasCmd = &cobra.Command{
 | 
				
			||||||
	Use:     "alias",
 | 
						Use:     "alias",
 | 
				
			||||||
 | 
						Aliases: []string{"aliases", "a"},
 | 
				
			||||||
	Short:   "Manage project aliases",
 | 
						Short:   "Manage project aliases",
 | 
				
			||||||
	Long:    aliasCmdLong,
 | 
						Long:    aliasCmdLong,
 | 
				
			||||||
	// Just re-use the hooks for project
 | 
						// Just re-use the hooks for project
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var aliasAddCmd = &cobra.Command{
 | 
					var aliasAddCmd = &cobra.Command{
 | 
				
			||||||
	Use:     "add",
 | 
						Use:     "add",
 | 
				
			||||||
 | 
						Aliases: []string{"set", "a", "s"},
 | 
				
			||||||
	Short:   "Add a project alias",
 | 
						Short:   "Add a project alias",
 | 
				
			||||||
	Args:    cobra.ArbitraryArgs,
 | 
						Args:    cobra.ArbitraryArgs,
 | 
				
			||||||
	Long:    aliasAddCmdLong,
 | 
						Long:    aliasAddCmdLong,
 | 
				
			||||||
@@ -57,7 +58,7 @@ func addNewAliases(projectID int) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Add aliases
 | 
						// Add aliases
 | 
				
			||||||
	for _, a := range aliases {
 | 
						for _, a := range aliases {
 | 
				
			||||||
		a = strings.Trim(a, " '\"%")
 | 
							a = strings.Trim(a, " '\"%<>|`")
 | 
				
			||||||
		if a == "" {
 | 
							if a == "" {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package cmd
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/pterm/pterm"
 | 
				
			||||||
	"github.com/spf13/cobra"
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
	"github.com/spf13/viper"
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
	"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/gitlab"
 | 
						"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/gitlab"
 | 
				
			||||||
@@ -10,6 +11,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var aliasDeleteCmd = &cobra.Command{
 | 
					var aliasDeleteCmd = &cobra.Command{
 | 
				
			||||||
	Use:     "delete [fuzzy project or alias]",
 | 
						Use:     "delete [fuzzy project or alias]",
 | 
				
			||||||
 | 
						Aliases: []string{"rm", "del", "d"},
 | 
				
			||||||
	Short:   "Delete a project alias",
 | 
						Short:   "Delete a project alias",
 | 
				
			||||||
	Long:    aliasDeleteCmdLong,
 | 
						Long:    aliasDeleteCmdLong,
 | 
				
			||||||
	Run:     runDeleteAliasCmd,
 | 
						Run:     runDeleteAliasCmd,
 | 
				
			||||||
@@ -17,14 +19,54 @@ var aliasDeleteCmd = &cobra.Command{
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func runDeleteAliasCmd(cmd *cobra.Command, args []string) {
 | 
					func runDeleteAliasCmd(cmd *cobra.Command, args []string) {
 | 
				
			||||||
	var project *gitlab.Project
 | 
						var project *gitlab.Project
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(args) > 0 {
 | 
						if len(args) > 0 {
 | 
				
			||||||
		project = fzfFindProject(args[0])
 | 
							project = fzfFindProject(args[0])
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		project, _ = fzfProject(cmd.Context())
 | 
							project, err = fzfProject(cmd.Context(), true)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fmt.Println(project.String())
 | 
						if project == nil || err != nil {
 | 
				
			||||||
 | 
							plog.Fatal("Failed to find project to delete aliases from", plog.Args(
 | 
				
			||||||
 | 
								"error", err,
 | 
				
			||||||
 | 
							))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						aliasStrings := cache.GetProjectAliasStrings(project)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						deletionCandidates, err := pterm.DefaultInteractiveMultiselect.
 | 
				
			||||||
 | 
							WithOptions(aliasStrings).
 | 
				
			||||||
 | 
							Show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil || len(deletionCandidates) < 1 {
 | 
				
			||||||
 | 
							plog.Fatal("Failed to find project to delete aliases from", plog.Args(
 | 
				
			||||||
 | 
								"error", err,
 | 
				
			||||||
 | 
							))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, a := range deletionCandidates {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							confirm, _ := pterm.DefaultInteractiveConfirm.
 | 
				
			||||||
 | 
								WithDefaultText(fmt.Sprintf("Really delete %s -> %s?",
 | 
				
			||||||
 | 
									a, project.String())).
 | 
				
			||||||
 | 
								WithConfirmText("y").
 | 
				
			||||||
 | 
								Show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !confirm {
 | 
				
			||||||
 | 
								plog.Warn("Alias deletion cancelled")
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							plog.Info("Deleting alias", plog.Args(
 | 
				
			||||||
 | 
								"project", project.String(),
 | 
				
			||||||
 | 
								"alias", a,
 | 
				
			||||||
 | 
							))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cache.DeleteAlias(cache.GetAliasByName(a))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Println(cache.ProjectString(project))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								cmd/alias_list.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								cmd/alias_list.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					package cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// listCmd represents the list command
 | 
				
			||||||
 | 
					var aliasListCmd = &cobra.Command{
 | 
				
			||||||
 | 
						Use:     "list",
 | 
				
			||||||
 | 
						Aliases: []string{"dump", "show", "ls", "ll", "l"},
 | 
				
			||||||
 | 
						Short:   "List Aliases",
 | 
				
			||||||
 | 
						Long:    aliasListCmdLong,
 | 
				
			||||||
 | 
						Run:     runListAliasCmd,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func runListAliasCmd(cmd *cobra.Command, args []string) {
 | 
				
			||||||
 | 
						fmt.Print("\n" + cache.AliasesByProjectString() + "\n")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						aliasCmd.AddCommand(aliasListCmd)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,26 +0,0 @@
 | 
				
			|||||||
package cmd
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/spf13/cobra"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// configCmd represents the config command
 | 
					 | 
				
			||||||
var configCmd = &cobra.Command{
 | 
					 | 
				
			||||||
	Use:   "config",
 | 
					 | 
				
			||||||
	Short: "A brief description of your command",
 | 
					 | 
				
			||||||
	Long: `A longer description that spans multiple lines and likely contains examples
 | 
					 | 
				
			||||||
and usage of using your command. For example:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Cobra is a CLI library for Go that empowers applications.
 | 
					 | 
				
			||||||
This application is a tool to generate the needed files
 | 
					 | 
				
			||||||
to quickly create a Cobra application.`,
 | 
					 | 
				
			||||||
	Run: func(cmd *cobra.Command, args []string) {
 | 
					 | 
				
			||||||
		fmt.Println("config called")
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func init() {
 | 
					 | 
				
			||||||
	rootCmd.AddCommand(configCmd)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -2,12 +2,14 @@ package cmd
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/spf13/cobra"
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
						"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/gitlab"
 | 
				
			||||||
	"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/projects"
 | 
						"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/projects"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var projectCmd = &cobra.Command{
 | 
					var projectCmd = &cobra.Command{
 | 
				
			||||||
	Use:               "project [fuzzy alias search]",
 | 
						Use:               "project [fuzzy alias search]",
 | 
				
			||||||
	Short:             "Use a GitLab project",
 | 
						Short:             "Use a GitLab project",
 | 
				
			||||||
 | 
						Aliases:           []string{"proj", "projects", "p"},
 | 
				
			||||||
	Args:              cobra.MaximumNArgs(1),
 | 
						Args:              cobra.MaximumNArgs(1),
 | 
				
			||||||
	ArgAliases:        []string{"alias"},
 | 
						ArgAliases:        []string{"alias"},
 | 
				
			||||||
	ValidArgsFunction: validAliasesFunc,
 | 
						ValidArgsFunction: validAliasesFunc,
 | 
				
			||||||
@@ -18,10 +20,15 @@ var projectCmd = &cobra.Command{
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func projectCmdRun(cmd *cobra.Command, args []string) {
 | 
					func projectCmdRun(cmd *cobra.Command, args []string) {
 | 
				
			||||||
 | 
						goToProject(getProject(args))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getProject(args []string) *gitlab.Project {
 | 
				
			||||||
	var searchString string
 | 
						var searchString string
 | 
				
			||||||
	if len(args) > 0 {
 | 
						if len(args) > 0 {
 | 
				
			||||||
		searchString = args[0]
 | 
							searchString = args[0]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	project := fzfFindProject(searchString)
 | 
						project := fzfFindProject(searchString)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if project == nil {
 | 
						if project == nil {
 | 
				
			||||||
@@ -33,6 +40,13 @@ func projectCmdRun(cmd *cobra.Command, args []string) {
 | 
				
			|||||||
				cache.GetProjectAliases(project)),
 | 
									cache.GetProjectAliases(project)),
 | 
				
			||||||
		))
 | 
							))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(cache.GetProjectAliases(project)) == 0 {
 | 
				
			||||||
 | 
							plog.Info("New project, set aliases or press enter for default")
 | 
				
			||||||
 | 
							addNewAliases(project.ID)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return project
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func initProjectCmd(cmd *cobra.Command, args []string) {
 | 
					func initProjectCmd(cmd *cobra.Command, args []string) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								cmd/project_go.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								cmd/project_go.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					package cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
						"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/gitlab"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var projectGoCmd = &cobra.Command{
 | 
				
			||||||
 | 
						Use:               "go [fuzzy alias search]",
 | 
				
			||||||
 | 
						Short:             "Go to a GitLab project",
 | 
				
			||||||
 | 
						Aliases:           []string{"goto", "projects", "p"},
 | 
				
			||||||
 | 
						Args:              cobra.MaximumNArgs(1),
 | 
				
			||||||
 | 
						ArgAliases:        []string{"project"},
 | 
				
			||||||
 | 
						ValidArgsFunction: validAliasesFunc,
 | 
				
			||||||
 | 
						Long:              projGoCmdLong,
 | 
				
			||||||
 | 
						Run:               projectCmdRun,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func projectGoCmdRun(cmd *cobra.Command, args []string) {
 | 
				
			||||||
 | 
						goToProject(getProject(args))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func goToProject(project *gitlab.Project) {
 | 
				
			||||||
 | 
						cache.GoTo(project)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,7 +3,6 @@ package cmd
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/pterm/pterm"
 | 
					 | 
				
			||||||
	"github.com/spf13/cobra"
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -34,9 +33,7 @@ func projectShowCmdRun(cmd *cobra.Command, args []string) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fmt.Println(pterm.LightGreen("\n--------------"))
 | 
					 | 
				
			||||||
	fmt.Println(cache.ProjectString(project))
 | 
						fmt.Println(cache.ProjectString(project))
 | 
				
			||||||
	fmt.Println(pterm.LightGreen("--------------\n"))
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,8 @@ const (
 | 
				
			|||||||
const aliasCmdLong = `Manages project aliases, with options for
 | 
					const aliasCmdLong = `Manages project aliases, with options for
 | 
				
			||||||
listing, adding, and deleting.`
 | 
					listing, adding, and deleting.`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const aliasListCmdLong = `Lists all aliases by project`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const aliasAddCmdLong = `Adds a project alias to a project
 | 
					const aliasAddCmdLong = `Adds a project alias to a project
 | 
				
			||||||
project ID can be provided, or will otherwise use fuzzy find`
 | 
					project ID can be provided, or will otherwise use fuzzy find`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -27,5 +29,11 @@ const projCmdLong = `Switches to a GitLab project by name or alias
 | 
				
			|||||||
If not found, will enter fzf mode. If not cloned, will clone
 | 
					If not found, will enter fzf mode. If not cloned, will clone
 | 
				
			||||||
the project locally.`
 | 
					the project locally.`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const projGoCmdLong = `Go to a project, searching by alias
 | 
				
			||||||
 | 
					If project is not already cloned, its path will be built and it
 | 
				
			||||||
 | 
					will be cloned from source control.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If conf.projects.alwaysPull, a git pull will be ran automatically`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const projShowCmdLong = `Shows detail for a particular project
 | 
					const projShowCmdLong = `Shows detail for a particular project
 | 
				
			||||||
Will always fuzzy find`
 | 
					Will always fuzzy find`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,23 +61,35 @@ func fzfAliasFromAliases(ctx context.Context, aliases []*projects.ProjectAlias)
 | 
				
			|||||||
	return alias
 | 
						return alias
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func fzfProject(ctx context.Context) (*gitlab.Project, error) {
 | 
					// If a bool=true is provided, will only allow selection of projects
 | 
				
			||||||
	i, err := fzf.Find(cache.Projects, fzfProjectString,
 | 
					// that have at least one alias defined
 | 
				
			||||||
		fzf.WithPreviewWindow(fzfPreviewWindow),
 | 
					func fzfProject(ctx context.Context, mustHaveAlias ...bool) (*gitlab.Project, error) {
 | 
				
			||||||
 | 
						var searchableProjects []*gitlab.Project
 | 
				
			||||||
 | 
						if len(mustHaveAlias) == 1 && mustHaveAlias[0] {
 | 
				
			||||||
 | 
							searchableProjects = cache.GetProjectsWithAliases()
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							searchableProjects = cache.Projects
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						i, err := fzf.Find(searchableProjects,
 | 
				
			||||||
 | 
							func(i int) string {
 | 
				
			||||||
 | 
								return searchableProjects[i].String()
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							fzf.WithPreviewWindow(
 | 
				
			||||||
 | 
								func(i, width, height int) string {
 | 
				
			||||||
 | 
									return cache.ProjectString(searchableProjects[i])
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
		fzf.WithContext(ctx),
 | 
							fzf.WithContext(ctx),
 | 
				
			||||||
		fzf.WithHeader("Fuzzy find yourself a project"),
 | 
							fzf.WithHeader("Fuzzy find yourself a project"),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	if err != nil || i < 0 {
 | 
						if err != nil || i < 0 {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return cache.Projects[i], nil
 | 
						return searchableProjects[i], nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func fzfPreviewWindow(i, w, h int) string {
 | 
					func fzfPreviewWindow(i, w, h int) string {
 | 
				
			||||||
	p := cache.Projects[i]
 | 
						p := cache.Projects[i]
 | 
				
			||||||
	return cache.ProjectString(p)
 | 
						return cache.ProjectString(p)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func fzfProjectString(i int) string {
 | 
					 | 
				
			||||||
	return cache.Projects[i].String()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,7 @@ func initProjectCache(cmd *cobra.Command, args []string) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cacheOpts := &projects.CacheOpts{
 | 
						cacheOpts := &projects.CacheOpts{
 | 
				
			||||||
 | 
							ProjectsPath: conf.ProjectPath,
 | 
				
			||||||
		Path:         conf.Cache.File,
 | 
							Path:         conf.Cache.File,
 | 
				
			||||||
		TTL:          conf.Cache.Ttl,
 | 
							TTL:          conf.Cache.Ttl,
 | 
				
			||||||
		Logger:       plog,
 | 
							Logger:       plog,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package gitlab
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/xanzy/go-gitlab"
 | 
						"github.com/xanzy/go-gitlab"
 | 
				
			||||||
@@ -55,6 +56,10 @@ func (p *Project) String() string {
 | 
				
			|||||||
	return fmt.Sprintf("%s (%s)", p.Path, p.PathWithNamespace)
 | 
						return fmt.Sprintf("%s (%s)", p.Path, p.PathWithNamespace)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *Project) SanitizedPath() string {
 | 
				
			||||||
 | 
						return strings.Trim(p.PathWithNamespace, " '\"%<>|`")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Given there may be thousands of projects, this will return
 | 
					// Given there may be thousands of projects, this will return
 | 
				
			||||||
// channels that stream progress info and then finally the full
 | 
					// channels that stream progress info and then finally the full
 | 
				
			||||||
// list of projects on separate channels
 | 
					// list of projects on separate channels
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,10 +22,12 @@ type Cache struct {
 | 
				
			|||||||
	file         string
 | 
						file         string
 | 
				
			||||||
	log          *pterm.Logger
 | 
						log          *pterm.Logger
 | 
				
			||||||
	gitlab       *gitlab.Client
 | 
						gitlab       *gitlab.Client
 | 
				
			||||||
 | 
						path         string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type CacheOpts struct {
 | 
					type CacheOpts struct {
 | 
				
			||||||
	Path         string
 | 
						Path         string
 | 
				
			||||||
 | 
						ProjectsPath string
 | 
				
			||||||
	TTL          time.Duration
 | 
						TTL          time.Duration
 | 
				
			||||||
	Logger       *pterm.Logger
 | 
						Logger       *pterm.Logger
 | 
				
			||||||
	Gitlab       *gitlab.Client
 | 
						Gitlab       *gitlab.Client
 | 
				
			||||||
@@ -102,7 +104,7 @@ func (c *Cache) Clear(clearAliases bool) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Cache) refresh() {
 | 
					func (c *Cache) refresh() {
 | 
				
			||||||
	c.log.Info("Refreshing project cache, this may take a while")
 | 
						c.log.Info("Loading project cache, this may take a while\n")
 | 
				
			||||||
	defer c.setUpdated()
 | 
						defer c.setUpdated()
 | 
				
			||||||
	c.LoadProjects()
 | 
						c.LoadProjects()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -172,6 +174,7 @@ func NewProjectCache(opts *CacheOpts) (*Cache, error) {
 | 
				
			|||||||
		lock:     &sync.Mutex{},
 | 
							lock:     &sync.Mutex{},
 | 
				
			||||||
		log:      opts.Logger,
 | 
							log:      opts.Logger,
 | 
				
			||||||
		gitlab:   opts.Gitlab,
 | 
							gitlab:   opts.Gitlab,
 | 
				
			||||||
 | 
							path:     opts.ProjectsPath,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cache, err
 | 
						return cache, err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,25 @@
 | 
				
			|||||||
package projects
 | 
					package projects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "errors"
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/gitlab"
 | 
				
			||||||
 | 
						"golang.org/x/exp/slices"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cache) deleteAlias(alias *ProjectAlias) {
 | 
				
			||||||
 | 
						for i, a := range c.Aliases {
 | 
				
			||||||
 | 
							if a.Alias == alias.Alias {
 | 
				
			||||||
 | 
								c.Aliases = append(c.Aliases[:i], c.Aliases[i+1:]...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cache) DeleteAlias(alias *ProjectAlias) {
 | 
				
			||||||
 | 
						c.lock.Lock()
 | 
				
			||||||
 | 
						defer c.lock.Unlock()
 | 
				
			||||||
 | 
						c.deleteAlias(alias)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Cache) addAlias(alias string, projectID int) error {
 | 
					func (c *Cache) addAlias(alias string, projectID int) error {
 | 
				
			||||||
	if c.GetAliasByName(alias) != nil {
 | 
						if c.GetAliasByName(alias) != nil {
 | 
				
			||||||
@@ -21,3 +40,24 @@ func (c *Cache) AddAlias(alias string, projectID int) error {
 | 
				
			|||||||
	defer c.lock.Unlock()
 | 
						defer c.lock.Unlock()
 | 
				
			||||||
	return c.addAlias(alias, projectID)
 | 
						return c.addAlias(alias, projectID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cache) GetProjectsWithAliases() []*gitlab.Project {
 | 
				
			||||||
 | 
						projectList := make([]*gitlab.Project, 0)
 | 
				
			||||||
 | 
						projectsFound := make([]int, 0)
 | 
				
			||||||
 | 
						for _, a := range c.Aliases {
 | 
				
			||||||
 | 
							if !slices.Contains(projectsFound, a.ProjectID) {
 | 
				
			||||||
 | 
								projectList = append(projectList, c.GetProjectByAlias(a))
 | 
				
			||||||
 | 
								projectsFound = append(projectsFound, a.ProjectID)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return projectList
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cache) GetProjectAliasStrings(project *gitlab.Project) []string {
 | 
				
			||||||
 | 
						aliases := c.GetProjectAliases(project)
 | 
				
			||||||
 | 
						strings := make([]string, len(aliases))
 | 
				
			||||||
 | 
						for i, a := range c.GetProjectAliases(project) {
 | 
				
			||||||
 | 
							strings[i] = a.Alias
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return strings
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,7 @@ func (c *Cache) FuzzyFindAlias(name string) []*ProjectAlias {
 | 
				
			|||||||
			found[i] = r.Target
 | 
								found[i] = r.Target
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		c.log.Warn("Fuzzy found multiple aliases, try being more specific",
 | 
							c.log.Warn("Fuzzy found multiple aliases, try being more specific",
 | 
				
			||||||
			c.log.Args("foundAliases", strings.Join(found, ",")))
 | 
								c.log.Args("foundAliases", strings.Join(found, ", ")))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var aliases []*ProjectAlias
 | 
						var aliases []*ProjectAlias
 | 
				
			||||||
	if ranks.Len() > 0 {
 | 
						if ranks.Len() > 0 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,10 @@
 | 
				
			|||||||
package projects
 | 
					package projects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
						"text/tabwriter"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/pterm/pterm"
 | 
						"github.com/pterm/pterm"
 | 
				
			||||||
	"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/gitlab"
 | 
						"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/gitlab"
 | 
				
			||||||
@@ -21,10 +23,29 @@ func ProjectAliasesString(aliases []*ProjectAlias) string {
 | 
				
			|||||||
	return strings.Trim(str, " ")
 | 
						return strings.Trim(str, " ")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cache) AliasesByProjectString() string {
 | 
				
			||||||
 | 
						var str bytes.Buffer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						w := new(tabwriter.Writer)
 | 
				
			||||||
 | 
						w.Init(&str, 10, 0, 0, ' ', tabwriter.AlignRight)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, p := range c.GetProjectsWithAliases() {
 | 
				
			||||||
 | 
							var pa string
 | 
				
			||||||
 | 
							pa += pterm.LightBlue("- ")
 | 
				
			||||||
 | 
							pa += fmt.Sprint(pterm.Bold.Sprint(p.String()) + " \t ")
 | 
				
			||||||
 | 
							pa += fmt.Sprint(ProjectAliasesString(c.GetProjectAliases(p)))
 | 
				
			||||||
 | 
							fmt.Fprintln(w, pa)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						w.Flush()
 | 
				
			||||||
 | 
						return str.String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Cache) ProjectString(p *gitlab.Project) string {
 | 
					func (c *Cache) ProjectString(p *gitlab.Project) string {
 | 
				
			||||||
	info := strings.Builder{}
 | 
						info := strings.Builder{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info.WriteString(pterm.LightBlue(p.Name))
 | 
						info.WriteString(pterm.LightGreen("\n--------------\n"))
 | 
				
			||||||
 | 
						info.WriteString(pterm.Bold.Sprint(p.Name))
 | 
				
			||||||
	info.WriteRune('\n')
 | 
						info.WriteRune('\n')
 | 
				
			||||||
	if p.Description != "" {
 | 
						if p.Description != "" {
 | 
				
			||||||
		info.WriteString(p.Description)
 | 
							info.WriteString(p.Description)
 | 
				
			||||||
@@ -40,6 +61,7 @@ func (c *Cache) ProjectString(p *gitlab.Project) string {
 | 
				
			|||||||
	aliases := c.GetProjectAliases(p)
 | 
						aliases := c.GetProjectAliases(p)
 | 
				
			||||||
	info.WriteString(ProjectAliasesString(aliases))
 | 
						info.WriteString(ProjectAliasesString(aliases))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						info.WriteString(pterm.LightGreen("\n--------------\n"))
 | 
				
			||||||
	return info.String()
 | 
						return info.String()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -107,7 +129,7 @@ func (c *Cache) LoadProjects() {
 | 
				
			|||||||
		WithShowPercentage(true).
 | 
							WithShowPercentage(true).
 | 
				
			||||||
		WithTotal(-1).
 | 
							WithTotal(-1).
 | 
				
			||||||
		WithTitle("Listing GitLab Projects").
 | 
							WithTitle("Listing GitLab Projects").
 | 
				
			||||||
		WithMaxWidth(0)
 | 
							WithMaxWidth(100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	defer pBar.Stop()
 | 
						defer pBar.Stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -133,6 +155,7 @@ func (c *Cache) LoadProjects() {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		case <-progressInfo.DoneChan:
 | 
							case <-progressInfo.DoneChan:
 | 
				
			||||||
			pBar.Add(pBar.Total - curProjects)
 | 
								pBar.Add(pBar.Total - curProjects)
 | 
				
			||||||
 | 
								fmt.Println("")
 | 
				
			||||||
			c.log.Info("Project load complete")
 | 
								c.log.Info("Project load complete")
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								internal/projects/projects_fs.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								internal/projects/projects_fs.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					package projects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/gitlab"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cache) GoTo(project *gitlab.Project) {
 | 
				
			||||||
 | 
						pPath := c.path + "/" + project.SanitizedPath()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.log.Debug("Going to project", c.log.Args(
 | 
				
			||||||
 | 
							"project", project.String(),
 | 
				
			||||||
 | 
							"path", pPath,
 | 
				
			||||||
 | 
						))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err := os.Stat(pPath); err != nil {
 | 
				
			||||||
 | 
							c.log.Info("Preparing project path")
 | 
				
			||||||
 | 
							c.PrepProjectPath(pPath)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cache) PrepProjectPath(path string) {
 | 
				
			||||||
 | 
						if err := os.MkdirAll(path, 0750); err != nil {
 | 
				
			||||||
 | 
							c.log.Fatal("Failed to prepare project path", c.log.Args(
 | 
				
			||||||
 | 
								"path", path,
 | 
				
			||||||
 | 
								"error", err,
 | 
				
			||||||
 | 
							))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user