client

package
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: Sep 13, 2026 License: BSD-3-Clause Imports: 30 Imported by: 0

Documentation

Index

Constants

View Source
const (
	FileURIScheme string = "tie:"
)

FileURIScheme prefixes the virtual path stored in every (uid, "path", …) triple, namespacing the tag/path tree. It is a private URI scheme conforming to RFC 3986 generic syntax ("tie" is a valid scheme name; "tie:/a/b" is a well-formed URI with no authority) — deliberately NOT the RFC 8089 "file:" scheme, since these are tie-internal tree nodes, not local-filesystem paths. The value is persisted, so changing it requires migrating existing path triples (see cmd/tie migration notes / test-env/migrate-scheme.sh).

Variables

View Source
var ErrNotFound = errors.New("key has no associated values")

ErrNotFound is returned when a key exists in no triple (the server reports "Key has no associated values"). Use errors.Is to distinguish "no data" from a real transport or server failure.

View Source
var ErrUnknownValueType = errors.New("client: unknown value type")

ErrUnknownValueType is returned by SetValueTypes when asked to declare a type outside the closed vocabulary.

Functions

func ConfigFileName

func ConfigFileName(configName string) string

ConfigFileName lets callers omit the extension: `tie -c myconf` resolves to myconf.toml. A name that already ends in .toml is left as-is.

func DownloadFrom

func DownloadFrom(host FileHost, sourceHash, dest string) error

DownloadFrom fetches sourceHash from an explicit filehost into dest, bypassing config lookup.

func DownloadFromWithProgress

func DownloadFromWithProgress(host FileHost, sourceHash, dest string, progress io.Writer) error

DownloadFromWithProgress behaves like DownloadFrom but, when progress is non-nil, writes each chunk of downloaded file bytes to it so callers can render a progress bar.

func DownloadSize

func DownloadSize(host FileHost, sourceHash string) (int64, error)

DownloadSize returns the total number of bytes a download of sourceHash would transfer, recursing into directories. Callers use it to size a progress bar before starting the transfer.

func ExtractMediaMetadata

func ExtractMediaMetadata(path string) metadata.Media

ExtractMediaMetadata reads embedded media tags from a local file. Audio files yield title/artist/album/year/track and playing-time duration via the vendored tie/tag fork; other types yield an empty Media (only placement templates and metadata triples consume this, and only audio currently carries usable tags). A read/parse failure is not fatal — it just means no metadata, so the caller falls back to path-based placement.

func GetDirType

func GetDirType(tie *TieClient, uid DirUID) ([]string, error)

GetDirType returns a directory's classification labels — its (uid,"tie-type",*) values with the structural "directory" marker filtered out — sorted. The marker is what ReadTieDir uses to tell subdirs from files, so it is never surfaced here. A directory with no extra labels returns an empty slice, not an error.

func GetTags

func GetTags(tie *TieClient, hash string) ([]string, error)

GetTags returns the tags currently attached to a content hash, sorted. It reads the (hash,"tag",<tag>) triples. A hash with no tags returns an empty slice, not an error.

func GetVideoHeight

func GetVideoHeight(source string) string

func HTTPClientFor

func HTTPClientFor(host FileHost) *http.Client

HTTPClientFor returns an *http.Client honoring the host's Insecure flag and credentials. A plain, credential-free secure host reuses http.DefaultClient; anything needing a custom TLS config or Basic Auth gets a dedicated client.

func InitKey

func InitKey() []byte

func IsArchiveType

func IsArchiveType(t TieType) bool

IsArchiveType reports whether t marks a blob that should be expanded as a virtual directory of members.

func RenameDir

func RenameDir(tie *TieClient, uid DirUID, oldPath, newPath string, oldParent, newParent DirUID) error

RenameDir renames and/or moves a directory in the path tree. A directory's identity in the path tree is its (uid,"path") triple, and every descendant directory carries the renamed prefix in its own path, so the rename cascades over all descendant dirs. Files need no path rewrite: they have no path triple and their parent DirUID is unchanged. A move swaps the top dir's (uid,"parent") edge.

func RenameFile

func RenameFile(tie *TieClient, hash string, oldParent, newParent DirUID, newName string) error

RenameFile renames and/or moves a file in the path tree. The file's identity is its content hash, so the display name lives in the (hash,"filename") and (hash,"name") triples; renaming updates both. A move swaps the (hash,"parent") edge from oldParent to newParent.

Because the name is a property of the content hash, renaming a file changes its name everywhere the same content appears (other directories, every tag query). This is inherent to the content-addressed model.

func RowFirst

func RowFirst(r Row, relation string) string

RowFirst returns the first value under relation, or "" when absent.

func RowHas

func RowHas(r Row, relation, value string) bool

RowHas reports whether relation holds value.

func RowValues

func RowValues(r Row, relation string) []string

RowValues returns all values a row holds under relation, or nil.

func SaveConfig

func SaveConfig(name string, config Config) error

func SetDirTypes

func SetDirTypes(tie *TieClient, uid DirUID, newLabels []string) error

SetDirTypes replaces a directory's classification labels with newLabels, diffing against the current labels: added labels get (uid,"tie-type",<label>) plus the (types,"all",<label>) registry entry, removed labels get a Delete. The structural "directory" marker is preserved untouched (never added, never removed), so a text-editor rewrite of the .type file cannot break navigation. Empty entries are ignored. The change is committed and synced.

func SetTags

func SetTags(tie *TieClient, hash string, newTags []string) error

SetTags replaces the tags on a content hash with newTags, computing the minimal diff against the current tags: tags in newTags but not stored are added (along with the (tags,"all",<tag>) registry entry that Tag writes), tags stored but absent from newTags are removed. Empty entries are ignored. The change is committed and synced.

Because tags attach to the content hash, this affects the tags everywhere the same content appears and in every tag query view.

func Tag

func Tag(tie *TieClient, info TagInfo, collection string) error

Types

type AddReply

type AddReply = *api.AddReply

type AlbumGroup added in v0.5.2

