import type { ByteSource } from '../../../io/types.ts';
import type { DispatchFn } from '../../../runtime/types.ts';
import type { PathSpec } from '../../../types.ts';
import { FileStat, type SetAttrFields } from '../../../types.ts';
import { type ResolveGlobFn } from '../../../utils/glob_walk.ts';
import type { MountView, SessionAccess } from '../../../view/types.ts';
import type { Context } from '../../config.ts';
import type { ReadTree } from '../utils/tree.ts';
/**
 * A command's files, path-first, every call sent to the dispatcher through
 * the session's files (`ctx.vfs`).
 *
 * The dispatcher checks hides, the command's path rule, the mount's mode and
 * policy, refuses a read of a directory and a write to a slash-terminated
 * name, serves a warm copy and fills a cold one, fills a stat's unknown size
 * from the read cache, gives way to the read for a file the read cache holds
 * where a call stands in for one, settles a write's caches and receipt under
 * its name's hold, and declines a one-call walk (a subtree read, search, a
 * tree copy or removal) whose subtree the caller's view restricts, so a
 * command's call answers what the same call through `ws.vfs` or FUSE
 * answers. A function the mount's VFS does not answer is the
 * dispatcher's ENOTSUP; a command asks `answers` before it takes a shortcut.
 * Mirrors Python's `CommandFiles`.
 */
export interface CommandFiles {
    /** The line's abort and the command's deadline, for a walk `treeWalk` answers. */
    readonly signal?: AbortSignal;
    /** The entry at `path` itself, as lstat answers. */
    readonly stat: (path: PathSpec) => Promise<FileStat>;
    readonly exists: (path: PathSpec) => Promise<boolean>;
    readonly readdir: (path: PathSpec, nofollow?: boolean, limit?: number) => Promise<string[]>;
    /**
     * `read(path, offset?, size?)`: the stored bytes or a window of them,
     * opened at the first pull; `materialize` collects them.
     */
    readonly read: (path: PathSpec, offset?: number, size?: number | null) => AsyncIterable<Uint8Array>;
    /**
     * Whether the read cache holds a copy a read would be served from; it
     * fetches neither the copy nor anything from the backend.
     */
    readonly isWarm: (path: PathSpec) => Promise<boolean>;
    readonly write: (path: PathSpec, data: ByteSource) => Promise<void>;
    readonly append: (path: PathSpec, data: ByteSource) => Promise<void>;
    readonly pwrite: (path: PathSpec, data: Uint8Array, offset: number) => Promise<void>;
    readonly mkdir: (path: PathSpec, parents?: boolean) => Promise<void>;
    readonly unlink: (path: PathSpec) => Promise<void>;
    readonly rmdir: (path: PathSpec) => Promise<void>;
    readonly rmR: (path: PathSpec) => Promise<void>;
    readonly rename: (src: PathSpec, dst: PathSpec) => Promise<void>;
    readonly copy: (src: PathSpec, dst: PathSpec) => Promise<void>;
    readonly dirCopy: (src: PathSpec, dst: PathSpec) => Promise<void>;
    /** noCreate requires an atomic existence precondition, or ENOTSUP before writing. */
    readonly truncate: (path: PathSpec, length: number, noCreate?: boolean) => Promise<void>;
    readonly setAttrs: (path: PathSpec, fields: SetAttrFields) => Promise<Record<string, number | string>>;
    /** The first `n` lines; null when the file is to be read, as it is when the read cache holds it. */
    readonly firstLines: (path: PathSpec, n: number) => Promise<Uint8Array | null>;
    /** The last `n` lines; null when the file is to be read. */
    readonly lastLines: (path: PathSpec, n: number) => Promise<Uint8Array | null>;
    /** How many lines the file holds; null when it is to be read. */
    readonly lineCount: (path: PathSpec) => Promise<number | null>;
    /** The digest the backend keeps; null when the file is to be read and hashed. */
    readonly checksum: (path: PathSpec, algorithm: string) => Promise<string | null>;
    /** The last `n` lines, then the lines added; null when the file is to be polled. */
    readonly follow: (path: PathSpec, n: number, interval: number) => Promise<AsyncIterable<Uint8Array> | null>;
    /** Every entry under `path`, keyed below it; null when the directory is to be walked. */
    readonly readTree: ReadTree;
    /** The files under `path` that may contain `text`; null when the search cannot answer for every file. */
    readonly filesContaining: (path: PathSpec, text: string, opts: {
        wholeWord: boolean;
        ignoreCase: boolean;
    }) => Promise<PathSpec[] | null>;
    /** The lines of `path` that may contain `text`; null when the search cannot answer for this file. */
    readonly linesContaining: (path: PathSpec, text: string, opts: {
        ignoreCase: boolean;
    }) => Promise<ByteSource | null>;
    /** Expand glob operands, a typed word as bash would. */
    readonly resolveGlob: ResolveGlobFn;
    /**
     * Whether the mount the command runs on, whatever routed it there (an
     * operand, an option, the working directory), answers `name` itself, as
     * the mount view says: where it does not, a shortcut is not taken.
     */
    readonly answers: (name: string) => boolean;
}
/**
 * What the factory says of one invocation of a generic builder: whether an
 * operand's read is cut into pieces (a pass-through builder keeps the
 * producer's chunks), and what streams an operand in place of the dispatched
 * read (null keeps it).
 */
