Skip to content

Commit 5578059

Browse files
committed
refactor commit local stack fetching
commit-id:7529635e
1 parent a1939e4 commit 5578059

17 files changed

+549
-486
lines changed

cmd/amend/main.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os"
77

88
"github.com/ejoffe/spr/config"
9+
"github.com/ejoffe/spr/config/config_parser"
910
"github.com/ejoffe/spr/git/realgit"
1011
"github.com/ejoffe/spr/github/githubclient"
1112
"github.com/ejoffe/spr/spr"
@@ -57,7 +58,7 @@ func main() {
5758
}
5859

5960
ctx := context.Background()
60-
cfg := config.ParseConfig(gitcmd)
61+
cfg := config_parser.ParseConfig(gitcmd)
6162
client := githubclient.NewGitHubClient(ctx, cfg)
6263
gitcmd = realgit.NewGitCmd(cfg)
6364

cmd/spr/main.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/ejoffe/rake"
99
"github.com/ejoffe/spr/config"
10+
"github.com/ejoffe/spr/config/config_parser"
1011
"github.com/ejoffe/spr/git/realgit"
1112
"github.com/ejoffe/spr/github/githubclient"
1213
"github.com/ejoffe/spr/spr"
@@ -38,7 +39,7 @@ func main() {
3839
os.Exit(2)
3940
}
4041

41-
cfg := config.ParseConfig(gitcmd)
42+
cfg := config_parser.ParseConfig(gitcmd)
4243
gitcmd = realgit.NewGitCmd(cfg)
4344

4445
ctx := context.Background()

config/config.go

-121
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,9 @@ package config
22

33
import (
44
"fmt"
5-
"os"
6-
"path"
7-
"path/filepath"
8-
"regexp"
95
"strings"
106

117
"github.com/ejoffe/rake"
12-
"github.com/ejoffe/spr/git"
138
"github.com/ejoffe/spr/github/githubclient/gen/genclient"
149
)
1510

@@ -84,77 +79,6 @@ func DefaultConfig() *Config {
8479
return cfg
8580
}
8681