type AlbumGroup struct {
	// SourceDir is the group's on-disk root: the directory itself for a dir
	// group, the common prefix of the member files for a merged/tag group,
	// the containing directory for an archive group.
	SourceDir string
	// Files, when non-nil, is the explicit audio file list to import (merged,
	// split and tag groups). Nil means the whole SourceDir tree is imported
	// (dir groups), sidecars and subdirectories included.
	Files []string
	// IsArchive marks a single-file group: an archive blob of audio members.
	// It imports as one file into Dest and gets no dir-type stamp — the blob
	// itself carries the audio-archive classification.
	IsArchive bool
	// Dest is the virtual import root without a scheme (e.g.
	// "/music/Miles Davis/1959. Kind of Blue"), rendered from the dir-type's
	// ImportDest template, or the on-disk source path when no template
	// applies. Empty when nothing could be rendered; the group is skipped.
	Dest   string
	Artist string // aggregated: AlbumArtist, falling back to Artist
	Album  string
	Year   int
	Tracks int   // audio file count (1 for archive groups)
	Size   int64 // total member bytes
	// Warnings lists review notes: missing tags, mixed artists without an
	// album-artist tag, destination collisions with other groups.
	Warnings []string
	// contains filtered or unexported fields
}

AlbumGroup is one album discovered by PlanAlbumImport: the source files, the rendered import destination, and human-reviewable warnings.

func PlanAlbumImport added in v0.5.2

func PlanAlbumImport(cfg Config, root string, opts AlbumPlanOptions) ([]AlbumGroup, error)

PlanAlbumImport scans root for albums and returns the import plan without touching the network: which groups import where, with what counts and warnings. dirType selects the destination template (Config.ImportDest), overridden by opts.Template. Grouping follows opts.Mode (see GroupMode).

An archive of audio members becomes a one-file group (imported as an audio-archive blob). A directory whose files carry conflicting album tags is split (auto mode), and directories sharing one album identity are merged (auto/tags mode); split and merged groups import their audio files only. A whole-tree group nested around another group double-parents the nested files (legitimate, but flagged in Warnings).

func (AlbumGroup) WholeTree added in v0.5.2

func (g AlbumGroup) WholeTree() bool

WholeTree reports whether the group imports its SourceDir as a faithful tree mirror via ImportDir (sidecars included), rather than an explicit audio file list.

type AlbumImportOptions added in v0.5.2

type AlbumImportOptions struct {
	Host          FileHost
	Collection    string
	DirType       string   // label stamped on each album root, e.g. "audio-dir"
	Tags          []string // extra tags applied to every imported file
	ForcedArchive TieType  // archive classification override (usually zero)
	// Progress, when non-nil, is called before each group's import with its
	// index and the total group count.
	Progress func(done, total int, g AlbumGroup)
}

AlbumImportOptions configures ImportAlbums.

type AlbumImportResult added in v0.5.2

type AlbumImportResult struct {
	Group AlbumGroup
	Err   error
}

AlbumImportResult pairs a planned group with its import outcome.

type AlbumPlanOptions added in v0.5.2

type AlbumPlanOptions struct {
	DirType string // ImportDest lookup key, e.g. "audio-dir"
	// Template overrides Config.ImportDest[DirType] when non-empty (the CLI's
	// --dest doubles as an inline template in album mode).
	Template string
	Mode     GroupMode
	// ScanProgress, when non-nil, is called during the library scan with the
	// probed and total file counts (at most once per 1000 files, plus a final
	// call). Libraries on slow or network filesystems take a while to probe.
	ScanProgress func(scanned, total int)
}

AlbumPlanOptions configures PlanAlbumImport.

type ArchiveEntry

type ArchiveEntry struct {
	Filename string
	Hash     string
	TieType  TieType
	Size     int
	TagDate  time.Time
}

ArchiveEntry is a directory child that is a single archive blob (a zip) carrying an archive tie-type. Unlike a SubDirectory it has no graph child-edges: its "directory" contents live inside the blob and are produced by expanding it at read time (see io/archivelib). Uid is the blob's content hash, which is the expansion key — never pass it to ReadTieDir.

type AssociatedReply

type AssociatedReply = *api.AssociatedReply

type BatchReply

type BatchReply = *api.BatchReply

type CollectionEntry

type CollectionEntry struct {
	Namespace        string
	Collection       string
	TripleStoreURL   string
	Username         string
	Password         string
	Insecure         bool
	FileHosts        []string
	DefaultRetention string
}

CollectionEntry is one named collection binding in Config.Collections. Every field is optional; an unset field falls back to the top-level Config value during resolution. DefaultRetention, when set, is a Go duration (or "infinite") the client may stamp on uploads for this collection.

type Config

type Config struct {
	Username   string
	Password   string
	Namespace  string
	Collection string
	// Webservice is the triplestore URL. Deprecated: use TripleStoreURL. It is
	// still honored (LoadConfig copies it into TripleStoreURL when the latter is
	// empty) so pre-existing configs keep working.
	Webservice string
	// TripleStoreURL is the tie-triplestore endpoint. It supersedes Webservice;
	// when unset LoadConfig falls back to Webservice.
	TripleStoreURL string
	// WebserviceInsecure enables TLS InsecureSkipVerify for the triplestore
	// connection (accept self-signed certificates).
	WebserviceInsecure bool
	DefaultFileHosts   []string
	FileHosts          map[string]FileHost
	// DefaultCollection names the entry in Collections used when no --collection
	// is given. Empty falls back to the flat Collection field.
	DefaultCollection string
	// Collections holds named collection bindings so one config can address
	// several collections. Each entry may override the top-level triplestore,
	// namespace, credentials and filehosts; unset fields fall back to the
	// top-level values. When empty, LoadConfig synthesizes a single entry from
	// the flat Namespace/Collection/DefaultFileHosts fields.
	Collections map[string]CollectionEntry
	// ImportDest maps a dir-type name (e.g. "audio-dir") to a virtual-path
	// template rendered from a directory's aggregated metadata, e.g.
	// "/music/{artist}/{year}. {album}". When a dir-type has an entry, imports
	// of that type are rooted at the rendered path instead of the source's
	// absolute on-disk path. Supported variables: artist, album, year, title,
	// track.
	ImportDest map[string]string
	// PrevVersions bounds how many superseded versions of a file are kept when a
	// directory is re-imported. When re-import replaces a file (same name, new
	// bytes) or drops one (renamed/deleted on disk), the old content's edge is
	// moved into a "<filename>_prev" history directory instead of being deleted;
	// only the newest PrevVersions are retained there, oldest dropped first. A
	// value of 0 keeps no history (the old edge is removed directly). NOTE:
	// LoadConfig fills a zero-value Config from TOML, so a config file that omits
	// this key gets 0 (no history), not the defaultConfig value.
	PrevVersions int
	// Queries maps a friendly name to a saved tag query, e.g.
	// "chill-jazz" = "jazz mellow -live". Each entry appears as a directory
	// under the mount's query/ tree, so "ls query/chill-jazz" runs the stored
	// query. The query string uses the same syntax as an ad-hoc query dir
	// (space-ANDed terms, "-" excludes, optional "type:" scope).
	Queries map[string]string
	// contains filtered or unexported fields
}

