From 7830287b82db50da54de23aaacceff72ff611649 Mon Sep 17 00:00:00 2001 From: Christian Haeusler Date: Sun, 12 Jan 2020 15:13:39 +0100 Subject: [PATCH] Name to tag Use regexp to extract tags from file names. --- cmd/name_to_tag.go | 87 ++++++++++++++++++++++++++++++++++++++++++++++ main.go | 1 + tag/set.go | 14 ++++++++ 3 files changed, 102 insertions(+) create mode 100644 cmd/name_to_tag.go diff --git a/cmd/name_to_tag.go b/cmd/name_to_tag.go new file mode 100644 index 0000000..f98314c --- /dev/null +++ b/cmd/name_to_tag.go @@ -0,0 +1,87 @@ +package cmd + +import ( + "context" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/corvus-ch/bilocation/tag" + "golang.org/x/sync/errgroup" + "gopkg.in/alecthomas/kingpin.v2" +) + +var test bool + +// NameToTag registers the name to tag sub command to the application. +func NameToTag(app *kingpin.Application, cfg *config) { + c := app.Command("ntt", "tags files based on their names") + c.Action(func(_ *kingpin.ParseContext) error { + log := cfg.Log() + for path := range findFiles(cfg) { + tags, err := tag.NewTagSet([]byte{}) + if err != nil { + return err + } + for _, rule := range cfg.Tags() { + parts := strings.SplitN(rule, "=", 2) + re, err := regexp.Compile(parts[1]) + if err != nil { + return err + } + matches := re.FindStringSubmatch(path) + if len(matches) < 1 { + continue + } + tags.Add(matches[1], parts[0]) + } + if test { + log.Infof("%s %v", path, tags) + } else if tags.Size() > 0 { + if err := tag.Write(path, tags); err != nil { + return err + } + } + } + return nil + }) + + c.Flag("path", "path to the directory containing the files to be tagged"). + Short('C'). + Default("."). + ExistingDirVar(&cfg.root) + c.Flag("dry-run", "print the result and does not touch the files"). + Short('n'). + BoolVar(&test) + c.Arg("rule", "a list of tag names and their regexp"). + Required(). + StringsVar(&cfg.tags) +} + +func findFiles(cfg *config) chan string { + g, ctx := errgroup.WithContext(context.Background()) + ch := make(chan string, 100) + g.Go(func() error { + defer close(ch) + + return filepath.Walk(cfg.Root(), func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.Mode().IsRegular() { + return nil + } + + select { + case ch <- path: + case <-ctx.Done(): + return ctx.Err() + } + return nil + }) + + }) + + return ch +} diff --git a/main.go b/main.go index 70d6c51..47ed4a9 100644 --- a/main.go +++ b/main.go @@ -31,6 +31,7 @@ func App(log logr.Logger) *kingpin.Application { cmd.Inspect(app, cfg) cmd.Search(app, cfg) cmd.Summary(app, cfg) + cmd.NameToTag(app, cfg) return app } diff --git a/tag/set.go b/tag/set.go index 705e512..918c52f 100644 --- a/tag/set.go +++ b/tag/set.go @@ -1,6 +1,9 @@ package tag import ( + "fmt" + "strings" + "github.com/corvus-ch/bilocation/tag/internal" "github.com/golang/protobuf/proto" ) @@ -104,3 +107,14 @@ func (s Set) Bytes() ([]byte, error) { } return proto.Marshal(set) } + +func (s Set) String() string { + var pairs []string + for value, keys := range s { + for key := range keys { + pairs = append(pairs, fmt.Sprintf("%s='%s'", key, value)) + } + } + + return strings.Join(pairs, " ") +}