Signed-off-by: storyicon <yuanchao@bilibili.com>
This commit is contained in:
storyicon 2021-07-21 00:24:43 +08:00
commit 9aac714c32
No known key found for this signature in database
GPG key ID: 245915D985F966CF
47 changed files with 5480 additions and 0 deletions

View file

@ -0,0 +1,31 @@
// Copyright 2021 storyicon@foxmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions
import (
"context"
"github.com/storyicon/powerproto/pkg/util/logger"
)
// CommonOptions is common options of action
type CommonOptions struct {
ConfigFilePath string
}
// ActionFunc defines the common prototype of action func
type ActionFunc func(ctx context.Context,
log logger.Logger,
args []string, options *CommonOptions) error

View file

@ -0,0 +1,64 @@
// Copyright 2021 storyicon@foxmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions
import (
"context"
"path/filepath"
"github.com/pkg/errors"
"github.com/storyicon/powerproto/pkg/util"
"github.com/storyicon/powerproto/pkg/util/command"
"github.com/storyicon/powerproto/pkg/util/logger"
)
// ActionCopy is used to copy directory or file from src to dest
// Its args prototype is:
// args: (src string, dest string)
func ActionCopy(ctx context.Context, log logger.Logger, args []string, options *CommonOptions) error {
if len(args) != 2 || util.ContainsEmpty(args...) {
return errors.Errorf("expected length of args is 3, but received %d", len(args))
}
var (
source = args[0]
destination = args[1]
path = filepath.Dir(options.ConfigFilePath)
absSource = filepath.Join(path, source)
absDestination = filepath.Join(path, destination)
)
if filepath.IsAbs(source) {
return errors.Errorf("absolute source %s is not allowed in action move", source)
}
if filepath.IsAbs(destination) {
return errors.Errorf("absolute destination %s is not allowed in action move", destination)
}
if command.IsDryRun(ctx) {
log.LogInfo(map[string]interface{}{
"action": "copy",
"from": absSource,
"to": absDestination,
}, "DryRun")
return nil
}
if err := util.CopyDirectory(absSource, absDestination); err != nil {
return err
}
return nil
}

View file

@ -0,0 +1,68 @@
// Copyright 2021 storyicon@foxmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions
import (
"context"
"os"
"path/filepath"
"github.com/pkg/errors"
"github.com/storyicon/powerproto/pkg/util"
"github.com/storyicon/powerproto/pkg/util/command"
"github.com/storyicon/powerproto/pkg/util/logger"
)
// ActionMove is used to move directory or file from src to dest
// Its args prototype is:
// args: (src string, dest string)
func ActionMove(ctx context.Context, log logger.Logger, args []string, options *CommonOptions) error {
if len(args) != 2 || util.ContainsEmpty(args...) {
return errors.Errorf("expected length of args is 3, but received %d", len(args))
}
var (
source = args[0]
destination = args[1]
path = filepath.Dir(options.ConfigFilePath)
absSource = filepath.Join(path, source)
absDestination = filepath.Join(path, destination)
)
if filepath.IsAbs(source) {
return errors.Errorf("absolute source %s is not allowed in action move", source)
}
if filepath.IsAbs(destination) {
return errors.Errorf("absolute destination %s is not allowed in action move", destination)
}
if command.IsDryRun(ctx) {
log.LogInfo(map[string]interface{}{
"action": "move",
"from": absSource,
"to": absDestination,
}, "DryRun")
return nil
}
if err := util.CopyDirectory(absSource, absDestination); err != nil {
return err
}
if err := os.RemoveAll(absSource); err != nil {
return err
}
return nil
}

View file

@ -0,0 +1,51 @@
// Copyright 2021 storyicon@foxmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions
import (
"context"
"os"
"path/filepath"
"github.com/pkg/errors"
"github.com/storyicon/powerproto/pkg/util/command"
"github.com/storyicon/powerproto/pkg/util/logger"
)
// ActionRemove is used to delete directories or files
// Its args prototype is:
// args: (path ...string)
func ActionRemove(ctx context.Context, log logger.Logger, args []string, options *CommonOptions) error {
for _, arg := range args {
if filepath.IsAbs(arg) {
return errors.Errorf("absolute path %s is not allowed in action remove", arg)
}
path := filepath.Join(filepath.Dir(options.ConfigFilePath), arg)
if command.IsDryRun(ctx) {
log.LogInfo(map[string]interface{}{
"action": "remove",
"target": path,
}, "DryRun")
return nil
}
if err := os.RemoveAll(path); err != nil {
return err
}
}
return nil
}

View file

@ -0,0 +1,80 @@
// Copyright 2021 storyicon@foxmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions
import (
"bytes"
"context"
"io/fs"
"io/ioutil"
"path/filepath"
"github.com/pkg/errors"
"github.com/storyicon/powerproto/pkg/util"
"github.com/storyicon/powerproto/pkg/util/command"
"github.com/storyicon/powerproto/pkg/util/logger"
)
// ActionReplace is used to replace text in bulk
// Its args prototype is:
// args: (pattern string, from string, to string)
// pattern is used to match files
func ActionReplace(ctx context.Context, log logger.Logger, args []string, options *CommonOptions) error {
if len(args) != 3 {
return errors.Errorf("expected length of args is 3, but received %d", len(args))
}
var (
pattern = args[0]
path = filepath.Dir(options.ConfigFilePath)
from = args[1]
to = args[2]
)
if pattern == "" || from == "" {
return errors.Errorf("pattern and from arguments in action replace can not be empty")
}
if filepath.IsAbs(pattern) {
return errors.Errorf("absolute path %s is not allowed in action replace", pattern)
}
pattern = filepath.Join(path, pattern)
return filepath.Walk(path, func(path string, info fs.FileInfo, err error) error {
if info.IsDir() {
return nil
}
matched, err := util.MatchPath(pattern, path)
if err != nil {
panic(err)
}
if matched {
if command.IsDryRun(ctx) {
log.LogInfo(map[string]interface{}{
"action": "replace",
"file": path,
"from": from,
"to": to,
}, "DryRun")
return nil
}
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
data = bytes.ReplaceAll(data, []byte(from), []byte(to))
return ioutil.WriteFile(path, data, fs.ModePerm)
}
return nil
})
}