Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improves workspace file finding
Browse files Browse the repository at this point in the history
filip-debricked committed Aug 30, 2024
1 parent 4cd4196 commit 54df1cc
Showing 13 changed files with 789 additions and 34 deletions.
8 changes: 4 additions & 4 deletions internal/file/finder_test.go
Original file line number Diff line number Diff line change
@@ -110,7 +110,7 @@ func TestGetGroups(t *testing.T) {
path := ""

excludedFiles := []string{"testdata/go/go.mod", "testdata/misc/requirements.txt", "testdata/misc/Cargo.lock"}
const nbrOfGroups = 9
const nbrOfGroups = 12

fileGroups, err := finder.GetGroups(
DebrickedOptions{
@@ -349,15 +349,15 @@ func TestGetGroupsWithStrictFlag(t *testing.T) {
name: "StrictnessSetTo0",
strictness: StrictAll,
testedGroupIndex: 3,
expectedNumberOfGroups: 14,
expectedNumberOfGroups: 17,
expectedManifestFile: "composer.json",
expectedLockFiles: []string{"composer.lock", "go.mod", "Cargo.lock", "requirements.txt.pip.debricked"},
},
{
name: "StrictnessSetTo1",
strictness: StrictLockAndPairs,
testedGroupIndex: 1,
expectedNumberOfGroups: 9,
expectedNumberOfGroups: 12,
expectedManifestFile: "",
expectedLockFiles: []string{
"composer.lock", "composer.lock", "go.mod", "Cargo.lock", "requirements.txt.pip.debricked", "requirements-dev.txt.pip.debricked",
@@ -367,7 +367,7 @@ func TestGetGroupsWithStrictFlag(t *testing.T) {
name: "StrictnessSetTo2",
strictness: StrictPairs,
testedGroupIndex: 0,
expectedNumberOfGroups: 7,
expectedNumberOfGroups: 10,
expectedManifestFile: "composer.json",
expectedLockFiles: []string{
"composer.lock", "requirements-dev.txt.pip.debricked.lock", "requirements.txt.pip.debricked.lock",
8 changes: 4 additions & 4 deletions internal/file/groups.go
Original file line number Diff line number Diff line change
@@ -130,12 +130,12 @@ func (gs *Groups) matchWorkspace(workspaceManifest WorkspaceManifest) {

func (gs *Groups) AddWorkspaceLockFiles() {
for _, group := range gs.groups {
workspaces, err := getWorkspaces(group.ManifestFile)
workspaces, err := getPackageJSONWorkspaces(group.ManifestFile)
if err == nil && group.HasLockFiles() {
workspaceManifest := WorkspaceManifest{
LockFiles: group.LockFiles,
RootManifest: group.ManifestFile,
Workspaces: workspaces,
LockFiles: group.LockFiles,
RootManifest: group.ManifestFile,
WorkspacePatterns: workspaces,
}
gs.matchWorkspace(workspaceManifest)
}
18 changes: 11 additions & 7 deletions internal/file/groups_test.go
Original file line number Diff line number Diff line change
@@ -198,9 +198,9 @@ func TestGroupsMatchWorkspaces(t *testing.T) {
gs.Add(*g4)

workspaceManifest := WorkspaceManifest{
LockFiles: []string{"package-lock.json"},
RootManifest: "package.json",
Workspaces: []string{"package/*"},
LockFiles: []string{"package-lock.json"},
RootManifest: "package.json",
WorkspacePatterns: []string{"package/*"},
}
gs.matchWorkspace(workspaceManifest)
for _, g := range gs.groups {
@@ -215,17 +215,21 @@ func TestGroupsMatchWorkspaces(t *testing.T) {
}

func TestAddWorkspaceLockFiles(t *testing.T) {
g1 := NewGroup("testdata/workspace/package.json", nil, []string{"testdata/workspace/package-lock.json"})
g2 := NewGroup("testdata/workspace/packages/package_one/package.json", nil, []string{})
g3 := NewGroup("testdata/workspace/packages/package_two/package.json", nil, []string{})
g1 := NewGroup(
"testdata/workspace/common/package.json",
nil,
[]string{"testdata/workspace/common/package-lock.json"},
)
g2 := NewGroup("testdata/workspace/common/packages/package_one/package.json", nil, []string{})
g3 := NewGroup("testdata/workspace/common/packages/package_two/package.json", nil, []string{})

gs := Groups{}
gs.Add(*g1)
gs.Add(*g2)
gs.Add(*g3)
gs.AddWorkspaceLockFiles()
for _, g := range gs.groups {
assert.Equal(t, len(g.LockFiles), 1)
assert.Equal(t, 1, len(g.LockFiles))
if len(g.LockFiles) == 1 {
assert.Equal(t, g.LockFiles[0], g1.LockFiles[0])
}
Original file line number Diff line number Diff line change
@@ -7,6 +7,6 @@
"typescript": "5.5.4"
},
"workspaces": [
"testdata/workspace/packages/*", "testdata\\workspace\\packages\\*"
"packages/*", "packages\\*"
]
}
650 changes: 650 additions & 0 deletions internal/file/testdata/workspace/rare/package-lock.json

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions internal/file/testdata/workspace/rare/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "npm-workspaces-test",
"private": true,
"devDependencies": {
"prettier": "3.3.3",
"rimraf": "6.0.1",
"typescript": "5.5.4"
},
"workspaces": {
"packages": [
"packages/*",
"packages\\*"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "package_one",
"version": "1.0.0",
"description": "testing workspaces",
"main": "lib/index.js",
"keywords": [],
"author": "test",
"license": "MIT",
"dependencies": {
"@types/node": "^20.0.0"
},
"devDependencies": {
"typescript": "5.5.4"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "package_two",
"version": "1.0.0",
"description": "test",
"main": "lib/main.js",
"keywords": [],
"author": "test",
"license": "MIT",
"dependencies": {
"package_one": "^1.0.0",
"@types/node": "16.11.40",
"minimist": "^1.2.5"
},
"devDependencies": {
"typescript": "5.5.4"
}
}
51 changes: 37 additions & 14 deletions internal/file/workspace.go
Original file line number Diff line number Diff line change
@@ -3,45 +3,68 @@ package file
import (
"encoding/json"
"os"
"path/filepath"

"github.com/becheran/wildmatch-go"
)

type WorkspaceManifest struct {
RootManifest string
LockFiles []string
Workspaces []string
RootManifest string
LockFiles []string
WorkspacePatterns []string
}

type NPMPackageJson struct {
// NPM Workspaces docs: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#workspaces
// Yarn Workspaces docs: https://yarnpkg.com/features/workspaces
type PackageJSON struct {
Name string `json:"name"`
Workspaces []string `json:"workspaces"`
}

type NestledPackageJSON struct {
Workspaces struct {
Packages []string `json:"packages"`
} `json:"workspaces"`
} // Rare format

func (workspaceManifest *WorkspaceManifest) matchManifest(manifestPath string) bool {
for _, workspacePattern := range workspaceManifest.Workspaces {
relativeManifestPath, err := filepath.Rel(
filepath.Dir(workspaceManifest.RootManifest),
manifestPath,
)
if err != nil {
relativeManifestPath = manifestPath
}
for _, workspacePattern := range workspaceManifest.WorkspacePatterns {
pattern := wildmatch.NewWildMatch(workspacePattern)
if pattern.IsMatch(manifestPath) {
if pattern.IsMatch(relativeManifestPath) {
return true
}
if workspacePattern == filepath.Dir(manifestPath) {
return true
} // Check if specific directory match
}

return false
}

func getWorkspaces(rootManifest string) ([]string, error) {
var npmPackageJson NPMPackageJson
func getPackageJSONWorkspaces(rootManifest string) ([]string, error) {
var packageJson PackageJSON

jsonFile, err := os.Open(rootManifest)
jsonData, err := os.ReadFile(rootManifest)
if err != nil {
return nil, err
}
defer jsonFile.Close()
decoder := json.NewDecoder(jsonFile)
err = decoder.Decode(&npmPackageJson)
if err != nil {
err = json.Unmarshal(jsonData, &packageJson)
if err != nil { // Try rare format instead
var nestledPackageJSON NestledPackageJSON
err = json.Unmarshal(jsonData, &nestledPackageJSON)
if err == nil {
return nestledPackageJSON.Workspaces.Packages, nil
}

return nil, err
}

return npmPackageJson.Workspaces, nil
return packageJson.Workspaces, nil
}
39 changes: 35 additions & 4 deletions internal/file/workspace_test.go
Original file line number Diff line number Diff line change
@@ -11,7 +11,12 @@ func TestMatchManifest(t *testing.T) {
wm := WorkspaceManifest{
RootManifest: "package.json",
LockFiles: []string{"package-lock.json"},
Workspaces: []string{"package/*", "pkg/internal/*", "pack/internal/package.json"},
WorkspacePatterns: []string{
"package/*",
"pkg/internal/*",
"pack/internal/package.json",
"packages/package_two",
},
}
cases := []struct {
manifestFile string
@@ -33,6 +38,14 @@ func TestMatchManifest(t *testing.T) {
manifestFile: "pkg/internal/package.json",
expected: true,
},
{
manifestFile: "packages/package_two/package.json",
expected: true,
},
{
manifestFile: "packages/package_two/internal/package.json",
expected: false,
},
}

for _, c := range cases {
@@ -44,14 +57,32 @@ func TestMatchManifest(t *testing.T) {
}
}

func TestDeeperMatchManifest(t *testing.T) {
wm := WorkspaceManifest{
RootManifest: "Src/app/package.json",
LockFiles: []string{"Src/app/package-lock.json"},
WorkspacePatterns: []string{"package/*", "pkg/internal/*", "pack/internal/package.json"},
}
match := (&wm).matchManifest("Src/app/package/test/package.json")
assert.True(t, match)

}

func TestGetWorkspaces(t *testing.T) {
workspaces, err := getWorkspaces("testdata/workspace/package.json")
workspaces, err := getPackageJSONWorkspaces("testdata/workspace/common/package.json")
assert.NoError(t, err)
assert.Equal(t, 2, len(workspaces))
assert.Equal(t, "packages/*", workspaces[0])
}

func TestGetWorkspacesRare(t *testing.T) {
workspaces, err := getPackageJSONWorkspaces("testdata/workspace/rare/package.json")
assert.NoError(t, err)
assert.Equal(t, 2, len(workspaces))
assert.Equal(t, "testdata/workspace/packages/*", workspaces[0])
assert.Equal(t, "packages/*", workspaces[0])
}

func TestGetWorkspacesNoFile(t *testing.T) {
_, err := getWorkspaces("testdata/non_existing_folder/package.json")
_, err := getPackageJSONWorkspaces("testdata/non_existing_folder/package.json")
assert.Error(t, err)
}

0 comments on commit 54df1cc

Please sign in to comment.