treeport

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2026 License: MIT Imports: 11 Imported by: 0

README

Treeport

한국어 · Profiles · JSON/API contract · Measured comparison

Check a whole filename tree before exporting, packaging, or moving it. Treeport is a Go library and standalone CLI that finds names that converge on the same destination, explains why they converge, and includes the destination root in path budgets. It reads directory names, JSONL manifests, or ZIP entry names. It never renames, copies, or extracts files.

CAFÉ/a?b.txt
café/a*b.txt
       ↓ export-fold: NFC → case fold → replace → trim → truncate
café/a_b.txt     collision: normalization + case + replacement

The two parents also converge, even when their children have different names. Reports include those implicit parent conflicts, duplicate entries, file/directory obstructions, and exact original bytes.

Use Treeport in export services, archive builders, artifact pipelines, and pre-commit checks. Choose a destination model explicitly: posix, windows, macos, or the precisely specified export-fold transformation pipeline. Results are known-compatible, incompatible, or unknown. The OS profiles do not certify arbitrary mounts; non-ASCII Windows/macOS semantics remain unknown where exact filesystem tables are unavailable.

Install and run

Download a binary and SHA-256 checksums from Releases, or build with Go 1.25+:

go install github.com/rad1092/treeport/cmd/treeport@v0.1.0
treeport version
treeport scan --profile windows --root 'C:\export\release' ./dist
treeport zip --profile windows --root 'C:\export\release' --json release.zip

All flags precede the input path. --root means the future destination root, not the input directory. It must be an absolute drive or UNC path for windows; it need not exist on the machine running Treeport.

A manifest can represent a tree the current filesystem cannot store:

printf '%s\n' '{"path":"CAFÉ/a?b.txt"}' '{"path":"cafe\u0301/a*b.txt"}' |
  treeport manifest --profile export-fold --json -

This exits 1 and reports both the parent alias and the full-path collision. Use --max-component and --max-path to match an export pipeline's explicit budgets; profile defaults and units are documented.

Exit Meaning
0 Known compatible with the selected model
1 At least one definite incompatibility
2 Invalid arguments, unreadable/malformed input, limit exceeded, cancellation, or runtime error
3 Uncertain semantics or symlink behavior; no definite incompatibility found

A nonzero result should stop a strict CI gate. Inspect complete as well: diagnostic truncation is explicitly marked and never becomes a success. CI and pre-commit examples retain JSON reports for diagnosis.

Embed in Go

report, err := treeport.Check(ctx, []treeport.Entry{
    {Path: "café/one.txt", Kind: "file"},
    {Path: "cafe\u0301/two.txt", Kind: "file"},
}, treeport.Options{Profile: "export-fold"})

Check does not mutate the input slice or touch the filesystem. See the runnable example and input adapters. A context cancels cooperative work; resource budgets bound entries, indexed parents, raw path bytes, and diagnostics.

Why a tree check?

Normalization differences have caused rclone filter mismatches and backend path failures. Syncthing documents case conflicts that stop synchronization. These are evidence of repeated cross-system filename problems, not endorsements of Treeport.

Existing tools are useful: pre-commit already checks case conflicts and illegal Windows names; CrossRename supports recursive dry-runs and length handling; Pathologize provides path sanitization. Treeport adds a read-only tree contract around combined transformations, destination root budgets, explained groups, and manifest/archive inputs. The independent corpus and pinned executions show concrete differences and give existing tools credit for what they already catch.

Scope and development

Treeport examines names and tree structure. It does not validate contents, destination permissions, free space, cloud-provider rules, existing destination files, link targets, or races with a changing source. No universal portability or archive-security guarantee is made. Read limitations before using a report as a release gate.

go test ./...
go test -race ./...
go vet ./...
go run ./examples/embed

The maintained corpus covers NFC/NFD, Korean, emoji UTF-16 budgets, fullwidth distinctions, superscript reserved names, invalid UTF-8, implicit parents, duplicates, and traversal. See verification for measured environments, CI scope, and reproducible stress runs. MIT license.

Documentation

Overview

Package treeport checks complete destination trees without changing the source.

Index

Constants

View Source
const SchemaVersion = "1"
View Source
const Version = "0.1.0"

Variables

This section is empty.

Functions

This section is empty.

Types

type Conflict

type Conflict struct {
	ID      string   `json:"id"`
	Target  string   `json:"target"`
	Status  string   `json:"status"`
	Causes  []string `json:"causes"`
	Members []Member `json:"members"`
}

type Entry

type Entry struct {
	Path string
	Kind string
}

type Issue

type Issue struct {
	Code   string   `json:"code"`
	Status string   `json:"status"`
	Path   Original `json:"path"`
	Detail string   `json:"detail"`
}

type Limits

type Limits struct {
	MaxEntries    int
	MaxNodes      int
	MaxPathBytes  int
	MaxTotalBytes int64
	MaxIssues     int
	MaxIndexBytes int64
}

Paths are slash-delimited relative raw bytes. Kind: file, directory, symlink.

func DefaultLimits

func DefaultLimits() Limits

func NormalizeLimits

func NormalizeLimits(l Limits) (Limits, error)

NormalizeLimits replaces zero values with defaults and rejects negative limits.

type Member

type Member struct {
	Path      Original `json:"path"`
	Kind      string   `json:"kind"`
	Implicit  bool     `json:"implicit"`
	Count     int      `json:"count"`
	Uncertain bool     `json:"uncertain"`
}

type Options

type Options struct {
	Profile         string
	DestinationRoot string
	MaxComponent    int
	MaxPath         int
	Limits          Limits
}

type Original

type Original struct {
	Display string `json:"display"`
	Base64  string `json:"base64"`
}

func OriginalPath

func OriginalPath(s string) Original

type Report

type Report struct {
	SchemaVersion   string     `json:"schema_version"`
	ToolVersion     string     `json:"tool_version"`
	Profile         string     `json:"profile"`
	ComponentBudget int        `json:"component_budget"`
	PathBudget      int        `json:"path_budget"`
	LengthUnit      string     `json:"length_unit"`
	ProfileVersion  string     `json:"profile_version"`
	UnicodeVersion  string     `json:"unicode_version"`
	DestinationRoot string     `json:"destination_root"`
	Status          string     `json:"status"`
	Complete        bool       `json:"complete"`
	EntryCount      int        `json:"entry_count"`
	NodeCount       int        `json:"node_count"`
	Issues          []Issue    `json:"issues"`
	Conflicts       []Conflict `json:"conflicts"`
	Limitations     []string   `json:"limitations"`
}

func Check

func Check(ctx context.Context, entries []Entry, opts Options) (report Report, retErr error)

Check evaluates names against an explicit, versioned model. A compatible result applies only to that model, not all mounts, OS APIs, or concurrent filesystem changes. Check never changes entries or reads their file contents. Partial scans return errors.

Directories

Path Synopsis
cmd
treeport command
Command treeport performs read-only, model-scoped destination tree checks.
Command treeport performs read-only, model-scoped destination tree checks.
examples
embed command
Embed the deterministic export model before accepting a generated tree.
Embed the deterministic export model before accepting a generated tree.
Package input reads source names without renaming, copying, following tree symlinks, or decompressing archive members.
Package input reads source names without renaming, copying, following tree symlinks, or decompressing archive members.
scripts
release command
Command release builds reproducible-layout release archives and SHA256SUMS.
Command release builds reproducible-layout release archives and SHA256SUMS.

Jump to

Keyboard shortcuts

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