export interface Reading {
    readonly split: boolean;
    readonly stream: ((ctx: Context, path: PathSpec) => AsyncIterable<Uint8Array> | null) | null;
}
/**
 * `ctx` as the factory hands it to a builder, its files read as `reading`
 * says and under the command tier's guards. Mirrors Python's `with_reading`.
 */
export declare function withReading(ctx: Context, reading: Reading): Context;
/**
 * What a command's whole read of an operand awaits first, and what learns the
 * operands its globs resolve to.
 *
 * A command reads its operands in turn, each whole once the one before is
 * done. On a whole read of one, the next READ_AHEAD go to the dispatcher as
 * one `read_many`, which keeps the small files among them in the read cache
 * (one request where the store reads a batch), and the batch after goes once
 * half of that one is read. A read whose file is still being warmed waits for
 * it, so it is served warm instead of fetching the file again. No bytes are
 * held here: a write in between drops the cached copy as it drops any. A
 * path that is not an operand warms nothing. Mirrors Python's `read_ahead`.
 */
export declare function readAhead(dispatch: DispatchFn, paths: readonly PathSpec[]): [(path: PathSpec) => Promise<void>, (found: PathSpec[]) => void];
/**
 * Send one call to the dispatcher and hand back its answer: the one way a
 * command's file call, a cross-mount run and a relayed command reach a mount.
 * Mirrors Python's `dispatched_call`.
 */
export declare function dispatchedCall(dispatch: DispatchFn, name: string, path: PathSpec, args?: readonly unknown[], kwargs?: Record<string, unknown>): Promise<unknown>;
/**
 * The `readTree` a walk through the dispatcher takes, asked only where the
 * mount a subtree lands on answers one; elsewhere null, and the walk lists
 * instead.
 *
 * The serving mount's answer is no guide: a walk through the dispatcher also
 * reaches the mounts below it and those a link above the subtree leads to, so
 * a subtree on one that answers no read_tree (a disk mount under the root RAM)
 * is walked rather than refused with ENOTSUP. A walk across mounts
 * (`crossing`) asks only where no mount sits below the subtree either: the
 * serving backend's answer holds keys a mount there shadows, and lacks the
 * mount's own. A subtree read stops at a link at the final name (ENOTDIR), so
 * a walk that follows links lists them directory by directory instead. One
 * level (`level`) is the listing a `readdir` answers with each child's stat,
 * which every mount that keeps listings answers, asked only where no mount
 * sits below, whose root the listing would name.
 * `mounts` is the boundary view a walk that does not cross them sees
 * (`mountView(files)`), undefined to take no shortcut; `landing` where a path lands, every link above its
 * final name followed (`linkLocation`, `NamespaceLinks.followParent`), null
 * for a walk whose paths name their own place. Mirrors Python's
 * `dispatched_read_tree`.
 */
