Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#91] add rm action #96

Merged
merged 1 commit into from
Feb 9, 2024
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
26 changes: 26 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ ___
| | | | |
| dirs`<unique_suffix>`[<sup>**ⓘ**</sup>](#Generate) | []string | ✅ | list of directories to create |
| | | | |
| rm`<unique_suffix>`[<sup>**ⓘ**</sup>](#rm) | []string | ✅ | list for remove (files, dirs, all file in a dir) |
| | | | |
| <a name="files_actio_desk"><a/>files`<unique_suffix>`[<sup>**ⓘ**</sup>](#Files) | | ✅ | list file's `path` and `data` |
| files.path | string | ❌ | save file `path` |
| files.local | string | `❕` | local file path to copy |
Expand Down Expand Up @@ -739,6 +741,30 @@ out:
└── file1
```

### <a name="rm"></a>Rm

`rm` use to remove files, directories or files inside a directory.

```yaml
rm:
# remove the dir
- some_dir
# remove all files in the dir
- some_dir_2/*
# remove the file
- some_dir_3/file.txt
```

```console
% progen -v
2024-02-09 22:50:51 INFO application working directory: /Users/user_1/GoProjects/progen
2023-02-12 14:01:45 INFO configuration file: progen.yml
2024-02-09 22:50:51 INFO rm: some_dir
2024-02-09 22:50:51 INFO rm all: some_dir_2/*
2024-02-09 22:50:51 INFO rm: some_dir_3/file.txt
2024-02-09 22:50:51 INFO execution time: 350.149µs
```

---

### Examples
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
Expand Down
9 changes: 6 additions & 3 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

const (
TagDirs = "dirs"
TagRm = "rm"
TagFiles = "files"
TagCmd = "cmd"
TagFS = "fs"
Expand All @@ -21,6 +22,7 @@ const (
type Config struct {
Settings Settings `yaml:"settings"`
Dirs []Section[[]string] `yaml:"dirs,flow"`
Rm []Section[[]string] `yaml:"rm,flow"`
Files []Section[[]File] `yaml:"files,flow"`
Cmd []Section[[]Command] `yaml:"cmd,flow"`
FS []Section[[]string] `yaml:"fs,flow"`
Expand Down Expand Up @@ -211,13 +213,14 @@ func validateConfigSections(conf Config) error {
var (
files = len(conf.Files)
dirs = len(conf.Dirs)
rm = len(conf.Rm)
cmd = len(conf.Cmd)
fs = len(conf.FS)
)
if files == 0 && dirs == 0 && cmd == 0 && fs == 0 {
if files == 0 && dirs == 0 && rm == 0 && cmd == 0 && fs == 0 {
return xerrors.Errorf(
"config not contains executable actions [dirs: %d, files: %d, cms: %d, fs: %d]",
dirs, files, cmd, fs,
"config not contains executable actions [dirs: %d, rm: %d, files: %d, cms: %d, fs: %d]",
dirs, rm, files, cmd, fs,
)
}
return nil
Expand Down
2 changes: 2 additions & 0 deletions internal/config/unmarshaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func (u *YamlUnmarshaler) Unmarshal(rawConfig []byte) (Config, error) {
conf.Settings = settings
case strings.Index(tag, TagDirs) == 0:
conf.Dirs, err = decode(conf.Dirs, node, tag)
case strings.Index(tag, TagRm) == 0:
conf.Rm, err = decode(conf.Rm, node, tag)
case strings.Index(tag, TagFiles) == 0:
conf.Files, err = decode(conf.Files, node, tag)
case strings.Index(tag, TagCmd) == 0:
Expand Down
5 changes: 5 additions & 0 deletions internal/entity/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const (
EqualsSign = "="
LessThan = "<"
Tilda = "~"
Astrix = "*"
NewLine = "\n"

LogSliceSep = Comma + Space
Expand All @@ -59,6 +60,10 @@ type (
Apply(path string) (string, error)
}

RmStrategy interface {
Apply(path string) error
}

TemplateProc interface {
Process(name, text string) (string, error)
}
Expand Down
85 changes: 85 additions & 0 deletions internal/exec/rm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package exec

import (
"os"
"path/filepath"
"strings"

"golang.org/x/xerrors"

"github.com/kozmod/progen/internal/entity"
)

type RmAllExecutor struct {
paths []string
strategies []entity.RmStrategy
}

func NewRmAllExecutor(paths []string, strategies []entity.RmStrategy) *RmAllExecutor {
return &RmAllExecutor{
paths: paths,
strategies: strategies,
}
}

func (p *RmAllExecutor) Exec() error {
for _, path := range p.paths {
for _, strategy := range p.strategies {
err := strategy.Apply(path)
if err != nil {
return xerrors.Errorf("execute rm: process rm [%s]: %w", path, err)
}
}
}
return nil
}

type RmAllStrategy struct {
logger entity.Logger
}

func NewRmAllStrategy(logger entity.Logger) *RmAllStrategy {
return &RmAllStrategy{
logger: logger,
}
}

func (p *RmAllStrategy) Apply(path string) error {
astrixIndex := strings.Index(path, entity.Astrix)
if astrixIndex == len(path)-1 {
contents, err := filepath.Glob(path)
if err != nil {
return xerrors.Errorf("rm [%s]: get names of the all files: %w", path, err)
}
for _, item := range contents {
err = os.RemoveAll(item)
if err != nil {
return xerrors.Errorf("rm content [%s]: %w", item, err)
}
}
p.logger.Infof("rm all: %s", path)
return nil
}

err := os.RemoveAll(path)
if err != nil {
return xerrors.Errorf("rm [%s]: %w", path, err)
}
p.logger.Infof("rm: %s", path)
return nil
}

type DryRunRmAllStrategy struct {
logger entity.Logger
}

func NewDryRmAllStrategy(logger entity.Logger) *DryRunRmAllStrategy {
return &DryRunRmAllStrategy{
logger: logger,
}
}

func (p *DryRunRmAllStrategy) Apply(path string) error {
p.logger.Infof("rm: %s", path)
return nil
}
117 changes: 117 additions & 0 deletions internal/exec/rm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package exec

import (
"fmt"
"os"
"path/filepath"
"strings"
"testing"

"github.com/stretchr/testify/assert"

"github.com/kozmod/progen/internal/entity"
)

func Test_RmAllStrategy(t *testing.T) {
SkipSLowTest(t)

const (
someDir = "some_dir"
someFile = "file_name.txt"
)

t.Run("rm_dir", func(t *testing.T) {
WithTempDir(t, func(tmpDir string) {
var (
a = assert.New(t)
path = filepath.Join(tmpDir, someDir)
mockLogger = MockLogger{
infof: func(format string, args ...any) {
assert.NotEmpty(t, format)
assert.ElementsMatch(t, []string{path}, args)
},
}
)

err := os.MkdirAll(path, os.ModePerm)
a.NoError(err)
a.DirExists(path)

err = NewRmAllStrategy(mockLogger).Apply(path)
a.NoError(err)
a.NoDirExists(path)
})
})

t.Run("rm_file", func(t *testing.T) {
WithTempDir(t, func(tmpDir string) {
var (
a = assert.New(t)
dir = filepath.Join(tmpDir, someDir, someFile)
filePath = filepath.Join(dir, someFile)
mockLogger = MockLogger{
infof: func(format string, args ...any) {
assert.NotEmpty(t, format)
assert.ElementsMatch(t, []string{filePath}, args)
},
}
)

err := os.MkdirAll(dir, os.ModePerm)
a.NoError(err)
a.DirExists(dir)

file, err := os.Create(filePath)
a.NoError(err)
a.FileExists(filePath)
a.Equal(filePath, file.Name())

err = NewRmAllStrategy(mockLogger).Apply(filePath)
a.NoError(err)
a.NoFileExists(filePath)
a.DirExists(dir)
})
})
t.Run("rm_all_files", func(t *testing.T) {
WithTempDir(t, func(tmpDir string) {
const (
filesQuantity = 5
)
var (
a = assert.New(t)
dir = filepath.Join(tmpDir, someDir)
rmPath = filepath.Join(dir, entity.Astrix)
filesPath = make([]string, 0, filesQuantity)
mockLogger = MockLogger{
infof: func(format string, args ...any) {
assert.NotEmpty(t, format)
},
}
)

err := os.MkdirAll(dir, os.ModePerm)
a.NoError(err)
a.DirExists(dir)

for i := 0; i < filesQuantity; i++ {
var (
fileExt = filepath.Ext(someFile)
fileName = fmt.Sprintf("%s_%d%s", strings.TrimSuffix(someFile, fileExt), i, fileExt)
filePath = filepath.Join(tmpDir, someDir, fileName)
)
filesPath = append(filesPath, filePath)
_, err = os.Create(filePath)
a.NoError(err)
a.FileExists(filePath)
}

err = NewRmAllStrategy(mockLogger).Apply(rmPath)
a.NoError(err)
a.DirExists(dir)
for _, path := range filesPath {
a.NoFileExists(path)
}
})
})

}
18 changes: 18 additions & 0 deletions internal/factory/chain_exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,24 @@ func NewExecutorChain(
},
})
}
for _, rm := range conf.Rm {
var (
r = rm
action = r.Tag
)

if !actionFilter.MatchString(action) {
continue
}
builders = append(builders,
ExecutorBuilder{
action: action,
line: r.Line,
procFn: func() (entity.Executor, error) {
return NewRmExecutor(r.Val, logger, dryRun)
},
})
}

var preprocessors []entity.Preprocessor
for _, files := range conf.Files {
Expand Down
21 changes: 21 additions & 0 deletions internal/factory/rm_exec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package factory

import (
"github.com/kozmod/progen/internal/entity"
"github.com/kozmod/progen/internal/exec"
)

func NewRmExecutor(paths []string, logger entity.Logger, dryRun bool) (entity.Executor, error) {
if len(paths) == 0 {
logger.Infof("rm executor: `rm` section is empty")
return nil, nil
}

pathsSet := entity.Unique(paths)

if dryRun {
return exec.NewRmAllExecutor(pathsSet, []entity.RmStrategy{exec.NewDryRmAllStrategy(logger)}), nil
}

return exec.NewRmAllExecutor(pathsSet, []entity.RmStrategy{exec.NewRmAllStrategy(logger)}), nil
}
Loading