func DefaultConfig

func DefaultConfig() Config

func LoadConfig

func LoadConfig(configName string) (Config, error)

func LoadOrCreateConfig

func LoadOrCreateConfig(configName string) (Config, bool, error)

LoadOrCreateConfig loads configName like LoadConfig, but when no config file exists in any of the searched locations it writes a default one to the user config dir and loads that instead. A file that exists but fails to parse is still reported as an error (so a stale/broken config is never overwritten). The returned bool reports whether a new default was created.

func ReadConfig

func ReadConfig(configName string) Config

Deprecated - use LoadConfig instead

func TestingConfig

func TestingConfig() Config

func (Config) Path

func (c Config) Path() string

Path returns the filesystem path the config was loaded from (empty for a default config that was never read from disk).

func (Config) ResolveCollection

func (c Config) ResolveCollection(name string) ResolvedCollection

ResolveCollection resolves a collection name to the concrete triplestore, namespace, collection id, credentials and filehosts to use, applying top-level fallbacks for any field the named entry leaves unset. An empty name selects DefaultCollection; a name matching no entry is treated as a bare collection id on the top-level triplestore/namespace.

type DeleteReply

type DeleteReply = *api.DeleteReply

type DirUID

type DirUID string

func (DirUID) String

func (d DirUID) String() string

type Directory

type Directory struct {
	Paths      []string
	Uid        DirUID
	SubDirs    []SubDirectory
	Files      []File
	Archives   []ArchiveEntry
	ParentUIDs []DirUID
}

func ReadTieDir

func ReadTieDir(tie *TieClient, uid DirUID) (Directory, error)

type DropReply

type DropReply = *api.DropReply

type DumpReply

type DumpReply = *api.DumpReply

type File

type File struct {
	Filename  string
	Uid       string
	TieType   TieType
	MediaType string
	Size      int
	// TagDate is the file's last import time, parsed from its (hash,"tag-date")
	// triple. Zero when no date is recorded. The FUSE mount surfaces it as the
	// file's mtime.
	TagDate time.Time
}

type FileHost

type FileHost struct {
	URL      string
	Insecure bool
	Username string
	Password string
	Store    string
}

FileHost is a filehost endpoint. Insecure enables TLS InsecureSkipVerify (accept self-signed certificates); the scheme lives in URL. Username/Password are optional HTTP Basic Auth credentials sent with every request to a filehost that requires authentication; leave them empty for an open filehost. Store, when set, names a physical store on a multi-store filehost and rides uploads as the Tie-Store header; leave empty for a single-store filehost.

type GroupMode added in v0.5.2

type GroupMode int

GroupMode selects how PlanAlbumImport clusters audio files into albums.

const (
	// GroupAuto groups by directory, then splits directories whose files carry
	// conflicting album tags and merges groups whose tags prove they are the
	// same album (multi-disc sets, scattered rips).
	GroupAuto GroupMode = iota
	// GroupDir groups strictly by directory: each directory containing audio
	// files directly is one album, imported as a faithful tree mirror.
	GroupDir
	// GroupTags ignores the directory layout and clusters by album tags;
	// untagged files fall back to per-directory groups.
	GroupTags
)

func ParseGroupMode added in v0.5.2

func ParseGroupMode(s string) (GroupMode, error)

ParseGroupMode converts a CLI flag value ("auto"|"dir"|"tags") to a GroupMode; the empty string selects the default (auto).

type MediaRelation

type MediaRelation struct {
	FromHash string
	Relation string
	ToHash   string
}

MediaRelation is a named, directed association from one media item to another, both identified by content hash (e.g. {hashA, "sampled-from", hashB}).

type MetadataGap

type MetadataGap struct {
	Subject string // DirUID or content hash
	IsDir   bool
	Missing []string // relation names, e.g. "filename"
}

MetadataGap is one node and the list of required relations it lacks.

type ParentRef

type ParentRef struct {
	Child  string // DirUID or content hash carrying the edge
	Parent string // the referenced DirUID that does not exist
}

ParentRef is one (child, parent) edge, used to report a dangling reference.

type QuerySpec

type QuerySpec struct {
	Terms   []string
	Exclude []string
	Scope   string
	// MissingRelation keeps only matches that carry no triple under this
	// relation (e.g. "tag" to list untagged items). It is the negation of
	// existence the tag algebra cannot express with Exclude, resolved
	// server-side so only the qualifying rows cross the wire.
	MissingRelation string
	Filter          string
	Reverse         bool
	Expand          bool
	Offset          int
	Limit           int
	SortBy          string
	// SortByValue orders matched keys by the value each holds under this
	// relation (e.g. "gendb-imported-at" for chronological order). Empty = none.
	SortByValue string
	// SortByValueNumeric reads those values as numbers instead of strings, so 9
	// precedes 10. Values that do not parse sort last in either direction. See
	// ValueTypes for declaring which relations hold numbers.
	SortByValueNumeric bool
	// Descending reverses the final ordering.
	Descending bool
}

QuerySpec describes a tag/association query. Terms is the full AND-list of values a match must be associated with (no positional seed). See api.Query.

type ResolvedCollection

type ResolvedCollection struct {
	Namespace      string
	Collection     string
	TripleStoreURL string
	Username       string
	Password       string
	Insecure       bool
	FileHosts      []string
}

ResolvedCollection is a CollectionEntry with all top-level fallbacks applied: the concrete triplestore/namespace/collection/credentials/filehosts to use for one operation.

type Row

type Row = tiedb.Row

Row is the flat query result unit: a key plus its attributes (relation -> values). Re-exported from tiedb so callers and future bindings need only the client package.

type StatInfo

type StatInfo struct {
	Key        string   // subject: content hash (file/archive) or DirUID (directory)
	Kind       StatKind //
	TieType    TieType  // full classification (e.g. audio-file, image-archive)
	Filename   string   //
	Name       string   // filename without extension
	MediaType  string   // MIME, e.g. "image/png"
	Size       int64    // recorded filesize triple (0 when absent)
	Tags       []string //
	TagDate    time.Time
	Meta       map[string]string // media metadata: title/artist/album/year/track when present
	Paths      []string          // stored virtual paths (directories); reconstructed path for files
	ParentUIDs []string

	// Directory only (from the child query):
	SubDirCount  int
	FileCount    int
	ArchiveCount int

	// TotalSize is the recursive download size; filled only when opts.Recursive.
	TotalSize int64

	// Versions holds superseded versions, newest first; filled only when
	// opts.Versions and the item is a file with a resolvable path.
	Versions []VersionInfo

	// Blob* are filled only when opts.CheckBlob (a filehost HEAD).
	BlobChecked bool
	BlobExists  bool
	BlobSize    int64

	// Attributes is the raw relation->values map from the store — an escape hatch
	// so a front-end can surface any triple StatInfo does not model explicitly.
	Attributes map[string][]string
}