export declare function dispatchedReadTree(dispatch: DispatchFn, mounts: MountView | undefined, landing: ((virtual: string) => string) | null, crossing: boolean): ReadTree;
export declare function dirAwareStat(files: CommandFiles, ctx: Context): (p: PathSpec) => Promise<FileStat>;
/**
 * A regular file's size from its stat, for a command whose answer is the size
 * alone (`wc -c`), as GNU takes it from `st_size`. Null reads the file
 * instead: for a file the read cache holds, which is read from there as the
 * read it replaces would be; for anything but a regular file (a device or a
 * pipe has no size to trust); for a size the stat does not know; for a path
 * pinned to an older revision, whose size the stat does not give; and for a
 * store that keeps permission bits (a disk, SFTP), where a file the stat sees
 * may still refuse its read, and a disk's named pipe stats as a file. A store
 * without them grants the read with the stat. A directory fails with EISDIR
 * as `dirAwareStat` has it. A listing the index holds can be up to its TTL
 * old, so the size is checked against a stat that asks the backend now
 * (`fresh`), and a file whose size moved since the listing is read: whether
 * that read serves the listed version (a GitHub blob the listing named) or the
 * current one, it is what the command counts. Mirrors Python's `file_size`.
 */
export declare function fileSize(files: CommandFiles, ctx: Context, opened?: boolean): (p: PathSpec) => Promise<number | null>;
export declare function dirAwareStream(files: CommandFiles, ctx: Context): (p: PathSpec) => AsyncIterable<Uint8Array>;
/**
 * Expand glob operands, or [] when there is nothing to resolve: no operand
 * resolves to no paths, which the generics read as stdin mode. Operand
 * semantics (report-and-continue, directory refusal) live in the generics
 * via `splitReadable`; this is wiring only. Mirrors Python's
 * `resolve_or_empty`.
 */
export declare function resolveOrEmpty(files: CommandFiles, paths: readonly PathSpec[]): Promise<PathSpec[]>;
/** Refuse a relocation that would surface a hidden path.
 *
 * A rename or a native directory copy re-anchors everything below its
 * source, and a hide's coverage does not move with the content, so
 * hidden bytes would land at paths the session can see. EACCES on the
 * source, which mv and cp render in GNU's permission-denied voice.
 * Only a directory has anything below it to re-anchor, so callers
 * check this for a source they know is a directory and skip it for a
 * file. Mirrors Python's `refuse_reveal`. */
export declare function refuseReveal(src: PathSpec, dst: PathSpec, access?: SessionAccess): void;
/**
 * The files of the command `ctx` runs, its operands `paths`.
 *
 * Every call goes to the dispatcher through `ctx.vfs`, which refuses a read
 * of a directory and a write to a slash-terminated name and fills a stat's
 * unknown size from the read cache. A command on one mount reads the stored
 * bytes (`filetype: null`), its whole reads warmed ahead of themselves
 * (`readAhead`), and, as the factory hands it on (`withReading`), under the
 * command tier's guards: no call started once the line's signal has fired,
 * each operand's read cut into pieces under its abort and deadline. A run
 * across mounts (`crossesMounts`) reads each operand as the
 * command that asked for it, through the path's renderer, after a stat that
 * refuses a directory, and lists with no boundary to stop at. Throws without
 * `ctx.vfs`: a builder outside a workspace has no files to read. Mirrors
 * Python's `command_files`.
 */
export declare function commandFiles(ctx: Context, paths?: readonly PathSpec[]): CommandFiles;
//# sourceMappingURL=files.d.ts.map