import type { LinkView, ReaddirPath, StatPath } from '../../../view/types.ts';
import type { Files } from '../../../workspace/files.ts';
import type { DispatchFn } from '../../../runtime/types.ts';
import { FileStat, PathSpec, type StatFn } from '../../../types.ts';
import { type FsError } from '../../../errors/types.ts';
import type { FlagValue } from '../../spec/types.ts';
import type { FsCondition } from '../../../errors/types.ts';
/**
 * Opt in by assigning a debug sink, as Python's module logger is off until
 * configured: every failed read runs the probe, and stdout may carry data.
 */
export declare const logger: {
    debug?: (message: string) => void;
};
export declare function resolvePathStat(dispatch: DispatchFn, path: PathSpec): Promise<FileStat | null>;
export declare function dispatchStat(dispatch: DispatchFn): StatFn;
export declare function vfsStatPath(files: Files | undefined): StatPath | undefined;
export declare function vfsReaddirPath(files: Files | undefined): ReaddirPath | undefined;
export declare function statOrEnoent(statPath: StatPath): StatFn;
/**
 * `path` keyed by its whole virtual path, the shape a command's paths take:
 * the dispatcher routes each one to its mount, so no command derives a mount
 * from a path's key. Mirrors Python's virtual_key.
 */
export declare function virtualKey(path: PathSpec): PathSpec;
/**
 * A command's flags with every path value keyed by its whole virtual path
 * (`virtualKey`): a single path (awk -f) or a list of them (repeated grep -f).
 * Everything else passes through unchanged. Mirrors Python's virtual_flags.
 */
export declare function virtualFlags(bag: Record<string, FlagValue>): Record<string, FlagValue>;
export declare function spelledFrom(path: PathSpec, operand: PathSpec): PathSpec;
export declare function descendantPath(root: PathSpec, virtual: string): PathSpec;
export declare function entryKind(stat: StatFn, path: PathSpec): Promise<{
    exists: boolean;
    isDir: boolean;
}>;
export declare function nearestAncestor(stat: StatFn, path: PathSpec): Promise<[string, boolean]>;
export declare function isImplicitDir(readdir: (path: PathSpec) => Promise<string[]>, path: PathSpec): Promise<boolean>;
/**
 * Whether a failed or empty read was a read of a directory.
 *
 * Asked after failure or EOF without bytes: some drivers return an empty
 * stream for directories. Nonempty reads need no extra probe. One that knows
 * says so (gdrive, box, dropbox and disk throw EISDIR), a keyed store answers
 * ENOENT because a directory there is a set of keys rather than an object,
 * and sftp answers with an error carrying no errno at all.
 *
 * Three ways the answer can be yes, in probe-cost order. The code itself
 * costs nothing. The stat is one call, and a stat that ANSWERS ends the
 * cascade either way: a file is a file, and the later probe only makes
 * sense for a path stat could not see. Reaching past a successful stat
 * read a rule-refused file as a directory, because its parent's listing
 * names it. The parent listing is one call and is the only thing that can
 * tell a missing key from a prefix that exists only through deeper keys.
 *
 * A no leaves the original error untouched, so nothing is swallowed: the
 * caller rethrows what the backend said. Both probes are broad for that
 * same reason: a probe that fails is a negative probe, never an error to
 * surface. Surfacing one would replace the read's error with one from a
 * call the user never made, and it is the read that failed.
 * `isImplicitDir` narrows to a miss because for its other caller the stat
 * IS the operation; here it is a probe, so the wider catch belongs on this
 * side of the call, and each failure it absorbs is logged. Mirrors Python's
 * `read_hit_a_dir`.
 */
export declare function readHitADir(stat: (path: PathSpec) => Promise<FileStat>, readdir: (path: PathSpec) => Promise<string[]>, path: PathSpec, err: unknown): Promise<boolean>;
export declare function absentDestError(stat: StatFn, target: PathSpec): Promise<FsCondition | null>;
export declare function linkFollow(links: LinkView | null | undefined): ((path: string) => string) | null;
export declare function linkTarget(links: LinkView | null | undefined): ((path: string) => string | null) | null;
/**
 * The typed spelling, links before `..`, while it names the path. Mirrors
 * Python's walk_spelling.
 *
 * Without a trailing slash: that is a final `.`, which `dotRefusal` proves,
 * and a store that keeps no directories reads a slashed key as one, so
 * `cat reg/` there was ENOENT, not ENOTDIR.
 */
export declare function walkSpelling(path: PathSpec, follow: ((path: string) => string) | null): string;
/**
 * ENOENT when the walk of a path's dots looks up a name the session cannot
 * see, null when it sees every one.
 *
 * `virtual` simplified the dots away, so a hidden name in front of one
 * (`secret/../f`, a hidden link's `lnk/../f`) is gone from the path the
 * hides judge, while the walk still has to find it. It answers as a missing
 * name does, and before `dotRefusal` proves anything a directory, so the
 * refusal cannot tell a hide from an absence. The walk stops at the hidden
 * name, so a link there is never followed. Mirrors Python's hidden_walk.
 */
export declare function hiddenWalk(path: PathSpec, follow: ((path: string) => string) | null, visible: (path: string) => boolean): FsError | null;
/**
 * What a path's dot components answer, null when every one resolves.
 *
 * The kernel resolves `.` and `..` against the directory they sit in, so a
 * walk through a missing name fails ENOENT and one through a plain file
 * ENOTDIR (`cat nope/../f`, `cat f.txt/.`), where the textual simplification
 * in `virtual` reached `f` regardless. Each name in front of a dot is proved
 * a directory, in walk order, and one that is not is judged by its chain the
 * way a create is, so a miss under a plain file is ENOTDIR on every store.
 * A link in front of a dot is followed first, as the kernel walks (only
 * bash's `cd` reads `link/..` logically). A trailing slash is a final `.`:
 * an existing name in front of it has to be a directory too (`cat reg/`); a
 * call that creates that name (`creates`: mkdir, symlink) answers EEXIST
 * instead (`mkdir reg/`), however the store keeps the name.
 *
 * Only the path the spelling names is walked: a path derived from it (a
 * child a walker builds, a respelled match) carries the field along but no
 * longer spells it, while the operand the kernel walk followed through a
 * link (`lnk/nope/../f`) still does, which `follow` recognizes. The error
 * names the operand as typed and is a DotWalkError, final for every layer
 * that re-reads a miss. Mirrors Python's dot_refusal.
 */
export declare function dotRefusal(stat: StatFn, path: PathSpec, follow?: ((path: string) => string) | null, creates?: boolean): Promise<FsError | null>;
export declare function resolveTarget(o: string | PathSpec, cwd: string): PathSpec;
export declare function defaultPaths(paths: PathSpec[], cwd: string): PathSpec[];
//# sourceMappingURL=paths.d.ts.map