StatInfo is the full metadata summary for one item. Filehost-derived and history fields are populated only when the matching StatOptions flag is set; everything else comes from the triple store in a single Get (plus one child query for directories).

type StatKind

type StatKind string

StatKind is the coarse classification of a stat target.

const (
	StatFile      StatKind = "file"
	StatDirectory StatKind = "directory"
	StatArchive   StatKind = "archive"
)

type StatOptions

type StatOptions struct {
	Recursive bool // compute TotalSize via a filehost (DownloadSize)
	CheckBlob bool // HEAD the filehost for blob existence + on-disk size
	Versions  bool // populate version history when resolvable
}

StatOptions controls the optional, network-touching parts of a stat. The zero value is fully offline (triple store only).

type SubDirectory

type SubDirectory struct {
	Paths    []string
	Uid      DirUID
	DirTypes []TieType
}

type TagInfo

type TagInfo struct {
	Hash      string
	File      string
	Size      int
	MediaType string
	TieType   TieType
	Tags      []string
	Directory DirUID
	IsDir     bool
	Metadata  metadata.Media
}

type TagOptions

type TagOptions struct {
	AddOriginalPath bool
}

type TaggedFile

type TaggedFile struct {
	Hash     string
	Filename string
	Size     int
	IsDir    bool
	// IsArchive marks a single archive blob (a zip) that is browsable as a
	// virtual directory of its members. It is a file structurally (IsDir is
	// false), but consumers should expand it at read time via io/archivelib
	// rather than treating it as plain downloadable content. TieType carries the
	// specific archive type when IsArchive is set.
	IsArchive bool
	TieType   TieType
}

TaggedFile is one entry in a tag-derived virtual directory: its content hash (used to fetch bytes, or a tiedir blob, from the filehost), display filename, size, and whether it is a directory. A tagged directory's hash points at an immutable tiedir blob, so it can be expanded with the content-addressed tree.

type TieCategory

type TieCategory int

type TieClient

type TieClient struct {
	Config Config
	// contains filtered or unexported fields
}

func NewTieClient

func NewTieClient(config Config) (client *TieClient)

NewTieClient builds a client for the config's default collection.

func NewTieClientFor

func NewTieClientFor(config Config, collection string) (client *TieClient)

NewTieClientFor builds a client bound to the named collection (empty selects the default). The transport targets that collection's resolved triplestore and credentials.

func (*TieClient) Add

func (tc *TieClient) Add(key, value1, value2 string) (AddReply, error)

Add a triple to the collection

func (*TieClient) Associated

func (tc *TieClient) Associated(key string) (AssociatedReply, error)

Get a TripleSet with all triples that are associated with 'key'. Returns ErrNotFound if nothing is associated with the key.

func (*TieClient) Batch

func (tc *TieClient) Batch(batch *api.Batch) (BatchReply, error)

Run a batch - make new Batch with NewBatch. The reply is always returned so callers can inspect per-request sub-replies; err is non-nil on transport failure or if the batch as a whole reports failure.

func (*TieClient) CoTagsForQuery

func (tc *TieClient) CoTagsForQuery(include, exclude []string, scope string) ([]string, error)

CoTagsForQuery returns all unique tags carried by entries that match ALL of include (AND) and NONE of exclude, optionally scoped to a tie-type value.

This is the "faceted refinement" (narrowing) query: given a user's current tag filter, it answers "what further tags can I narrow by?" For example, given include=["tree","nature"] it returns tags such as ["2026","norway", "sunset"] that appear on files tagged with both "tree" and "nature".

The returned slice is sorted and deduplicated. Returns ErrNotFound (with a nil slice) when no entries match the given include terms.

func (*TieClient) CoTagsForQueryExcludingInput

func (tc *TieClient) CoTagsForQueryExcludingInput(include, exclude []string, scope string) ([]string, error)

CoTagsForQueryExcludingInput is a convenience wrapper around CoTagsForQuery that removes the input include tags from the returned set. Use this when building a "refine further" UI where the seed tags are already selected and should not appear again as options.

func (*TieClient) CollectionInfo

func (tc *TieClient) CollectionInfo() api.CollectionInfo

func (*TieClient) CreateTieRootDir

func (tie *TieClient) CreateTieRootDir() error

func (*TieClient) Delete

func (tc *TieClient) Delete(key, value1, value2 string) (DeleteReply, error)

Delete a triple from the collection

func (*TieClient) DeleteTable

func (tc *TieClient) DeleteTable(uid string) error

DeleteTable removes a table and all its row entities. It is idempotent: deleting a missing or already-deleted table is a no-op that returns nil.

func (*TieClient) DeleteTag

func (tie *TieClient) DeleteTag(tag string) (int, error)

DeleteTag removes tag from every item that carries it and from the ("tags","all",<tag>) registry, across the current collection. It returns the number of items the tag was removed from. The registry entry is dropped even when no item carries the tag, so a dangling registered tag can be cleaned up.

Because a tag attaches to a content hash, this removes the tag everywhere that content appears and from every tag-query view.

func (*TieClient) DirUIDFromPath

func (tie *TieClient) DirUIDFromPath(path string) (DirUID, error)

func (*TieClient) Download

func (tc *TieClient) Download(hostName, sourceHash, dest string) error

Download fetches sourceHash from the named filehost into dest. Pass an empty hostName to use the default filehost.

func (*TieClient) DropCollection

func (tc *TieClient) DropCollection() error

DropCollection deletes the entire current collection — its on-disk .tie file and in-memory index — server-side. The collection reloads empty on next access. Unlike Delete (one triple) this discards the whole collection, so it is the destructive setup for an overwriting Restore.

func (*TieClient) Dump

func (tc *TieClient) Dump() (DumpReply, error)

Dump returns every forward triple in the current collection, for backup or interop. Order is unspecified. It collects the streamed dump into a slice; callers that must not hold the whole collection in memory should use DumpStream instead.

func (*TieClient) DumpStream

func (tc *TieClient) DumpStream(fn func(tiedb.StringTriple) error) error

DumpStream streams every forward triple in the current collection to fn, one at a time, without ever buffering the whole collection on the client. Order is unspecified. If fn returns an error, streaming stops and that error is returned.

func (*TieClient) Exists

func (tc *TieClient) Exists(key string) bool

Check if the key exists

func (*TieClient) Expand

func (tc *TieClient) Expand(keys []string) ([]Row, error)

Expand fetches the forward attributes of many keys in one round trip, one Row per key that exists (missing keys are omitted). Order follows keys.

func (*TieClient) ExpandIn

func (tc *TieClient) ExpandIn(collection string, keys []string) ([]Row, error)

ExpandIn fetches the forward attributes of many keys from a specific collection in one round trip. An empty collection falls back to the configured default.

func (*TieClient) FilesWithTags

func (tie *TieClient) FilesWithTags(scope string, include, exclude []string, offset, limit int) ([]TaggedFile, int, error)

FilesWithTags returns the files that carry ALL of include and NONE of exclude, optionally scoped to a single tie-type value (e.g. "audio-file" for "find music with tag1, tag2 but not tag4", or a custom dir-type label like "live-album"). Tags share the "tag" relation so they AND/NOT together inside one QueryTags call; the tie-type scoping keys on a different relation (tie-type), so it rides along as the query's Scope, which the server intersects by hash identity — no client-side filtering. Pass an empty scope to query across all types. When include is empty the whole scope is browsed directly (or, with no scope, nothing is returned since there is no set to seed from). The scope is a raw tie-type value string so built-in media types and custom labels are handled uniformly. The server paginates via offset/limit; limit <= 0 means no limit. The second return is the total number of matching files before pagination.

func (*TieClient) Get

func (tc *TieClient) Get(key string) (Row, error)

Get fetches the forward attributes of a single key. Returns ErrNotFound if the key has no associated values. It is Expand for one key; use Query to search for keys by their associations.

func (*TieClient) GetIn

func (tc *TieClient) GetIn(collection, key string) (Row, error)

GetIn fetches the forward attributes of a single key from a specific collection. An empty collection falls back to the configured default.

func (*TieClient) ImportAlbums added in v0.5.2

func (tie *TieClient) ImportAlbums(plan []AlbumGroup, opts AlbumImportOptions) []AlbumImportResult

ImportAlbums executes a plan from PlanAlbumImport, importing group by group and collecting per-group errors (one failure does not abort the rest). Groups without a destination are recorded as errors.

func (*TieClient) ImportDir

func (tie *TieClient) ImportDir(dir string, host FileHost, collection string, dirType string, tags []string, dest string, forcedArchive TieType) error

func (*TieClient) ImportFile

func (tie *TieClient) ImportFile(file string, host FileHost, collection string, tags []string, directory DirUID, forcedArchive TieType) error

func (*TieClient) InsertTable

func (tc *TieClient) InsertTable(uid string, headers []string, rows [][]string) (string, error)

InsertTable writes headers + rows as a table entity and returns its uid. An empty uid mints a fresh one; a non-empty uid replaces the table already stored there (idempotent re-import) — its old row entities are cleared first. rows are row-major; each inner slice holds one row's cells in header order. Short rows are padded with empty cells and cells past len(headers) are ignored. Empty cells are not stored (ReadTable reconstructs them as "").

func (*TieClient) InsertTableLevels added in v0.5.1

func (tc *TieClient) InsertTableLevels(uid string, headerRows [][]string, rows [][]string) (string, error)

InsertTableLevels writes a table whose header spans several rows. headerRows is row-major — headerRows[i][j] is level i of column j — matching the layout of the source sheet; it must be rectangular, with merged parent cells already forward-filled and blanks explicit (deciding where a merged cell ends is file-parsing work that belongs to the caller, not to storage). Each column's key is its non-empty levels joined, and those keys must be unique. Otherwise it behaves exactly like InsertTable.

A single header row is stored identically to the equivalent InsertTable call, so depth 1 is not a special case for callers.

func (*TieClient) ListDirTypes

func (tie *TieClient) ListDirTypes() ([]string, error)

ListDirTypes returns the dir-type classification labels known to the store: the custom labels registered in (types,"all",<label>) unioned with the built-in directory TieTypes (the *-dir / *-archive / directory stringers), sorted and de-duplicated. The union means /query/types shows both user-created labels and the built-in vocabulary without pre-seeding the registry with built-ins.

func (*TieClient) ListFavorites

func (tie *TieClient) ListFavorites() ([]string, error)

ListFavorites returns the registered favorite tags, sorted. A collection with no favorites yields an empty slice, not an error.

func (*TieClient) ListTags

func (tie *TieClient) ListTags(offset, limit int) ([]string, int, error)

ListTags returns tag names known to the store, read from the ("tags", "all", <tag>) registry that Tag writes, ordered by tag name. offset/limit paginate; limit <= 0 means no limit. The second return is the total number of tags before pagination.

func (*TieClient) ListVersions

func (tc *TieClient) ListVersions(mainCollection, path string) ([]VersionInfo, error)

ListVersions returns the superseded versions of the file at path, newest first. An empty mainCollection uses the configured default. A file with no history yields an empty slice, not an error.

func (*TieClient) MkTieDir

func (tie *TieClient) MkTieDir(path string) (DirUID, error)

func (*TieClient) MkTieDirAll

func (tie *TieClient) MkTieDirAll(dirPath string) (DirUID, error)

func (*TieClient) NewBatch

func (tc *TieClient) NewBatch() *api.Batch

Make a new Batch - run with Batch function

func (*TieClient) NewBatchIn

func (tc *TieClient) NewBatchIn(collection string) *api.Batch

NewBatchIn makes a Batch targeting a specific collection. An empty collection falls back to the configured default.

func (*TieClient) NewUpdate

func (tc *TieClient) NewUpdate(key, value1, value2, newValue2 string) api.Update

func (*TieClient) PrintState

func (tc *TieClient) PrintState()

func (*TieClient) Query

func (tc *TieClient) Query(spec QuerySpec) ([]Row, int, error)

Query runs a tag/association query and returns the matching rows (ordered and paginated per spec), the total match count before pagination, and an error. Returns ErrNotFound (with nil rows) when nothing matches.

func (*TieClient) QueryIn

func (tc *TieClient) QueryIn(collection string, spec QuerySpec) ([]Row, int, error)

QueryIn runs a Query against a specific collection. An empty collection falls back to the configured default.

func (*TieClient) ReadTable

func (tc *TieClient) ReadTable(uid string) (headers []string, rows [][]string, err error)

