walker

package
v0.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package walker provides filesystem traversal with .sentraignore support and a concurrent stat pipeline. It is the producer that feeds the snapshot path: emit a stream of file metadata, skip what the user has marked ignored, and bail cleanly when the caller cancels the context.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Walk

func Walk(ctx context.Context, root string, opts Options, fn func(Entry) error) error

Walk visits every regular file under root, calling fn for each non-ignored entry. fn is called concurrently from up to N goroutines (Options.Concurrency); callers MUST be safe for concurrent calls.

Walk returns the first non-nil error from fn, or any I/O error from the walk itself. ctx cancellation is respected: a cancel during the walk surfaces as ctx.Err() (typically context.Canceled).

Two failures are deliberately not errors, because on a real machine they happen on every run: an entry that vanishes between readdir and stat is dropped, and a subdirectory (never the root) whose listing is denied is skipped as a subtree and reported through Options.OnSkip.

Symlinks are not followed (treated as non-regular and silently skipped). Future: symlink policy.

Types

type Entry

type Entry struct {
	Kind    EntryKind
	AbsPath string
	RelPath string
	// Size is the file's byte length. Zero for dirs and symlinks —
	// neither contributes content bytes to a snapshot.
	Size int64
	// Mode is the lstat mode. The bits the manifest cares about are
	// the permission bits (Mode.Perm()); type bits are carried by
	// Kind instead.
	Mode  os.FileMode
	MTime time.Time
	// LinkTarget is the symlink's target exactly as stored on disk
	// (os.Readlink output — relative or absolute, never resolved).
	// Empty for every other kind.
	LinkTarget string
}

Entry is the metadata for one filesystem object emitted by Walk. It is the minimum a downstream chunker / encryption pipeline needs to do its job: where the object lives on disk, what to call it relative to the snapshot root, and the stat fields needed for change detection.

type EntryKind

type EntryKind int

EntryKind distinguishes what an Entry describes. The zero value is KindFile so pre-existing callers that never look at the field keep their exact semantics (Walk only emits the other kinds behind the Options.IncludeNonRegular opt-in).

const (
	KindFile EntryKind = iota
	KindDir
	KindSymlink
)

type Matcher

type Matcher struct {
	// contains filtered or unexported fields
}

Matcher decides whether a repo-relative path is excluded by the project's .sentraignore. Patterns follow gitignore syntax: literal globs, "**" recursion, leading "!" to negate, trailing "/" to scope to directories.

A nil *Matcher is valid and matches nothing — this lets callers avoid threading a "no ignore file" sentinel through the walk.

func LoadIgnoreFile

func LoadIgnoreFile(path string) (*Matcher, error)

LoadIgnoreFile reads patterns from path (one per line, "#" comments and blank lines allowed, CRLF tolerated) and returns a Matcher.

A missing file is not an error: a project without a .sentraignore should walk happily, so we return an empty Matcher. Any other I/O failure (permissions, EISDIR) is surfaced.

func NewMatcher

func NewMatcher(patterns []string) *Matcher

NewMatcher compiles patterns into a Matcher. Empty / nil input produces a matcher that never matches.

func (*Matcher) Match

func (m *Matcher) Match(path string) bool

Match reports whether path is ignored. path is forward-slash, repo-relative, no leading "/". The caller is responsible for normalizing OS-native paths before calling Match.

type Options

type Options struct {
	// IgnoreFile is the basename (or relative path) of the ignore
	// file at the walk root. Empty means ".sentraignore".
	IgnoreFile string

	// ExcludeCaches honors the CACHEDIR.TAG convention: a directory
	// containing a CACHEDIR.TAG file whose first line carries the
	// canonical signature is skipped entirely.
	ExcludeCaches bool

	// Concurrency is the number of worker goroutines that stat and
	// invoke fn. Zero means GOMAXPROCS, which is the right default
	// for stat-bound workloads on modern disks.
	Concurrency int

	// IncludeNonRegular additionally emits KindDir entries for every
	// directory under root (the root itself excluded) and KindSymlink
	// entries carrying LinkTarget. Neither is followed. Off by
	// default so file-only consumers (backup plans, agent heuristics)
	// keep their exact historical behavior; snapshot capture opts in
	// for filesystem fidelity.
	IncludeNonRegular bool

	// OnSkip is told about every subtree the walk dropped because its
	// directory listing was denied (fs.ErrPermission — TCC-protected
	// folders under ~/Library on macOS are the everyday case). The
	// walk continues without that subtree rather than failing the
	// whole backup over one folder, but a skipped subtree is data the
	// operator did not get, so it is never hidden: nil means the
	// caller chose silence, not that nothing happened. Called from the
	// producer goroutine; must be safe to call concurrently with fn.
	OnSkip func(path string, err error)
}

Options tunes the walk. Zero-value Options runs with sensible defaults: ".sentraignore" as the ignore filename, no cache-tag honoring, and one worker per logical CPU.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL