Skip to content

Commit

Permalink
fix: set remote URL after cloning git repo [IDE-674] (#692)
Browse files Browse the repository at this point in the history
  • Loading branch information
ShawkyZ authored Oct 8, 2024
1 parent 990ddda commit a8e770a
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
1 change: 1 addition & 0 deletions application/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ func getParsedEnvFromShell(shell string) gotenv.Env {
ctx, cancelFunc := context.WithTimeout(context.Background(), 2*time.Second)
defer cancelFunc()

// deepcode ignore CommandInjection: false positive
env, err := exec.CommandContext(ctx, shell, "--login", "-i", "-c", "env && exit").Output()
if err != nil {
return gotenv.Env{}
Expand Down
51 changes: 51 additions & 0 deletions internal/vcs/git_cloner.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package vcs

import (
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/otiai10/copy"
"github.com/rs/zerolog"
Expand Down Expand Up @@ -48,9 +49,59 @@ func Clone(logger *zerolog.Logger, srcRepoPath string, destinationPath string, t
return targetRepo, nil
}

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

func patchClonedRepoRemoteOrigin(logger *zerolog.Logger, srcRepoPath string, clonedRepo *git.Repository) error {
srcRepo, err := git.PlainOpen(srcRepoPath)
if err != nil {
logger.Error().Err(err).Msgf("Could not open source repo: %s", srcRepoPath)
return err
}

srcConfig, err := srcRepo.Config()
if err != nil {
logger.Error().Err(err).Msg("Could not get config from source repo")
return err
}

var originURLs []string
if origin, ok := srcConfig.Remotes["origin"]; ok && len(origin.URLs) > 0 {
originURLs = origin.URLs
} else {
logger.Warn().Msg("Source repo has no origin remote or no URLs. Skipping patching clone origin")
return nil
}

clonedConfig, err := clonedRepo.Config()
if err != nil {
logger.Error().Err(err).Msg("Could not get config from cloned repo")
return err
}

if origin, ok := clonedConfig.Remotes["origin"]; ok {
origin.URLs = originURLs
} else {
clonedConfig.Remotes["origin"] = &config.RemoteConfig{
Name: "origin",
URLs: originURLs,
}
}

err = clonedRepo.Storer.SetConfig(clonedConfig)
if err != nil {
logger.Error().Err(err).Msg("Could not set config for cloned repo")
return err
}

return nil
}

func cloneRepoWithFsCopy(logger *zerolog.Logger, srcRepoPath string, destinationRepoPath string, targetBranchReferenceName plumbing.ReferenceName) *git.Repository {
repo, err := git.PlainOpen(srcRepoPath)
if err != nil {
Expand Down
70 changes: 70 additions & 0 deletions internal/vcs/git_cloner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package vcs

import (
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/snyk/snyk-ls/internal/testutil"
Expand All @@ -40,6 +41,31 @@ func TestClone_ShouldClone(t *testing.T) {
assert.NoError(t, err)
}

func TestClone_ShouldClone_SameOriginRemoteUrl(t *testing.T) {
c := testutil.UnitTest(t)
repoPath := t.TempDir()
srcRepo, _ := initGitRepo(t, repoPath, false)

tmpFolderPath := t.TempDir()
cloneTargetBranchName := "master"
clonedRepo, err := Clone(c.Logger(), repoPath, tmpFolderPath, cloneTargetBranchName)

assert.NotNil(t, clonedRepo)
assert.NoError(t, err)

srcConfig, err := srcRepo.Config()
assert.NoError(t, err)
remoteSrcConfig := srcConfig.Remotes["origin"]
assert.NotNil(t, remoteSrcConfig)

clonedRepoConfig, err := clonedRepo.Config()
assert.NoError(t, err)
remoteDstConfig := clonedRepoConfig.Remotes["origin"]
assert.NotNil(t, remoteDstConfig)

assert.Equal(t, remoteSrcConfig.URLs[0], remoteDstConfig.URLs[0])
}

func TestClone_InvalidBranchName(t *testing.T) {
c := testutil.UnitTest(t)
repoPath := t.TempDir()
Expand Down Expand Up @@ -75,6 +101,40 @@ func TestClone_DetachedHead_TargetBranchExists(t *testing.T) {
assert.NotNil(t, cloneRepo)
}

func TestClone_DetachedHead_TargetBranchExists_SameOriginRemoteUrl(t *testing.T) {
c := testutil.UnitTest(t)
repoPath := t.TempDir()
destinationPath := t.TempDir()
srcRepo, currentHead := initGitRepo(t, repoPath, true)
worktree, err := srcRepo.Worktree()
assert.NoError(t, err)
_, err = worktree.Commit("testCommit", &git.CommitOptions{
Author: &object.Signature{Name: t.Name()},
})
assert.NoError(t, err)

// Now checkout the old head hash
err = worktree.Checkout(&git.CheckoutOptions{Hash: currentHead.Hash()})
assert.NoError(t, err)
cloneTargetBranchName := "master"
clonedRepo, err := Clone(c.Logger(), repoPath, destinationPath, cloneTargetBranchName)

assert.NoError(t, err)
assert.NotNil(t, clonedRepo)

srcConfig, err := srcRepo.Config()
assert.NoError(t, err)
remoteSrcConfig := srcConfig.Remotes["origin"]
assert.NotNil(t, remoteSrcConfig)

clonedRepoConfig, err := clonedRepo.Config()
assert.NoError(t, err)
remoteDstConfig := clonedRepoConfig.Remotes["origin"]
assert.NotNil(t, remoteDstConfig)

assert.Equal(t, remoteSrcConfig.URLs[0], remoteDstConfig.URLs[0])
}

func TestClone_DetachedHead_TargetBranchDoesNotExists(t *testing.T) {
c := testutil.UnitTest(t)
repoPath := t.TempDir()
Expand Down Expand Up @@ -221,8 +281,18 @@ func initGitRepo(t *testing.T, repoPath string, isModified bool) (*git.Repositor
})
assert.NoError(t, err)
}

head, err := repo.Head()
assert.NoError(t, err)

repoConfig, err := repo.Config()
assert.NoError(t, err)

repoConfig.Remotes["origin"] = &config.RemoteConfig{
Name: "origin",
URLs: []string{"[email protected]:snyk/snyk-goof.git"},
}
err = repo.Storer.SetConfig(repoConfig)
assert.NoError(t, err)
return repo, head
}

0 comments on commit a8e770a

Please sign in to comment.