87-
func ParseConfig(gitcmd git.GitInterface) *Config {
88-
cfg := EmptyConfig()
89-
90-
rake.LoadSources(cfg.Repo,
91-
rake.DefaultSource(),
92-
GitHubRemoteSource(cfg, gitcmd),
93-
rake.YamlFileSource(RepoConfigFilePath(gitcmd)),
94-
rake.YamlFileWriter(RepoConfigFilePath(gitcmd)),
95-
)
96-
if cfg.Repo.GitHubHost == "" {
97-
fmt.Println("unable to auto configure repository host - must be set manually in .spr.yml")
98-
os.Exit(2)
99-
}
100-
if cfg.Repo.GitHubRepoOwner == "" {
101-
fmt.Println("unable to auto configure repository owner - must be set manually in .spr.yml")
102-
os.Exit(3)
103-
}
104-
105-
if cfg.Repo.GitHubRepoName == "" {
106-
fmt.Println("unable to auto configure repository name - must be set manually in .spr.yml")
107-
os.Exit(4)
108-
}
109-
110-
rake.LoadSources(cfg.User,
111-
rake.DefaultSource(),
112-
rake.YamlFileSource(UserConfigFilePath()),
113-
)
114-
115-
rake.LoadSources(cfg.Internal,
116-
rake.DefaultSource(),
117-
rake.YamlFileSource(InternalConfigFilePath()),
118-
)
119-
120-
rake.LoadSources(cfg.User,
121-
rake.YamlFileWriter(UserConfigFilePath()))
122-
123-
cfg.Internal.RunCount = cfg.Internal.RunCount + 1
124-
125-
rake.LoadSources(cfg.Internal,
126-
rake.YamlFileWriter(InternalConfigFilePath()))
127-
128-
return cfg
129-
}
130-
131-
func RepoConfigFilePath(gitcmd git.GitInterface) string {
132-
rootdir := gitcmd.RootDir()
133-
filepath := filepath.Clean(path.Join(rootdir, ".spr.yml"))
134-
return filepath
135-
}
136-
137-
func UserConfigFilePath() string {
138-
rootdir, err := os.UserHomeDir()
139-
check(err)
140-
filepath := filepath.Clean(path.Join(rootdir, ".spr.yml"))
141-
return filepath
142-
}
143-
144-
func InternalConfigFilePath() string {
145-
rootdir, err := os.UserHomeDir()
146-
check(err)
147-
filepath := filepath.Clean(path.Join(rootdir, ".spr.state"))
148-
return filepath
149-
}
150-
151-
func GitHubRemoteSource(config *Config, gitcmd git.GitInterface) *remoteSource {
152-
return &remoteSource{
153-
gitcmd: gitcmd,
154-
config: config,
155-
}
156-
}
157-
15882
func (c Config) MergeMethod() (genclient.PullRequestMergeMethod, error) {
15983
var mergeMethod genclient.PullRequestMergeMethod
16084
var err error
@@ -174,51 +98,6 @@ func (c Config) MergeMethod() (genclient.PullRequestMergeMethod, error) {
17498
return mergeMethod, err
17599
}
176100

177-
type remoteSource struct {
178-
gitcmd git.GitInterface
179-
config *Config
180-
}
181-
182-
func (s *remoteSource) Load(_ interface{}) {
183-
var output string
184-
err := s.gitcmd.Git("remote -v", &output)
185-
check(err)
186-
lines := strings.Split(output, "\n")
187-
188-
for _, line := range lines {
189-
githubHost, repoOwner, repoName, match := getRepoDetailsFromRemote(line)
190-
if match {
191-
s.config.Repo.GitHubHost = githubHost
192-
s.config.Repo.GitHubRepoOwner = repoOwner
193-
s.config.Repo.GitHubRepoName = repoName
194-
break
195-
}
196-
}
197-
}
198-
199-
func getRepoDetailsFromRemote(remote string) (string, string, string, bool) {
200-
// Allows "https://", "ssh://" or no protocol at all (this means ssh)
201-
protocolFormat := `(?:(https://)|(ssh://))?`
202-
// This may or may not be present in the address
203-
userFormat := `(git@)?`
204-
// "/" is expected in "http://" or "ssh://" protocol, when no protocol given
205-
// it should be ":"
206-
repoFormat := `(?P<githubHost>[a-z0-9._\-]+)(/|:)(?P<repoOwner>\w+)/(?P<repoName>[\w-]+)`
207-
// This is neither required in https access nor in ssh one
208-
suffixFormat := `(.git)?`
209-
regexFormat := fmt.Sprintf(`^origin\s+%s%s%s%s \(push\)`,
210-
protocolFormat, userFormat, repoFormat, suffixFormat)
211-
regex := regexp.MustCompile(regexFormat)
212-
matches := regex.FindStringSubmatch(remote)
213-
if matches != nil {
214-
githubHostIndex := regex.SubexpIndex("githubHost")
215-
repoOwnerIndex := regex.SubexpIndex("repoOwner")
216-
repoNameIndex := regex.SubexpIndex("repoName")
217-
return matches[githubHostIndex], matches[repoOwnerIndex], matches[repoNameIndex], true
218-
}
219-
return "", "", "", false
220-
}
221-
222101
func check(err error) {
223102
if err != nil {
224103
panic(err)

config/config_parser/config_parser.go

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package config_parser
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path"
7+
"path/filepath"
8+
9+
"github.com/ejoffe/rake"
10+
"github.com/ejoffe/spr/config"
11+
"github.com/ejoffe/spr/git"
12+
)
13+
14+
func ParseConfig(gitcmd git.GitInterface) *config.Config {
15+
cfg := config.EmptyConfig()
16+
17+
rake.LoadSources(cfg.Repo,
18+
rake.DefaultSource(),
19+
GitHubRemoteSource(cfg, gitcmd),
20+
rake.YamlFileSource(RepoConfigFilePath(gitcmd)),
21+
rake.YamlFileWriter(RepoConfigFilePath(gitcmd)),
22+
)
23+
if cfg.Repo.GitHubHost == "" {
24+
fmt.Println("unable to auto configure repository host - must be set manually in .spr.yml")
25+
os.Exit(2)
26+
}
27+
if cfg.Repo.GitHubRepoOwner == "" {
28+
fmt.Println("unable to auto configure repository owner - must be set manually in .spr.yml")
29+
os.Exit(3)
30+
}
31+
32+
if cfg.Repo.GitHubRepoName == "" {
33+
fmt.Println("unable to auto configure repository name - must be set manually in .spr.yml")
34+
os.Exit(4)
35+
}
36+
37+
rake.LoadSources(cfg.User,
38+
rake.DefaultSource(),
39+
rake.YamlFileSource(UserConfigFilePath()),
40+
)
41+
42+
rake.LoadSources(cfg.Internal,
43+
rake.DefaultSource(),
44+
rake.YamlFileSource(InternalConfigFilePath()),
45+
)
46+
47+
rake.LoadSources(cfg.User,
48+
rake.YamlFileWriter(UserConfigFilePath()))
49+
50+
cfg.Internal.RunCount = cfg.Internal.RunCount + 1
51+
52+
rake.LoadSources(cfg.Internal,
53+
rake.YamlFileWriter(InternalConfigFilePath()))
54+
55+
return cfg
56+
}
57+
58+
func RepoConfigFilePath(gitcmd git.GitInterface) string {
59+
rootdir := gitcmd.RootDir()
60+
filepath := filepath.Clean(path.Join(rootdir, ".spr.yml"))
61+
return filepath
62+
}
63+
64+
func UserConfigFilePath() string {
65+
rootdir, err := os.UserHomeDir()
66+
check(err)
67+
filepath := filepath.Clean(path.Join(rootdir, ".spr.yml"))
68+
return filepath
69+
}
70+
71+
func InternalConfigFilePath() string {
72+
rootdir, err := os.UserHomeDir()
73+
check(err)
74+
filepath := filepath.Clean(path.Join(rootdir, ".spr.state"))
75+
return filepath
76+
}
77+
78+
func GitHubRemoteSource(config *config.Config, gitcmd git.GitInterface) *remoteSource {
79+
return &remoteSource{
80+
gitcmd: gitcmd,
81+
config: config,
82+
}
83+
}
+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package config_parser
2+
3+
import (
4+
"testing"
5+
6+
"github.com/ejoffe/spr/config"
7+
"github.com/ejoffe/spr/git/mockgit"
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestGetRepoDetailsFromRemote(t *testing.T) {
12+
type testCase struct {
13+
remote string
14+
githubHost string
15+
repoOwner string
16+
repoName string
17+
match bool
18+
}
19+
testCases := []testCase{
20+
{"origin https://github.com/r2/d2.git (push)", "github.com", "r2", "d2", true},
21+
{"origin https://github.com/r2/d2.git (fetch)", "", "", "", false},
22+
{"origin https://github.com/r2/d2 (push)", "github.com", "r2", "d2", true},
23+
24+
{"origin ssh://[email protected]/r2/d2.git (push)", "github.com", "r2", "d2", true},
25+
{"origin ssh://[email protected]/r2/d2.git (fetch)", "", "", "", false},
26+
{"origin ssh://[email protected]/r2/d2 (push)", "github.com", "r2", "d2", true},
27+
28+
{"origin [email protected]:r2/d2.git (push)", "github.com", "r2", "d2", true},
29+
{"origin [email protected]:r2/d2.git (fetch)", "", "", "", false},
30+
{"origin [email protected]:r2/d2 (push)", "github.com", "r2", "d2", true},
31+
32+
{"origin [email protected]:r2/d2.git (push)", "gh.enterprise.com", "r2", "d2", true},
33+
{"origin [email protected]:r2/d2.git (fetch)", "", "", "", false},
34+
{"origin [email protected]:r2/d2 (push)", "gh.enterprise.com", "r2", "d2", true},
35+
36+
{"origin https://github.com/r2/d2-a.git (push)", "github.com", "r2", "d2-a", true},
37+
{"origin https://github.com/r2/d2_a.git (push)", "github.com", "r2", "d2_a", true},
38+
}
39+
for i, testCase := range testCases {
40+
t.Logf("Testing %v %q", i, testCase.remote)
41+
githubHost, repoOwner, repoName, match := getRepoDetailsFromRemote(testCase.remote)
42+
if githubHost != testCase.githubHost {
43+
t.Fatalf("Wrong \"githubHost\" returned for test case %v, expected %q, got %q", i, testCase.githubHost, githubHost)
44+
}
45+
if repoOwner != testCase.repoOwner {
46+
t.Fatalf("Wrong \"repoOwner\" returned for test case %v, expected %q, got %q", i, testCase.repoOwner, repoOwner)
47+
}
48+
if repoName != testCase.repoName {
49+
t.Fatalf("Wrong \"repoName\" returned for test case %v, expected %q, got %q", i, testCase.repoName, repoName)
50+
}
51+
if match != testCase.match {
52+
t.Fatalf("Wrong \"match\" returned for test case %v, expected %t, got %t", i, testCase.match, match)
53+
}
54+
}
55+
}
56+
57+
func TestGitHubRemoteSource(t *testing.T) {
58+
mock := mockgit.NewMockGit(t)
59+
mock.ExpectRemote("https://github.com/r2/d2.git")
60+
61+
expect := config.Config{
62+
Repo: &config.RepoConfig{
63+
GitHubRepoOwner: "r2",
64+
GitHubRepoName: "d2",
65+
GitHubHost: "github.com",
66+
RequireChecks: false,
67+
RequireApproval: false,
68+
GitHubRemote: "",
69+
GitHubBranch: "",
70+
MergeMethod: "",
71+
},
72+
User: &config.UserConfig{
73+
ShowPRLink: false,
74+
LogGitCommands: false,
75+
LogGitHubCalls: false,
76+
StatusBitsHeader: false,
77+
},
78+
}
79+
80+
actual := config.Config{
81+
Repo: &config.RepoConfig{},
82+
User: &config.UserConfig{},
83+
}
84+
source := GitHubRemoteSource(&actual, mock)
85+
source.Load(nil)
86+
assert.Equal(t, expect, actual)
87+
}

0 commit comments

Comments
 (0)