Skip to content

Commit a8e770a

Browse files
authored
fix: set remote URL after cloning git repo [IDE-674] (#692)
1 parent 990ddda commit a8e770a

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

application/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ func getParsedEnvFromShell(shell string) gotenv.Env {
398398
ctx, cancelFunc := context.WithTimeout(context.Background(), 2*time.Second)
399399
defer cancelFunc()
400400

401+
// deepcode ignore CommandInjection: false positive
401402
env, err := exec.CommandContext(ctx, shell, "--login", "-i", "-c", "env && exit").Output()
402403
if err != nil {
403404
return gotenv.Env{}

internal/vcs/git_cloner.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package vcs
1818

1919
import (
2020
"github.com/go-git/go-git/v5"
21+
"github.com/go-git/go-git/v5/config"
2122
"github.com/go-git/go-git/v5/plumbing"
2223
"github.com/otiai10/copy"
2324
"github.com/rs/zerolog"
@@ -48,9 +49,59 @@ func Clone(logger *zerolog.Logger, srcRepoPath string, destinationPath string, t
4849
return targetRepo, nil
4950
}
5051

52+
// Patch Origin Remote for the cloned repo. This is only necessary if we use checkout since the remote origin URL will be the srcRepoPath
53+
err = patchClonedRepoRemoteOrigin(logger, srcRepoPath, clonedRepo)
54+
if err != nil {
55+
logger.Error().Err(err).Msgf("Could not patch origin remote url in cloned repo %s", destinationPath)
56+
}
5157
return clonedRepo, nil
5258
}
5359

60+
func patchClonedRepoRemoteOrigin(logger *zerolog.Logger, srcRepoPath string, clonedRepo *git.Repository) error {
61+
srcRepo, err := git.PlainOpen(srcRepoPath)
62+
if err != nil {
63+
logger.Error().Err(err).Msgf("Could not open source repo: %s", srcRepoPath)
64+
return err
65+
}
66+
67+
srcConfig, err := srcRepo.Config()
68+
if err != nil {
69+
logger.Error().Err(err).Msg("Could not get config from source repo")
70+
return err
71+
}
72+
73+
var originURLs []string
74+
if origin, ok := srcConfig.Remotes["origin"]; ok && len(origin.URLs) > 0 {
75+
originURLs = origin.URLs
76+
} else {
77+
logger.Warn().Msg("Source repo has no origin remote or no URLs. Skipping patching clone origin")
78+
return nil
79+
}
80+
81+
clonedConfig, err := clonedRepo.Config()
82+
if err != nil {
83+
logger.Error().Err(err).Msg("Could not get config from cloned repo")
84+
return err
85+
}
86+
87+
if origin, ok := clonedConfig.Remotes["origin"]; ok {
88+
origin.URLs = originURLs
89+
} else {
90+
clonedConfig.Remotes["origin"] = &config.RemoteConfig{
91+
Name: "origin",
92+
URLs: originURLs,
93+
}
94+
}
95+
96+
err = clonedRepo.Storer.SetConfig(clonedConfig)
97+
if err != nil {
98+
logger.Error().Err(err).Msg("Could not set config for cloned repo")
99+
return err
100+
}
101+
102+
return nil
103+
}
104+
54105
func cloneRepoWithFsCopy(logger *zerolog.Logger, srcRepoPath string, destinationRepoPath string, targetBranchReferenceName plumbing.ReferenceName) *git.Repository {
55106
repo, err := git.PlainOpen(srcRepoPath)
56107
if err != nil {

internal/vcs/git_cloner_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package vcs
1818

1919
import (
2020
"github.com/go-git/go-git/v5"
21+
"github.com/go-git/go-git/v5/config"
2122
"github.com/go-git/go-git/v5/plumbing"
2223
"github.com/go-git/go-git/v5/plumbing/object"
2324
"github.com/snyk/snyk-ls/internal/testutil"
@@ -40,6 +41,31 @@ func TestClone_ShouldClone(t *testing.T) {
4041
assert.NoError(t, err)
4142
}
4243

44+
func TestClone_ShouldClone_SameOriginRemoteUrl(t *testing.T) {
45+
c := testutil.UnitTest(t)
46+
repoPath := t.TempDir()
47+
srcRepo, _ := initGitRepo(t, repoPath, false)
48+
49+
tmpFolderPath := t.TempDir()
50+
cloneTargetBranchName := "master"
51+
clonedRepo, err := Clone(c.Logger(), repoPath, tmpFolderPath, cloneTargetBranchName)
52+
53+
assert.NotNil(t, clonedRepo)
54+
assert.NoError(t, err)
55+
56+
srcConfig, err := srcRepo.Config()
57+
assert.NoError(t, err)
58+
remoteSrcConfig := srcConfig.Remotes["origin"]
59+
assert.NotNil(t, remoteSrcConfig)
60+
61+
clonedRepoConfig, err := clonedRepo.Config()
62+
assert.NoError(t, err)
63+
remoteDstConfig := clonedRepoConfig.Remotes["origin"]
64+
assert.NotNil(t, remoteDstConfig)
65+
66+
assert.Equal(t, remoteSrcConfig.URLs[0], remoteDstConfig.URLs[0])
67+
}
68+
4369
func TestClone_InvalidBranchName(t *testing.T) {
4470
c := testutil.UnitTest(t)
4571
repoPath := t.TempDir()
@@ -75,6 +101,40 @@ func TestClone_DetachedHead_TargetBranchExists(t *testing.T) {
75101
assert.NotNil(t, cloneRepo)
76102
}
77103

104+
func TestClone_DetachedHead_TargetBranchExists_SameOriginRemoteUrl(t *testing.T) {
105+
c := testutil.UnitTest(t)
106+
repoPath := t.TempDir()
107+
destinationPath := t.TempDir()
108+
srcRepo, currentHead := initGitRepo(t, repoPath, true)
109+
worktree, err := srcRepo.Worktree()
110+
assert.NoError(t, err)
111+
_, err = worktree.Commit("testCommit", &git.CommitOptions{
112+
Author: &object.Signature{Name: t.Name()},
113+
})
114+
assert.NoError(t, err)
115+
116+
// Now checkout the old head hash
117+
err = worktree.Checkout(&git.CheckoutOptions{Hash: currentHead.Hash()})
118+
assert.NoError(t, err)
119+
cloneTargetBranchName := "master"
120+
clonedRepo, err := Clone(c.Logger(), repoPath, destinationPath, cloneTargetBranchName)
121+
122+
assert.NoError(t, err)
123+
assert.NotNil(t, clonedRepo)
124+
125+
srcConfig, err := srcRepo.Config()
126+
assert.NoError(t, err)
127+
remoteSrcConfig := srcConfig.Remotes["origin"]
128+
assert.NotNil(t, remoteSrcConfig)
129+
130+
clonedRepoConfig, err := clonedRepo.Config()
131+
assert.NoError(t, err)
132+
remoteDstConfig := clonedRepoConfig.Remotes["origin"]
133+
assert.NotNil(t, remoteDstConfig)
134+
135+
assert.Equal(t, remoteSrcConfig.URLs[0], remoteDstConfig.URLs[0])
136+
}
137+
78138
func TestClone_DetachedHead_TargetBranchDoesNotExists(t *testing.T) {
79139
c := testutil.UnitTest(t)
80140
repoPath := t.TempDir()
@@ -221,8 +281,18 @@ func initGitRepo(t *testing.T, repoPath string, isModified bool) (*git.Repositor
221281
})
222282
assert.NoError(t, err)
223283
}
284+
224285
head, err := repo.Head()
225286
assert.NoError(t, err)
226287

288+
repoConfig, err := repo.Config()
289+
assert.NoError(t, err)
290+
291+
repoConfig.Remotes["origin"] = &config.RemoteConfig{
292+
Name: "origin",
293+
URLs: []string{"[email protected]:snyk/snyk-goof.git"},
294+
}
295+
err = repo.Storer.SetConfig(repoConfig)
296+
assert.NoError(t, err)
227297
return repo, head
228298
}

0 commit comments

Comments
 (0)