wip
This commit is contained in:
parent
424e572fe0
commit
f17ce69ef8
49
cmd/alias.go
49
cmd/alias.go
@ -1,57 +1,18 @@
|
||||
/*
|
||||
Copyright © 2023 Ryan McGuire <ryand_mcguire@sweetwater.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// aliasCmd represents the alias command
|
||||
var aliasCmd = &cobra.Command{
|
||||
Use: "alias",
|
||||
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("alias called")
|
||||
},
|
||||
Short: "Manage project aliases",
|
||||
Long: aliasCmdLong,
|
||||
// Just re-use the hooks for project
|
||||
PersistentPreRun: initProjectCmd,
|
||||
PersistentPostRun: postProjectCmd,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(aliasCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
// Cobra supports Persistent Flags which will work for this command
|
||||
// and all subcommands, e.g.:
|
||||
// aliasCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||
|
||||
// Cobra supports local flags which will only run when this command
|
||||
// is called directly, e.g.:
|
||||
// aliasCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
|
95
cmd/alias_add.go
Normal file
95
cmd/alias_add.go
Normal file
@ -0,0 +1,95 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/spf13/cobra"
|
||||
"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/projects"
|
||||
)
|
||||
|
||||
var aliasAddCmd = &cobra.Command{
|
||||
Use: "add",
|
||||
Short: "Add a project alias",
|
||||
Long: aliasAddCmdLong,
|
||||
Run: runAddAliasCmd,
|
||||
}
|
||||
|
||||
func runAddAliasCmd(cmd *cobra.Command, args []string) {
|
||||
var project *gitlab.Project
|
||||
|
||||
// Check by flag
|
||||
if projectID := viper.GetInt("alias.add.projectid"); projectID > 0 {
|
||||
plog.Debug(fmt.Sprintf("Adding for inbound project ID %d", projectID))
|
||||
project = cache.GetProjectByID(projectID)
|
||||
}
|
||||
|
||||
// Collect by fzf
|
||||
if project == nil {
|
||||
var err error
|
||||
project, err = fzfProject(cmd.Context())
|
||||
if err != nil || project == nil {
|
||||
plog.Fatal("No project to alias, nothing to do", plog.Args("error", err))
|
||||
}
|
||||
}
|
||||
|
||||
addNewAliases(project.ID)
|
||||
}
|
||||
|
||||
func addNewAliases(projectID int) {
|
||||
project := cache.GetProjectByID(projectID)
|
||||
if project == nil {
|
||||
plog.Error("Failed to find project to alias", plog.Args("projectID", projectID))
|
||||
return
|
||||
}
|
||||
|
||||
// Collect the aliases
|
||||
aliases := promptAliasesForProject(project)
|
||||
|
||||
// Add aliases
|
||||
for _, a := range aliases {
|
||||
a = strings.Trim(a, " '\"%")
|
||||
if a == "" {
|
||||
continue
|
||||
}
|
||||
if err := cache.AddAlias(a, project.ID); err != nil {
|
||||
plog.Debug("Skipping alias add", plog.Args(
|
||||
"error", err,
|
||||
"alias", a,
|
||||
))
|
||||
} else {
|
||||
plog.Info("Successfully added alias to project", plog.Args(
|
||||
"project", project.String(),
|
||||
"alias", a,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func promptAliasesForProject(p *gitlab.Project) []string {
|
||||
aliases := cache.GetProjectAliases(p)
|
||||
if len(aliases) > 0 {
|
||||
plog.Info("Adding aliases to project", plog.Args(
|
||||
"project", p.String(),
|
||||
"existingAliases", projects.ProjectAliasesString(aliases),
|
||||
))
|
||||
} else {
|
||||
pterm.Info.Printfln("Adding aliases to %s", p.Name)
|
||||
}
|
||||
|
||||
response, _ := pterm.DefaultInteractiveTextInput.
|
||||
WithMultiLine(false).
|
||||
WithDefaultValue(p.Path + " ").
|
||||
Show("Enter aliases separated by space")
|
||||
|
||||
return strings.Split(response, " ")
|
||||
}
|
||||
|
||||
func init() {
|
||||
aliasCmd.AddCommand(aliasAddCmd)
|
||||
aliasAddCmd.PersistentFlags().Int("projectID", 0, "Specify a project by ID")
|
||||
viper.BindPFlag("alias.add.projectID", aliasAddCmd.Flag("projectID"))
|
||||
}
|
95
cmd/alias_delete.go
Normal file
95
cmd/alias_delete.go
Normal file
@ -0,0 +1,95 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/spf13/cobra"
|
||||
"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/projects"
|
||||
)
|
||||
|
||||
var aliasAddCmd = &cobra.Command{
|
||||
Use: "add",
|
||||
Short: "Add a project alias",
|
||||
Long: aliasAddCmdLong,
|
||||
Run: runAddAliasCmd,
|
||||
}
|
||||
|
||||
func runAddAliasCmd(cmd *cobra.Command, args []string) {
|
||||
var project *gitlab.Project
|
||||
|
||||
// Check by flag
|
||||
if projectID := viper.GetInt("alias.add.projectid"); projectID > 0 {
|
||||
plog.Debug(fmt.Sprintf("Adding for inbound project ID %d", projectID))
|
||||
project = cache.GetProjectByID(projectID)
|
||||
}
|
||||
|
||||
// Collect by fzf
|
||||
if project == nil {
|
||||
var err error
|
||||
project, err = fzfProject(cmd.Context())
|
||||
if err != nil || project == nil {
|
||||
plog.Fatal("No project to alias, nothing to do", plog.Args("error", err))
|
||||
}
|
||||
}
|
||||
|
||||
addNewAliases(project.ID)
|
||||
}
|
||||
|
||||
func addNewAliases(projectID int) {
|
||||
project := cache.GetProjectByID(projectID)
|
||||
if project == nil {
|
||||
plog.Error("Failed to find project to alias", plog.Args("projectID", projectID))
|
||||
return
|
||||
}
|
||||
|
||||
// Collect the aliases
|
||||
aliases := promptAliasesForProject(project)
|
||||
|
||||
// Add aliases
|
||||
for _, a := range aliases {
|
||||
a = strings.Trim(a, " '\"%")
|
||||
if a == "" {
|
||||
continue
|
||||
}
|
||||
if err := cache.AddAlias(a, project.ID); err != nil {
|
||||
plog.Debug("Skipping alias add", plog.Args(
|
||||
"error", err,
|
||||
"alias", a,
|
||||
))
|
||||
} else {
|
||||
plog.Info("Successfully added alias to project", plog.Args(
|
||||
"project", project.String(),
|
||||
"alias", a,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func promptAliasesForProject(p *gitlab.Project) []string {
|
||||
aliases := cache.GetProjectAliases(p)
|
||||
if len(aliases) > 0 {
|
||||
plog.Info("Adding aliases to project", plog.Args(
|
||||
"project", p.String(),
|
||||
"existingAliases", projects.ProjectAliasesString(aliases),
|
||||
))
|
||||
} else {
|
||||
pterm.Info.Printfln("Adding aliases to %s", p.Name)
|
||||
}
|
||||
|
||||
response, _ := pterm.DefaultInteractiveTextInput.
|
||||
WithMultiLine(false).
|
||||
WithDefaultValue(p.Path + " ").
|
||||
Show("Enter aliases separated by space")
|
||||
|
||||
return strings.Split(response, " ")
|
||||
}
|
||||
|
||||
func init() {
|
||||
aliasCmd.AddCommand(aliasAddCmd)
|
||||
aliasAddCmd.PersistentFlags().Int("projectID", 0, "Specify a project by ID")
|
||||
viper.BindPFlag("alias.add.projectID", aliasAddCmd.Flag("projectID"))
|
||||
}
|
@ -8,16 +8,12 @@ import (
|
||||
"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/projects"
|
||||
)
|
||||
|
||||
const desc = `Contains sub-commands for managing project cache.
|
||||
The project cache keeps this speedy, without smashing against the GitLab
|
||||
API every time a new project is added / searched for`
|
||||
|
||||
var cache *projects.Cache
|
||||
|
||||
var cacheCmd = &cobra.Command{
|
||||
Use: "cache",
|
||||
Short: "Manage GitLab project cache",
|
||||
Long: desc,
|
||||
Long: cacheCmdLong,
|
||||
PersistentPreRun: initCacheCmd,
|
||||
PersistentPostRun: postCacheCmd,
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var dumpCmd = &cobra.Command{
|
||||
@ -11,10 +12,16 @@ var dumpCmd = &cobra.Command{
|
||||
Short: "Dump GitLab project cache",
|
||||
Long: `Dumps cache to display`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(cache.String())
|
||||
if conf.Dump.Full {
|
||||
fmt.Println(cache.DumpString())
|
||||
} else {
|
||||
plog.Info(cache.String())
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
cacheCmd.AddCommand(dumpCmd)
|
||||
dumpCmd.PersistentFlags().BoolP("full", "f", false, "Dumps entire cache")
|
||||
viper.BindPFlag("dump.full", dumpCmd.LocalFlags().Lookup("full"))
|
||||
}
|
48
cmd/project.go
Normal file
48
cmd/project.go
Normal file
@ -0,0 +1,48 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/projects"
|
||||
)
|
||||
|
||||
var projectCmd = &cobra.Command{
|
||||
Use: "project [fuzzy alias search]",
|
||||
Short: "Use a GitLab project",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
ArgAliases: []string{"alias"},
|
||||
ValidArgsFunction: validAliasesFunc,
|
||||
Long: projCmdLong,
|
||||
PersistentPreRun: initProjectCmd,
|
||||
PersistentPostRun: postProjectCmd,
|
||||
Run: projectCmdRun,
|
||||
}
|
||||
|
||||
func projectCmdRun(cmd *cobra.Command, args []string) {
|
||||
var searchString string
|
||||
if len(args) > 0 {
|
||||
searchString = args[0]
|
||||
}
|
||||
project := fzfFindProject(searchString)
|
||||
|
||||
if project == nil {
|
||||
plog.Fatal("Failed to find a project, nothing to do")
|
||||
} else {
|
||||
plog.Info("Houston, we have a project", plog.Args(
|
||||
"project", project.String(),
|
||||
"aliases", projects.ProjectAliasesString(
|
||||
cache.GetProjectAliases(project)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
func initProjectCmd(cmd *cobra.Command, args []string) {
|
||||
initProjectCache(cmd, args)
|
||||
}
|
||||
|
||||
func postProjectCmd(cmd *cobra.Command, args []string) {
|
||||
postProjectCache(cmd, args)
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(projectCmd)
|
||||
}
|
44
cmd/project_show.go
Normal file
44
cmd/project_show.go
Normal file
@ -0,0 +1,44 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var projectShowCmd = &cobra.Command{
|
||||
Use: "show [fuzzy alias search]",
|
||||
Short: "Show detail for a GitLab project",
|
||||
Args: cobra.ArbitraryArgs,
|
||||
ValidArgsFunction: validProjectsOrAliasesFunc,
|
||||
Long: projShowCmdLong,
|
||||
Run: projectShowCmdRun,
|
||||
}
|
||||
|
||||
func projectShowCmdRun(cmd *cobra.Command, args []string) {
|
||||
var searchString string
|
||||
if len(args) > 0 {
|
||||
searchString = args[0]
|
||||
}
|
||||
|
||||
project := fzfFindProject(searchString)
|
||||
|
||||
if project == nil {
|
||||
var err error
|
||||
project, err = fzfProject(cmd.Context())
|
||||
if err != nil || project == nil {
|
||||
plog.Fatal("Failed to find project, nothing to show", plog.Args(
|
||||
"error", err,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(pterm.LightGreen("\n--------------"))
|
||||
fmt.Println(cache.ProjectString(project))
|
||||
fmt.Println(pterm.LightGreen("--------------\n"))
|
||||
}
|
||||
|
||||
func init() {
|
||||
projectCmd.AddCommand(projectShowCmd)
|
||||
}
|
10
cmd/root.go
10
cmd/root.go
@ -12,21 +12,13 @@ import (
|
||||
"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/config"
|
||||
)
|
||||
|
||||
const (
|
||||
defGitlabHost = "gitlab.sweetwater.com"
|
||||
defProjectsPath = "~/work/projects"
|
||||
defLogLevel = "info"
|
||||
)
|
||||
|
||||
var conf config.Config
|
||||
var plog *pterm.Logger
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "gitlab-project-manager",
|
||||
Short: "Find and use GitLab projects locally",
|
||||
Long: `Finds GitLab projects using fuzzy-find, remembering
|
||||
your chosen term for the project as an alias, and offers helpful
|
||||
shortcuts for moving around in projects and opening your code`,
|
||||
Long: rootCmdLong,
|
||||
PersistentPreRun: initRootCmd,
|
||||
}
|
||||
|
||||
|
20
cmd/util_completion.go
Normal file
20
cmd/util_completion.go
Normal file
@ -0,0 +1,20 @@
|
||||
package cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func validProjectsFunc(cmd *cobra.Command, args []string, toComplete string) (
|
||||
[]string, cobra.ShellCompDirective) {
|
||||
return cache.ProjectStrings(), cobra.ShellCompDirectiveDefault
|
||||
}
|
||||
|
||||
func validAliasesFunc(cmd *cobra.Command, args []string, toComplete string) (
|
||||
[]string, cobra.ShellCompDirective) {
|
||||
return cache.AliasStrings(), cobra.ShellCompDirectiveDefault
|
||||
}
|
||||
|
||||
func validProjectsOrAliasesFunc(cmd *cobra.Command, args []string, toComplete string) (
|
||||
[]string, cobra.ShellCompDirective) {
|
||||
projectStrings, _ := validAliasesFunc(cmd, args, toComplete)
|
||||
aliasStrings, _ := validProjectsFunc(cmd, args, toComplete)
|
||||
return append(projectStrings, aliasStrings...), cobra.ShellCompDirectiveDefault
|
||||
}
|
28
cmd/util_constants.go
Normal file
28
cmd/util_constants.go
Normal file
@ -0,0 +1,28 @@
|
||||
package cmd
|
||||
|
||||
const (
|
||||
defGitlabHost = "gitlab.sweetwater.com"
|
||||
defProjectsPath = "~/work/projects"
|
||||
defLogLevel = "info"
|
||||
)
|
||||
|
||||
const aliasCmdLong = `Manages project aliases, with options for
|
||||
listing, adding, and deleting.`
|
||||
|
||||
const aliasAddCmdLong = `Adds a project alias to a project
|
||||
project ID can be provided, or will otherwise use fuzzy find`
|
||||
|
||||
const cacheCmdLong = `Contains sub-commands for managing project cache.
|
||||
The project cache keeps this speedy, without smashing against the GitLab
|
||||
API every time a new project is added / searched for`
|
||||
|
||||
const rootCmdLong = `Finds GitLab projects using fuzzy-find, remembering
|
||||
your chosen term for the project as an alias, and offers helpful
|
||||
shortcuts for moving around in projects and opening your code`
|
||||
|
||||
const projCmdLong = `Switches to a GitLab project by name or alias
|
||||
If not found, will enter fzf mode. If not cloned, will clone
|
||||
the project locally.`
|
||||
|
||||
const projShowCmdLong = `Shows detail for a particular project
|
||||
Will always fuzzy find`
|
83
cmd/util_fzf.go
Normal file
83
cmd/util_fzf.go
Normal file
@ -0,0 +1,83 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
fzf "github.com/ktr0731/go-fuzzyfinder"
|
||||
"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/gitlab"
|
||||
"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/projects"
|
||||
)
|
||||
|
||||
func fzfFindProject(searchString string) *gitlab.Project {
|
||||
var project *gitlab.Project
|
||||
|
||||
if searchString != "" {
|
||||
project = fzfSearchProjectAliases(searchString)
|
||||
} else {
|
||||
var err error
|
||||
project, err = fzfProject(rootCmd.Context())
|
||||
if project == nil || err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return project
|
||||
}
|
||||
|
||||
func fzfSearchProjectAliases(searchString string) *gitlab.Project {
|
||||
var project *gitlab.Project
|
||||
var alias *projects.ProjectAlias
|
||||
if alias = cache.GetAliasByName(searchString); alias != nil {
|
||||
project = cache.GetProjectByAlias(alias)
|
||||
plog.Info("Perfect alias match... flawless")
|
||||
} else {
|
||||
// Get fuzzy if we don't have an exact match
|
||||
aliases := cache.FuzzyFindAlias(searchString)
|
||||
if len(aliases) > 1 {
|
||||
alias = fzfAliasFromAliases(aliasAddCmd.Context(), aliases)
|
||||
} else if len(aliases) == 1 {
|
||||
alias = aliases[0]
|
||||
}
|
||||
project = cache.GetProjectByAlias(alias)
|
||||
}
|
||||
return project
|
||||
}
|
||||
|
||||
func fzfAliasFromAliases(ctx context.Context, aliases []*projects.ProjectAlias) *projects.ProjectAlias {
|
||||
var alias *projects.ProjectAlias
|
||||
i, err := fzf.Find(
|
||||
aliases,
|
||||
func(i int) string {
|
||||
return aliases[i].Alias + " -> " + cache.GetProjectByAlias(aliases[i]).PathWithNamespace
|
||||
},
|
||||
fzf.WithContext(ctx),
|
||||
fzf.WithHeader("Choose an Alias"),
|
||||
)
|
||||
if err != nil {
|
||||
plog.Error("Failed to fzf alias slice", plog.Args("error", err))
|
||||
} else {
|
||||
alias = aliases[i]
|
||||
}
|
||||
return alias
|
||||
}
|
||||
|
||||
func fzfProject(ctx context.Context) (*gitlab.Project, error) {
|
||||
i, err := fzf.Find(cache.Projects, fzfProjectString,
|
||||
fzf.WithPreviewWindow(fzfPreviewWindow),
|
||||
fzf.WithContext(ctx),
|
||||
fzf.WithHeader("Fuzzy find yourself a project"),
|
||||
)
|
||||
if err != nil || i < 0 {
|
||||
return nil, err
|
||||
}
|
||||
return cache.Projects[i], nil
|
||||
}
|
||||
|
||||
func fzfPreviewWindow(i, w, h int) string {
|
||||
p := cache.Projects[i]
|
||||
return cache.ProjectString(p)
|
||||
}
|
||||
|
||||
func fzfProjectString(i int) string {
|
||||
return cache.Projects[i].String()
|
||||
}
|
@ -18,8 +18,8 @@ import (
|
||||
// func from their PersistentPreRun commands
|
||||
|
||||
func initProjectCache(cmd *cobra.Command, args []string) {
|
||||
plog.Debug("Running persistent pre-run for cacheCmd")
|
||||
conf.Cache.File = conf.ProjectPath + "/.cache.json"
|
||||
plog.Debug("Running pre-run for cacheCmd")
|
||||
conf.Cache.File = conf.ProjectPath + "/.cache.yaml"
|
||||
|
||||
gitlabClient, err := gitlab.NewGitlabClient(cmd.Context(), conf.GitlabHost, conf.GitlabToken)
|
||||
if err != nil {
|
||||
@ -38,7 +38,7 @@ func initProjectCache(cmd *cobra.Command, args []string) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := cache.Load(); err != nil {
|
||||
if err := cache.Read(); err != nil {
|
||||
plog.Error("Cache load failed", plog.Args("error", err))
|
||||
os.Exit(1)
|
||||
}
|
9
go.mod
9
go.mod
@ -3,6 +3,8 @@ module gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager
|
||||
go 1.21.2
|
||||
|
||||
require (
|
||||
github.com/ktr0731/go-fuzzyfinder v0.8.0
|
||||
github.com/lithammer/fuzzysearch v1.1.8
|
||||
github.com/pterm/pterm v0.12.71
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/viper v1.17.0
|
||||
@ -18,6 +20,8 @@ require (
|
||||
atomicgo.dev/schedule v0.1.0 // indirect
|
||||
github.com/containerd/console v1.0.3 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/gdamore/encoding v1.0.0 // indirect
|
||||
github.com/gdamore/tcell/v2 v2.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
@ -25,11 +29,14 @@ require (
|
||||
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.8 // indirect
|
||||
github.com/ktr0731/go-ansisgr v0.1.0 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/nsf/termbox-go v1.1.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
|
22
go.sum
22
go.sum
@ -83,6 +83,10 @@ github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0X
|
||||
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg=
|
||||
github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@ -126,10 +130,12 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
@ -183,21 +189,32 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/ktr0731/go-ansisgr v0.1.0 h1:fbuupput8739hQbEmZn1cEKjqQFwtCCZNznnF6ANo5w=
|
||||
github.com/ktr0731/go-ansisgr v0.1.0/go.mod h1:G9lxwgBwH0iey0Dw5YQd7n6PmQTwTuTM/X5Sgm/UrzE=
|
||||
github.com/ktr0731/go-fuzzyfinder v0.8.0 h1:+yobwo9lqZZ7jd1URPdCgZXTE2U1mpIVTkQoo4roi6w=
|
||||
github.com/ktr0731/go-fuzzyfinder v0.8.0/go.mod h1:Bjpz5im+tppKE9Ii6UK1h+6RaX/lUvJ0ruO4LIYRkqo=
|
||||
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
|
||||
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY=
|
||||
github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@ -214,6 +231,7 @@ github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkG
|
||||
github.com/pterm/pterm v0.12.71 h1:KcEJ98EiVCbzDkFbktJ2gMlr4pn8IzyGb9bwK6ffkuA=
|
||||
github.com/pterm/pterm v0.12.71/go.mod h1:SUAcoZjRt+yjPWlWba+/Fd8zJJ2lSXBQWf0Z0HbFiIQ=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
|
@ -8,6 +8,9 @@ type Config struct {
|
||||
LogLevel string `yaml:"logLevel" json:"logLevel" enum:"info,warn,debug,error"`
|
||||
ProjectPath string `yaml:"projectPath" json:"projectPath"`
|
||||
Cache cacheConfig `yaml:"cache" json:"cache"`
|
||||
Dump struct {
|
||||
Full bool
|
||||
}
|
||||
}
|
||||
|
||||
type cacheConfig struct {
|
||||
|
@ -2,12 +2,13 @@ package gitlab
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/xanzy/go-gitlab"
|
||||
)
|
||||
|
||||
const defProjectsPerPage = 100
|
||||
const defProjectsPerPage = 30
|
||||
|
||||
type Client struct {
|
||||
Ctx context.Context
|
||||
@ -20,7 +21,6 @@ type Project struct {
|
||||
SSHURLToRepo string
|
||||
HTTPURLToRepo string
|
||||
WebURL string
|
||||
// Owner User
|
||||
Name string
|
||||
NameWithNamespace string
|
||||
Path string
|
||||
@ -51,6 +51,10 @@ type Progress struct {
|
||||
TotalProjects int
|
||||
}
|
||||
|
||||
func (p *Project) String() string {
|
||||
return fmt.Sprintf("%s (%s)", p.Path, p.PathWithNamespace)
|
||||
}
|
||||
|
||||
// Given there may be thousands of projects, this will return
|
||||
// channels that stream progress info and then finally the full
|
||||
// list of projects on separate channels
|
||||
@ -77,6 +81,7 @@ func (c *Client) streamProjects(pi *ProgressInfo) {
|
||||
Page: 1,
|
||||
},
|
||||
Archived: new(bool),
|
||||
Owned: gitlab.Ptr[bool](true),
|
||||
}
|
||||
|
||||
var numProjects int
|
||||
|
@ -2,8 +2,8 @@ package projects
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -48,7 +48,7 @@ func (c *Cache) Load() error {
|
||||
|
||||
// Saves the current state of the cache to disk
|
||||
func (c *Cache) write() {
|
||||
file, err := os.OpenFile(c.file, os.O_RDWR, fs.ModeAppend)
|
||||
file, err := os.OpenFile(c.file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0640)
|
||||
if err != nil {
|
||||
c.log.Error("Failed to write cache to disk", c.log.Args("error", err))
|
||||
}
|
||||
@ -66,7 +66,7 @@ func (c *Cache) Write() {
|
||||
}
|
||||
|
||||
// Loads and unmarshals the project cache from disk.
|
||||
func (c *Cache) Read() {
|
||||
func (c *Cache) Read() error {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
c.log.Debug("Reading project cache from disk", c.log.Args("file", c.file))
|
||||
@ -74,18 +74,14 @@ func (c *Cache) Read() {
|
||||
file, err := os.Open(c.file)
|
||||
if err != nil {
|
||||
c.log.Error("Failed to read project cache", c.log.Args("error", err))
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
d := yaml.NewDecoder(file)
|
||||
d.Decode(c)
|
||||
|
||||
if time.Since(c.Updated) > c.ttl {
|
||||
c.refresh()
|
||||
}
|
||||
|
||||
c.readFromFile = true
|
||||
c.log.Debug(c.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
// Resets projects cache and also optionally clears
|
||||
@ -98,7 +94,6 @@ func (c *Cache) clear(clearAliases bool) {
|
||||
c.Aliases = make([]*ProjectAlias, 0)
|
||||
}
|
||||
c.setUpdated()
|
||||
c.log.Debug(c.String())
|
||||
}
|
||||
func (c *Cache) Clear(clearAliases bool) {
|
||||
c.lock.Lock()
|
||||
@ -127,6 +122,24 @@ func (c *Cache) String() string {
|
||||
len(c.Aliases))
|
||||
}
|
||||
|
||||
func (c *Cache) DumpString() string {
|
||||
str := strings.Builder{}
|
||||
str.WriteString(c.String() + "\n\nProjects:\n")
|
||||
for _, project := range c.Projects {
|
||||
str.WriteString(" - " + pterm.FgLightBlue.Sprint(project.Name) + " (")
|
||||
str.WriteString(project.PathWithNamespace + ")\n")
|
||||
aliases := c.GetProjectAliases(project)
|
||||
if len(aliases) > 0 {
|
||||
str.WriteString(pterm.FgLightGreen.Sprint(" aliases:"))
|
||||
for _, a := range aliases {
|
||||
str.WriteString(" [" + pterm.FgCyan.Sprint(a.Alias) + "]")
|
||||
}
|
||||
str.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
return str.String()
|
||||
}
|
||||
|
||||
func (c *Cache) setUpdated() {
|
||||
c.Updated = time.Now()
|
||||
}
|
||||
|
23
internal/projects/cache_aliases.go
Normal file
23
internal/projects/cache_aliases.go
Normal file
@ -0,0 +1,23 @@
|
||||
package projects
|
||||
|
||||
import "errors"
|
||||
|
||||
func (c *Cache) addAlias(alias string, projectID int) error {
|
||||
if c.GetAliasByName(alias) != nil {
|
||||
return errors.New("Failed to add alias, already exists")
|
||||
}
|
||||
|
||||
c.Aliases = append(c.Aliases,
|
||||
&ProjectAlias{
|
||||
Alias: alias,
|
||||
ProjectID: projectID,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) AddAlias(alias string, projectID int) error {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
return c.addAlias(alias, projectID)
|
||||
}
|
37
internal/projects/fuzz.go
Normal file
37
internal/projects/fuzz.go
Normal file
@ -0,0 +1,37 @@
|
||||
package projects
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/lithammer/fuzzysearch/fuzzy"
|
||||
)
|
||||
|
||||
// Performs a fuzzy find on the input string, returning the closest
|
||||
// matched based on its Levenshtein distance, along with an integer
|
||||
// indicating number of matches found
|
||||
func (c *Cache) FuzzyFindAlias(name string) []*ProjectAlias {
|
||||
ranks := fuzzy.RankFindFold(name, c.AliasStrings())
|
||||
if ranks.Len() == 1 {
|
||||
c.log.Debug("Fuzzy found alias result",
|
||||
c.log.Args(
|
||||
"searchTerm", ranks[0].Source,
|
||||
"foundAlias", ranks[0].Target,
|
||||
"levenshteinDistance", ranks[0].Distance,
|
||||
))
|
||||
} else if ranks.Len() > 1 {
|
||||
found := make([]string, ranks.Len())
|
||||
for i, r := range ranks {
|
||||
found[i] = r.Target
|
||||
}
|
||||
c.log.Warn("Fuzzy found multiple aliases, try being more specific",
|
||||
c.log.Args("foundAliases", strings.Join(found, ",")))
|
||||
}
|
||||
var aliases []*ProjectAlias
|
||||
if ranks.Len() > 0 {
|
||||
aliases = make([]*ProjectAlias, ranks.Len())
|
||||
for i, r := range ranks {
|
||||
aliases[i] = c.GetAliasByName(r.Target)
|
||||
}
|
||||
}
|
||||
return aliases
|
||||
}
|
@ -2,6 +2,7 @@ package projects
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pterm/pterm"
|
||||
"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/gitlab"
|
||||
@ -9,8 +10,93 @@ import (
|
||||
|
||||
type ProjectAlias struct {
|
||||
Alias string
|
||||
ProjectID string
|
||||
Project *gitlab.Project
|
||||
ProjectID int
|
||||
}
|
||||
|
||||
func ProjectAliasesString(aliases []*ProjectAlias) string {
|
||||
var str string
|
||||
for _, a := range aliases {
|
||||
str += "[" + pterm.LightCyan(a.Alias) + "] "
|
||||
}
|
||||
return strings.Trim(str, " ")
|
||||
}
|
||||
|
||||
func (c *Cache) ProjectString(p *gitlab.Project) string {
|
||||
info := strings.Builder{}
|
||||
|
||||
info.WriteString(pterm.LightBlue(p.Name))
|
||||
info.WriteRune('\n')
|
||||
if p.Description != "" {
|
||||
info.WriteString(p.Description)
|
||||
info.WriteRune('\n')
|
||||
}
|
||||
|
||||
info.WriteString("\nPath: " + pterm.LightGreen(p.PathWithNamespace))
|
||||
info.WriteString("\nProjectID: " + pterm.LightGreen(p.ID))
|
||||
info.WriteString("\nURL: " + pterm.LightGreen(p.WebURL))
|
||||
info.WriteString("\nLastActivity: " + pterm.LightMagenta(p.LastActivityAt.String()))
|
||||
info.WriteString("\nAliases: ")
|
||||
|
||||
aliases := c.GetProjectAliases(p)
|
||||
info.WriteString(ProjectAliasesString(aliases))
|
||||
|
||||
return info.String()
|
||||
}
|
||||
|
||||
func (c *Cache) ProjectStrings() []string {
|
||||
projects := make([]string, len(c.Projects))
|
||||
for i, p := range c.Projects {
|
||||
projects[i] = p.NameWithNamespace
|
||||
}
|
||||
return projects
|
||||
}
|
||||
|
||||
func (c *Cache) AliasStrings() []string {
|
||||
aliases := make([]string, len(c.Aliases))
|
||||
for i, a := range c.Aliases {
|
||||
aliases[i] = a.Alias
|
||||
}
|
||||
return aliases
|
||||
}
|
||||
|
||||
func (c *Cache) GetAliasByName(name string) *ProjectAlias {
|
||||
for _, a := range c.Aliases {
|
||||
if name == a.Alias {
|
||||
return a
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) GetProjectByID(id int) *gitlab.Project {
|
||||
for _, p := range c.Projects {
|
||||
if p.ID == id {
|
||||
return p
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) GetProjectByAlias(alias *ProjectAlias) *gitlab.Project {
|
||||
if alias == nil {
|
||||
return nil
|
||||
}
|
||||
for _, p := range c.Projects {
|
||||
if p.ID == alias.ProjectID {
|
||||
return p
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) GetProjectAliases(project *gitlab.Project) []*ProjectAlias {
|
||||
aliases := make([]*ProjectAlias, 0)
|
||||
for _, alias := range c.Aliases {
|
||||
if alias.ProjectID == project.ID {
|
||||
aliases = append(aliases, alias)
|
||||
}
|
||||
}
|
||||
return aliases
|
||||
}
|
||||
|
||||
func (c *Cache) LoadProjects() {
|
||||
@ -46,6 +132,7 @@ func (c *Cache) LoadProjects() {
|
||||
c.log.Warn("LoadProjects cancelled", c.log.Args("reason", c.gitlab.Ctx.Err()))
|
||||
return
|
||||
case <-progressInfo.DoneChan:
|
||||
pBar.Add(pBar.Total - curProjects)
|
||||
c.log.Info("Project load complete")
|
||||
return
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
package gitlab
|
||||
|
||||
import "github.com/xanzy/go-gitlab"
|
||||
|
||||
type Client struct {
|
||||
gitlab *gitlab.Client
|
||||
}
|
||||
|
||||
func NewGitlabClient(host, token string) (*Client, error) {
|
||||
client, err := gitlab.NewClient(token, gitlab.WithBaseURL(host))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gitlabClient := &Client{
|
||||
gitlab: client,
|
||||
}
|
||||
return gitlabClient, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user