Skip to content

Commit

Permalink
move getProvider from Parse to on-demand
Browse files Browse the repository at this point in the history
  • Loading branch information
ATGardner committed Jul 31, 2022
1 parent c97dd2a commit e6dceb0
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 77 deletions.
96 changes: 53 additions & 43 deletions pkg/git/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ type (
url string
revision string
path string
provider Provider
}

PushOptions struct {
Expand All @@ -78,9 +77,10 @@ type (

repo struct {
gogit.Repository
auth Auth
progress io.Writer
provider Provider
auth Auth
progress io.Writer
providerType string
repoURL string
}
)

Expand All @@ -106,6 +106,29 @@ var (
return r.checkoutBranch(branch, upsertBranch)
}

getProvider = func(providerType, repoURL string, auth *Auth) (Provider, error) {
if providerType == "" {
u, err := url.Parse(repoURL)
if err != nil {
return nil, err
}

if strings.Contains(u.Hostname(), AzureHostName) {
providerType = Azure
} else {
providerType = strings.TrimSuffix(u.Hostname(), ".com")
}

log.G().Warnf("--provider not specified, assuming provider from url: %s", providerType)
}

return newProvider(&ProviderOptions{
Type: providerType,
Auth: auth,
RepoURL: repoURL,
})
}

ggClone = func(ctx context.Context, s storage.Storer, worktree billy.Filesystem, o *gg.CloneOptions) (gogit.Repository, error) {
return gg.CloneContext(ctx, s, worktree, o)
}
Expand Down Expand Up @@ -187,7 +210,6 @@ func (o *CloneOptions) GetRepo(ctx context.Context) (Repository, fs.FS, error) {
return nil, nil, ErrNoParse
}

o.provider, err = getProvider(o.Provider, o.url, &o.Auth)
if err != nil {
log.G(ctx).Warn("failed initializing git provider: %s", err.Error())
}
Expand Down Expand Up @@ -327,10 +349,13 @@ func (r *repo) getAuthor(ctx context.Context) (*object.Signature, error) {
username := cfg.User.Name
email := cfg.User.Email

if (username == "" || email == "") && r.provider != nil {
username, email, err = r.provider.GetAuthor(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get author information: %w", err)
if username == "" || email == "" {
provider, _ := getProvider(r.providerType, r.repoURL, &r.auth)
if provider != nil {
username, email, err = provider.GetAuthor(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get author information: %w", err)
}
}
}

Expand Down Expand Up @@ -411,10 +436,11 @@ var clone = func(ctx context.Context, opts *CloneOptions) (*repo, error) {
}

repo := &repo{
Repository: r,
auth: opts.Auth,
progress: progress,
provider: opts.provider,
Repository: r,
auth: opts.Auth,
progress: progress,
providerType: opts.Provider,
repoURL: opts.Repo,
}

if opts.revision != "" {
Expand All @@ -440,35 +466,13 @@ var clone = func(ctx context.Context, opts *CloneOptions) (*repo, error) {
}

var createRepo = func(ctx context.Context, opts *CloneOptions) (string, error) {
if opts.provider == nil {
provider, _ := getProvider(opts.Provider, opts.Repo, &opts.Auth)
if provider == nil {
return "", errors.New("failed creating repository - no git provider supplied")
}

_, orgRepo, _, _, _, _, _ := util.ParseGitUrl(opts.Repo)
return opts.provider.CreateRepository(ctx, orgRepo)
}

func getProvider(providerType, repoUrl string, auth *Auth) (Provider, error) {
if providerType == "" {
u, err := url.Parse(repoUrl)
if err != nil {
return nil, err
}

if strings.Contains(u.Hostname(), AzureHostName) {
providerType = Azure
} else {
providerType = strings.TrimSuffix(u.Hostname(), ".com")
}

log.G().Warnf("--provider not specified, assuming provider from url: %s", providerType)
}

return newProvider(&ProviderOptions{
Type: providerType,
Auth: auth,
RepoURL: repoUrl,
})
return provider.CreateRepository(ctx, orgRepo)
}

func getDefaultRepoOptions(orgRepo string) (*CreateRepoOptions, error) {
Expand Down Expand Up @@ -498,10 +502,11 @@ var initRepo = func(ctx context.Context, opts *CloneOptions) (*repo, error) {
}

r := &repo{
Repository: ggr,
auth: opts.Auth,
progress: progress,
provider: opts.provider,
Repository: ggr,
progress: progress,
providerType: opts.Provider,
repoURL: opts.Repo,
auth: opts.Auth,
}
if err = r.addRemote("origin", opts.url); err != nil {
return nil, err
Expand All @@ -528,7 +533,12 @@ var initRepo = func(ctx context.Context, opts *CloneOptions) (*repo, error) {

func (r *repo) getDefaultBranch(ctx context.Context, repo string) (string, error) {
_, orgRepo, _, _, _, _, _ := util.ParseGitUrl(repo)
defaultBranch, err := r.provider.GetDefaultBranch(ctx, orgRepo)
provider, err := getProvider(r.providerType, r.repoURL, &r.auth)
if err != nil {
return "", err
}

defaultBranch, err := provider.GetDefaultBranch(ctx, orgRepo)
if err != nil {
return "", fmt.Errorf("failed to get default branch from provider. Error: %w", err)
}
Expand Down
74 changes: 40 additions & 34 deletions pkg/git/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ func Test_initRepo(t *testing.T) {
},
},
"Should fail when addRemote fails": {
repo: "https://github.com/owner/name",
repo: "https://github.com/owner/name",
wantErr: "some error",
beforeFn: func(r *mocks.MockRepository, _ *mocks.MockWorktree, _ *mockProvider) {
r.EXPECT().CreateRemote(&config.RemoteConfig{
Expand All @@ -322,7 +322,7 @@ func Test_initRepo(t *testing.T) {
},
},
"Should fail when initBranch fails": {
repo: "https://github.com/owner/name",
repo: "https://github.com/owner/name",
wantErr: "failed to commit while trying to initialize the branch. Error: some error",
beforeFn: func(r *mocks.MockRepository, wt *mocks.MockWorktree, p *mockProvider) {
r.EXPECT().CreateRemote(&config.RemoteConfig{
Expand All @@ -343,9 +343,14 @@ func Test_initRepo(t *testing.T) {
}

orgInitRepo := ggInitRepo
defer func() { ggInitRepo = orgInitRepo }()
orgGetProvider := getProvider
orgWorktree := worktree
defer func() { worktree = orgWorktree }()
defer func() {
ggInitRepo = orgInitRepo
worktree = orgWorktree
getProvider = orgGetProvider
}()

for tname, tt := range tests {
t.Run(tname, func(t *testing.T) {
ctrl := gomock.NewController(t)
Expand All @@ -358,10 +363,10 @@ func Test_initRepo(t *testing.T) {

ggInitRepo = func(s storage.Storer, worktree billy.Filesystem) (gogit.Repository, error) { return mockRepo, nil }
worktree = func(r gogit.Repository) (gogit.Worktree, error) { return mockWt, nil }
getProvider = func(providerType, repoURL string, auth *Auth) (Provider, error) { return mockProvider, nil }

opts := &CloneOptions{
Repo: tt.repo,
provider: mockProvider,
Repo: tt.repo,
}
opts.Parse()
got, err := initRepo(context.Background(), opts)
Expand Down Expand Up @@ -538,7 +543,8 @@ func Test_clone(t *testing.T) {
},
}

origCheckoutRef, origClone := checkoutRef, ggClone
origCheckoutRef := checkoutRef
origClone := ggClone
defer func() {
checkoutRef = origCheckoutRef
ggClone = origClone
Expand Down Expand Up @@ -704,6 +710,7 @@ func TestGetRepo(t *testing.T) {
},
},
}

origClone, origCreateRepo, origInitRepo := clone, createRepo, initRepo
defer func() {
clone = origClone
Expand Down Expand Up @@ -839,8 +846,12 @@ func Test_repo_Persist(t *testing.T) {
},
}

worktreeOrg := worktree
defer func() { worktree = worktreeOrg }()
orgGetProvider := getProvider
orgWorktree := worktree
defer func() {
getProvider = orgGetProvider
worktree = orgWorktree
}()

for tname, tt := range tests {
t.Run(tname, func(t *testing.T) {
Expand All @@ -850,10 +861,12 @@ func Test_repo_Persist(t *testing.T) {
mockProvider := &mockProvider{}

mockRepo.EXPECT().ConfigScoped(gomock.Any()).Return(gitConfig, nil).AnyTimes()
getProvider = func(providerType, repoURL string, auth *Auth) (Provider, error) { return mockProvider, nil }
worktree = func(r gogit.Repository) (gogit.Worktree, error) { return mockWt, nil }

r := &repo{Repository: mockRepo, progress: os.Stderr, provider: mockProvider}
worktree = func(r gogit.Repository) (gogit.Worktree, error) {
return mockWt, nil
r := &repo{
Repository: mockRepo,
progress: os.Stderr,
}

tt.beforeFn(mockRepo, mockWt)
Expand Down Expand Up @@ -1309,35 +1322,25 @@ func Test_createRepo(t *testing.T) {
Username: "username",
Password: "password",
},
provider: &mockProvider{func(orgRepo string) (string, error) {
assert.Equal(t, "owner/name", orgRepo)
return "https://github.com/owner/name.git", nil
}, nil, nil},
},
want: "https://github.com/owner/name.git",
},
"Should infer correct provider type from repo url": {
opts: &CloneOptions{
Repo: "https://github.com/owner/name.git",
provider: &mockProvider{func(orgRepo string) (string, error) {
return "https://github.com/owner/name.git", nil
}, nil, nil},
},
want: "https://github.com/owner/name.git",
},
"Should succesfully parse owner and name for long orgRepos": {
opts: &CloneOptions{
Repo: "https://github.com/foo22/bar/fizz.git",
provider: &mockProvider{func(orgRepo string) (string, error) {
assert.Equal(t, "foo22/bar/fizz", orgRepo)
return "https://github.com/foo22/bar/fizz.git", nil
}, nil, nil},
},
want: "https://github.com/foo22/bar/fizz.git",
},
}

orgGetProvider := getProvider
defer func() { getProvider = orgGetProvider }()
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
mockProvider := &mockProvider{func(orgRepo string) (string, error) {
return "https://github.com/owner/name.git", nil
}, nil, nil}
getProvider = func(providerType, repoURL string, auth *Auth) (Provider, error) { return mockProvider, nil }
got, err := createRepo(context.Background(), tt.opts)
if err != nil || tt.wantErr != "" {
assert.EqualError(t, err, tt.wantErr)
Expand Down Expand Up @@ -1518,19 +1521,22 @@ func Test_repo_commit(t *testing.T) {
},
}

orgGetProvider := getProvider
orgWorktree := worktree
defer func() { worktree = orgWorktree }()
defer func() {
getProvider = orgGetProvider
worktree = orgWorktree
}()
for tname, tt := range tests {
t.Run(tname, func(t *testing.T) {
ctrl := gomock.NewController(t)
mockRepo := mocks.NewMockRepository(ctrl)
mockWt := mocks.NewMockWorktree(ctrl)
mockProvider := &mockProvider{}
getProvider = func(providerType, repoURL string, auth *Auth) (Provider, error) { return mockProvider, nil }
worktree = func(r gogit.Repository) (gogit.Worktree, error) { return mockWt, nil }

r := &repo{Repository: mockRepo, provider: mockProvider}
worktree = func(r gogit.Repository) (gogit.Worktree, error) {
return mockWt, nil
}
r := &repo{Repository: mockRepo}

tt.beforeFn(mockRepo, mockWt, mockProvider)

Expand Down

0 comments on commit e6dceb0

Please sign in to comment.