diff --git a/internal/pkg/datasources/datasource_git.go b/internal/pkg/datasources/datasource_git.go index 5f053f1..b4ac900 100644 --- a/internal/pkg/datasources/datasource_git.go +++ b/internal/pkg/datasources/datasource_git.go @@ -325,7 +325,7 @@ func (d *GitLoader) removeStaleHEADLock(gitDir string) (bool, error) { return true, nil } -func (d *GitLoader) resetHardToTargetBranch(logger *logrus.Entry, gitDir string, branch string) error { +func (d *GitLoader) resetHardToRef(logger *logrus.Entry, gitDir string, ref string) error { logger = logger.WithFields(logrus.Fields{ "workingDirectory": gitDir, }) @@ -333,11 +333,7 @@ func (d *GitLoader) resetHardToTargetBranch(logger *logrus.Entry, gitDir string, args := []string{ "reset", "--hard", - } - if branch != "" { - args = append(args, branch) - } else { - args = append(args, "origin/HEAD") + ref, } cmd := exec.Command("git", args...) @@ -515,11 +511,11 @@ func (d *GitLoader) branch(logger *logrus.Entry, forPath string) (string, error) return branch, nil } -func (d *GitLoader) pull(logger *logrus.Entry, alteredFromURI string, pullForPath string, remoteName string) error { +func (d *GitLoader) fetch(logger *logrus.Entry, alteredFromURI string, fetchForPath string, remoteName string) error { logger = logger.WithFields(logrus.Fields{ "alteredFromURI": utils.ObscureString(alteredFromURI, d.secrets()), - "pullForPath": pullForPath, - "workingDirectory": pullForPath, + "fetchForPath": fetchForPath, + "workingDirectory": fetchForPath, }) if d.gitOptions.sshPrivateKey != "" && d.gitOptions.sshPrivateKeyFullPath != "" { logger = logger.WithFields(logrus.Fields{ @@ -527,16 +523,16 @@ func (d *GitLoader) pull(logger *logrus.Entry, alteredFromURI string, pullForPat }) } - logger.Debugf("performing git pull command to replicate data served by git server") + logger.Debugf("performing git fetch command to replicate data served by git server") args := []string{ - "pull", + "fetch", remoteName, } if d.gitOptions.Branch != "" { args = append(args, d.gitOptions.Branch) } else { - currentBranch, err := d.branch(logger, pullForPath) + currentBranch, err := d.branch(logger, fetchForPath) if err != nil { return err } @@ -546,7 +542,7 @@ func (d *GitLoader) pull(logger *logrus.Entry, alteredFromURI string, pullForPat args = append(args, "-v") cmd := exec.Command("git", args...) - cmd.Dir = pullForPath + cmd.Dir = fetchForPath cmd.Env = os.Environ() if d.gitOptions.sshPrivateKey != "" { cmd.Env = append(cmd.Env, fmt.Sprintf("GIT_SSH_COMMAND=ssh -o StrictHostKeyChecking=no -i %s", d.gitOptions.sshPrivateKeyFullPath)) @@ -640,13 +636,8 @@ func (d *GitLoader) syncWithPull(logger *logrus.Entry, _ string, alteredFromURI if err != nil { return err } - - err = d.resetHardToTargetBranch(logger, finalizedGitDir, d.gitOptions.Branch) - if err != nil { - return err - } } else { - logger.Debug("git repository has no initial commit; skipping stash and reset before initial pull") + logger.Debug("git repository has no initial commit; skipping stash before initial fetch") } pullRemoteName := fmt.Sprintf("dataset-pull-remote-%s", utils.RandomHashString(8)) @@ -665,7 +656,12 @@ func (d *GitLoader) syncWithPull(logger *logrus.Entry, _ string, alteredFromURI return err } - err = d.pull(logger, alteredFromURI, finalizedGitDir, pullRemoteName) + err = d.fetch(logger, alteredFromURI, finalizedGitDir, pullRemoteName) + if err != nil { + return err + } + + err = d.resetHardToRef(logger, finalizedGitDir, "FETCH_HEAD") if err != nil { return err } diff --git a/internal/pkg/datasources/datasource_git_test.go b/internal/pkg/datasources/datasource_git_test.go index 83e0f71..fb914fb 100644 --- a/internal/pkg/datasources/datasource_git_test.go +++ b/internal/pkg/datasources/datasource_git_test.go @@ -49,6 +49,27 @@ func TestGitLoaderSyncFromUnbornRepository(t *testing.T) { } } +func TestGitLoaderSyncResetsDivergedRepository(t *testing.T) { + remoteDir, branch := createBareGitRemote(t) + rootDir := t.TempDir() + t.Setenv("GIT_CONFIG_GLOBAL", filepath.Join(rootDir, "gitconfig")) + t.Setenv("GIT_CONFIG_NOSYSTEM", "1") + + loader, err := NewGitLoader(map[string]string{"branch": branch}, Options{Root: rootDir}, Secrets{}) + require.NoError(t, err) + require.NoError(t, loader.Sync(remoteDir, "repository")) + + repoDir := filepath.Join(rootDir, "repository") + runGit(t, repoDir, "config", "user.name", "test user") + runGit(t, repoDir, "config", "user.email", "test@example.com") + require.NoError(t, os.WriteFile(filepath.Join(repoDir, "README.md"), []byte("local change\n"), 0600)) + runGit(t, repoDir, "add", "README.md") + runGit(t, repoDir, "commit", "-m", "local divergent commit") + + require.NoError(t, loader.Sync(remoteDir, "repository")) + assert.Equal(t, "initial content\n", string(requireFileContents(t, filepath.Join(repoDir, "README.md")))) +} + func createBareGitRemote(t *testing.T) (string, string) { t.Helper() @@ -289,8 +310,10 @@ func TestGitLoader(t *testing.T) { assert.NoError(t, err) }) bbs := fakeGit.GetAllInputs() - assert.Contains(t, string(bbs[6]), "remote add") - assert.Contains(t, string(bbs[7]), "pull") + assert.Contains(t, string(bbs[5]), "remote add") + assert.Contains(t, string(bbs[6]), "fetch") + assert.Equal(t, "reset --hard FETCH_HEAD\n", string(bbs[7])) + bbs[5] = []byte{} bbs[6] = []byte{} bbs[7] = []byte{} assert.Equal(t, [][]byte{ @@ -299,7 +322,7 @@ func TestGitLoader(t *testing.T) { []byte("update-index --refresh\n"), []byte("add -u\n"), []byte("stash\n"), - []byte("reset --hard master\n"), + {}, {}, {}, }, bbs) @@ -372,9 +395,13 @@ func TestGitLoader(t *testing.T) { assert.NoError(t, err) }) bbs := fakeGit.GetAllInputs() - assert.Contains(t, string(bbs[6]), "remote add") + assert.Contains(t, string(bbs[5]), "remote add") + assert.Contains(t, string(bbs[6]), "branch --show-current") + assert.Contains(t, string(bbs[7]), "fetch") + assert.Equal(t, "reset --hard FETCH_HEAD\n", string(bbs[8])) + bbs[5] = []byte{} bbs[6] = []byte{} - assert.Contains(t, string(bbs[8]), "branch1") + bbs[7] = []byte{} bbs[8] = []byte{} assert.Equal(t, [][]byte{ []byte("config --global safe.directory *\n"), @@ -382,9 +409,9 @@ func TestGitLoader(t *testing.T) { []byte("update-index --refresh\n"), []byte("add -u\n"), []byte("stash\n"), - []byte("reset --hard origin/HEAD\n"), {}, - []byte("branch --show-current\n"), + {}, + {}, {}, }, bbs) })