Skip to content

Commit e09fbab

Browse files
committed
feat: add Composer lock file handling and testing
This commit introduces functionality to read and parse the composer.lock file, encapsulated in the new `ReadComposerLock` function. It also adds a comprehensive test suite for this functionality, ensuring correct behavior for valid, non-existent, and invalid JSON files. Additionally, a new rules file is created to enforce coding standards and practices.
1 parent abae3b3 commit e09fbab

File tree

4 files changed

+106
-8
lines changed

4 files changed

+106
-8
lines changed

.cursor/rules/repository.mdc

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
description:
3+
globs:
4+
alwaysApply: true
5+
---
6+
# General rules
7+
8+
- Use convential commit messages
9+
- Use always Go 1.24 syntax, use slices package for slice containing
10+
- Inline error into if condition like this:
11+
12+
```go
13+
if err := foo(); err != nil {
14+
// something
15+
}
16+
```
17+

extension/project.go

+5-8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"regexp"
1111
"strings"
1212

13+
"github.com/shopware/shopware-cli/internal/packagist"
1314
"github.com/shopware/shopware-cli/internal/phpexec"
1415

1516
"github.com/shopware/shopware-cli/shop"
@@ -45,17 +46,13 @@ func GetShopwareProjectConstraint(project string) (*version.Constraints, error)
4546
c, err := version.NewConstraint(constraint)
4647
if err != nil {
4748
if strings.Contains(err.Error(), "malformed constraint") {
48-
var lock composerLock
49-
50-
lockFile, readErr := os.ReadFile(path.Join(project, "composer.lock"))
51-
52-
if readErr != nil {
53-
// popup real error
49+
if _, statErr := os.Stat(path.Join(project, "composer.lock")); os.IsNotExist(statErr) {
5450
return nil, err
5551
}
5652

57-
if err := json.Unmarshal(lockFile, &lock); err != nil {
58-
return nil, fmt.Errorf("could not parse composer.lock: %w", err)
53+
lock, err := packagist.ReadComposerLock(path.Join(project, "composer.lock"))
54+
if err != nil {
55+
return nil, err
5956
}
6057

6158
for _, pkg := range lock.Packages {

internal/packagist/lock.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package packagist
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
)
8+
9+
type ComposerLock struct {
10+
Packages []struct {
11+
Name string `json:"name"`
12+
Version string `json:"version"`
13+
PackageType string `json:"type"`
14+
} `json:"packages"`
15+
}
16+
17+
func ReadComposerLock(pathToFile string) (*ComposerLock, error) {
18+
content, err := os.ReadFile(pathToFile)
19+
if err != nil {
20+
return nil, err
21+
}
22+
23+
var lock ComposerLock
24+
if err := json.Unmarshal(content, &lock); err != nil {
25+
return nil, fmt.Errorf("could not parse composer.lock: %w", err)
26+
}
27+
28+
return &lock, nil
29+
}

internal/packagist/lock_test.go

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package packagist
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestReadComposerLock(t *testing.T) {
12+
t.Run("valid composer.lock", func(t *testing.T) {
13+
// Create a temporary composer.lock file
14+
dir := t.TempDir()
15+
lockFile := filepath.Join(dir, "composer.lock")
16+
content := `{
17+
"packages": [
18+
{
19+
"name": "symfony/console",
20+
"version": "v6.3.0",
21+
"type": "library"
22+
}
23+
]
24+
}`
25+
err := os.WriteFile(lockFile, []byte(content), 0644)
26+
assert.NoError(t, err)
27+
28+
// Test reading the file
29+
lock, err := ReadComposerLock(lockFile)
30+
assert.NoError(t, err)
31+
assert.NotNil(t, lock)
32+
assert.Len(t, lock.Packages, 1)
33+
assert.Equal(t, "symfony/console", lock.Packages[0].Name)
34+
assert.Equal(t, "v6.3.0", lock.Packages[0].Version)
35+
assert.Equal(t, "library", lock.Packages[0].PackageType)
36+
})
37+
38+
t.Run("non-existent file", func(t *testing.T) {
39+
lock, err := ReadComposerLock("non-existent-file.lock")
40+
assert.Error(t, err)
41+
assert.Nil(t, lock)
42+
})
43+
44+
t.Run("invalid JSON", func(t *testing.T) {
45+
// Create a temporary file with invalid JSON
46+
dir := t.TempDir()
47+
lockFile := filepath.Join(dir, "invalid.lock")
48+
err := os.WriteFile(lockFile, []byte("invalid json"), 0644)
49+
assert.NoError(t, err)
50+
51+
lock, err := ReadComposerLock(lockFile)
52+
assert.Error(t, err)
53+
assert.Nil(t, lock)
54+
})
55+
}

0 commit comments

Comments
 (0)