aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/cli/internal/context
diff options
context:
space:
mode:
Diffstat (limited to 'cli/internal/context')
-rw-r--r--cli/internal/context/context.go480
-rw-r--r--cli/internal/context/context_test.go162
-rw-r--r--cli/internal/context/testdata/dupe-workspace-names/apps/a/package.json6
-rw-r--r--cli/internal/context/testdata/dupe-workspace-names/apps/b/package.json6
-rw-r--r--cli/internal/context/testdata/dupe-workspace-names/package.json7
-rw-r--r--cli/internal/context/testdata/dupe-workspace-names/packages/ui/package.json3
-rw-r--r--cli/internal/context/testdata/dupe-workspace-names/pnpm-lock.yaml21
-rw-r--r--cli/internal/context/testdata/dupe-workspace-names/pnpm-workspace.yaml3
8 files changed, 0 insertions, 688 deletions
diff --git a/cli/internal/context/context.go b/cli/internal/context/context.go
deleted file mode 100644
index 2376d2d..0000000
--- a/cli/internal/context/context.go
+++ /dev/null
@@ -1,480 +0,0 @@
-package context
-
-import (
- "fmt"
- "path/filepath"
- "sort"
- "strings"
- "sync"
-
- "github.com/hashicorp/go-multierror"
- "github.com/vercel/turbo/cli/internal/core"
- "github.com/vercel/turbo/cli/internal/fs"
- "github.com/vercel/turbo/cli/internal/lockfile"
- "github.com/vercel/turbo/cli/internal/packagemanager"
- "github.com/vercel/turbo/cli/internal/turbopath"
- "github.com/vercel/turbo/cli/internal/util"
- "github.com/vercel/turbo/cli/internal/workspace"
-
- "github.com/Masterminds/semver"
- mapset "github.com/deckarep/golang-set"
- "github.com/pyr-sh/dag"
- "golang.org/x/sync/errgroup"
-)
-
-// Warnings Error type for errors that don't prevent the creation of a functional Context
-type Warnings struct {
- warns *multierror.Error
- mu sync.Mutex
-}
-
-var _ error = (*Warnings)(nil)
-
-func (w *Warnings) Error() string {
- return w.warns.Error()
-}
-
-func (w *Warnings) errorOrNil() error {
- if w.warns != nil {
- return w
- }
- return nil
-}
-
-func (w *Warnings) append(err error) {
- w.mu.Lock()
- defer w.mu.Unlock()
- w.warns = multierror.Append(w.warns, err)
-}
-
-// Context of the CLI
-type Context struct {
- // WorkspaceInfos contains the contents of package.json for every workspace
- // TODO(gsoltis): should the RootPackageJSON be included in WorkspaceInfos?
- WorkspaceInfos workspace.Catalog
-
- // WorkspaceNames is all the names of the workspaces
- WorkspaceNames []string
-
- // WorkspaceGraph is a graph of workspace dependencies
- // (based on package.json dependencies and devDependencies)
- WorkspaceGraph dag.AcyclicGraph
-
- // RootNode is a sigil identifying the root workspace
- RootNode string
-
- // Lockfile is a struct to read the lockfile based on the package manager
- Lockfile lockfile.Lockfile
-
- // PackageManager is an abstraction for all the info a package manager
- // can give us about the repo.
- PackageManager *packagemanager.PackageManager
-
- // Used to arbitrate access to the graph. We parallelise most build operations
- // and Go maps aren't natively threadsafe so this is needed.
- mutex sync.Mutex
-}
-
-// Splits "npm:^1.2.3" and "github:foo/bar.git" into a protocol part and a version part.
-func parseDependencyProtocol(version string) (string, string) {
- parts := strings.Split(version, ":")
- if len(parts) == 1 {
- return "", parts[0]
- }
-
- return parts[0], strings.Join(parts[1:], ":")
-}
-
-func isProtocolExternal(protocol string) bool {
- // The npm protocol for yarn by default still uses the workspace package if the workspace
- // version is in a compatible semver range. See https://github.com/yarnpkg/berry/discussions/4015
- // For now, we will just assume if the npm protocol is being used and the version matches
- // its an internal dependency which matches the existing behavior before this additional
- // logic was added.
-
- // TODO: extend this to support the `enableTransparentWorkspaces` yarn option
- return protocol != "" && protocol != "npm"
-}
-
-func isWorkspaceReference(packageVersion string, dependencyVersion string, cwd string, rootpath string) bool {
- protocol, dependencyVersion := parseDependencyProtocol(dependencyVersion)
-
- if protocol == "workspace" {
- // TODO: Since support at the moment is non-existent for workspaces that contain multiple
- // versions of the same package name, just assume its a match and don't check the range
- // for an exact match.
- return true
- } else if protocol == "file" || protocol == "link" {
- abs, err := filepath.Abs(filepath.Join(cwd, dependencyVersion))
- if err != nil {
- // Default to internal if we have the package but somehow cannot get the path
- // TODO(gsoltis): log this?
- return true
- }
- isWithinRepo, err := fs.DirContainsPath(rootpath, filepath.FromSlash(abs))
- if err != nil {
- // Default to internal if we have the package but somehow cannot get the path
- // TODO(gsoltis): log this?
- return true
- }
- return isWithinRepo
- } else if isProtocolExternal(protocol) {
- // Other protocols are assumed to be external references ("github:", etc)
- return false
- } else if dependencyVersion == "*" {
- return true
- }
-
- // If we got this far, then we need to check the workspace package version to see it satisfies
- // the dependencies range to determin whether or not its an internal or external dependency.
-
- constraint, constraintErr := semver.NewConstraint(dependencyVersion)
- pkgVersion, packageVersionErr := semver.NewVersion(packageVersion)
- if constraintErr != nil || packageVersionErr != nil {
- // For backwards compatibility with existing behavior, if we can't parse the version then we
- // treat the dependency as an internal package reference and swallow the error.
-
- // TODO: some package managers also support tags like "latest". Does extra handling need to be
- // added for this corner-case
- return true
- }
-
- return constraint.Check(pkgVersion)
-}
-
-// SinglePackageGraph constructs a Context instance from a single package.
-func SinglePackageGraph(repoRoot turbopath.AbsoluteSystemPath, rootPackageJSON *fs.PackageJSON) (*Context, error) {
- workspaceInfos := workspace.Catalog{
- PackageJSONs: map[string]*fs.PackageJSON{util.RootPkgName: rootPackageJSON},
- TurboConfigs: map[string]*fs.TurboJSON{},
- }
- c := &Context{
- WorkspaceInfos: workspaceInfos,
- RootNode: core.ROOT_NODE_NAME,
- }
- c.WorkspaceGraph.Connect(dag.BasicEdge(util.RootPkgName, core.ROOT_NODE_NAME))
- packageManager, err := packagemanager.GetPackageManager(repoRoot, rootPackageJSON)
- if err != nil {
- return nil, err
- }
- c.PackageManager = packageManager
- return c, nil
-}
-
-// BuildPackageGraph constructs a Context instance with information about the package dependency graph
-func BuildPackageGraph(repoRoot turbopath.AbsoluteSystemPath, rootPackageJSON *fs.PackageJSON) (*Context, error) {
- c := &Context{}
- rootpath := repoRoot.ToStringDuringMigration()
- c.WorkspaceInfos = workspace.Catalog{
- PackageJSONs: map[string]*fs.PackageJSON{},
- TurboConfigs: map[string]*fs.TurboJSON{},
- }
- c.RootNode = core.ROOT_NODE_NAME
-
- var warnings Warnings
-
- packageManager, err := packagemanager.GetPackageManager(repoRoot, rootPackageJSON)
- if err != nil {
- return nil, err
- }
- c.PackageManager = packageManager
-
- if lockfile, err := c.PackageManager.ReadLockfile(repoRoot, rootPackageJSON); err != nil {
- warnings.append(err)
- } else {
- c.Lockfile = lockfile
- }
-
- if err := c.resolveWorkspaceRootDeps(rootPackageJSON, &warnings); err != nil {
- // TODO(Gaspar) was this the intended return error?
- return nil, fmt.Errorf("could not resolve workspaces: %w", err)
- }
-
- // Get the workspaces from the package manager.
- // workspaces are absolute paths
- workspaces, err := c.PackageManager.GetWorkspaces(repoRoot)
-
- if err != nil {
- return nil, fmt.Errorf("workspace configuration error: %w", err)
- }
-
- // We will parse all package.json's simultaneously. We use a
- // wait group because we cannot fully populate the graph (the next step)
- // until all parsing is complete
- parseJSONWaitGroup := &errgroup.Group{}
- for _, workspace := range workspaces {
- pkgJSONPath := fs.UnsafeToAbsoluteSystemPath(workspace)
- parseJSONWaitGroup.Go(func() error {
- return c.parsePackageJSON(repoRoot, pkgJSONPath)
- })
- }
-
- if err := parseJSONWaitGroup.Wait(); err != nil {
- return nil, err
- }
- populateGraphWaitGroup := &errgroup.Group{}
- for _, pkg := range c.WorkspaceInfos.PackageJSONs {
- pkg := pkg
- populateGraphWaitGroup.Go(func() error {
- return c.populateWorkspaceGraphForPackageJSON(pkg, rootpath, pkg.Name, &warnings)
- })
- }
-
- if err := populateGraphWaitGroup.Wait(); err != nil {
- return nil, err
- }
- // Resolve dependencies for the root package. We override the vertexName in the graph
- // for the root package, since it can have an arbitrary name. We need it to have our
- // RootPkgName so that we can identify it as the root later on.
- err = c.populateWorkspaceGraphForPackageJSON(rootPackageJSON, rootpath, util.RootPkgName, &warnings)
- if err != nil {
- return nil, fmt.Errorf("failed to resolve dependencies for root package: %v", err)
- }
- c.WorkspaceInfos.PackageJSONs[util.RootPkgName] = rootPackageJSON
-
- return c, warnings.errorOrNil()
-}
-
-func (c *Context) resolveWorkspaceRootDeps(rootPackageJSON *fs.PackageJSON, warnings *Warnings) error {
- pkg := rootPackageJSON
- pkg.UnresolvedExternalDeps = make(map[string]string)
- for dep, version := range pkg.DevDependencies {
- pkg.UnresolvedExternalDeps[dep] = version
- }
- for dep, version := range pkg.OptionalDependencies {
- pkg.UnresolvedExternalDeps[dep] = version
- }
- for dep, version := range pkg.Dependencies {
- pkg.UnresolvedExternalDeps[dep] = version
- }
- if c.Lockfile != nil {
- depSet, err := lockfile.TransitiveClosure(
- pkg.Dir.ToUnixPath(),
- pkg.UnresolvedExternalDeps,
- c.Lockfile,
- )
- if err != nil {
- warnings.append(err)
- // Return early to skip using results of incomplete dep graph resolution
- return nil
- }
- pkg.TransitiveDeps = make([]lockfile.Package, 0, depSet.Cardinality())
- for _, v := range depSet.ToSlice() {
- dep := v.(lockfile.Package)
- pkg.TransitiveDeps = append(pkg.TransitiveDeps, dep)
- }
- sort.Sort(lockfile.ByKey(pkg.TransitiveDeps))
- hashOfExternalDeps, err := fs.HashObject(pkg.TransitiveDeps)
- if err != nil {
- return err
- }
- pkg.ExternalDepsHash = hashOfExternalDeps
- } else {
- pkg.TransitiveDeps = []lockfile.Package{}
- pkg.ExternalDepsHash = ""
- }
-
- return nil
-}
-
-// populateWorkspaceGraphForPackageJSON fills in the edges for the dependencies of the given package
-// that are within the monorepo, as well as collecting and hashing the dependencies of the package
-// that are not within the monorepo. The vertexName is used to override the package name in the graph.
-// This can happen when adding the root package, which can have an arbitrary name.
-func (c *Context) populateWorkspaceGraphForPackageJSON(pkg *fs.PackageJSON, rootpath string, vertexName string, warnings *Warnings) error {
- c.mutex.Lock()
- defer c.mutex.Unlock()
- depMap := make(map[string]string)
- internalDepsSet := make(dag.Set)
- externalUnresolvedDepsSet := make(dag.Set)
- pkg.UnresolvedExternalDeps = make(map[string]string)
-
- for dep, version := range pkg.DevDependencies {
- depMap[dep] = version
- }
-
- for dep, version := range pkg.OptionalDependencies {
- depMap[dep] = version
- }
-
- for dep, version := range pkg.Dependencies {
- depMap[dep] = version
- }
-
- // split out internal vs. external deps
- for depName, depVersion := range depMap {
- if item, ok := c.WorkspaceInfos.PackageJSONs[depName]; ok && isWorkspaceReference(item.Version, depVersion, pkg.Dir.ToStringDuringMigration(), rootpath) {
- internalDepsSet.Add(depName)
- c.WorkspaceGraph.Connect(dag.BasicEdge(vertexName, depName))
- } else {
- externalUnresolvedDepsSet.Add(depName)
- }
- }
-
- for _, name := range externalUnresolvedDepsSet.List() {
- name := name.(string)
- if item, ok := pkg.DevDependencies[name]; ok {
- pkg.UnresolvedExternalDeps[name] = item
- }
-
- if item, ok := pkg.OptionalDependencies[name]; ok {
- pkg.UnresolvedExternalDeps[name] = item
- }
-
- if item, ok := pkg.Dependencies[name]; ok {
- pkg.UnresolvedExternalDeps[name] = item
- }
- }
-
- externalDeps, err := lockfile.TransitiveClosure(
- pkg.Dir.ToUnixPath(),
- pkg.UnresolvedExternalDeps,
- c.Lockfile,
- )
- if err != nil {
- warnings.append(err)
- // reset external deps to original state
- externalDeps = mapset.NewSet()
- }
-
- // when there are no internal dependencies, we need to still add these leafs to the graph
- if internalDepsSet.Len() == 0 {
- c.WorkspaceGraph.Connect(dag.BasicEdge(pkg.Name, core.ROOT_NODE_NAME))
- }
- pkg.TransitiveDeps = make([]lockfile.Package, 0, externalDeps.Cardinality())
- for _, dependency := range externalDeps.ToSlice() {
- dependency := dependency.(lockfile.Package)
- pkg.TransitiveDeps = append(pkg.TransitiveDeps, dependency)
- }
- pkg.InternalDeps = make([]string, 0, internalDepsSet.Len())
- for _, v := range internalDepsSet.List() {
- pkg.InternalDeps = append(pkg.InternalDeps, fmt.Sprintf("%v", v))
- }
- sort.Strings(pkg.InternalDeps)
- sort.Sort(lockfile.ByKey(pkg.TransitiveDeps))
- hashOfExternalDeps, err := fs.HashObject(pkg.TransitiveDeps)
- if err != nil {
- return err
- }
- pkg.ExternalDepsHash = hashOfExternalDeps
- return nil
-}
-
-func (c *Context) parsePackageJSON(repoRoot turbopath.AbsoluteSystemPath, pkgJSONPath turbopath.AbsoluteSystemPath) error {
- c.mutex.Lock()
- defer c.mutex.Unlock()
-
- if pkgJSONPath.FileExists() {
- pkg, err := fs.ReadPackageJSON(pkgJSONPath)
- if err != nil {
- return fmt.Errorf("parsing %s: %w", pkgJSONPath, err)
- }
-
- relativePkgJSONPath, err := repoRoot.PathTo(pkgJSONPath)
- if err != nil {
- return err
- }
- c.WorkspaceGraph.Add(pkg.Name)
- pkg.PackageJSONPath = turbopath.AnchoredSystemPathFromUpstream(relativePkgJSONPath)
- pkg.Dir = turbopath.AnchoredSystemPathFromUpstream(filepath.Dir(relativePkgJSONPath))
- if c.WorkspaceInfos.PackageJSONs[pkg.Name] != nil {
- existing := c.WorkspaceInfos.PackageJSONs[pkg.Name]
- return fmt.Errorf("Failed to add workspace \"%s\" from %s, it already exists at %s", pkg.Name, pkg.Dir, existing.Dir)
- }
- c.WorkspaceInfos.PackageJSONs[pkg.Name] = pkg
- c.WorkspaceNames = append(c.WorkspaceNames, pkg.Name)
- }
- return nil
-}
-
-// InternalDependencies finds all dependencies required by the slice of starting
-// packages, as well as the starting packages themselves.
-func (c *Context) InternalDependencies(start []string) ([]string, error) {
- vertices := make(dag.Set)
- for _, v := range start {
- vertices.Add(v)
- }
- s := make(dag.Set)
- memoFunc := func(v dag.Vertex, d int) error {
- s.Add(v)
- return nil
- }
-
- if err := c.WorkspaceGraph.DepthFirstWalk(vertices, memoFunc); err != nil {
- return nil, err
- }
-
- // Use for loop so we can coerce to string
- // .List() returns a list of interface{} types, but
- // we know they are strings.
- targets := make([]string, 0, s.Len())
- for _, dep := range s.List() {
- targets = append(targets, dep.(string))
- }
- sort.Strings(targets)
-
- return targets, nil
-}
-
-// ChangedPackages returns a list of changed packages based on the contents of a previous lockfile
-// This assumes that none of the package.json in the workspace change, it is
-// the responsibility of the caller to verify this.
-func (c *Context) ChangedPackages(previousLockfile lockfile.Lockfile) ([]string, error) {
- if lockfile.IsNil(previousLockfile) || lockfile.IsNil(c.Lockfile) {
- return nil, fmt.Errorf("Cannot detect changed packages without previous and current lockfile")
- }
-
- didPackageChange := func(pkgName string, pkg *fs.PackageJSON) bool {
- previousDeps, err := lockfile.TransitiveClosure(
- pkg.Dir.ToUnixPath(),
- pkg.UnresolvedExternalDeps,
- previousLockfile,
- )
- if err != nil || previousDeps.Cardinality() != len(pkg.TransitiveDeps) {
- return true
- }
-
- prevExternalDeps := make([]lockfile.Package, 0, previousDeps.Cardinality())
- for _, d := range previousDeps.ToSlice() {
- prevExternalDeps = append(prevExternalDeps, d.(lockfile.Package))
- }
- sort.Sort(lockfile.ByKey(prevExternalDeps))
-
- for i := range prevExternalDeps {
- if prevExternalDeps[i] != pkg.TransitiveDeps[i] {
- return true
- }
- }
- return false
- }
-
- changedPkgs := make([]string, 0, len(c.WorkspaceInfos.PackageJSONs))
-
- // check if prev and current have "global" changes e.g. lockfile bump
- globalChange := c.Lockfile.GlobalChange(previousLockfile)
-
- for pkgName, pkg := range c.WorkspaceInfos.PackageJSONs {
- if globalChange {
- break
- }
- if didPackageChange(pkgName, pkg) {
- if pkgName == util.RootPkgName {
- globalChange = true
- } else {
- changedPkgs = append(changedPkgs, pkgName)
- }
- }
- }
-
- if globalChange {
- changedPkgs = make([]string, 0, len(c.WorkspaceInfos.PackageJSONs))
- for pkgName := range c.WorkspaceInfos.PackageJSONs {
- changedPkgs = append(changedPkgs, pkgName)
- }
- sort.Strings(changedPkgs)
- return changedPkgs, nil
- }
-
- sort.Strings(changedPkgs)
- return changedPkgs, nil
-}
diff --git a/cli/internal/context/context_test.go b/cli/internal/context/context_test.go
deleted file mode 100644
index 692c0a8..0000000
--- a/cli/internal/context/context_test.go
+++ /dev/null
@@ -1,162 +0,0 @@
-package context
-
-import (
- "os"
- "path/filepath"
- "regexp"
- "testing"
-
- testifyAssert "github.com/stretchr/testify/assert"
- "github.com/vercel/turbo/cli/internal/fs"
- "github.com/vercel/turbo/cli/internal/turbopath"
-)
-
-func Test_isWorkspaceReference(t *testing.T) {
- rootpath, err := filepath.Abs(filepath.FromSlash("/some/repo"))
- if err != nil {
- t.Fatalf("failed to create absolute root path %v", err)
- }
- pkgDir, err := filepath.Abs(filepath.FromSlash("/some/repo/packages/libA"))
- if err != nil {
- t.Fatalf("failed to create absolute pkgDir %v", err)
- }
- tests := []struct {
- name string
- packageVersion string
- dependencyVersion string
- want bool
- }{
- {
- name: "handles exact match",
- packageVersion: "1.2.3",
- dependencyVersion: "1.2.3",
- want: true,
- },
- {
- name: "handles semver range satisfied",
- packageVersion: "1.2.3",
- dependencyVersion: "^1.0.0",
- want: true,
- },
- {
- name: "handles semver range not-satisfied",
- packageVersion: "2.3.4",
- dependencyVersion: "^1.0.0",
- want: false,
- },
- {
- name: "handles workspace protocol with version",
- packageVersion: "1.2.3",
- dependencyVersion: "workspace:1.2.3",
- want: true,
- },
- {
- name: "handles workspace protocol with relative path",
- packageVersion: "1.2.3",
- dependencyVersion: "workspace:../other-package/",
- want: true,
- },
- {
- name: "handles npm protocol with satisfied semver range",
- packageVersion: "1.2.3",
- dependencyVersion: "npm:^1.2.3",
- want: true, // default in yarn is to use the workspace version unless `enableTransparentWorkspaces: true`. This isn't currently being checked.
- },
- {
- name: "handles npm protocol with non-satisfied semver range",
- packageVersion: "2.3.4",
- dependencyVersion: "npm:^1.2.3",
- want: false,
- },
- {
- name: "handles pre-release versions",
- packageVersion: "1.2.3",
- dependencyVersion: "1.2.2-alpha-1234abcd.0",
- want: false,
- },
- {
- name: "handles non-semver package version",
- packageVersion: "sometag",
- dependencyVersion: "1.2.3",
- want: true, // for backwards compatability with the code before versions were verified
- },
- {
- name: "handles non-semver package version",
- packageVersion: "1.2.3",
- dependencyVersion: "sometag",
- want: true, // for backwards compatability with the code before versions were verified
- },
- {
- name: "handles file:... inside repo",
- packageVersion: "1.2.3",
- dependencyVersion: "file:../libB",
- want: true, // this is a sibling package
- },
- {
- name: "handles file:... outside repo",
- packageVersion: "1.2.3",
- dependencyVersion: "file:../../../otherproject",
- want: false, // this is not within the repo root
- },
- {
- name: "handles link:... inside repo",
- packageVersion: "1.2.3",
- dependencyVersion: "link:../libB",
- want: true, // this is a sibling package
- },
- {
- name: "handles link:... outside repo",
- packageVersion: "1.2.3",
- dependencyVersion: "link:../../../otherproject",
- want: false, // this is not within the repo root
- },
- {
- name: "handles development versions",
- packageVersion: "0.0.0-development",
- dependencyVersion: "*",
- want: true, // "*" should always match
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got := isWorkspaceReference(tt.packageVersion, tt.dependencyVersion, pkgDir, rootpath)
- if got != tt.want {
- t.Errorf("isWorkspaceReference(%v, %v, %v, %v) got = %v, want %v", tt.packageVersion, tt.dependencyVersion, pkgDir, rootpath, got, tt.want)
- }
- })
- }
-}
-
-func TestBuildPackageGraph_DuplicateNames(t *testing.T) {
- path := getTestDir(t, "dupe-workspace-names")
- pkgJSON := &fs.PackageJSON{
- Name: "dupe-workspace-names",
- PackageManager: "pnpm@7.15.0",
- }
-
- _, actualErr := BuildPackageGraph(path, pkgJSON)
-
- // Not asserting the full error message, because it includes a path with slashes and backslashes
- // getting the regex incantation to check that is not worth it.
- // We have to use regex because the actual error may be different depending on which workspace was
- // added first and which one was second, causing the error.
- testifyAssert.Regexp(t, regexp.MustCompile("^Failed to add workspace \"same-name\".+$"), actualErr)
-}
-
-// This is duplicated from fs.turbo_json_test.go.
-// I wasn't able to pull it into a helper file/package because
-// it requires the `fs` package and it would cause cyclical dependencies
-// when used in turbo_json_test.go and would require more changes to fix that.
-func getTestDir(t *testing.T, testName string) turbopath.AbsoluteSystemPath {
- defaultCwd, err := os.Getwd()
- if err != nil {
- t.Errorf("failed to get cwd: %v", err)
- }
- cwd, err := fs.CheckedToAbsoluteSystemPath(defaultCwd)
- if err != nil {
- t.Fatalf("cwd is not an absolute directory %v: %v", defaultCwd, err)
- }
-
- return cwd.UntypedJoin("testdata", testName)
-}
diff --git a/cli/internal/context/testdata/dupe-workspace-names/apps/a/package.json b/cli/internal/context/testdata/dupe-workspace-names/apps/a/package.json
deleted file mode 100644
index 94301a3..0000000
--- a/cli/internal/context/testdata/dupe-workspace-names/apps/a/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "same-name",
- "dependencies": {
- "ui": "workspace:*"
- }
-}
diff --git a/cli/internal/context/testdata/dupe-workspace-names/apps/b/package.json b/cli/internal/context/testdata/dupe-workspace-names/apps/b/package.json
deleted file mode 100644
index 94301a3..0000000
--- a/cli/internal/context/testdata/dupe-workspace-names/apps/b/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "same-name",
- "dependencies": {
- "ui": "workspace:*"
- }
-}
diff --git a/cli/internal/context/testdata/dupe-workspace-names/package.json b/cli/internal/context/testdata/dupe-workspace-names/package.json
deleted file mode 100644
index 3bf7403..0000000
--- a/cli/internal/context/testdata/dupe-workspace-names/package.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "name": "dupe-workspace-names",
- "workspaces": [
- "apps/*"
- ],
- "packageManager": "pnpm@7.15.0"
-}
diff --git a/cli/internal/context/testdata/dupe-workspace-names/packages/ui/package.json b/cli/internal/context/testdata/dupe-workspace-names/packages/ui/package.json
deleted file mode 100644
index 1cd75b5..0000000
--- a/cli/internal/context/testdata/dupe-workspace-names/packages/ui/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "name": "ui"
-}
diff --git a/cli/internal/context/testdata/dupe-workspace-names/pnpm-lock.yaml b/cli/internal/context/testdata/dupe-workspace-names/pnpm-lock.yaml
deleted file mode 100644
index 0909cde..0000000
--- a/cli/internal/context/testdata/dupe-workspace-names/pnpm-lock.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-lockfileVersion: 5.4
-
-importers:
-
- .:
- specifiers: {}
-
- apps/a:
- specifiers:
- ui: workspace:*
- dependencies:
- ui: link:../../packages/ui
-
- apps/b:
- specifiers:
- ui: workspace:*
- dependencies:
- ui: link:../../packages/ui
-
- packages/ui:
- specifiers: {}
diff --git a/cli/internal/context/testdata/dupe-workspace-names/pnpm-workspace.yaml b/cli/internal/context/testdata/dupe-workspace-names/pnpm-workspace.yaml
deleted file mode 100644
index 3ff5faa..0000000
--- a/cli/internal/context/testdata/dupe-workspace-names/pnpm-workspace.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-packages:
- - "apps/*"
- - "packages/*"