From d88661935fa2b6e2c0fe93345800113e1a71b451 Mon Sep 17 00:00:00 2001 From: ewy Date: Wed, 22 Apr 2026 21:51:29 +0200 Subject: docs --- cache/cache.go | 6 ++++++ crawl/crawl.go | 5 +++++ describe/describe.go | 3 +++ env/env.go | 4 ++++ flags/flags.go | 31 +++++++++++++++++++++---------- git/git.go | 3 +++ identity/identity.go | 4 ++++ search/search.go | 19 ++++++++++++++----- 8 files changed, 60 insertions(+), 15 deletions(-) diff --git a/cache/cache.go b/cache/cache.go index c51acbc..328b1e9 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -101,6 +101,7 @@ func (c Cache) String() string { return string(c.Marshal()) } +// New creates a new Cache from a model.State func New(st *model.State) Cache { c := &Cache{} for _, s := range st.Sources { @@ -112,6 +113,7 @@ func New(st *model.State) Cache { return *c } +// SaveFile helps you use Save with a file path instead of a reader func SaveFile(path string, s *model.State, loaded Cache) error { fd, err := os.Create(path) if err != nil { @@ -123,6 +125,7 @@ func SaveFile(path string, s *model.State, loaded Cache) error { return Save(s, fd, loaded) } +// Save writes the cache combined with the "loaded" cache to the writer. func Save(s *model.State, w io.Writer, loaded Cache) error { result := New(s).Merge(loaded) _, err := w.Write([]byte(result.Marshal())) @@ -130,6 +133,7 @@ func Save(s *model.State, w io.Writer, loaded Cache) error { } +// LoadState creates a state with model.NewState based on cache content func LoadState(f fs.FS, cache Cache, indexers []model.Indexer, runners []model.Runner) (*model.State, []error) { var locs []string for _, e := range cache.Entries { @@ -138,6 +142,8 @@ func LoadState(f fs.FS, cache Cache, indexers []model.Indexer, runners []model.R return model.NewState(f, locs, indexers, runners) } +// Strip removes the needle's entries from the receiver's entries when they have matching paths. +// used to skip already indexed locations when auto-all-ing func (c Cache) Strip(needle Cache) Cache { var result []Entry outer: diff --git a/crawl/crawl.go b/crawl/crawl.go index fccd81d..cc3d16c 100644 --- a/crawl/crawl.go +++ b/crawl/crawl.go @@ -7,10 +7,12 @@ import ( "strings" ) +// Evaluated returns a path with evaluated symlinks func Evaluated(loc string) (string, error) { return filepath.EvalSymlinks(loc) } +// RichLocations combines the path and Evaluated path Locations func RichLocations(origin string) []string { locs := Locations(origin) @@ -24,6 +26,8 @@ func RichLocations(origin string) []string { return locs } +// Locations returns a slice of increasingly shorter file paths, +// losing a segment each time. func Locations(origin string) []string { origin = path.Clean(origin) var locs = []string{ @@ -40,6 +44,7 @@ func Locations(origin string) []string { return locs } +// ParentDir returns a path with the top element missing func ParentDir(origin string) string { trimmedOrigin := strings.TrimSuffix(origin, "/") dir, _ := path.Split(trimmedOrigin) diff --git a/describe/describe.go b/describe/describe.go index 0863b6d..a7070a1 100644 --- a/describe/describe.go +++ b/describe/describe.go @@ -15,6 +15,7 @@ var DescriptionPrefixes = []string{ var descriptions = make(map[model.Target]*string) +// Describe attempts to read a description from a file and stores it in the cache func Describe(key model.Target, file string) (string, error) { if d := descriptions[key]; d != nil { return *d, nil @@ -35,6 +36,8 @@ func Describe(key model.Target, file string) (string, error) { return text, err } +// FromReader reads a description from an io.Reader and returns it. +// this is not stored in the cache. func FromReader(reader io.Reader) (string, error) { scanner := bufio.NewScanner(reader) scanner.Split(bufio.ScanLines) diff --git a/env/env.go b/env/env.go index 2a76e33..f1bd9d8 100644 --- a/env/env.go +++ b/env/env.go @@ -12,6 +12,8 @@ import ( "slices" ) +// IsEnv returns whether a given file is suitable for environment loading +// this method respects the --env flag func IsEnv(file string) bool { options := []string{ ".env", @@ -26,6 +28,7 @@ func IsEnv(file string) bool { return slices.Contains(options, file) } +// Files returns a list of files (that exist) that should be indexed and used as environment files func Files(f fs.FS, p string, deep bool) []string { var result []string dir, err := fs.ReadDir(f, p) @@ -43,6 +46,7 @@ func Files(f fs.FS, p string, deep bool) []string { return result } +// Get returns all environment key-value pairs we should index for a source func Get(src *model.Source) []string { f := os.DirFS(src.Path) var result []string diff --git a/flags/flags.go b/flags/flags.go index c500356..9fb8d44 100644 --- a/flags/flags.go +++ b/flags/flags.go @@ -3,15 +3,26 @@ package flags import "github.com/spf13/pflag" var ( - Here = pflag.BoolP("here", "h", false, "run target in current directory instead of source location") - At = pflag.StringP("at", "@", "", "override run location") - Single = pflag.BoolP("single", "s", false, "do not run any triggers") - All = pflag.BoolP("all", "a", false, "get sources from cache instead of crawling") - Dry = pflag.BoolP("dry", "d", false, "print cmdlines instead of running them") - Root = pflag.BoolP("root", "r", false, "run targets (including triggers) with sudo") - Yes = pflag.BoolP("yes", "y", false, "auto-confirm y/n confirmations") - Env = pflag.StringArray("env", nil, "environment files or pre- or suffix") + // Here makes pik run the target at the current location instead of in its source directory + Here = pflag.BoolP("here", "h", false, "run target in current directory instead of source location") + // At makes pik run in an arbitrary location + At = pflag.StringP("at", "@", "", "override run location") + // Single will make pik skip triggers + Single = pflag.BoolP("single", "s", false, "do not run any triggers") + // All will make pik load cached state instead of crawling + All = pflag.BoolP("all", "a", false, "get sources from cache instead of crawling") + // Dry will prevent pik from running targets and output the command as text instead + Dry = pflag.BoolP("dry", "d", false, "print cmdlines instead of running them") + // Root will prefix the target with sudo to run it as root + Root = pflag.BoolP("root", "r", false, "run targets (including triggers) with sudo") + // Yes will skip y/n prompts and always answer yes + Yes = pflag.BoolP("yes", "y", false, "auto-confirm y/n confirmations") + // Env can be used to load additional .env files + Env = pflag.StringArray("env", nil, "environment files or pre- or suffix") + // Version means we should print the pik version and exit Version = pflag.BoolP("version", "v", false, "print version and exit") - List = pflag.BoolP("list", "l", false, "list available targets and exit") - Inline = pflag.BoolP("inline", "i", false, "do not use terminal alt screen") + // List means we should output available targets separated by $IFS + List = pflag.BoolP("list", "l", false, "list available targets and exit") + // Inline means pik does not go to the terminal alt screen + Inline = pflag.BoolP("inline", "i", false, "do not use terminal alt screen") ) diff --git a/git/git.go b/git/git.go index 163922b..2b5130e 100644 --- a/git/git.go +++ b/git/git.go @@ -28,6 +28,7 @@ func (g *gitMod) Init() error { var Git = &gitMod{} +// Mod is the git hydration mod func (g *gitMod) Mod(source *model.Source, result *model.HydratedSource) error { gitFolder := filepath.Join(source.Path, ".git") if st, err := os.Stat(gitFolder); err == nil && st.IsDir() { @@ -56,6 +57,7 @@ func (g *gitMod) Mod(source *model.Source, result *model.HydratedSource) error { return nil } +// Branch returns the git branch of a given source func (g *gitMod) Branch(source *model.Source) (string, error) { cmd := exec.Command(g.Git, "branch", "--show-current") cmd.Dir = source.Path @@ -65,6 +67,7 @@ func (g *gitMod) Branch(source *model.Source) (string, error) { var UnknownResponseError = errors.New("unknown response") +// Diff returns the number of changes of a given source func (g *gitMod) Diff(source *model.Source) (changes int, insertions int, deletions int, err error) { cmd := exec.Command(g.Git, "diff", "--shortstat") cmd.Dir = source.Path diff --git a/identity/identity.go b/identity/identity.go index 06bd421..e1cd74d 100644 --- a/identity/identity.go +++ b/identity/identity.go @@ -7,15 +7,18 @@ type Identity struct { Reduced string } +// I return whether the other identity "means the same" as this one func (i Identity) I(other Identity) bool { return i.Reduced == other.Reduced } +// Is returns whether the other string "means the same" as this one func (i Identity) Is(input string) bool { reduced := Reduce(input) return i.Reduced == reduced } +// New creates a new Identity with default reduction func New(input string) Identity { reduced := Reduce(input) return Identity{ @@ -25,6 +28,7 @@ func New(input string) Identity { } +// Reduce normalizes input (commands and filenames) to simplify them func Reduce(input string) string { reduced := input reduced = strings.TrimPrefix(input, ".") diff --git a/search/search.go b/search/search.go index fd06ab5..7d863b9 100644 --- a/search/search.go +++ b/search/search.go @@ -5,16 +5,25 @@ import ( "slices" ) +// Result is a struct containing information about the search and search results type Result struct { - Target model.Target - Source *model.Source + // Target is the target selected by the search + Target model.Target + // Source is the source belonging to the selected Target + Source *model.Source + // NeedsConfirmation is true when there are discrepancies between expected and actual invocation NeedsConfirmation bool - Overridden bool - Sub []string - Args []string + // Overridden is whether it was overridden by a .override target + Overridden bool + // Sub is the subcategory or -folder + Sub []string + // Args are the remaining arguments which we should pass to the target + Args []string } // Search is the meat of pik +// since there are a ton of different ways to invoke targets, leave a unit test +// when you change this func Search(s *model.State, args ...string) *Result { var target model.Target var targetSource *model.Source -- cgit v1.3.1