ReadTable returns a table's headers and rows (row-major, header order), or ErrNotFound if uid holds no table entity. On a table with a multi-row header the headers are the derived column keys; use ReadTableLevels to get the levels.

func (*TieClient) ReadTableFull added in v0.5.1

func (tc *TieClient) ReadTableFull(uid string) (keys []string, headerRows [][]string, rows [][]string, err error)

ReadTableFull returns both views of a table's header in one round trip: the column keys ReadTable yields and the row-major header rows ReadTableLevels yields, plus the rows. It exists for callers that need both at once — a GUI keys each cell by its column key while rendering the levels above it — which the two narrower readers can only serve by reading the table twice. Deriving the keys from the levels instead is not an option outside this package: levelSep is deliberately unexported, so the key rule lives in exactly one place.

func (*TieClient) ReadTableLevels added in v0.5.1

func (tc *TieClient) ReadTableLevels(uid string) (headerRows [][]string, rows [][]string, err error)

ReadTableLevels returns a table's header levels as row-major header rows, in the same shape InsertTableLevels accepts, plus its rows. A table stored with a single-row header yields exactly one header row, so callers need not distinguish the two cases.

func (*TieClient) RegisterFavorite

func (tie *TieClient) RegisterFavorite(tag string) error

RegisterFavorite marks tag as a favorite in the ("tags","favorite",<tag>) registry. Registering an existing favorite is a harmless no-op. An empty tag is rejected.

func (*TieClient) RegisterTag

func (tie *TieClient) RegisterTag(tag string) error

RegisterTag records tag in the ("tags","all",<tag>) registry that backs ListTags, so a tag name is known to the store even before any file carries it. It writes the same registry triple Tag/SetTags write. Registering an existing tag is a harmless no-op. An empty tag is rejected.

func (*TieClient) RelateFiles

func (tie *TieClient) RelateFiles(fromHash, relation, toHash string) error

RelateFiles records an open-vocabulary relation between two media items by content hash, e.g. RelateFiles(track, "sampled-from", source). Both directed edges are written as forward triples — (from, relation, to) and (to, relation, from) — because forward associations are always stored (the reverse index is a fixed allowlist that arbitrary relation names are not in). Writing both directions makes the relation browsable from either media item with a plain forward lookup. relation must not be one of the reserved metadata relations (filename, tag, parent, ...).

func (*TieClient) RelationsFrom

func (tie *TieClient) RelationsFrom(hash string) ([]MediaRelation, error)

RelationsFrom returns every media-to-media relation recorded on hash. Because RelateFiles writes both directions as forward edges, this one forward lookup surfaces relations pointing both from and into hash. Only triples whose object is itself a content hash are returned, so file metadata (filename, tag, ...) is excluded.

func (*TieClient) RenameTag

func (tie *TieClient) RenameTag(oldTag, newTag string) (int, error)

RenameTag rewrites tag oldTag to newTag on every item that carries it and in the ("tags","all",<tag>) registry, across the current collection. It returns the number of items rewritten. The registry entry is renamed even when no item carries the tag, so a dangling registered tag can be renamed too.

Because a tag attaches to a content hash, this renames the tag everywhere that content appears and in every tag-query view. Re-tagging an item that already carries newTag is a harmless no-op.

func (*TieClient) RepairOrphans

func (tie *TieClient) RepairOrphans(collection string, rep *VerifyReport, destDir string) (int, error)

RepairOrphans re-homes every orphan in rep under a timestamped restored/ directory, making them reachable from the tree root again. It is the explicit, mutating counterpart to Verify and is only ever called at the user's request (`tie verify --repair`). Only orphans are repaired — duplicate paths, cycles, dangling refs and missing metadata are reported but left for a human decision.

Each orphan is re-parented under tie:/restored/<date>/ (directories and files share the one recovery dir); its own metadata is left untouched. The restore directory is created via MkTieDirAll (so it also gets its structural triples and is itself browsable).

rep should come from a just-run Verify on the same collection; stale reports are harmless (re-parenting an already-parented node just adds another parent edge), but a fresh pass avoids re-homing nodes another client already fixed.

func (*TieClient) ResolveHost

func (tc *TieClient) ResolveHost(name string) (FileHost, error)

ResolveHost looks up a filehost by name. An empty name selects the first entry in DefaultFileHosts.

func (*TieClient) ResolveHosts added in v0.5.2

func (tc *TieClient) ResolveHosts(collection string, explicit []string) []string

ResolveHosts picks the filehost names an upload/import targets. An explicit list (e.g. one or more --host flags) wins. Otherwise the hosts come from the resolved entry of the named collection — the client's bound collection (the global -c selection) when collection is empty — so a collection's own FileHosts override the top-level DefaultFileHosts.

func (*TieClient) Restore

func (tc *TieClient) Restore(triples [][3]string) error

Restore adds every (key, value1, value2) triple into the current collection via a single batch. It is additive and idempotent: re-adding an existing triple is a no-op, so restoring a dump merges rather than replaces.

func (*TieClient) RestoreVersion

func (tc *TieClient) RestoreVersion(mainCollection, path, versionHash string) (string, error)

RestoreVersion makes a superseded version of path the live content again. If versionHash is empty the newest version is restored; otherwise the version whose hash equals or is prefixed by versionHash is used. The currently-live content (if any) is first recorded as a version (prev-first ordering), then the target is installed live in main from its history snapshot, and finally the target's now-redundant history record is removed. The target's blob already exists on the filehost, so no upload happens. Returns the restored content hash.

func (*TieClient) Set

func (tc *TieClient) Set(key, relation string, values []string) error

Set makes (key, relation) hold exactly values, replacing any existing values for that relation in one server-side op. An empty values slice clears it.

func (*TieClient) SetDirType

func (tie *TieClient) SetDirType(uid DirUID, dirType string) error

func (*TieClient) SetValueTypes added in v0.5.2

func (tc *TieClient) SetValueTypes(types map[string]ValueType) error

SetValueTypes declares the value type of each named relation, merging into whatever the collection already holds: relations not named are left alone. Declaring ValueTypeString (or the empty string) clears a relation's entry, since an absent declaration already means string.

Every type is checked before anything is written, so a map containing one bad entry declares nothing. Declarations replace rather than accumulate — a relation carries one type, not a set of them.

func (*TieClient) Stat

func (tc *TieClient) Stat(subject string, opts StatOptions) (StatInfo, error)

