feat: auto detect hostname
This commit is contained in:
parent
2c27823e18
commit
c0baf4fa3b
13 changed files with 300 additions and 125 deletions
18
README.md
18
README.md
|
|
@ -87,12 +87,12 @@ fgj pr view 123 # Automatically uses current repo
|
||||||
fgj pr list -R owner/repo
|
fgj pr list -R owner/repo
|
||||||
```
|
```
|
||||||
|
|
||||||
The tool reads `.git/config` to find the origin remote and extract the owner/repo information. If you're not in a git repository, you'll need to use the `-R` flag.
|
The tool reads `.git/config` to find the origin remote and extract both the owner/repo information and the Forgejo instance hostname. If you're not in a git repository, you'll need to use the `-R` flag.
|
||||||
|
|
||||||
### Pull Requests
|
### Pull Requests
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# List pull requests (auto-detects repo from git)
|
# List pull requests (auto-detects repo and hostname from git)
|
||||||
fgj pr list
|
fgj pr list
|
||||||
|
|
||||||
# Or specify explicitly
|
# Or specify explicitly
|
||||||
|
|
@ -114,7 +114,7 @@ fgj pr merge 123 --merge-method squash
|
||||||
### Issues
|
### Issues
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# List issues (auto-detects repo from git)
|
# List issues (auto-detects repo and hostname from git)
|
||||||
fgj issue list
|
fgj issue list
|
||||||
|
|
||||||
# Or specify explicitly
|
# Or specify explicitly
|
||||||
|
|
@ -237,14 +237,22 @@ hosts:
|
||||||
|
|
||||||
### Environment Variables
|
### Environment Variables
|
||||||
|
|
||||||
- `FGJ_HOST`: Override the default Forgejo instance
|
- `FGJ_HOST`: Override the default Forgejo instance (auto-detected from git remote if not set)
|
||||||
- `FGJ_TOKEN`: Provide authentication token
|
- `FGJ_TOKEN`: Provide authentication token
|
||||||
|
|
||||||
|
Hostname is resolved in this priority order:
|
||||||
|
1. Command-specific flags (e.g., `--hostname`)
|
||||||
|
2. `FGJ_HOST` environment variable
|
||||||
|
3. Auto-detected from git remote URL
|
||||||
|
4. Default to `codeberg.org`
|
||||||
|
|
||||||
### Command-line Flags
|
### Command-line Flags
|
||||||
|
|
||||||
- `--hostname`: Specify Forgejo instance for a command
|
- `--hostname`: Specify Forgejo instance for a command (overrides auto-detection and environment variables)
|
||||||
- `--config`: Use a custom config file
|
- `--config`: Use a custom config file
|
||||||
|
|
||||||
|
When working in a git repository, `fgj` automatically detects the Forgejo instance from your origin remote URL, so you typically don't need to specify `--hostname` unless working with multiple instances.
|
||||||
|
|
||||||
## Use with AI Coding Agents
|
## Use with AI Coding Agents
|
||||||
|
|
||||||
`fgj` is designed to work seamlessly with AI coding agents like Claude Code. Common patterns:
|
`fgj` is designed to work seamlessly with AI coding agents like Claude Code. Common patterns:
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,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, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -277,7 +277,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, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -507,7 +507,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, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -550,7 +550,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, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -591,7 +591,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, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -626,7 +626,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, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -654,7 +654,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, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -683,7 +683,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, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -712,7 +712,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, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client: %w", err)
|
return fmt.Errorf("failed to create client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
cmd/issue.go
12
cmd/issue.go
|
|
@ -108,7 +108,7 @@ func runIssueList(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +166,7 @@ func runIssueView(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +220,7 @@ func runIssueCreate(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +261,7 @@ func runIssueComment(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -296,7 +296,7 @@ func runIssueClose(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -339,7 +339,7 @@ func runIssueEdit(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
27
cmd/pr.go
27
cmd/pr.go
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"codeberg.org/romaintb/fgj/internal/api"
|
"codeberg.org/romaintb/fgj/internal/api"
|
||||||
"codeberg.org/romaintb/fgj/internal/config"
|
"codeberg.org/romaintb/fgj/internal/config"
|
||||||
"codeberg.org/romaintb/fgj/internal/git"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var prCmd = &cobra.Command{
|
var prCmd = &cobra.Command{
|
||||||
|
|
@ -88,7 +87,7 @@ func runPRList(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -144,7 +143,7 @@ func runPRView(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -198,7 +197,7 @@ func runPRCreate(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -252,7 +251,7 @@ func runPRMerge(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -281,21 +280,3 @@ func runPRMerge(cmd *cobra.Command, args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseRepo(repo string) (string, string, error) {
|
|
||||||
// If repo flag is provided, use it
|
|
||||||
if repo != "" {
|
|
||||||
parts := strings.Split(repo, "/")
|
|
||||||
if len(parts) != 2 {
|
|
||||||
return "", "", fmt.Errorf("invalid repository format: %s (expected: owner/name)", repo)
|
|
||||||
}
|
|
||||||
return parts[0], parts[1], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to auto-detect from git
|
|
||||||
owner, name, err := git.DetectRepo()
|
|
||||||
if err != nil {
|
|
||||||
return "", "", fmt.Errorf("repository flag is required (use -R owner/name) or run from a git repository: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return owner, name, nil
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ func runReleaseList(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -176,7 +176,7 @@ func runReleaseView(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -258,7 +258,7 @@ func runReleaseCreate(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -309,7 +309,7 @@ func runReleaseUpload(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -341,7 +341,7 @@ func runReleaseDelete(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ func runRepoView(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -108,7 +108,7 @@ func runRepoList(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +160,7 @@ func runRepoClone(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -221,7 +221,7 @@ func runRepoFork(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := api.NewClientFromConfig(cfg, "")
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
cmd/root.go
33
cmd/root.go
|
|
@ -3,9 +3,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
"codeberg.org/romaintb/fgj/internal/git"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cfgFile string
|
var cfgFile string
|
||||||
|
|
@ -53,3 +55,34 @@ func initConfig() {
|
||||||
|
|
||||||
_ = viper.ReadInConfig()
|
_ = viper.ReadInConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseRepo parses the repository string in the format "owner/name".
|
||||||
|
// If not provided, it attempts to auto-detect from the git repository.
|
||||||
|
func parseRepo(repo string) (string, string, error) {
|
||||||
|
// If repo flag is provided, use it
|
||||||
|
if repo != "" {
|
||||||
|
parts := strings.Split(repo, "/")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return "", "", fmt.Errorf("invalid repository format: %s (expected: owner/name)", repo)
|
||||||
|
}
|
||||||
|
return parts[0], parts[1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to auto-detect from git
|
||||||
|
owner, name, err := git.DetectRepo()
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf("repository flag is required (use -R owner/name) or run from a git repository: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return owner, name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getDetectedHost attempts to auto-detect the Forgejo instance hostname.
|
||||||
|
// Returns empty string if detection fails, which will fall back to other methods.
|
||||||
|
func getDetectedHost() string {
|
||||||
|
host, err := git.DetectHost()
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return host
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ func NewClient(hostname, token string) (*Client, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientFromConfig(cfg *config.Config, hostname string) (*Client, error) {
|
func NewClientFromConfig(cfg *config.Config, hostname string, detectedHost string) (*Client, error) {
|
||||||
host, err := cfg.GetHost(hostname)
|
host, err := cfg.GetHost(hostname, detectedHost)
|
||||||
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")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,14 @@ func (c *Config) SaveToPath(path string) error {
|
||||||
return os.WriteFile(path, data, 0600)
|
return os.WriteFile(path, data, 0600)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetHost(hostname string) (HostConfig, error) {
|
// GetHost resolves the hostname to use for API client creation.
|
||||||
|
// Priority order:
|
||||||
|
// 1. Explicitly provided hostname parameter
|
||||||
|
// 2. CLI flag (--hostname)
|
||||||
|
// 3. Environment variable (FGJ_HOST)
|
||||||
|
// 4. Auto-detected hostname from git remote
|
||||||
|
// 5. Default to codeberg.org
|
||||||
|
func (c *Config) GetHost(hostname string, detectedHost string) (HostConfig, error) {
|
||||||
if hostname == "" {
|
if hostname == "" {
|
||||||
hostname = viper.GetString("hostname")
|
hostname = viper.GetString("hostname")
|
||||||
}
|
}
|
||||||
|
|
@ -96,6 +103,10 @@ func (c *Config) GetHost(hostname string) (HostConfig, error) {
|
||||||
hostname = os.Getenv("FGJ_HOST")
|
hostname = os.Getenv("FGJ_HOST")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hostname == "" {
|
||||||
|
hostname = detectedHost
|
||||||
|
}
|
||||||
|
|
||||||
if hostname == "" {
|
if hostname == "" {
|
||||||
hostname = "codeberg.org"
|
hostname = "codeberg.org"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +261,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)
|
||||||
}
|
}
|
||||||
|
|
@ -282,7 +282,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 {
|
||||||
|
|
@ -301,7 +301,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)
|
||||||
}
|
}
|
||||||
|
|
@ -331,7 +331,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)
|
||||||
}
|
}
|
||||||
|
|
@ -374,7 +374,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
|
||||||
|
|
@ -408,12 +408,12 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,28 @@ func DetectRepo() (owner, name string, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract owner/name from URL
|
// Extract owner/name from URL
|
||||||
return parseRemoteURL(remoteURL)
|
owner, name, _, err = parseRemoteURL(remoteURL)
|
||||||
|
return owner, name, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DetectHost attempts to detect the Forgejo instance hostname from the current git directory.
|
||||||
|
// It reads .git/config and parses the origin remote URL to extract the hostname.
|
||||||
|
func DetectHost() (hostname string, err error) {
|
||||||
|
// Find .git/config file
|
||||||
|
gitConfigPath, err := findGitConfig()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse .git/config
|
||||||
|
remoteURL, err := parseGitConfig(gitConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract hostname from URL
|
||||||
|
_, _, hostname, err = parseRemoteURL(remoteURL)
|
||||||
|
return hostname, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// findGitConfig searches for .git/config starting from the current directory
|
// findGitConfig searches for .git/config starting from the current directory
|
||||||
|
|
@ -93,33 +114,33 @@ func parseGitConfig(configPath string) (string, error) {
|
||||||
return "", fmt.Errorf("no origin remote found in git config")
|
return "", fmt.Errorf("no origin remote found in git config")
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseRemoteURL extracts owner/name from various git URL formats:
|
// parseRemoteURL extracts owner/name/hostname from various git URL formats:
|
||||||
// - https://codeberg.org/owner/name.git
|
// - https://codeberg.org/owner/name.git
|
||||||
// - git@codeberg.org:owner/name.git
|
// - git@codeberg.org:owner/name.git
|
||||||
// - ssh://git@codeberg.org/owner/name.git
|
// - ssh://git@codeberg.org/owner/name.git
|
||||||
func parseRemoteURL(url string) (owner, name string, err error) {
|
func parseRemoteURL(url string) (owner, name, hostname string, err error) {
|
||||||
url = strings.TrimSpace(url)
|
url = strings.TrimSpace(url)
|
||||||
|
|
||||||
// Remove .git suffix
|
// Remove .git suffix
|
||||||
url = strings.TrimSuffix(url, ".git")
|
url = strings.TrimSuffix(url, ".git")
|
||||||
|
|
||||||
// Pattern for HTTPS URLs: https://host/owner/name
|
// Pattern for HTTPS URLs: https://host/owner/name
|
||||||
httpsRegex := regexp.MustCompile(`https?://[^/]+/([^/]+)/([^/]+)`)
|
httpsRegex := regexp.MustCompile(`https?://([^/]+)/([^/]+)/([^/]+)`)
|
||||||
if matches := httpsRegex.FindStringSubmatch(url); len(matches) == 3 {
|
if matches := httpsRegex.FindStringSubmatch(url); len(matches) == 4 {
|
||||||
return matches[1], matches[2], nil
|
return matches[2], matches[3], matches[1], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pattern for SSH URLs: git@host:owner/name
|
// Pattern for SSH URLs: git@host:owner/name
|
||||||
sshRegex := regexp.MustCompile(`git@[^:]+:([^/]+)/(.+)`)
|
sshRegex := regexp.MustCompile(`git@([^:]+):([^/]+)/(.+)`)
|
||||||
if matches := sshRegex.FindStringSubmatch(url); len(matches) == 3 {
|
if matches := sshRegex.FindStringSubmatch(url); len(matches) == 4 {
|
||||||
return matches[1], matches[2], nil
|
return matches[2], matches[3], matches[1], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pattern for SSH URLs with protocol: ssh://git@host/owner/name
|
// Pattern for SSH URLs with protocol: ssh://git@host/owner/name
|
||||||
sshProtocolRegex := regexp.MustCompile(`ssh://git@[^/]+/([^/]+)/(.+)`)
|
sshProtocolRegex := regexp.MustCompile(`ssh://(?:git@)?([^/]+)/([^/]+)/(.+)`)
|
||||||
if matches := sshProtocolRegex.FindStringSubmatch(url); len(matches) == 3 {
|
if matches := sshProtocolRegex.FindStringSubmatch(url); len(matches) == 4 {
|
||||||
return matches[1], matches[2], nil
|
return matches[2], matches[3], matches[1], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", "", fmt.Errorf("unable to parse repository from URL: %s", url)
|
return "", "", "", fmt.Errorf("unable to parse repository from URL: %s", url)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,56 +1,67 @@
|
||||||
package git
|
package git
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func TestParseRemoteURL(t *testing.T) {
|
func TestParseRemoteURL(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
url string
|
url string
|
||||||
wantOwner string
|
wantOwner string
|
||||||
wantName string
|
wantName string
|
||||||
wantErr bool
|
wantHost string
|
||||||
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "HTTPS URL with .git",
|
name: "HTTPS URL with .git",
|
||||||
url: "https://codeberg.org/romaintb/fgj.git",
|
url: "https://codeberg.org/romaintb/fgj.git",
|
||||||
wantOwner: "romaintb",
|
wantOwner: "romaintb",
|
||||||
wantName: "fgj",
|
wantName: "fgj",
|
||||||
wantErr: false,
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "HTTPS URL without .git",
|
name: "HTTPS URL without .git",
|
||||||
url: "https://codeberg.org/romaintb/fgj",
|
url: "https://codeberg.org/romaintb/fgj",
|
||||||
wantOwner: "romaintb",
|
wantOwner: "romaintb",
|
||||||
wantName: "fgj",
|
wantName: "fgj",
|
||||||
wantErr: false,
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "SSH URL with .git",
|
name: "SSH URL with .git",
|
||||||
url: "git@codeberg.org:romaintb/fgj.git",
|
url: "git@codeberg.org:romaintb/fgj.git",
|
||||||
wantOwner: "romaintb",
|
wantOwner: "romaintb",
|
||||||
wantName: "fgj",
|
wantName: "fgj",
|
||||||
wantErr: false,
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "SSH URL without .git",
|
name: "SSH URL without .git",
|
||||||
url: "git@codeberg.org:romaintb/fgj",
|
url: "git@codeberg.org:romaintb/fgj",
|
||||||
wantOwner: "romaintb",
|
wantOwner: "romaintb",
|
||||||
wantName: "fgj",
|
wantName: "fgj",
|
||||||
wantErr: false,
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "SSH protocol URL",
|
name: "SSH protocol URL",
|
||||||
url: "ssh://git@codeberg.org/romaintb/fgj.git",
|
url: "ssh://git@codeberg.org/romaintb/fgj.git",
|
||||||
wantOwner: "romaintb",
|
wantOwner: "romaintb",
|
||||||
wantName: "fgj",
|
wantName: "fgj",
|
||||||
wantErr: false,
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "GitHub HTTPS URL",
|
name: "GitHub HTTPS URL",
|
||||||
url: "https://github.com/user/repo.git",
|
url: "https://github.com/user/repo.git",
|
||||||
wantOwner: "user",
|
wantOwner: "user",
|
||||||
wantName: "repo",
|
wantName: "repo",
|
||||||
wantErr: false,
|
wantHost: "github.com",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Invalid URL",
|
name: "Invalid URL",
|
||||||
|
|
@ -63,56 +74,60 @@ func TestParseRemoteURL(t *testing.T) {
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "URL with trailing whitespace",
|
name: "URL with trailing whitespace",
|
||||||
url: " https://codeberg.org/owner/repo.git ",
|
url: " https://codeberg.org/owner/repo.git ",
|
||||||
wantOwner: "owner",
|
wantOwner: "owner",
|
||||||
wantName: "repo",
|
wantName: "repo",
|
||||||
wantErr: false,
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "URL with port number",
|
name: "URL with port number",
|
||||||
url: "https://git.example.com:443/owner/repo.git",
|
url: "https://git.example.com:443/owner/repo.git",
|
||||||
wantOwner: "owner",
|
wantOwner: "owner",
|
||||||
wantName: "repo",
|
wantName: "repo",
|
||||||
wantErr: false,
|
wantHost: "git.example.com:443",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "SSH URL with port parses incorrectly",
|
name: "SSH URL with port parses incorrectly",
|
||||||
url: "ssh://git@git.example.com:22/owner/repo.git",
|
url: "ssh://git@git.example.com:22/owner/repo.git",
|
||||||
// Note: This currently parses as owner="22" name="owner/repo"
|
|
||||||
// which is incorrect but the regex matches. We document this
|
|
||||||
// limitation rather than make the test fail.
|
|
||||||
wantOwner: "22",
|
wantOwner: "22",
|
||||||
wantName: "owner/repo",
|
wantName: "owner/repo",
|
||||||
wantErr: false,
|
wantHost: "git.example.com",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "HTTP URL (not HTTPS)",
|
name: "HTTP URL (not HTTPS)",
|
||||||
url: "http://codeberg.org/owner/repo",
|
url: "http://codeberg.org/owner/repo",
|
||||||
wantOwner: "owner",
|
wantOwner: "owner",
|
||||||
wantName: "repo",
|
wantName: "repo",
|
||||||
wantErr: false,
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Repo name with dashes",
|
name: "Repo name with dashes",
|
||||||
url: "https://codeberg.org/owner/my-cool-repo.git",
|
url: "https://codeberg.org/owner/my-cool-repo.git",
|
||||||
wantOwner: "owner",
|
wantOwner: "owner",
|
||||||
wantName: "my-cool-repo",
|
wantName: "my-cool-repo",
|
||||||
wantErr: false,
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Repo name with dots",
|
name: "Repo name with dots",
|
||||||
url: "https://codeberg.org/owner/my.repo.name.git",
|
url: "https://codeberg.org/owner/my.repo.name.git",
|
||||||
wantOwner: "owner",
|
wantOwner: "owner",
|
||||||
wantName: "my.repo.name",
|
wantName: "my.repo.name",
|
||||||
wantErr: false,
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Owner with dots",
|
name: "Owner with dots",
|
||||||
url: "https://codeberg.org/owner.name/repo.git",
|
url: "https://codeberg.org/owner.name/repo.git",
|
||||||
wantOwner: "owner.name",
|
wantOwner: "owner.name",
|
||||||
wantName: "repo",
|
wantName: "repo",
|
||||||
wantErr: false,
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Missing owner/repo",
|
name: "Missing owner/repo",
|
||||||
|
|
@ -128,7 +143,7 @@ func TestParseRemoteURL(t *testing.T) {
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
owner, name, err := parseRemoteURL(tt.url)
|
owner, name, host, err := parseRemoteURL(tt.url)
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("parseRemoteURL() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("parseRemoteURL() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
|
|
@ -140,6 +155,112 @@ func TestParseRemoteURL(t *testing.T) {
|
||||||
if name != tt.wantName {
|
if name != tt.wantName {
|
||||||
t.Errorf("parseRemoteURL() name = %v, want %v", name, tt.wantName)
|
t.Errorf("parseRemoteURL() name = %v, want %v", name, tt.wantName)
|
||||||
}
|
}
|
||||||
|
if host != tt.wantHost {
|
||||||
|
t.Errorf("parseRemoteURL() host = %v, want %v", host, tt.wantHost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDetectHost(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
gitConfig string
|
||||||
|
wantHost string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "HTTPS URL",
|
||||||
|
gitConfig: `[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
[remote "origin"]
|
||||||
|
url = https://codeberg.org/owner/repo.git
|
||||||
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||||
|
`,
|
||||||
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SSH URL",
|
||||||
|
gitConfig: `[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
[remote "origin"]
|
||||||
|
url = git@codeberg.org:owner/repo.git
|
||||||
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||||
|
`,
|
||||||
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "HTTPS URL with port",
|
||||||
|
gitConfig: `[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
[remote "origin"]
|
||||||
|
url = https://git.example.com:443/owner/repo.git
|
||||||
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||||
|
`,
|
||||||
|
wantHost: "git.example.com:443",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SSH protocol URL",
|
||||||
|
gitConfig: `[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
[remote "origin"]
|
||||||
|
url = ssh://git@codeberg.org/owner/repo.git
|
||||||
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||||
|
`,
|
||||||
|
wantHost: "codeberg.org",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "No origin remote",
|
||||||
|
gitConfig: `[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
[remote "upstream"]
|
||||||
|
url = https://codeberg.org/owner/repo.git
|
||||||
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||||
|
`,
|
||||||
|
wantHost: "",
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
gitDir := filepath.Join(tmpDir, ".git")
|
||||||
|
if err := os.MkdirAll(gitDir, 0755); err != nil {
|
||||||
|
t.Fatalf("Failed to create .git directory: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
configPath := filepath.Join(gitDir, "config")
|
||||||
|
if err := os.WriteFile(configPath, []byte(tt.gitConfig), 0644); err != nil {
|
||||||
|
t.Fatalf("Failed to write git config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
oldWd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get current directory: %v", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err := os.Chdir(oldWd); err != nil {
|
||||||
|
t.Logf("Failed to change directory back: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := os.Chdir(tmpDir); err != nil {
|
||||||
|
t.Fatalf("Failed to change to temp directory: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
host, err := DetectHost()
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("DetectHost() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !tt.wantErr && host != tt.wantHost {
|
||||||
|
t.Errorf("DetectHost() host = %v, want %v", host, tt.wantHost)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue