feat: add directory-scoped host defaults (match_dirs) and repo list --limit
Add match_dirs field to host config entries for directory-based host resolution. When no --hostname flag, FGJ_HOST env var, or git remote is detected, the longest matching directory prefix determines the host. Symlinks are resolved on both sides for macOS compatibility (/tmp → /private/tmp). Also adds --limit/-L flag to repo list.
This commit is contained in:
parent
113505de95
commit
c293e233d2
17 changed files with 252 additions and 79 deletions
|
|
@ -420,7 +420,7 @@ func runRunList(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -469,7 +469,7 @@ func runRunView(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -668,7 +668,7 @@ func runRunWatch(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -718,7 +718,7 @@ func runRunRerun(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -749,7 +749,7 @@ func runRunCancel(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -866,7 +866,7 @@ func runWorkflowList(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -939,7 +939,7 @@ func runWorkflowView(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1000,7 +1000,7 @@ func runWorkflowRun(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1077,7 +1077,7 @@ func runWorkflowEnable(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1122,7 +1122,7 @@ func runWorkflowDisable(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1206,7 +1206,7 @@ func runActionsSecretList(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1241,7 +1241,7 @@ func runActionsSecretCreate(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1282,7 +1282,7 @@ func runActionsSecretDelete(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1318,7 +1318,7 @@ func runActionsVariableList(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1359,7 +1359,7 @@ func runActionsVariableGet(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1387,7 +1387,7 @@ func runActionsVariableCreate(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1416,7 +1416,7 @@ func runActionsVariableUpdate(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1445,7 +1445,7 @@ func runActionsVariableDelete(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to load config: %w", err)
|
return fmt.Errorf("failed to load config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ func runAPI(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
detectedHost := getDetectedHost()
|
detectedHost := getDetectedHost()
|
||||||
|
|
||||||
host, err := cfg.GetHost(hostname, detectedHost)
|
host, err := cfg.GetHost(hostname, detectedHost, getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
cmd/issue.go
16
cmd/issue.go
|
|
@ -203,7 +203,7 @@ func runIssueList(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -275,7 +275,7 @@ func runIssueView(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -375,7 +375,7 @@ func runIssueCreate(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -464,7 +464,7 @@ func runIssueComment(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -503,7 +503,7 @@ func runIssueClose(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -564,7 +564,7 @@ func runIssueEdit(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -687,7 +687,7 @@ func runIssueDelete(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -732,7 +732,7 @@ func runIssueReopen(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ func newLabelClient(cmd *cobra.Command) (*api.Client, string, string, error) {
|
||||||
return nil, "", "", err
|
return nil, "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", "", err
|
return nil, "", "", err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ func runMilestoneList(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -249,7 +249,7 @@ func runMilestoneView(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -264,7 +264,7 @@ func runMilestoneView(cmd *cobra.Command, args []string) error {
|
||||||
if web, _ := cmd.Flags().GetBool("web"); web {
|
if web, _ := cmd.Flags().GetBool("web"); web {
|
||||||
// Milestones don't have HTMLURL in the API, construct it
|
// Milestones don't have HTMLURL in the API, construct it
|
||||||
cfg2, _ := config.Load()
|
cfg2, _ := config.Load()
|
||||||
host, _ := cfg2.GetHost("", getDetectedHost())
|
host, _ := cfg2.GetHost("", getDetectedHost(), getCwd())
|
||||||
url := fmt.Sprintf("https://%s/%s/%s/milestone/%d", host.Hostname, owner, name, ms.ID)
|
url := fmt.Sprintf("https://%s/%s/%s/milestone/%d", host.Hostname, owner, name, ms.ID)
|
||||||
return ios.OpenInBrowser(url)
|
return ios.OpenInBrowser(url)
|
||||||
}
|
}
|
||||||
|
|
@ -315,7 +315,7 @@ func runMilestoneCreate(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -363,7 +363,7 @@ func runMilestoneEdit(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -450,7 +450,7 @@ func runMilestoneDelete(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
cmd/pr.go
16
cmd/pr.go
|
|
@ -228,7 +228,7 @@ func runPRList(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -367,7 +367,7 @@ func runPRView(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -500,7 +500,7 @@ func runPRCreate(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -611,7 +611,7 @@ func runPRMerge(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -678,7 +678,7 @@ func runPRClose(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -727,7 +727,7 @@ func runPRReopen(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -766,7 +766,7 @@ func runPRCheckout(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -886,7 +886,7 @@ func runPREdit(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ func runPRChecks(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ func runPRDiff(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ func runPRComment(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -191,7 +191,7 @@ func runPRReview(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ func runReleaseList(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -251,7 +251,7 @@ func runReleaseView(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -363,7 +363,7 @@ func runReleaseCreate(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -420,7 +420,7 @@ func runReleaseUpload(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -460,7 +460,7 @@ func runReleaseDownload(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -547,7 +547,7 @@ func runReleaseDelete(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
cmd/repo.go
22
cmd/repo.go
|
|
@ -125,6 +125,7 @@ func init() {
|
||||||
repoViewCmd.Flags().BoolP("web", "w", false, "Open in web browser")
|
repoViewCmd.Flags().BoolP("web", "w", false, "Open in web browser")
|
||||||
|
|
||||||
addJSONFlags(repoListCmd, "Output repositories as JSON")
|
addJSONFlags(repoListCmd, "Output repositories as JSON")
|
||||||
|
repoListCmd.Flags().IntP("limit", "L", 0, "Maximum number of repositories to list (0 = no limit)")
|
||||||
|
|
||||||
repoCloneCmd.Flags().StringP("protocol", "p", "https", "Clone protocol: https or ssh")
|
repoCloneCmd.Flags().StringP("protocol", "p", "https", "Clone protocol: https or ssh")
|
||||||
|
|
||||||
|
|
@ -158,7 +159,7 @@ func runRepoView(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -203,7 +204,7 @@ func runRepoList(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -221,6 +222,11 @@ func runRepoList(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to list repositories: %w", err)
|
return fmt.Errorf("failed to list repositories: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
limit, _ := cmd.Flags().GetInt("limit")
|
||||||
|
if limit > 0 && len(repos) > limit {
|
||||||
|
repos = repos[:limit]
|
||||||
|
}
|
||||||
|
|
||||||
if wantJSON(cmd) {
|
if wantJSON(cmd) {
|
||||||
return outputJSON(cmd, repos)
|
return outputJSON(cmd, repos)
|
||||||
}
|
}
|
||||||
|
|
@ -257,7 +263,7 @@ func runRepoClone(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -324,7 +330,7 @@ func runRepoFork(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -371,7 +377,7 @@ func runRepoCreate(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -439,7 +445,7 @@ func runRepoCreate(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
if doClone {
|
if doClone {
|
||||||
cloneURL := repo.CloneURL
|
cloneURL := repo.CloneURL
|
||||||
if hostCfg, hostErr := cfg.GetHost("", getDetectedHost()); hostErr == nil {
|
if hostCfg, hostErr := cfg.GetHost("", getDetectedHost(), getCwd()); hostErr == nil {
|
||||||
if hostCfg.GitProtocol == "ssh" {
|
if hostCfg.GitProtocol == "ssh" {
|
||||||
cloneURL = repo.SSHURL
|
cloneURL = repo.SSHURL
|
||||||
}
|
}
|
||||||
|
|
@ -494,7 +500,7 @@ func runRepoEdit(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -591,7 +597,7 @@ func runRepoRename(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,15 @@ func getDetectedHost() string {
|
||||||
return host
|
return host
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getCwd returns the current working directory, or "" on error.
|
||||||
|
func getCwd() string {
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return cwd
|
||||||
|
}
|
||||||
|
|
||||||
// promptLine prints a prompt to stderr and reads a line from stdin.
|
// promptLine prints a prompt to stderr and reads a line from stdin.
|
||||||
func promptLine(prompt string) (string, error) {
|
func promptLine(prompt string) (string, error) {
|
||||||
fmt.Fprint(ios.ErrOut, prompt)
|
fmt.Fprint(ios.ErrOut, prompt)
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ func newWikiClient(cmd *cobra.Command) (*api.Client, string, string, error) {
|
||||||
return nil, "", "", err
|
return nil, "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", "", err
|
return nil, "", "", err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@ func NewClient(hostname, token string) (*Client, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientFromConfig(cfg *config.Config, hostname string, detectedHost string) (*Client, error) {
|
func NewClientFromConfig(cfg *config.Config, hostname string, detectedHost string, cwd string) (*Client, error) {
|
||||||
host, err := cfg.GetHost(hostname, detectedHost)
|
host, err := cfg.GetHost(hostname, detectedHost, cwd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ func TestNewClientFromConfig_MissingHost(t *testing.T) {
|
||||||
Hosts: map[string]config.HostConfig{},
|
Hosts: map[string]config.HostConfig{},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := NewClientFromConfig(cfg, "nonexistent.org", "")
|
_, err := NewClientFromConfig(cfg, "nonexistent.org", "", "")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Expected error for nonexistent host")
|
t.Error("Expected error for nonexistent host")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
@ -14,10 +15,11 @@ type Config struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostConfig struct {
|
type HostConfig struct {
|
||||||
Hostname string `yaml:"hostname"`
|
Hostname string `yaml:"hostname"`
|
||||||
Token string `yaml:"token"`
|
Token string `yaml:"token"`
|
||||||
User string `yaml:"user,omitempty"`
|
User string `yaml:"user,omitempty"`
|
||||||
GitProtocol string `yaml:"git_protocol,omitempty"`
|
GitProtocol string `yaml:"git_protocol,omitempty"`
|
||||||
|
MatchDirs []string `yaml:"match_dirs,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetConfigDir() (string, error) {
|
func GetConfigDir() (string, error) {
|
||||||
|
|
@ -96,8 +98,9 @@ func (c *Config) SaveToPath(path string) error {
|
||||||
// 2. CLI flag (--hostname)
|
// 2. CLI flag (--hostname)
|
||||||
// 3. Environment variable (FGJ_HOST)
|
// 3. Environment variable (FGJ_HOST)
|
||||||
// 4. Auto-detected hostname from git remote
|
// 4. Auto-detected hostname from git remote
|
||||||
// 5. Default to codeberg.org
|
// 5. match_dirs lookup (longest prefix match)
|
||||||
func (c *Config) GetHost(hostname string, detectedHost string) (HostConfig, error) {
|
// 6. Default to codeberg.org
|
||||||
|
func (c *Config) GetHost(hostname string, detectedHost string, cwd string) (HostConfig, error) {
|
||||||
if hostname == "" {
|
if hostname == "" {
|
||||||
hostname = viper.GetString("hostname")
|
hostname = viper.GetString("hostname")
|
||||||
}
|
}
|
||||||
|
|
@ -110,6 +113,10 @@ func (c *Config) GetHost(hostname string, detectedHost string) (HostConfig, erro
|
||||||
hostname = detectedHost
|
hostname = detectedHost
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hostname == "" {
|
||||||
|
hostname = c.ResolveHostByPath(cwd)
|
||||||
|
}
|
||||||
|
|
||||||
if hostname == "" {
|
if hostname == "" {
|
||||||
hostname = "codeberg.org"
|
hostname = "codeberg.org"
|
||||||
}
|
}
|
||||||
|
|
@ -122,6 +129,50 @@ func (c *Config) GetHost(hostname string, detectedHost string) (HostConfig, erro
|
||||||
return host, nil
|
return host, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResolveHostByPath finds the host whose match_dirs entry is the longest
|
||||||
|
// prefix of cwd. Returns "" if no match is found.
|
||||||
|
// Both cwd and match_dirs entries are resolved through filepath.EvalSymlinks
|
||||||
|
// to handle symlinks (e.g. macOS /tmp → /private/tmp).
|
||||||
|
func (c *Config) ResolveHostByPath(cwd string) string {
|
||||||
|
if cwd == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve symlinks in cwd so /tmp becomes /private/tmp on macOS, etc.
|
||||||
|
if resolved, err := filepath.EvalSymlinks(cwd); err == nil {
|
||||||
|
cwd = resolved
|
||||||
|
}
|
||||||
|
|
||||||
|
bestHost := ""
|
||||||
|
bestLen := 0
|
||||||
|
|
||||||
|
for hostname, host := range c.Hosts {
|
||||||
|
for _, dir := range host.MatchDirs {
|
||||||
|
if dir == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Resolve symlinks in the configured dir as well
|
||||||
|
if resolved, err := filepath.EvalSymlinks(dir); err == nil {
|
||||||
|
dir = resolved
|
||||||
|
}
|
||||||
|
// Normalize: ensure trailing slash for prefix matching
|
||||||
|
prefix := dir
|
||||||
|
if !strings.HasSuffix(prefix, "/") {
|
||||||
|
prefix += "/"
|
||||||
|
}
|
||||||
|
// Match if cwd equals dir exactly or is under it
|
||||||
|
if cwd == dir || strings.HasPrefix(cwd, prefix) {
|
||||||
|
if len(dir) > bestLen {
|
||||||
|
bestLen = len(dir)
|
||||||
|
bestHost = hostname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestHost
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Config) SetHost(hostname string, host HostConfig) {
|
func (c *Config) SetHost(hostname string, host HostConfig) {
|
||||||
if c.Hosts == nil {
|
if c.Hosts == nil {
|
||||||
c.Hosts = make(map[string]HostConfig)
|
c.Hosts = make(map[string]HostConfig)
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ func TestConfig_GetHost(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
host, err := cfg.GetHost("codeberg.org", "")
|
host, err := cfg.GetHost("codeberg.org", "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +58,7 @@ func TestConfig_GetHost(t *testing.T) {
|
||||||
t.Errorf("Expected hostname 'codeberg.org', got '%s'", host.Hostname)
|
t.Errorf("Expected hostname 'codeberg.org', got '%s'", host.Hostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = cfg.GetHost("nonexistent.org", "")
|
_, err = cfg.GetHost("nonexistent.org", "", "")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Expected error for nonexistent host")
|
t.Error("Expected error for nonexistent host")
|
||||||
}
|
}
|
||||||
|
|
@ -275,7 +275,7 @@ func TestConfig_GetHost_EmptyString(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty hostname should default to codeberg.org
|
// Empty hostname should default to codeberg.org
|
||||||
host, err := cfg.GetHost("", "")
|
host, err := cfg.GetHost("", "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -296,7 +296,7 @@ func TestConfig_GetHost_WhitespaceString(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whitespace-only hostname should default to codeberg.org
|
// Whitespace-only hostname should default to codeberg.org
|
||||||
host, err := cfg.GetHost(" ", "")
|
host, err := cfg.GetHost(" ", "", "")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Logf("Got host: %+v (this may be expected behavior)", host)
|
t.Logf("Got host: %+v (this may be expected behavior)", host)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -315,7 +315,7 @@ func TestConfig_SetHost_EmptyToken(t *testing.T) {
|
||||||
|
|
||||||
cfg.SetHost("codeberg.org", hostConfig)
|
cfg.SetHost("codeberg.org", hostConfig)
|
||||||
|
|
||||||
host, err := cfg.GetHost("codeberg.org", "")
|
host, err := cfg.GetHost("codeberg.org", "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -345,7 +345,7 @@ func TestConfig_SetHost_OverwriteExisting(t *testing.T) {
|
||||||
|
|
||||||
cfg.SetHost("codeberg.org", newConfig)
|
cfg.SetHost("codeberg.org", newConfig)
|
||||||
|
|
||||||
host, err := cfg.GetHost("codeberg.org", "")
|
host, err := cfg.GetHost("codeberg.org", "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -388,7 +388,7 @@ func TestConfig_MultipleHosts(t *testing.T) {
|
||||||
|
|
||||||
// Verify each host can be retrieved correctly
|
// Verify each host can be retrieved correctly
|
||||||
for _, h := range hosts {
|
for _, h := range hosts {
|
||||||
host, err := cfg.GetHost(h.hostname, "")
|
host, err := cfg.GetHost(h.hostname, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to get host %s: %v", h.hostname, err)
|
t.Errorf("Failed to get host %s: %v", h.hostname, err)
|
||||||
continue
|
continue
|
||||||
|
|
@ -422,13 +422,120 @@ func TestConfig_GitProtocol(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Verify protocols are stored correctly
|
// Verify protocols are stored correctly
|
||||||
sshHost, _ := cfg.GetHost("test-ssh.org", "")
|
sshHost, _ := cfg.GetHost("test-ssh.org", "", "")
|
||||||
if sshHost.GitProtocol != "ssh" {
|
if sshHost.GitProtocol != "ssh" {
|
||||||
t.Errorf("Expected git_protocol 'ssh', got '%s'", sshHost.GitProtocol)
|
t.Errorf("Expected git_protocol 'ssh', got '%s'", sshHost.GitProtocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
httpsHost, _ := cfg.GetHost("test-https.org", "")
|
httpsHost, _ := cfg.GetHost("test-https.org", "", "")
|
||||||
if httpsHost.GitProtocol != "https" {
|
if httpsHost.GitProtocol != "https" {
|
||||||
t.Errorf("Expected git_protocol 'https', got '%s'", httpsHost.GitProtocol)
|
t.Errorf("Expected git_protocol 'https', got '%s'", httpsHost.GitProtocol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResolveHostByPath(t *testing.T) {
|
||||||
|
cfg := &Config{
|
||||||
|
Hosts: map[string]HostConfig{
|
||||||
|
"forgejo.zerova.net": {
|
||||||
|
Hostname: "forgejo.zerova.net",
|
||||||
|
Token: "token1",
|
||||||
|
MatchDirs: []string{"/Users/sid/repos/fgj", "/Users/sid/repos/zerova"},
|
||||||
|
},
|
||||||
|
"codeberg.org": {
|
||||||
|
Hostname: "codeberg.org",
|
||||||
|
Token: "token2",
|
||||||
|
MatchDirs: []string{"/"},
|
||||||
|
},
|
||||||
|
"gitea.example.com": {
|
||||||
|
Hostname: "gitea.example.com",
|
||||||
|
Token: "token3",
|
||||||
|
// no match_dirs — should never be selected by path
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cwd string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"exact dir match", "/Users/sid/repos/fgj", "forgejo.zerova.net"},
|
||||||
|
{"nested dir match", "/Users/sid/repos/fgj/cmd/root.go", "forgejo.zerova.net"},
|
||||||
|
{"second match dir", "/Users/sid/repos/zerova/pkg", "forgejo.zerova.net"},
|
||||||
|
{"longest prefix wins over /", "/Users/sid/repos/fgj/internal", "forgejo.zerova.net"},
|
||||||
|
{"/ as global catch-all", "/tmp", "codeberg.org"},
|
||||||
|
{"/ matches root itself", "/", "codeberg.org"},
|
||||||
|
{"no match_dirs host not selected", "/some/random/path", "codeberg.org"},
|
||||||
|
{"empty cwd returns empty", "", ""},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := cfg.ResolveHostByPath(tt.cwd)
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("ResolveHostByPath(%q) = %q, want %q", tt.cwd, got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolveHostByPath_LongestPrefixAcrossHosts(t *testing.T) {
|
||||||
|
cfg := &Config{
|
||||||
|
Hosts: map[string]HostConfig{
|
||||||
|
"broad.org": {
|
||||||
|
Hostname: "broad.org",
|
||||||
|
Token: "t1",
|
||||||
|
MatchDirs: []string{"/Users/sid"},
|
||||||
|
},
|
||||||
|
"specific.org": {
|
||||||
|
Hostname: "specific.org",
|
||||||
|
Token: "t2",
|
||||||
|
MatchDirs: []string{"/Users/sid/repos/myproject"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
got := cfg.ResolveHostByPath("/Users/sid/repos/myproject/main.go")
|
||||||
|
if got != "specific.org" {
|
||||||
|
t.Errorf("expected specific.org, got %q", got)
|
||||||
|
}
|
||||||
|
|
||||||
|
got = cfg.ResolveHostByPath("/Users/sid/other")
|
||||||
|
if got != "broad.org" {
|
||||||
|
t.Errorf("expected broad.org, got %q", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetHost_MatchDirsIntegration(t *testing.T) {
|
||||||
|
cfg := &Config{
|
||||||
|
Hosts: map[string]HostConfig{
|
||||||
|
"forgejo.zerova.net": {
|
||||||
|
Hostname: "forgejo.zerova.net",
|
||||||
|
Token: "token1",
|
||||||
|
MatchDirs: []string{"/Users/sid/repos/fgj"},
|
||||||
|
},
|
||||||
|
"codeberg.org": {
|
||||||
|
Hostname: "codeberg.org",
|
||||||
|
Token: "token2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// cwd match should resolve to forgejo.zerova.net
|
||||||
|
host, err := cfg.GetHost("", "", "/Users/sid/repos/fgj/cmd")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if host.Hostname != "forgejo.zerova.net" {
|
||||||
|
t.Errorf("expected forgejo.zerova.net, got %s", host.Hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
// no cwd match falls through to codeberg.org default
|
||||||
|
host, err = cfg.GetHost("", "", "/tmp")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if host.Hostname != "codeberg.org" {
|
||||||
|
t.Errorf("expected codeberg.org, got %s", host.Hostname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue