-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathremote.go
97 lines (83 loc) · 2.35 KB
/
remote.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package main
import (
"context"
"errors"
"fmt"
"github.com/charmbracelet/log"
"go.abhg.dev/gs/internal/forge"
"go.abhg.dev/gs/internal/git"
"go.abhg.dev/gs/internal/secret"
)
type unsupportedForgeError struct {
Remote string // required
RemoteURL string // required
}
func (e *unsupportedForgeError) Error() string {
return fmt.Sprintf("unsupported Git remote %q: %s", e.Remote, e.RemoteURL)
}
type notLoggedInError struct {
Forge forge.Forge // required
}
func (e *notLoggedInError) Error() string {
return fmt.Sprintf("not logged in to %s", e.Forge.ID())
}
// Attempts to open the forge.Repository associated with the given Git remote.
//
// Does not print any error messages to the user.
// Instead, returns one of the following errors:
//
// - unsupportedForgeError if the remote URL does not match
// any any known forges.
// - notLoggedInError if the user is not authenticated with the forge.
func openRemoteRepositorySilent(
ctx context.Context,
stash secret.Stash,
gitRepo *git.Repository,
remote string,
) (forge.Repository, error) {
remoteURL, err := gitRepo.RemoteURL(ctx, remote)
if err != nil {
return nil, fmt.Errorf("get remote URL: %w", err)
}
f, ok := forge.MatchForgeURL(remoteURL)
if !ok {
return nil, &unsupportedForgeError{
Remote: remote,
RemoteURL: remoteURL,
}
}
tok, err := f.LoadAuthenticationToken(stash)
if err != nil {
if errors.Is(err, secret.ErrNotFound) {
return nil, ¬LoggedInError{Forge: f}
}
return nil, fmt.Errorf("load authentication token: %w", err)
}
return f.OpenURL(ctx, tok, remoteURL)
}
func openRemoteRepository(
ctx context.Context,
log *log.Logger,
stash secret.Stash,
gitRepo *git.Repository,
remote string,
) (forge.Repository, error) {
forgeRepo, err := openRemoteRepositorySilent(ctx, stash, gitRepo, remote)
var (
unsupportedErr *unsupportedForgeError
notLoggedInErr *notLoggedInError
)
switch {
case errors.As(err, &unsupportedErr):
log.Error("Could not guess repository from remote URL", "url", unsupportedErr.RemoteURL)
log.Error("Are you sure the remote identifies a supported Git host?")
return nil, err
case errors.As(err, ¬LoggedInErr):
f := notLoggedInErr.Forge
log.Errorf("No authentication token found for %s.", f.ID())
log.Errorf("Try running `gs auth login --forge=%s`", f.ID())
return nil, err
default:
return forgeRepo, err
}
}