fishi0x01/vsh

View on GitHub
cli/grep.go

Summary

Maintainability
A
0 mins
Test Coverage
package cli

import (
    "fmt"
    "os"

    "github.com/fishi0x01/vsh/client"
    "github.com/fishi0x01/vsh/log"
)

// GrepCommand container for all 'grep' parameters
type GrepCommand struct {
    name string
    args *GrepCommandArgs

    client   *client.Client
    searcher *Searcher
    Mode     KeyValueMode
}

// GrepCommandArgs provides a struct for go-arg parsing
type GrepCommandArgs struct {
    Search  string `arg:"positional,required"`
    Path    string `arg:"positional"`
    Keys    bool   `arg:"-k,--keys" help:"Match against keys (true if -v is not specified)"`
    Regexp  bool   `arg:"-e,--regexp" help:"Treat search string as a regexp"`
    Shallow bool   `arg:"-S,--shallow" help:"Only search leaf nodes of the path rather than recurse deeper"`
    Values  bool   `arg:"-v,--values" help:"Match against values (true if -k is not specified)"`
}

// Description provides detail on what the command does
func (GrepCommandArgs) Description() string {
    return "recursive searches for a pattern starting at a path"
}

// NewGrepCommand creates a new GrepCommand parameter container
func NewGrepCommand(c *client.Client) *GrepCommand {
    return &GrepCommand{
        name:   "grep",
        client: c,
        args:   &GrepCommandArgs{},
    }
}

// GetName returns the GrepCommand's name identifier
func (cmd *GrepCommand) GetName() string {
    return cmd.name
}

// GetArgs provides the struct holding arguments for the command
func (cmd *GrepCommand) GetArgs() interface{} {
    return cmd.args
}

// IsSane returns true if command is sane
func (cmd *GrepCommand) IsSane() bool {
    return cmd.args.Path != "" && cmd.args.Search != ""
}

// PrintUsage print command usage
func (cmd *GrepCommand) PrintUsage() {
    fmt.Println(Help(cmd))
}

// Parse given arguments and return status
func (cmd *GrepCommand) Parse(args []string) error {
    _, err := parseCommandArgs(args, cmd)
    if err != nil {
        return err
    }
    if cmd.args.Path == "" {
        cmd.args.Path = cmd.client.Pwd
    }
    if cmd.args.Keys == true {
        cmd.Mode |= ModeKeys
    }
    if cmd.args.Values == true {
        cmd.Mode |= ModeValues
    }
    if cmd.Mode == 0 {
        cmd.Mode = ModeKeys + ModeValues
    }

    searcher, err := NewSearcher(cmd)
    if err != nil {
        return err
    }
    cmd.searcher = searcher

    return nil
}

// Run executes 'grep' with given GrepCommand's parameters
func (cmd *GrepCommand) Run() int {
    path := cmdPath(cmd.client.Pwd, cmd.args.Path)
    filePaths, err := cmd.client.SubpathsForPath(path, cmd.args.Shallow)
    if err != nil {
        log.UserError(fmt.Sprintf("%s", err))
        return 1
    }

    for _, curPath := range filePaths {
        matches, err := cmd.grepFile(cmd.args.Search, curPath)
        if err != nil {
            return 1
        }
        for _, match := range matches {
            match.print(os.Stdout, MatchOutputHighlight)
        }
    }
    return 0
}

// GetSearchParams returns the search parameters the command was run with
func (cmd *GrepCommand) GetSearchParams() SearchParameters {
    return SearchParameters{
        Search:   cmd.args.Search,
        Mode:     cmd.Mode,
        IsRegexp: cmd.args.Regexp,
    }
}

func (cmd *GrepCommand) grepFile(search string, path string) (matches []*Match, err error) {
    matches = []*Match{}

    if cmd.client.GetType(path) == client.LEAF {
        secret, err := cmd.client.Read(path)
        if err != nil {
            return matches, err
        }

        for k, v := range secret.GetData() {
            matches = append(matches, cmd.searcher.DoSearch(path, k, fmt.Sprintf("%v", v))...)
        }
    }

    return matches, nil
}