avoid-project-id-collisions #2

Merged
rmcguire merged 3 commits from avoid-project-id-collisions into main 2025-01-01 01:23:11 +00:00
7 changed files with 51 additions and 25 deletions
Showing only changes of commit 70027a9880 - Show all commits

View File

@ -28,7 +28,15 @@ func runAddAliasCmd(cmd *cobra.Command, args []string) {
// Check by flag // Check by flag
if projectID := viper.GetInt(util.ViperAliasAddPID); projectID > 0 { if projectID := viper.GetInt(util.ViperAliasAddPID); projectID > 0 {
utils.Logger().Debug(fmt.Sprintf("Adding for inbound project ID %d", projectID)) utils.Logger().Debug(fmt.Sprintf("Adding for inbound project ID %d", projectID))
project = utils.Cache().GetProjectByID(projectID)
projects := utils.Cache().GetProjectsByID(projectID)
if len(projects) > 0 {
project = projects[0]
}
if len(projects) > 1 {
utils.Logger().
Warn(fmt.Sprintf("found %d remotes with same ID, using first remote", len(projects)))
}
} }
// Check by arg // Check by arg
@ -45,10 +53,10 @@ func runAddAliasCmd(cmd *cobra.Command, args []string) {
} }
} }
AddNewAliases(cmd, project.ID) AddNewAliases(cmd, project.GetID())
} }
func AddNewAliases(cmd *cobra.Command, projectID int) { func AddNewAliases(cmd *cobra.Command, projectID string) {
u := util.MustFromCtx(cmd.Context()) u := util.MustFromCtx(cmd.Context())
project := u.Cache().GetProjectByID(projectID) project := u.Cache().GetProjectByID(projectID)
if project == nil { if project == nil {
@ -65,7 +73,7 @@ func AddNewAliases(cmd *cobra.Command, projectID int) {
if a == "" { if a == "" {
continue continue
} }
if err := u.Cache().AddAlias(a, project.ID, project.Remote); err != nil { if err := u.Cache().AddAlias(a, project); err != nil {
u.Logger().Debug("Skipping alias add", u.Logger().Args( u.Logger().Debug("Skipping alias add", u.Logger().Args(
"error", err, "error", err,
"alias", a, "alias", a,

View File

@ -50,7 +50,7 @@ func getProject(cmd *cobra.Command, args []string) *projects.Project {
if len(utils.Cache().GetProjectAliases(project)) == 0 { if len(utils.Cache().GetProjectAliases(project)) == 0 {
utils.Logger().Info("New project, set aliases or press enter for default") utils.Logger().Info("New project, set aliases or press enter for default")
alias.AddNewAliases(cmd, project.ID) alias.AddNewAliases(cmd, project.GetID())
} }
return project return project

View File

@ -22,7 +22,7 @@ func (c *Cache) DeleteAlias(alias *ProjectAlias) {
c.deleteAlias(alias) c.deleteAlias(alias)
} }
func (c *Cache) addAlias(alias string, projectID int, remote string) error { func (c *Cache) addAlias(alias string, project *projects.Project) error {
if c.GetAliasByName(alias) != nil { if c.GetAliasByName(alias) != nil {
return errors.New("failed to add alias, already exists") return errors.New("failed to add alias, already exists")
} }
@ -30,26 +30,27 @@ func (c *Cache) addAlias(alias string, projectID int, remote string) error {
c.Aliases = append(c.Aliases, c.Aliases = append(c.Aliases,
&ProjectAlias{ &ProjectAlias{
Alias: alias, Alias: alias,
ProjectID: projectID, ProjectID: project.ID,
Remote: remote, ID: project.GetID(),
Remote: project.Remote,
}) })
return nil return nil
} }
func (c *Cache) AddAlias(alias string, projectID int, remote string) error { func (c *Cache) AddAlias(alias string, project *projects.Project) error {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
return c.addAlias(alias, projectID, remote) return c.addAlias(alias, project)
} }
func (c *Cache) GetProjectsWithAliases() []*projects.Project { func (c *Cache) GetProjectsWithAliases() []*projects.Project {
projectList := make([]*projects.Project, 0) projectList := make([]*projects.Project, 0)
projectsFound := make([]int, 0) projectsFound := make([]string, 0)
for _, a := range c.Aliases { for _, a := range c.Aliases {
if !slices.Contains(projectsFound, a.ProjectID) { if !slices.Contains(projectsFound, a.ID) {
projectList = append(projectList, c.GetProjectByAlias(a)) projectList = append(projectList, c.GetProjectByAlias(a))
projectsFound = append(projectsFound, a.ProjectID) projectsFound = append(projectsFound, a.ID)
} }
} }
return projectList return projectList
@ -68,12 +69,13 @@ func (c *Cache) setAliasRemotes() {
} }
func (c *Cache) setAliasRemote(alias *ProjectAlias) { func (c *Cache) setAliasRemote(alias *ProjectAlias) {
project := c.GetProjectByID(alias.ProjectID) project := c.GetProjectByID(alias.ID)
if project != nil { if project != nil {
alias.Remote = project.Remote alias.Remote = project.Remote
c.log.Debug("Fixed missing alias remote", c.log.Args( c.log.Debug("Fixed missing alias remote", c.log.Args(
"alias", alias.Alias, "alias", alias.Alias,
"projectID", alias.ProjectID, "projectID", alias.ProjectID,
"ID", alias.ID,
"remote", alias.Remote, "remote", alias.Remote,
)) ))
} }

View File

@ -4,8 +4,9 @@ import (
"strings" "strings"
"github.com/pterm/pterm" "github.com/pterm/pterm"
"gitea.libretechconsulting.com/rmcguire/git-project-manager/internal/remotes/projects"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"gitea.libretechconsulting.com/rmcguire/git-project-manager/internal/remotes/projects"
) )
func (c *Cache) ProjectString(p *projects.Project) string { func (c *Cache) ProjectString(p *projects.Project) string {
@ -60,9 +61,9 @@ func (c *Cache) GetProjectByRemoteAndId(remote string, id int) *projects.Project
return nil return nil
} }
func (c *Cache) GetProjectByID(id int) *projects.Project { func (c *Cache) GetProjectByID(id string) *projects.Project {
for _, p := range c.Projects { for _, p := range c.Projects {
if p.ID == id { if p.GetID() == id {
return p return p
} }
} }

View File

@ -7,13 +7,15 @@ import (
"text/tabwriter" "text/tabwriter"
"github.com/pterm/pterm" "github.com/pterm/pterm"
"gitea.libretechconsulting.com/rmcguire/git-project-manager/internal/remotes/projects"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"gitea.libretechconsulting.com/rmcguire/git-project-manager/internal/remotes/projects"
) )
type ProjectAlias struct { type ProjectAlias struct {
Alias string Alias string
ProjectID int ProjectID int
ID string
Remote string Remote string
} }
@ -96,7 +98,7 @@ func (c *Cache) GetProjectByAlias(alias *ProjectAlias) *projects.Project {
return nil return nil
} }
for _, p := range c.Projects { for _, p := range c.Projects {
if p.ID == alias.ProjectID && p.Remote == alias.Remote { if p.GetID() == alias.ID {
return p return p
} }
} }

View File

@ -1,6 +1,7 @@
package projects package projects
import ( import (
"crypto/sha1"
"fmt" "fmt"
"strings" "strings"
"time" "time"
@ -35,8 +36,7 @@ type ProjectLanguage struct {
} }
func NewProjectLanguages() *ProjectLanguages { func NewProjectLanguages() *ProjectLanguages {
var pLangs ProjectLanguages var pLangs ProjectLanguages = make([]*ProjectLanguage, 0)
pLangs = make([]*ProjectLanguage, 0)
return &pLangs return &pLangs
} }
@ -44,6 +44,21 @@ func (pl *ProjectLanguages) AddLanguage(lang *ProjectLanguage) {
*pl = append(*pl, lang) *pl = append(*pl, lang)
} }
// Gets a unique ID using a short-sha of the http repo URL
// along with the numerical ID of the project.
// Uses SSH URL and then Remote if previous is empty
func (p *Project) GetID() string {
shaText := p.HTTPURLToRepo
if shaText == "" && p.SSHURLToRepo != "" {
shaText = p.SSHURLToRepo
} else if shaText == "" {
shaText = p.Remote
}
shortSha := fmt.Sprintf("%x", sha1.Sum([]byte(shaText)))[:12]
return fmt.Sprintf("%s||%d", shortSha, p.ID)
}
func (p *Project) String() string { func (p *Project) String() string {
var projectString string var projectString string
if p != nil { if p != nil {

View File

@ -20,9 +20,7 @@ const (
GitProtoHTTP GitProtoHTTP
) )
var ( var ErrUnknownHost error = errors.New("no addresses found for host")
ErrUnknownHost error = errors.New("No addresses found for host")
)
func (p *Project) CheckHost(proto GitProto) error { func (p *Project) CheckHost(proto GitProto) error {
switch proto { switch proto {
@ -31,7 +29,7 @@ func (p *Project) CheckHost(proto GitProto) error {
case GitProtoSSH: case GitProtoSSH:
return p.checkSSHRemote() return p.checkSSHRemote()
} }
return errors.New("Unknown git protocol") return errors.New("unknown git protocol")
} }
func (p *Project) checkHTTPRemote() error { func (p *Project) checkHTTPRemote() error {