From 0905d36e9d73d32a3b67d978c90f18a900b457da Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 27 Nov 2024 14:29:18 +0100 Subject: [PATCH] Properly read git metadata when inside Workspace Since there is no .git directory in Workspace file system, we need to make an API call to fetch git checkout status (root of the repo, current branch, etc). (api/2.0/workspace/get-status?return_git_info=true). Refactor Repository to accept repository root rather than calculate it. This helps, because Repository is currently created in multiple places and finding the repository root is expensive. --- bundle/bundle.go | 3 + bundle/bundle_read_only.go | 4 + bundle/config/mutator/load_git_details.go | 38 +++--- bundle/config/validate/files_to_sync_test.go | 1 + bundle/deploy/files/sync.go | 9 +- cmd/sync/sync.go | 22 +++- libs/git/fileset.go | 10 +- libs/git/fileset_test.go | 8 +- libs/git/info.go | 115 +++++++++++++++++++ libs/git/repository.go | 14 +-- libs/git/view.go | 8 +- libs/git/view_test.go | 30 ++--- libs/sync/snapshot_test.go | 12 +- libs/sync/sync.go | 11 +- libs/sync/sync_test.go | 6 +- 15 files changed, 208 insertions(+), 83 deletions(-) create mode 100644 libs/git/info.go diff --git a/bundle/bundle.go b/bundle/bundle.go index 46710538a..9de6dc88d 100644 --- a/bundle/bundle.go +++ b/bundle/bundle.go @@ -48,6 +48,9 @@ type Bundle struct { // Exclusively use this field for filesystem operations. SyncRoot vfs.Path + // Path to root of git worktree + WorktreeRoot vfs.Path + // Config contains the bundle configuration. // It is loaded from the bundle configuration files and mutators may update it. Config config.Root diff --git a/bundle/bundle_read_only.go b/bundle/bundle_read_only.go index ceab95c0b..4bdd94e59 100644 --- a/bundle/bundle_read_only.go +++ b/bundle/bundle_read_only.go @@ -32,6 +32,10 @@ func (r ReadOnlyBundle) SyncRoot() vfs.Path { return r.b.SyncRoot } +func (r ReadOnlyBundle) WorktreeRoot() vfs.Path { + return r.b.WorktreeRoot +} + func (r ReadOnlyBundle) WorkspaceClient() *databricks.WorkspaceClient { return r.b.WorkspaceClient() } diff --git a/bundle/config/mutator/load_git_details.go b/bundle/config/mutator/load_git_details.go index 00e7f54d1..44100e125 100644 --- a/bundle/config/mutator/load_git_details.go +++ b/bundle/config/mutator/load_git_details.go @@ -7,7 +7,6 @@ import ( "github.com/databricks/cli/bundle" "github.com/databricks/cli/libs/diag" "github.com/databricks/cli/libs/git" - "github.com/databricks/cli/libs/log" ) type loadGitDetails struct{} @@ -21,38 +20,28 @@ func (m *loadGitDetails) Name() string { } func (m *loadGitDetails) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - // Load relevant git repository - repo, err := git.NewRepository(b.BundleRoot) + info, err := git.FetchRepositoryInfo(ctx, b.BundleRoot, b.WorkspaceClient()) if err != nil { return diag.FromErr(err) } - // Read branch name of current checkout - branch, err := repo.CurrentBranch() - if err == nil { - b.Config.Bundle.Git.ActualBranch = branch - if b.Config.Bundle.Git.Branch == "" { - // Only load branch if there's no user defined value - b.Config.Bundle.Git.Inferred = true - b.Config.Bundle.Git.Branch = branch - } - } else { - log.Warnf(ctx, "failed to load current branch: %s", err) + b.WorktreeRoot = info.WorktreeRoot + + b.Config.Bundle.Git.ActualBranch = info.CurrentBranch + if b.Config.Bundle.Git.Branch == "" { + // Only load branch if there's no user defined value + b.Config.Bundle.Git.Inferred = true + b.Config.Bundle.Git.Branch = info.CurrentBranch } // load commit hash if undefined if b.Config.Bundle.Git.Commit == "" { - commit, err := repo.LatestCommit() - if err != nil { - log.Warnf(ctx, "failed to load latest commit: %s", err) - } else { - b.Config.Bundle.Git.Commit = commit - } + b.Config.Bundle.Git.Commit = info.LatestCommit } + // load origin url if undefined if b.Config.Bundle.Git.OriginURL == "" { - remoteUrl := repo.OriginUrl() - b.Config.Bundle.Git.OriginURL = remoteUrl + b.Config.Bundle.Git.OriginURL = info.OriginURL } // Compute relative path of the bundle root from the Git repo root. @@ -60,11 +49,12 @@ func (m *loadGitDetails) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagn if err != nil { return diag.FromErr(err) } - // repo.Root() returns the absolute path of the repo - relBundlePath, err := filepath.Rel(repo.Root(), absBundlePath) + + relBundlePath, err := filepath.Rel(info.WorktreeRoot.Native(), absBundlePath) if err != nil { return diag.FromErr(err) } + b.Config.Bundle.Git.BundleRootPath = filepath.ToSlash(relBundlePath) return nil } diff --git a/bundle/config/validate/files_to_sync_test.go b/bundle/config/validate/files_to_sync_test.go index 2a598fa72..30af9026d 100644 --- a/bundle/config/validate/files_to_sync_test.go +++ b/bundle/config/validate/files_to_sync_test.go @@ -44,6 +44,7 @@ func setupBundleForFilesToSyncTest(t *testing.T) *bundle.Bundle { BundleRoot: vfs.MustNew(dir), SyncRootPath: dir, SyncRoot: vfs.MustNew(dir), + WorktreeRoot: vfs.MustNew(dir), Config: config.Root{ Bundle: config.Bundle{ Target: "default", diff --git a/bundle/deploy/files/sync.go b/bundle/deploy/files/sync.go index 347ed3079..f0d96ae8f 100644 --- a/bundle/deploy/files/sync.go +++ b/bundle/deploy/files/sync.go @@ -28,10 +28,11 @@ func GetSyncOptions(ctx context.Context, rb bundle.ReadOnlyBundle) (*sync.SyncOp } opts := &sync.SyncOptions{ - LocalRoot: rb.SyncRoot(), - Paths: rb.Config().Sync.Paths, - Include: includes, - Exclude: rb.Config().Sync.Exclude, + LocalRoot: rb.SyncRoot(), + WorktreeRoot: rb.WorktreeRoot(), + Paths: rb.Config().Sync.Paths, + Include: includes, + Exclude: rb.Config().Sync.Exclude, RemotePath: rb.Config().Workspace.FilePath, Host: rb.WorkspaceClient().Config.Host, diff --git a/cmd/sync/sync.go b/cmd/sync/sync.go index 2092d9e33..307e0b34a 100644 --- a/cmd/sync/sync.go +++ b/cmd/sync/sync.go @@ -12,6 +12,7 @@ import ( "github.com/databricks/cli/bundle/deploy/files" "github.com/databricks/cli/cmd/root" "github.com/databricks/cli/libs/flags" + "github.com/databricks/cli/libs/git" "github.com/databricks/cli/libs/sync" "github.com/databricks/cli/libs/vfs" "github.com/spf13/cobra" @@ -37,6 +38,7 @@ func (f *syncFlags) syncOptionsFromBundle(cmd *cobra.Command, args []string, b * opts.Full = f.full opts.PollInterval = f.interval + opts.WorktreeRoot = b.WorktreeRoot return opts, nil } @@ -60,11 +62,21 @@ func (f *syncFlags) syncOptionsFromArgs(cmd *cobra.Command, args []string) (*syn } } + ctx := cmd.Context() + client := root.WorkspaceClient(ctx) + + localRoot := vfs.MustNew(args[0]) + info, err := git.FetchRepositoryInfo(ctx, localRoot, client) + if err != nil { + return nil, err + } + opts := sync.SyncOptions{ - LocalRoot: vfs.MustNew(args[0]), - Paths: []string{"."}, - Include: nil, - Exclude: nil, + WorktreeRoot: info.WorktreeRoot, + LocalRoot: localRoot, + Paths: []string{"."}, + Include: nil, + Exclude: nil, RemotePath: args[1], Full: f.full, @@ -75,7 +87,7 @@ func (f *syncFlags) syncOptionsFromArgs(cmd *cobra.Command, args []string) (*syn // The sync code will automatically create this directory if it doesn't // exist and add it to the `.gitignore` file in the root. SnapshotBasePath: filepath.Join(args[0], ".databricks"), - WorkspaceClient: root.WorkspaceClient(cmd.Context()), + WorkspaceClient: client, OutputHandler: outputHandler, } diff --git a/libs/git/fileset.go b/libs/git/fileset.go index bb1cd4692..c2802ee26 100644 --- a/libs/git/fileset.go +++ b/libs/git/fileset.go @@ -13,10 +13,10 @@ type FileSet struct { view *View } -// NewFileSet returns [FileSet] for the Git repository located at `root`. -func NewFileSet(root vfs.Path, paths ...[]string) (*FileSet, error) { +// NewFileSet returns [FileSet] for the directory `root` which is contained within Git repository located at `worktreeRoot`. +func NewFileSet(worktreeRoot, root vfs.Path, paths ...[]string) (*FileSet, error) { fs := fileset.New(root, paths...) - v, err := NewView(root) + v, err := NewView(worktreeRoot, root) if err != nil { return nil, err } @@ -27,6 +27,10 @@ func NewFileSet(root vfs.Path, paths ...[]string) (*FileSet, error) { }, nil } +func NewFileSetAtRoot(root vfs.Path, paths ...[]string) (*FileSet, error) { + return NewFileSet(root, root, paths...) +} + func (f *FileSet) IgnoreFile(file string) (bool, error) { return f.view.IgnoreFile(file) } diff --git a/libs/git/fileset_test.go b/libs/git/fileset_test.go index 37f3611d1..d8ee6b859 100644 --- a/libs/git/fileset_test.go +++ b/libs/git/fileset_test.go @@ -13,7 +13,7 @@ import ( ) func testFileSetAll(t *testing.T, root string) { - fileSet, err := NewFileSet(vfs.MustNew(root)) + fileSet, err := NewFileSetAtRoot(vfs.MustNew(root)) require.NoError(t, err) files, err := fileSet.Files() require.NoError(t, err) @@ -35,7 +35,7 @@ func TestFileSetNonCleanRoot(t *testing.T) { // Test what happens if the root directory can be simplified. // Path simplification is done by most filepath functions. // This should yield the same result as above test. - fileSet, err := NewFileSet(vfs.MustNew("./testdata/../testdata")) + fileSet, err := NewFileSetAtRoot(vfs.MustNew("./testdata/../testdata")) require.NoError(t, err) files, err := fileSet.Files() require.NoError(t, err) @@ -44,7 +44,7 @@ func TestFileSetNonCleanRoot(t *testing.T) { func TestFileSetAddsCacheDirToGitIgnore(t *testing.T) { projectDir := t.TempDir() - fileSet, err := NewFileSet(vfs.MustNew(projectDir)) + fileSet, err := NewFileSetAtRoot(vfs.MustNew(projectDir)) require.NoError(t, err) fileSet.EnsureValidGitIgnoreExists() @@ -59,7 +59,7 @@ func TestFileSetDoesNotCacheDirToGitIgnoreIfAlreadyPresent(t *testing.T) { projectDir := t.TempDir() gitIgnorePath := filepath.Join(projectDir, ".gitignore") - fileSet, err := NewFileSet(vfs.MustNew(projectDir)) + fileSet, err := NewFileSetAtRoot(vfs.MustNew(projectDir)) require.NoError(t, err) err = os.WriteFile(gitIgnorePath, []byte(".databricks"), 0o644) require.NoError(t, err) diff --git a/libs/git/info.go b/libs/git/info.go new file mode 100644 index 000000000..e5ef77eb4 --- /dev/null +++ b/libs/git/info.go @@ -0,0 +1,115 @@ +package git + +// move it inside git package + +import ( + "context" + "errors" + "io/fs" + "net/http" + "strings" + + "github.com/databricks/cli/libs/dbr" + "github.com/databricks/cli/libs/vfs" + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/client" +) + +type GitRepositoryInfo struct { + OriginURL string + LatestCommit string + CurrentBranch string + WorktreeRoot vfs.Path +} + +type gitInfo struct { + Branch string `json:"branch"` + HeadCommitID string `json:"head_commit_id"` + Path string `json:"path"` + URL string `json:"url"` +} + +type response struct { + GitInfo *gitInfo `json:"git_info,omitempty"` +} + +func FetchRepositoryInfo(ctx context.Context, path vfs.Path, w *databricks.WorkspaceClient) (GitRepositoryInfo, error) { + if strings.HasPrefix(path.Native(), "/Workspace/") && dbr.RunsOnRuntime(ctx) { + return FetchRepositoryInfoAPI(ctx, path, w) + } else { + return FetchRepositoryInfoDotGit(ctx, path) + } +} + +func FetchRepositoryInfoAPI(ctx context.Context, path vfs.Path, w *databricks.WorkspaceClient) (GitRepositoryInfo, error) { + apiClient, err := client.New(w.Config) + if err != nil { + return GitRepositoryInfo{}, err + } + + var response response + + err = apiClient.Do( + ctx, + http.MethodGet, + "/api/2.0/workspace/get-status", + nil, + map[string]string{ + "path": path.Native(), + "return_git_info": "true", + }, + &response, + ) + + if err != nil { + return GitRepositoryInfo{}, err + } + + // Check if GitInfo is present and extract relevant fields + gi := response.GitInfo + // XXX log warning if missing + if gi != nil { + return GitRepositoryInfo{ + OriginURL: gi.URL, + LatestCommit: gi.HeadCommitID, + CurrentBranch: gi.Branch, + WorktreeRoot: vfs.MustNew(gi.Path), + }, nil + } + + return GitRepositoryInfo{ + WorktreeRoot: path, + }, nil +} + +func FetchRepositoryInfoDotGit(ctx context.Context, path vfs.Path) (GitRepositoryInfo, error) { + rootDir, err := vfs.FindLeafInTree(path, GitDirectoryName) + if err != nil { + if !errors.Is(err, fs.ErrNotExist) { + return GitRepositoryInfo{}, err + } + rootDir = path + } + + repo, err := NewRepository(rootDir) + if err != nil { + return GitRepositoryInfo{}, err + } + + branch, err := repo.CurrentBranch() + if err != nil { + return GitRepositoryInfo{}, nil + } + + commit, err := repo.LatestCommit() + if err != nil { + return GitRepositoryInfo{}, nil + } + + return GitRepositoryInfo{ + OriginURL: repo.OriginUrl(), + LatestCommit: commit, + CurrentBranch: branch, + WorktreeRoot: rootDir, + }, nil +} diff --git a/libs/git/repository.go b/libs/git/repository.go index f0e9e1eb2..b94297ab9 100644 --- a/libs/git/repository.go +++ b/libs/git/repository.go @@ -1,9 +1,7 @@ package git import ( - "errors" "fmt" - "io/fs" "net/url" "path" "path/filepath" @@ -204,17 +202,7 @@ func (r *Repository) Ignore(relPath string) (bool, error) { return false, nil } -func NewRepository(path vfs.Path) (*Repository, error) { - rootDir, err := vfs.FindLeafInTree(path, GitDirectoryName) - if err != nil { - if !errors.Is(err, fs.ErrNotExist) { - return nil, err - } - // Cannot find `.git` directory. - // Treat the specified path as a potential repository root checkout. - rootDir = path - } - +func NewRepository(rootDir vfs.Path) (*Repository, error) { // Derive $GIT_DIR and $GIT_COMMON_DIR paths if this is a real repository. // If it isn't a real repository, they'll point to the (non-existent) `.git` directory. gitDir, gitCommonDir, err := resolveGitDirs(rootDir) diff --git a/libs/git/view.go b/libs/git/view.go index 2d2e39a60..2eaba1f8b 100644 --- a/libs/git/view.go +++ b/libs/git/view.go @@ -72,8 +72,8 @@ func (v *View) IgnoreDirectory(dir string) (bool, error) { return v.Ignore(dir + "/") } -func NewView(root vfs.Path) (*View, error) { - repo, err := NewRepository(root) +func NewView(worktreeRoot, root vfs.Path) (*View, error) { + repo, err := NewRepository(worktreeRoot) if err != nil { return nil, err } @@ -96,6 +96,10 @@ func NewView(root vfs.Path) (*View, error) { }, nil } +func NewViewAtRoot(root vfs.Path) (*View, error) { + return NewView(root, root) +} + func (v *View) EnsureValidGitIgnoreExists() error { ign, err := v.IgnoreDirectory(".databricks") if err != nil { diff --git a/libs/git/view_test.go b/libs/git/view_test.go index 76fba3458..06f6f9419 100644 --- a/libs/git/view_test.go +++ b/libs/git/view_test.go @@ -90,19 +90,19 @@ func testViewAtRoot(t *testing.T, tv testView) { } func TestViewRootInBricksRepo(t *testing.T) { - v, err := NewView(vfs.MustNew("./testdata")) + v, err := NewViewAtRoot(vfs.MustNew("./testdata")) require.NoError(t, err) testViewAtRoot(t, testView{t, v}) } func TestViewRootInTempRepo(t *testing.T) { - v, err := NewView(vfs.MustNew(createFakeRepo(t, "testdata"))) + v, err := NewViewAtRoot(vfs.MustNew(createFakeRepo(t, "testdata"))) require.NoError(t, err) testViewAtRoot(t, testView{t, v}) } func TestViewRootInTempDir(t *testing.T) { - v, err := NewView(vfs.MustNew(copyTestdata(t, "testdata"))) + v, err := NewViewAtRoot(vfs.MustNew(copyTestdata(t, "testdata"))) require.NoError(t, err) testViewAtRoot(t, testView{t, v}) } @@ -125,20 +125,21 @@ func testViewAtA(t *testing.T, tv testView) { } func TestViewAInBricksRepo(t *testing.T) { - v, err := NewView(vfs.MustNew("./testdata/a")) + v, err := NewView(vfs.MustNew("."), vfs.MustNew("./testdata/a")) require.NoError(t, err) testViewAtA(t, testView{t, v}) } func TestViewAInTempRepo(t *testing.T) { - v, err := NewView(vfs.MustNew(filepath.Join(createFakeRepo(t, "testdata"), "a"))) + repo := createFakeRepo(t, "testdata") + v, err := NewView(vfs.MustNew(repo), vfs.MustNew(filepath.Join(repo, "a"))) require.NoError(t, err) testViewAtA(t, testView{t, v}) } func TestViewAInTempDir(t *testing.T) { // Since this is not a fake repo it should not traverse up the tree. - v, err := NewView(vfs.MustNew(filepath.Join(copyTestdata(t, "testdata"), "a"))) + v, err := NewViewAtRoot(vfs.MustNew(filepath.Join(copyTestdata(t, "testdata"), "a"))) require.NoError(t, err) tv := testView{t, v} @@ -175,20 +176,21 @@ func testViewAtAB(t *testing.T, tv testView) { } func TestViewABInBricksRepo(t *testing.T) { - v, err := NewView(vfs.MustNew("./testdata/a/b")) + v, err := NewView(vfs.MustNew("."), vfs.MustNew("./testdata/a/b")) require.NoError(t, err) testViewAtAB(t, testView{t, v}) } func TestViewABInTempRepo(t *testing.T) { - v, err := NewView(vfs.MustNew(filepath.Join(createFakeRepo(t, "testdata"), "a", "b"))) + repo := createFakeRepo(t, "testdata") + v, err := NewView(vfs.MustNew(repo), vfs.MustNew(filepath.Join(repo, "a", "b"))) require.NoError(t, err) testViewAtAB(t, testView{t, v}) } func TestViewABInTempDir(t *testing.T) { // Since this is not a fake repo it should not traverse up the tree. - v, err := NewView(vfs.MustNew(filepath.Join(copyTestdata(t, "testdata"), "a", "b"))) + v, err := NewViewAtRoot(vfs.MustNew(filepath.Join(copyTestdata(t, "testdata"), "a", "b"))) tv := testView{t, v} require.NoError(t, err) @@ -215,7 +217,7 @@ func TestViewDoesNotChangeGitignoreIfCacheDirAlreadyIgnoredAtRoot(t *testing.T) // Since root .gitignore already has .databricks, there should be no edits // to root .gitignore - v, err := NewView(vfs.MustNew(repoPath)) + v, err := NewViewAtRoot(vfs.MustNew(repoPath)) require.NoError(t, err) err = v.EnsureValidGitIgnoreExists() @@ -235,7 +237,7 @@ func TestViewDoesNotChangeGitignoreIfCacheDirAlreadyIgnoredInSubdir(t *testing.T // Since root .gitignore already has .databricks, there should be no edits // to a/.gitignore - v, err := NewView(vfs.MustNew(filepath.Join(repoPath, "a"))) + v, err := NewView(vfs.MustNew(repoPath), vfs.MustNew(filepath.Join(repoPath, "a"))) require.NoError(t, err) err = v.EnsureValidGitIgnoreExists() @@ -253,7 +255,7 @@ func TestViewAddsGitignoreWithCacheDir(t *testing.T) { assert.NoError(t, err) // Since root .gitignore was deleted, new view adds .databricks to root .gitignore - v, err := NewView(vfs.MustNew(repoPath)) + v, err := NewViewAtRoot(vfs.MustNew(repoPath)) require.NoError(t, err) err = v.EnsureValidGitIgnoreExists() @@ -271,7 +273,7 @@ func TestViewAddsGitignoreWithCacheDirAtSubdir(t *testing.T) { require.NoError(t, err) // Since root .gitignore was deleted, new view adds .databricks to a/.gitignore - v, err := NewView(vfs.MustNew(filepath.Join(repoPath, "a"))) + v, err := NewView(vfs.MustNew(repoPath), vfs.MustNew(filepath.Join(repoPath, "a"))) require.NoError(t, err) err = v.EnsureValidGitIgnoreExists() @@ -288,7 +290,7 @@ func TestViewAddsGitignoreWithCacheDirAtSubdir(t *testing.T) { func TestViewAlwaysIgnoresCacheDir(t *testing.T) { repoPath := createFakeRepo(t, "testdata") - v, err := NewView(vfs.MustNew(repoPath)) + v, err := NewViewAtRoot(vfs.MustNew(repoPath)) require.NoError(t, err) err = v.EnsureValidGitIgnoreExists() diff --git a/libs/sync/snapshot_test.go b/libs/sync/snapshot_test.go index b7830406d..eef526e58 100644 --- a/libs/sync/snapshot_test.go +++ b/libs/sync/snapshot_test.go @@ -30,7 +30,7 @@ func TestDiff(t *testing.T) { // Create temp project dir projectDir := t.TempDir() - fileSet, err := git.NewFileSet(vfs.MustNew(projectDir)) + fileSet, err := git.NewFileSetAtRoot(vfs.MustNew(projectDir)) require.NoError(t, err) state := Snapshot{ SnapshotState: &SnapshotState{ @@ -94,7 +94,7 @@ func TestSymlinkDiff(t *testing.T) { // Create temp project dir projectDir := t.TempDir() - fileSet, err := git.NewFileSet(vfs.MustNew(projectDir)) + fileSet, err := git.NewFileSetAtRoot(vfs.MustNew(projectDir)) require.NoError(t, err) state := Snapshot{ SnapshotState: &SnapshotState{ @@ -125,7 +125,7 @@ func TestFolderDiff(t *testing.T) { // Create temp project dir projectDir := t.TempDir() - fileSet, err := git.NewFileSet(vfs.MustNew(projectDir)) + fileSet, err := git.NewFileSetAtRoot(vfs.MustNew(projectDir)) require.NoError(t, err) state := Snapshot{ SnapshotState: &SnapshotState{ @@ -170,7 +170,7 @@ func TestPythonNotebookDiff(t *testing.T) { // Create temp project dir projectDir := t.TempDir() - fileSet, err := git.NewFileSet(vfs.MustNew(projectDir)) + fileSet, err := git.NewFileSetAtRoot(vfs.MustNew(projectDir)) require.NoError(t, err) state := Snapshot{ SnapshotState: &SnapshotState{ @@ -245,7 +245,7 @@ func TestErrorWhenIdenticalRemoteName(t *testing.T) { // Create temp project dir projectDir := t.TempDir() - fileSet, err := git.NewFileSet(vfs.MustNew(projectDir)) + fileSet, err := git.NewFileSetAtRoot(vfs.MustNew(projectDir)) require.NoError(t, err) state := Snapshot{ SnapshotState: &SnapshotState{ @@ -282,7 +282,7 @@ func TestNoErrorRenameWithIdenticalRemoteName(t *testing.T) { // Create temp project dir projectDir := t.TempDir() - fileSet, err := git.NewFileSet(vfs.MustNew(projectDir)) + fileSet, err := git.NewFileSetAtRoot(vfs.MustNew(projectDir)) require.NoError(t, err) state := Snapshot{ SnapshotState: &SnapshotState{ diff --git a/libs/sync/sync.go b/libs/sync/sync.go index cc9c73944..6bd26f224 100644 --- a/libs/sync/sync.go +++ b/libs/sync/sync.go @@ -19,10 +19,11 @@ import ( type OutputHandler func(context.Context, <-chan Event) type SyncOptions struct { - LocalRoot vfs.Path - Paths []string - Include []string - Exclude []string + WorktreeRoot vfs.Path + LocalRoot vfs.Path + Paths []string + Include []string + Exclude []string RemotePath string @@ -62,7 +63,7 @@ type Sync struct { // New initializes and returns a new [Sync] instance. func New(ctx context.Context, opts SyncOptions) (*Sync, error) { - fileSet, err := git.NewFileSet(opts.LocalRoot, opts.Paths) + fileSet, err := git.NewFileSet(opts.WorktreeRoot, opts.LocalRoot, opts.Paths) if err != nil { return nil, err } diff --git a/libs/sync/sync_test.go b/libs/sync/sync_test.go index 2d800f466..6168dc217 100644 --- a/libs/sync/sync_test.go +++ b/libs/sync/sync_test.go @@ -37,7 +37,7 @@ func TestGetFileSet(t *testing.T) { dir := setupFiles(t) root := vfs.MustNew(dir) - fileSet, err := git.NewFileSet(root) + fileSet, err := git.NewFileSetAtRoot(root) require.NoError(t, err) err = fileSet.EnsureValidGitIgnoreExists() @@ -103,7 +103,7 @@ func TestRecursiveExclude(t *testing.T) { dir := setupFiles(t) root := vfs.MustNew(dir) - fileSet, err := git.NewFileSet(root) + fileSet, err := git.NewFileSetAtRoot(root) require.NoError(t, err) err = fileSet.EnsureValidGitIgnoreExists() @@ -133,7 +133,7 @@ func TestNegateExclude(t *testing.T) { dir := setupFiles(t) root := vfs.MustNew(dir) - fileSet, err := git.NewFileSet(root) + fileSet, err := git.NewFileSetAtRoot(root) require.NoError(t, err) err = fileSet.EnsureValidGitIgnoreExists()