Skip to content

Commit

Permalink
refactor commit local stack fetching
Browse files Browse the repository at this point in the history
commit-id:7529635e
  • Loading branch information
ejoffe committed Apr 22, 2023
1 parent a1939e4 commit 5578059
Show file tree
Hide file tree
Showing 17 changed files with 549 additions and 486 deletions.
3 changes: 2 additions & 1 deletion cmd/amend/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"

"github.com/ejoffe/spr/config"
"github.com/ejoffe/spr/config/config_parser"
"github.com/ejoffe/spr/git/realgit"
"github.com/ejoffe/spr/github/githubclient"
"github.com/ejoffe/spr/spr"
Expand Down Expand Up @@ -57,7 +58,7 @@ func main() {
}

ctx := context.Background()
cfg := config.ParseConfig(gitcmd)
cfg := config_parser.ParseConfig(gitcmd)
client := githubclient.NewGitHubClient(ctx, cfg)
gitcmd = realgit.NewGitCmd(cfg)

Expand Down
3 changes: 2 additions & 1 deletion cmd/spr/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/ejoffe/rake"
"github.com/ejoffe/spr/config"
"github.com/ejoffe/spr/config/config_parser"
"github.com/ejoffe/spr/git/realgit"
"github.com/ejoffe/spr/github/githubclient"
"github.com/ejoffe/spr/spr"
Expand Down Expand Up @@ -38,7 +39,7 @@ func main() {
os.Exit(2)
}

cfg := config.ParseConfig(gitcmd)
cfg := config_parser.ParseConfig(gitcmd)
gitcmd = realgit.NewGitCmd(cfg)

ctx := context.Background()
Expand Down
121 changes: 0 additions & 121 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@ package config

import (
"fmt"
"os"
"path"
"path/filepath"
"regexp"
"strings"

"github.com/ejoffe/rake"
"github.com/ejoffe/spr/git"
"github.com/ejoffe/spr/github/githubclient/gen/genclient"
)

Expand Down Expand Up @@ -84,77 +79,6 @@ func DefaultConfig() *Config {
return cfg
}

func ParseConfig(gitcmd git.GitInterface) *Config {
cfg := EmptyConfig()

rake.LoadSources(cfg.Repo,
rake.DefaultSource(),
GitHubRemoteSource(cfg, gitcmd),
rake.YamlFileSource(RepoConfigFilePath(gitcmd)),
rake.YamlFileWriter(RepoConfigFilePath(gitcmd)),
)
if cfg.Repo.GitHubHost == "" {
fmt.Println("unable to auto configure repository host - must be set manually in .spr.yml")
os.Exit(2)
}
if cfg.Repo.GitHubRepoOwner == "" {
fmt.Println("unable to auto configure repository owner - must be set manually in .spr.yml")
os.Exit(3)
}

if cfg.Repo.GitHubRepoName == "" {
fmt.Println("unable to auto configure repository name - must be set manually in .spr.yml")
os.Exit(4)
}

rake.LoadSources(cfg.User,
rake.DefaultSource(),
rake.YamlFileSource(UserConfigFilePath()),
)

rake.LoadSources(cfg.Internal,
rake.DefaultSource(),
rake.YamlFileSource(InternalConfigFilePath()),
)

rake.LoadSources(cfg.User,
rake.YamlFileWriter(UserConfigFilePath()))

cfg.Internal.RunCount = cfg.Internal.RunCount + 1

rake.LoadSources(cfg.Internal,
rake.YamlFileWriter(InternalConfigFilePath()))

return cfg
}

func RepoConfigFilePath(gitcmd git.GitInterface) string {
rootdir := gitcmd.RootDir()
filepath := filepath.Clean(path.Join(rootdir, ".spr.yml"))
return filepath
}

func UserConfigFilePath() string {
rootdir, err := os.UserHomeDir()
check(err)
filepath := filepath.Clean(path.Join(rootdir, ".spr.yml"))
return filepath
}

func InternalConfigFilePath() string {
rootdir, err := os.UserHomeDir()
check(err)
filepath := filepath.Clean(path.Join(rootdir, ".spr.state"))
return filepath
}