Stat gathers metadata for a subject key (a content hash for files/archives, or a DirUID for directories). tie-fm passes the key it already holds on a selected entry. Returns ErrNotFound when the key carries no triples (e.g. a raw tiedir-snapshot blob hash, whose triples live on its DirUID).

func (*TieClient) StatBlob

func (tc *TieClient) StatBlob(hash string) (exists bool, size int64, err error)

StatBlob issues a HEAD for hash against the first configured default filehost and reports whether the blob is present and its on-disk byte size (from the Content-Length header). A 404 returns (false, 0, nil); any other non-200 status or transport error is surfaced as an error.

func (*TieClient) StatPath

func (tc *TieClient) StatPath(path string, opts StatOptions) (StatInfo, error)

StatPath resolves a virtual path (a directory path, or a file leaf) to its subject key and then stats it. Because the path is known, version history is always resolvable here when requested.

func (*TieClient) Sync

func (tc *TieClient) Sync() error

Wait until all changes has been committed to the collection

func (*TieClient) SyncIn

func (tc *TieClient) SyncIn(collection string) error

SyncIn waits until all changes have been committed to a specific collection. An empty collection falls back to the configured default.

func (*TieClient) UnregisterFavorite

func (tie *TieClient) UnregisterFavorite(tag string) error

UnregisterFavorite removes tag from the ("tags","favorite",<tag>) registry. Unregistering a tag that is not a favorite is a harmless no-op. An empty tag is rejected.

func (*TieClient) UntaggedFiles

func (tie *TieClient) UntaggedFiles(scope string, offset, limit int) ([]TaggedFile, int, error)

UntaggedFiles returns items that carry a tie-type but no tag, i.e. files/dirs in the store that have never been tagged. scope names a single tie-type to browse (e.g. "audio-file", or a custom dir-type label); an empty scope browses the structural universes "file" and "directory", covering every imported file and directory. offset/limit paginate the untagged result; limit <= 0 means no limit. The second return is the total number of untagged items before pagination.

