Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 20 additions & 13 deletions cmd/extension/extension_fix.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package extension

import (
"errors"
"fmt"
"os"
"path/filepath"
Expand All @@ -18,10 +19,23 @@ var extensionFixCmd = &cobra.Command{
Use: "fix path",
Short: "Apply code-quality fixes to an extension",
Args: cobra.ExactArgs(1),
PreRunE: func(cmd *cobra.Command, args []string) error {
return verifier.SetupTools(cmd.Context(), cmd.Root().Version)
},
RunE: func(cmd *cobra.Command, args []string) error {
allTools := verifier.GetToolsOf[verifier.FixTool]()
only, _ := cmd.Flags().GetString("only")
exclude, _ := cmd.Flags().GetString("exclude")

requestedTools, err := allTools.Only(only)
if err != nil {
return err
}
tools, err := requestedTools.Exclude(exclude)
if err != nil {
return err
}
if len(tools) == 0 {
return errors.New("no fixers selected after applying --exclude")
}

allowNonGit, _ := cmd.Flags().GetBool("allow-non-git")

if !allowNonGit {
Expand All @@ -40,7 +54,7 @@ var extensionFixCmd = &cobra.Command{
return err
}

toolCfg, err := verifier.ConvertExtensionToToolConfig(ext)
toolCfg, err := verifier.SetupExtensionToolConfig(cmd.Context(), cmd.Root().Version, ext)
if err != nil {
return err
}
Expand All @@ -49,22 +63,14 @@ var extensionFixCmd = &cobra.Command{

var gr errgroup.Group

allTools := verifier.GetToolsOf[verifier.FixTool]()
only, _ := cmd.Flags().GetString("only")

tools, err := allTools.Only(only)
if err != nil {
return err
}

for _, tool := range tools {
gr.Go(func() error {
return tool.Fix(cmd.Context(), *toolCfg)
})
}

runErr := gr.Wait()
if err := validation.PrintToolInvocationTable(os.Stdout, "Fixers", extensionToolInvocationStatuses(allTools, tools)); err != nil {
if err := validation.PrintToolInvocationTable(os.Stdout, "Fixers", extensionToolInvocationStatuses(allTools, requestedTools, tools)); err != nil {
return err
}
return runErr
Expand All @@ -74,5 +80,6 @@ var extensionFixCmd = &cobra.Command{
func init() {
extensionRootCmd.AddCommand(extensionFixCmd)
extensionFixCmd.Flags().String("only", "", "Run only specific fixers by name (comma-separated, e.g. eslint,rector)")
extensionFixCmd.Flags().String("exclude", "", "Exclude fixers after applying --only (comma-separated, e.g. eslint,rector)")
extensionFixCmd.Flags().Bool("allow-non-git", false, "Allow running the fix command on non-git repositories")
}
33 changes: 20 additions & 13 deletions cmd/extension/extension_format.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package extension

import (
"errors"
"fmt"
"os"
"path/filepath"
Expand All @@ -18,10 +19,23 @@ var extensionFormat = &cobra.Command{
Use: "format path",
Short: "Format an extension's PHP, JavaScript, SCSS, and Administration Twig files",
Args: cobra.ExactArgs(1),
PreRunE: func(cmd *cobra.Command, args []string) error {
return verifier.SetupTools(cmd.Context(), cmd.Root().Version)
},
RunE: func(cmd *cobra.Command, args []string) error {
allTools := verifier.GetToolsOf[verifier.FormatTool]()
only, _ := cmd.Flags().GetString("only")
exclude, _ := cmd.Flags().GetString("exclude")

requestedTools, err := allTools.Only(only)
if err != nil {
return err
}
tools, err := requestedTools.Exclude(exclude)
if err != nil {
return err
}
if len(tools) == 0 {
return errors.New("no formatters selected after applying --exclude")
}

dryRun, _ := cmd.Flags().GetBool("dry-run")

path, err := filepath.Abs(args[0])
Expand All @@ -34,7 +48,7 @@ var extensionFormat = &cobra.Command{
return err
}

toolCfg, err := verifier.ConvertExtensionToToolConfig(ext)
toolCfg, err := verifier.SetupExtensionToolConfig(cmd.Context(), cmd.Root().Version, ext)
if err != nil {
return err
}
Expand All @@ -43,22 +57,14 @@ var extensionFormat = &cobra.Command{

var gr errgroup.Group

allTools := verifier.GetToolsOf[verifier.FormatTool]()
only, _ := cmd.Flags().GetString("only")

tools, err := allTools.Only(only)
if err != nil {
return err
}

for _, tool := range tools {
gr.Go(func() error {
return tool.Format(cmd.Context(), *toolCfg, dryRun)
})
}

runErr := gr.Wait()
if err := validation.PrintToolInvocationTable(os.Stdout, "Formatters", extensionToolInvocationStatuses(allTools, tools)); err != nil {
if err := validation.PrintToolInvocationTable(os.Stdout, "Formatters", extensionToolInvocationStatuses(allTools, requestedTools, tools)); err != nil {
return err
}
return runErr
Expand All @@ -68,5 +74,6 @@ var extensionFormat = &cobra.Command{
func init() {
extensionRootCmd.AddCommand(extensionFormat)
extensionFormat.Flags().String("only", "", "Run only specific formatters by name (comma-separated, e.g. prettier,php-cs-fixer)")
extensionFormat.Flags().String("exclude", "", "Exclude formatters after applying --only (comma-separated, e.g. prettier,php-cs-fixer)")
extensionFormat.Flags().Bool("dry-run", false, "Run in dry run mode")
}
7 changes: 5 additions & 2 deletions cmd/extension/extension_tool_invocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ import (
"github.com/shopware/shopware-cli/internal/verifier"
)

func extensionToolInvocationStatuses[T verifier.Tool](all, selected verifier.ToolList[T]) []validation.ToolInvocationStatus {
func extensionToolInvocationStatuses[T verifier.Tool](all, requested, selected verifier.ToolList[T]) []validation.ToolInvocationStatus {
statuses := make([]validation.ToolInvocationStatus, 0, len(all))
for _, tool := range all {
status := validation.ToolInvocationStatus{Name: tool.Name(), Status: "skipped", Reason: "not selected by --only"}
if slices.ContainsFunc(selected, func(selected T) bool { return selected.Name() == tool.Name() }) {
switch {
case slices.ContainsFunc(selected, func(selected T) bool { return selected.Name() == tool.Name() }):
status.Status = "invoked"
status.Reason = ""
case slices.ContainsFunc(requested, func(requested T) bool { return requested.Name() == tool.Name() }):
status.Reason = "excluded by --exclude"
}
statuses = append(statuses, status)
}
Expand Down
17 changes: 14 additions & 3 deletions cmd/extension/extension_tool_invocation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,23 @@ func TestExtensionToolInvocationStatuses(t *testing.T) {

func assertExtensionToolInvocationStatuses[T verifier.Tool](t *testing.T, all verifier.ToolList[T]) {
t.Helper()
selected, err := all.Only(all[0].Name())
requested, err := all.Only(all[0].Name() + "," + all[1].Name())
require.NoError(t, err)
selected, err := requested.Exclude(all[1].Name())
require.NoError(t, err)

statuses := extensionToolInvocationStatuses(all, selected)
statuses := extensionToolInvocationStatuses(all, requested, selected)
assert.Len(t, statuses, len(all))
assert.Equal(t, "invoked", toolStatusByName(t, statuses, all[0].Name()).Status)
assert.Equal(t, "skipped", toolStatusByName(t, statuses, all[1].Name()).Status)
assert.Equal(t, "not selected by --only", toolStatusByName(t, statuses, all[1].Name()).Reason)
assert.Equal(t, "excluded by --exclude", toolStatusByName(t, statuses, all[1].Name()).Reason)
assert.Equal(t, "not selected by --only", toolStatusByName(t, statuses, all[2].Name()).Reason)

_, err = requested.Exclude(all[2].Name())
require.ErrorContains(t, err, "not found")
}

func TestExtensionFixAndFormatHaveExcludeFlag(t *testing.T) {
assert.NotNil(t, extensionFixCmd.Flags().Lookup("exclude"))
assert.NotNil(t, extensionFormat.Flags().Lookup("exclude"))
}
9 changes: 2 additions & 7 deletions cmd/extension/extension_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,9 @@ func selectExtensionValidationTools(full bool, only, exclude string) (verifier.T
return nil, nil, errors.New("no validation checks selected after applying --exclude")
}

statuses := extensionToolInvocationStatuses(validationTools, selected)
statuses := extensionToolInvocationStatuses(validationTools, requestedTools, selected)
for i := range statuses {
if statuses[i].Status == "invoked" {
continue
}
if slices.ContainsFunc(requestedTools, func(tool verifier.CheckTool) bool { return tool.Name() == statuses[i].Name }) {
statuses[i].Reason = "excluded by --exclude"
} else if only == "" {
if only == "" && statuses[i].Reason == "not selected by --only" {
statuses[i].Reason = "not selected; use --full or --only"
}
}
Expand Down
7 changes: 7 additions & 0 deletions internal/verifier/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ import (
"github.com/shopware/shopware-cli/internal/validation"
)

func SetupExtensionToolConfig(ctx context.Context, version string, ext extension.Extension) (*ToolConfig, error) {
if err := SetupTools(ctx, version); err != nil {
return nil, err
}
return ConvertExtensionToToolConfig(ext)
}

func ConvertExtensionToToolConfig(ext extension.Extension) (*ToolConfig, error) {
var ignores []validation.ToolConfigIgnore

Expand Down
28 changes: 28 additions & 0 deletions internal/verifier/extension_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package verifier

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/shopware/shopware-cli/internal/extension"
"github.com/shopware/shopware-cli/internal/testhelper"
)

func TestSetupExtensionToolConfigUsesConfiguredToolDirectory(t *testing.T) {
stubShopwareVersions(t)
previous := toolDirectory
t.Cleanup(func() { setToolDirectory(previous) })
setToolDirectory(filepath.Join(t.TempDir(), "stale"))

toolDir := filepath.Join(t.TempDir(), "tools")
t.Setenv("SHOPWARE_CLI_TOOLS_DIR", toolDir)
ext, err := extension.GetExtensionByFolder(t.Context(), testhelper.NewPlugin(t, "Example"))
require.NoError(t, err)

cfg, err := SetupExtensionToolConfig(t.Context(), "test", ext)
require.NoError(t, err)
assert.Equal(t, toolDir, cfg.ToolDirectory)
}
Loading