func GitHubRemoteSource(config *Config, gitcmd git.GitInterface) *remoteSource {
return &remoteSource{
gitcmd: gitcmd,
config: config,
}
}

func (c Config) MergeMethod() (genclient.PullRequestMergeMethod, error) {
var mergeMethod genclient.PullRequestMergeMethod
var err error
Expand All @@ -174,51 +98,6 @@ func (c Config) MergeMethod() (genclient.PullRequestMergeMethod, error) {
return mergeMethod, err
}

type remoteSource struct {
gitcmd git.GitInterface
config *Config
}

func (s *remoteSource) Load(_ interface{}) {
var output string
err := s.gitcmd.Git("remote -v", &output)
check(err)
lines := strings.Split(output, "\n")

for _, line := range lines {
githubHost, repoOwner, repoName, match := getRepoDetailsFromRemote(line)
if match {
s.config.Repo.GitHubHost = githubHost
s.config.Repo.GitHubRepoOwner = repoOwner
s.config.Repo.GitHubRepoName = repoName
break
}
}
}

func getRepoDetailsFromRemote(remote string) (string, string, string, bool) {
// Allows "https://", "ssh://" or no protocol at all (this means ssh)
protocolFormat := `(?:(https://)|(ssh://))?`
// This may or may not be present in the address
userFormat := `(git@)?`
// "/" is expected in "http://" or "ssh://" protocol, when no protocol given
// it should be ":"
repoFormat := `(?P<githubHost>[a-z0-9._\-]+)(/|:)(?P<repoOwner>\w+)/(?P<repoName>[\w-]+)`
// This is neither required in https access nor in ssh one
suffixFormat := `(.git)?`
regexFormat := fmt.Sprintf(`^origin\s+%s%s%s%s \(push\)`,
protocolFormat, userFormat, repoFormat, suffixFormat)
regex := regexp.MustCompile(regexFormat)
matches := regex.FindStringSubmatch(remote)
if matches != nil {
githubHostIndex := regex.SubexpIndex("githubHost")
repoOwnerIndex := regex.SubexpIndex("repoOwner")
repoNameIndex := regex.SubexpIndex("repoName")
return matches[githubHostIndex], matches[repoOwnerIndex], matches[repoNameIndex], true
}
return "", "", "", false
}

func check(err error) {
if err != nil {
panic(err)
Expand Down
83 changes: 83 additions & 0 deletions config/config_parser/config_parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package config_parser

import (
"fmt"
"os"
"path"
"path/filepath"

"github.com/ejoffe/rake"
"github.com/ejoffe/spr/config"
"github.com/ejoffe/spr/git"
)

func ParseConfig(gitcmd git.GitInterface) *config.Config {
cfg := config.EmptyConfig()

rake.LoadSources(cfg.Repo,
rake.DefaultSource(),
GitHubRemoteSource(cfg, gitcmd),
rake.YamlFileSource(RepoConfigFilePath(gitcmd)),
rake.YamlFileWriter(RepoConfigFilePath(gitcmd)),
)
if cfg.Repo.GitHubHost == "" {
fmt.Println("unable to auto configure repository host - must be set manually in .spr.yml")
os.Exit(2)
}
if cfg.Repo.GitHubRepoOwner == "" {
fmt.Println("unable to auto configure repository owner - must be set manually in .spr.yml")
os.Exit(3)
}

if cfg.Repo.GitHubRepoName == "" {
fmt.Println("unable to auto configure repository name - must be set manually in .spr.yml")
os.Exit(4)
}

rake.LoadSources(cfg.User,
rake.DefaultSource(),
rake.YamlFileSource(UserConfigFilePath()),
)

rake.LoadSources(cfg.Internal,
rake.DefaultSource(),
rake.YamlFileSource(InternalConfigFilePath()),
)

rake.LoadSources(cfg.User,
rake.YamlFileWriter(UserConfigFilePath()))

cfg.Internal.RunCount = cfg.Internal.RunCount + 1

rake.LoadSources(cfg.Internal,
rake.YamlFileWriter(InternalConfigFilePath()))

return cfg
}

func RepoConfigFilePath(gitcmd git.GitInterface) string {
rootdir := gitcmd.RootDir()
filepath := filepath.Clean(path.Join(rootdir, ".spr.yml"))
return filepath
}

func UserConfigFilePath() string {
rootdir, err := os.UserHomeDir()
check(err)
filepath := filepath.Clean(path.Join(rootdir, ".spr.yml"))
return filepath
}

func InternalConfigFilePath() string {
rootdir, err := os.UserHomeDir()
check(err)
filepath := filepath.Clean(path.Join(rootdir, ".spr.state"))
return filepath
}

func GitHubRemoteSource(config *config.Config, gitcmd git.GitInterface) *remoteSource {
return &remoteSource{
gitcmd: gitcmd,
config: config,
}
}
87 changes: 87 additions & 0 deletions config/config_parser/config_parser_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package config_parser

import (
"testing"

"github.com/ejoffe/spr/config"
"github.com/ejoffe/spr/git/mockgit"
"github.com/stretchr/testify/assert"
)

func TestGetRepoDetailsFromRemote(t *testing.T) {
type testCase struct {
remote string
githubHost string
repoOwner string
repoName string
match bool
}
testCases := []testCase{
{"origin https://github.com/r2/d2.git (push)", "github.com", "r2", "d2", true},
{"origin https://github.com/r2/d2.git (fetch)", "", "", "", false},
{"origin https://github.com/r2/d2 (push)", "github.com", "r2", "d2", true},

{"origin ssh://[email protected]/r2/d2.git (push)", "github.com", "r2", "d2", true},
{"origin ssh://[email protected]/r2/d2.git (fetch)", "", "", "", false},
{"origin ssh://[email protected]/r2/d2 (push)", "github.com", "r2", "d2", true},

{"origin [email protected]:r2/d2.git (push)", "github.com", "r2", "d2", true},
{"origin [email protected]:r2/d2.git (fetch)", "", "", "", false},
{"origin [email protected]:r2/d2 (push)", "github.com", "r2", "d2", true},

{"origin [email protected]:r2/d2.git (push)", "gh.enterprise.com", "r2", "d2", true},
{"origin [email protected]:r2/d2.git (fetch)", "", "", "", false},
{"origin [email protected]:r2/d2 (push)", "gh.enterprise.com", "r2", "d2", true},

{"origin https://github.com/r2/d2-a.git (push)", "github.com", "r2", "d2-a", true},
{"origin https://github.com/r2/d2_a.git (push)", "github.com", "r2", "d2_a", true},
}
for i, testCase := range testCases {
t.Logf("Testing %v %q", i, testCase.remote)
githubHost, repoOwner, repoName, match := getRepoDetailsFromRemote(testCase.remote)
if githubHost != testCase.githubHost {
t.Fatalf("Wrong \"githubHost\" returned for test case %v, expected %q, got %q", i, testCase.githubHost, githubHost)
}
if repoOwner != testCase.repoOwner {
t.Fatalf("Wrong \"repoOwner\" returned for test case %v, expected %q, got %q", i, testCase.repoOwner, repoOwner)
}
if repoName != testCase.repoName {
t.Fatalf("Wrong \"repoName\" returned for test case %v, expected %q, got %q", i, testCase.repoName, repoName)
}
if match != testCase.match {
t.Fatalf("Wrong \"match\" returned for test case %v, expected %t, got %t", i, testCase.match, match)
}
}
}

func TestGitHubRemoteSource(t *testing.T) {
mock := mockgit.NewMockGit(t)
mock.ExpectRemote("https://github.com/r2/d2.git")

expect := config.Config{
Repo: &config.RepoConfig{
GitHubRepoOwner: "r2",
GitHubRepoName: "d2",
GitHubHost: "github.com",
RequireChecks: false,
RequireApproval: false,
GitHubRemote: "",
GitHubBranch: "",
MergeMethod: "",
},
User: &config.UserConfig{
ShowPRLink: false,
LogGitCommands: false,
LogGitHubCalls: false,
StatusBitsHeader: false,
},
}

actual := config.Config{
Repo: &config.RepoConfig{},
User: &config.UserConfig{},
}
source := GitHubRemoteSource(&actual, mock)
source.Load(nil)
assert.Equal(t, expect, actual)
}
Loading

0 comments on commit 5578059

Please sign in to comment.