The "has no tag" filter runs server-side via QuerySpec.MissingRelation, so only untagged rows cross the wire (not the scope's full metadata). A single scope is paginated by the server; the empty-scope case unions the two structural types and paginates the merged result client-side.

func (*TieClient) Update

func (tc *TieClient) Update(update api.Update) (UpdateReply, error)

Update a triple in the collection

func (*TieClient) Upload

func (tc *TieClient) Upload(hostName, file string) (*UploadResult, error)

Upload stores file (or directory) on the named filehost and returns the resulting hashes. Pass an empty hostName to use the default filehost.

func (*TieClient) UploadWithOptions added in v0.5.2

func (tc *TieClient) UploadWithOptions(hostName, file string, opts UploadOptions) (*UploadResult, error)

UploadWithOptions behaves like Upload but applies opts, letting callers set retention and an owner token.

func (*TieClient) ValueTypes added in v0.5.2

func (tc *TieClient) ValueTypes() (map[string]ValueType, error)

ValueTypes returns every value type declared in the collection, keyed by relation. A collection with no declarations yields an empty map and a nil error, so callers need not distinguish "no registry" from "nothing declared". Relations declared with a type this client does not know are omitted rather than reported: an unknown type reads as a string, which is the default anyway.

This is one round trip for a whole collection's schema; fetch it once per collection and cache it rather than calling it per table or per row.

func (*TieClient) Verify

func (tie *TieClient) Verify(collection string, checkBlobs bool) (*VerifyReport, error)

Verify scans collection's virtual file tree and reports structural and metadata inconsistencies. An empty collection falls back to the configured default. When checkBlobs is true, every file's content hash is also stat'ed on each configured default filehost (HEAD request) and reported if absent — the slow part of the pass, so it is opt-in.

The pass is read-only. It fetches the full directory and file universes (unpaginated) and expands each node's forward attributes; memory is O(tree size), consistent with the rest of the client.

func (*TieClient) WriteFile

func (tc *TieClient) WriteFile(host FileHost, collection string, parent DirUID, name, srcPath string, extraTags []string) (string, error)

WriteFile uploads srcPath's bytes to host and places the content as name under directory parent, writing the standard file triples (filename, name, media-type, tie-type, filesize, tag-date, parent). It is the single write path shared by the FUSE mount's create/edit-save and by direct client callers (e.g. tie-fm copy-in).

If parent already holds a file named name with different content, the superseded version is recorded in the isolated "<Collection>_prev" history collection, keeping at most Config.PrevVersions of it (oldest dropped first) — the same reconciliation ImportDir performs, but scoped to this one file so other children of parent are never disturbed. When PrevVersions is 0 the old edge is removed outright (and the content garbage-collected if unreferenced).

The new content inherits the superseded version's tags and all other descriptive attributes (title/artist/album/year/track/…); only the fields recomputed from the new bytes (filename/name/filesize/tag-date/media-type/ tie-type) and the parent edge are set fresh. An unchanged re-save (identical bytes → identical hash) is a no-op. Returns the new content hash.

func (*TieClient) WriteFileWithProgress

func (tc *TieClient) WriteFileWithProgress(host FileHost, collection string, parent DirUID, name, srcPath string, extraTags []string, progress io.Writer) (string, error)

WriteFileWithProgress behaves exactly like WriteFile but, when progress is non-nil, writes each chunk of uploaded bytes to it so callers can render an upload progress bar. The total byte count equals srcPath's size.

type TieProperty

type TieProperty int
const (
	TieUid          TieProperty = iota // tie-uid
	TieFilename                        // filename
	TieFilesize                        // filesize
	TieName                            // name
	TieMediaType                       // media-type
	TieFileHost                        // filehost
	TieTag                             // tag
	TiePath                            // path
	TieParent                          // parent
	TieTags                            // tags
	TieTagDate                         // tag-date
	TieCollection                      // collection
	TieTypeProperty                    // tie-type
	TieAll                             // all
	TieTitle                           // title
	TieArtist                          // artist
	TieAlbum                           // album
	TieYear                            // year
	TieTrack                           // track
	TieTiedirHash                      // tiedir-hash
	TieDirUID                          // dir-uid
	TieVersionOf                       // version-of
	TieVersionDate                     // version-date
	TieFavorite                        // favorite
)

func (TieProperty) String

func (i TieProperty) String() string

type TieType

type TieType int
const (
	TieUnknownFile     TieType = iota // unknown-file
	TieImageFile                      // image-file
	TieAudioFile                      // audio-file
	TieVideoFile                      // video-file
	TieDocumentFile                   // document-file
	TieArchiveFile                    // archive-file
	TieImageDir                       // image-dir
	TieAudioDir                       // audio-dir
	TieVideoDir                       // video-dir
	TieDocumentDir                    // document-dir
	TieImageArchive                   // image-archive
	TieAudioArchive                   // audio-archive
	TieVideoArchive                   // video-archive
	TieDocumentArchive                // document-archive
	TieDirectory                      // directory
	TieFile                           // file
)

func ArchiveTieType

func ArchiveTieType(k archivelib.Kind) TieType

ArchiveTieType maps an archivelib member-kind to the archive tie-type stored on the blob. An unrecognized/mixed archive stays the generic archive-file.

func GetTieType

func GetTieType(file io.Reader) (TieType, error)

GetTieType classifies a file by sniffing its leading bytes. An empty or short file is a valid input — it simply classifies on whatever bytes exist (an empty file is unknown-file) — so io.EOF / io.ErrUnexpectedEOF from the read are not errors. Only a genuine read failure is returned. This mirrors archivelib's member sniffing, which uses the same 261-byte window.

func GetTieTypeFromPath

func GetTieTypeFromPath(path string) (TieType, error)

func SliceToTieType

func SliceToTieType(types []string) (t []TieType)

func StringToTieType

func StringToTieType(t string) TieType

func (TieType) String

func (i TieType) String() string

type Update

type Update = api.Update

type UpdateReply

type UpdateReply = *api.UpdateReply

type UploadOptions added in v0.5.2

type UploadOptions struct {
	// Retention is a Go duration (e.g. "72h") or "infinite". Empty means the
	// store's DefaultRetention applies, which may be finite — callers storing a
	// blob that a triple will keep referencing should pass "infinite" so the
	// filehost reaper cannot collect it out from under them.
	Retention string
	// OwnerToken, when non-empty, lets the uploader change the blob's retention
	// later. Only its hash is kept server-side.
	OwnerToken string
	// Progress, when non-nil, receives each chunk of uploaded bytes so callers
	// can render a progress bar. The total is the file (or manifest) size.
	Progress io.Writer
}

UploadOptions carries the optional upload knobs. The zero value uploads with the store's default retention and no owner token, matching UploadTo.

type UploadResult

type UploadResult struct {
	Items    []UploadedItem
	ErrorMsg string
}

UploadResult reports the outcome of an upload. It mirrors the transport-layer status with only FFI-friendly fields so bindings never touch putlib types.

func UploadTo

func UploadTo(host FileHost, file string) (*UploadResult, error)

UploadTo stores file (or directory) on an explicit filehost, bypassing config lookup. Useful for one-off targets (e.g. a raw --server address).

func UploadToWithOptions added in v0.5.2

func UploadToWithOptions(host FileHost, file string, opts UploadOptions) (*UploadResult, error)

UploadToWithOptions stores file (or directory) on an explicit filehost with full control over retention, owner token and progress reporting.

A nil error does not mean the upload succeeded: the filehost answers 200 even when its recomputed checksum disagrees with the client's (it drops the blob but still reports a hash), so callers must check UploadResult.ErrorMsg and each item's ErrorMsg.

func UploadToWithProgress

func UploadToWithProgress(host FileHost, file string, progress io.Writer) (*UploadResult, error)

UploadToWithProgress behaves like UploadTo but, when progress is non-nil, writes each chunk of uploaded bytes to it so callers can render a progress bar. The total byte count is the file (or manifest) size.

type UploadedItem

type UploadedItem struct {
	Hash      string
	Filename  string
	MediaType string
	Size      int
	ErrorMsg  string
}

UploadedItem is a single stored file.

type ValueType added in v0.5.2

type ValueType string

ValueType is a declared reading of the values under a relation. The set is closed; readers treat anything else as ValueTypeString so a collection written by a newer client stays readable.

const (
	// ValueTypeString is the default and need not be declared.
	ValueTypeString ValueType = "string"
	// ValueTypeInt is an optionally signed run of decimal digits (strconv.ParseInt).
	ValueTypeInt ValueType = "int"
	// ValueTypeFloat is a decimal number with "." as the point and no thousands
	// separators (strconv.ParseFloat, 64-bit).
	ValueTypeFloat ValueType = "float"
	// ValueTypeBool is "true" or "false", lower case.
	ValueTypeBool ValueType = "bool"
	// ValueTypeDate is YYYY-MM-DD.
	ValueTypeDate ValueType = "date"
	// ValueTypeDatetime is RFC3339.
	ValueTypeDatetime ValueType = "datetime"
)

func (ValueType) Valid added in v0.5.2

func (t ValueType) Valid() bool

Valid reports whether t is one of the declared types. ValueTypeString counts: it is a legal declaration even though it is also the default.

type VerifyReport

type VerifyReport struct {
	// OrphanDirs are directories with no parent edge (unreachable from root).
	OrphanDirs []DirUID
	// OrphanFiles are file content-hashes with no parent edge.
	OrphanFiles []string
	// DanglingParentRefs are (child, parentUID) edges whose parentUID no longer
	// exists as a directory — a half-deleted link.
	DanglingParentRefs []ParentRef
	// Cycles are parent-edge loops (a directory that is its own ancestor); each
	// entry is the loop's UID chain. Reported, never auto-repaired.
	Cycles [][]DirUID
	// DuplicatePaths maps a virtual path to the >1 DirUIDs that all claim it.
	// Reported, never auto-repaired (merging UIDs is a destructive decision).
	DuplicatePaths map[string][]DirUID
	// MissingMetadata are files lacking one of the core triples appendTagOps
	// always writes (filename, filesize, media-type, tie-type), or directories
	// lacking a name — a sign of an incomplete import.
	MissingMetadata []MetadataGap
	// MissingBlobs are file hashes whose content is absent from the filehost
	// (never uploaded, or reaped). Only populated when checkBlobs is set.
	MissingBlobs []string
	// Counts of the universes scanned, for the summary line.
	DirCount  int
	FileCount int
}

VerifyReport is the result of a Verify pass. Each slice holds the subjects (DirUIDs or content hashes) that failed one check; a healthy store returns all of them empty. The report is meant to be both printed for a human and consumed programmatically (e.g. by RepairOrphans).

func (*VerifyReport) Problems

func (r *VerifyReport) Problems() int

Problems reports whether any check failed (i.e. the store is not clean).

type VersionInfo

type VersionInfo struct {
	Hash     string
	Filename string
	Size     int
	TieType  TieType
	Date     time.Time
}

VersionInfo describes one superseded version of a file, read from the history collection. Date is the supersession time (when this content was replaced).

Jump to

Keyboard shortcuts

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