filesystem

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package filesystem provides virtual filesystem abstraction for TA archives.

Package filesystem provides a virtual filesystem that layers multiple archive formats (HPI, UFO, CCX, GP3) with physical files in a directory.

The VFS presents a unified view of files from multiple sources: - Archive files (.hpi, .ufo, .ccx, .gp3) - Physical files on disk

Files in archives are layered with higher-priority archives overriding lower-priority ones. Physical files always override archive files.

For multi-source layering (a base game, optional parent contexts and a writable work folder overlaid on top) see NewLayered in layered.go.

Example usage:

config := &filesystem.Config{
    Extensions: []string{".hpi", ".ccx", ".gp3", ".ufo"},
}
vfs, err := filesystem.NewVirtualFileSystem("/path/to/game", config)
if err != nil {
    log.Fatal(err)
}
defer func() { _ = vfs.Close() }()

// List all files
files := vfs.List()

// Open a file
reader, err := vfs.Open("units/ARMCOM.FBI")
if err != nil {
    log.Fatal(err)
}
defer func() { _ = reader.Close() }()

// Walk the filesystem
_ = vfs.Walk(func(path string, info FileInfo) error {
    fmt.Printf("%s (%d bytes)\n", path, info.Size)
    return nil
})

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Extensions specifies which archive extensions to load
	// Example: []string{".hpi", ".ufo", ".ccx", ".gp3"}
	// If empty, defaults to all supported formats
	Extensions []string

	// ExcludeDirectories is a list of directory names to ignore (case-insensitive)
	// Example: []string{"Docs", "Backup"}
	ExcludeDirectories []string

	// ExcludeExtensions is a list of file extensions to ignore (case-insensitive)
	// Example: []string{".dll", ".exe", ".ico"}
	ExcludeExtensions []string

	// ExcludePrefixes is a list of filename prefixes to ignore (case-insensitive)
	// Example: []string{"goggame", "temp_"}
	ExcludePrefixes []string

	// CaseSensitive controls path matching (default: false for TA compatibility)
	CaseSensitive bool

	// SkipErrors continues loading even if some archives fail
	SkipErrors bool
}

Config configures the virtual filesystem

type FileInfo

type FileInfo struct {
	Path   string // Virtual path (e.g., "units/ARMCOM.FBI")
	Size   int64  // File size in bytes
	Source string // Source (archive name or "disk")
	IsDir  bool   // True if this is a directory
}

FileInfo provides information about a virtual file

type FileLayer

type FileLayer struct {
	Source   string // Archive name or physical/overlay label
	Priority int    // Layer priority (lower = higher priority); assigned by GetFileLayers
	Size     int64  // File size in this layer
	// contains filtered or unexported fields
}

FileLayer represents a single layer containing a file

type FileSystem

type FileSystem interface {
	// Open opens a file for reading
	Open(path string) (io.ReadCloser, error)

	// ReadFile reads the entire contents of a file
	ReadFile(path string) ([]byte, error)

	// Exists checks if a file exists
	Exists(path string) bool

	// List returns all file paths in the filesystem
	List() []string

	// Close closes the filesystem and releases resources
	Close() error
}

FileSystem provides an abstraction for file operations

type MemoryFileSystem

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

MemoryFileSystem implements FileSystem for in-memory content (useful for testing)

func NewMemoryFileSystem

func NewMemoryFileSystem() *MemoryFileSystem

NewMemoryFileSystem creates an in-memory filesystem

func (*MemoryFileSystem) AddFile

func (mfs *MemoryFileSystem) AddFile(path string, content []byte)

AddFile adds a file to the in-memory filesystem

func (*MemoryFileSystem) Close

func (mfs *MemoryFileSystem) Close() error

Close closes any resources (no-op for memory filesystem)

func (*MemoryFileSystem) Exists

func (mfs *MemoryFileSystem) Exists(path string) bool

Exists checks if a file exists

func (*MemoryFileSystem) List

func (mfs *MemoryFileSystem) List() []string

List returns all file paths

func (*MemoryFileSystem) Open

func (mfs *MemoryFileSystem) Open(path string) (io.ReadCloser, error)

Open opens a file for reading

func (*MemoryFileSystem) ReadFile

func (mfs *MemoryFileSystem) ReadFile(path string) ([]byte, error)

ReadFile reads the entire file content

type PhysicalFileSystem

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

PhysicalFileSystem implements FileSystem for local disk access

func NewPhysicalFileSystem

func NewPhysicalFileSystem(basePath string) (*PhysicalFileSystem, error)

NewPhysicalFileSystem creates a filesystem that reads from a local directory

func (*PhysicalFileSystem) Close

func (pfs *PhysicalFileSystem) Close() error

Close closes any resources (no-op for physical filesystem)

func (*PhysicalFileSystem) Exists

func (pfs *PhysicalFileSystem) Exists(path string) bool

Exists checks if a file exists

func (*PhysicalFileSystem) List

func (pfs *PhysicalFileSystem) List() []string

List returns all file paths (recursively walks the directory)

func (*PhysicalFileSystem) Open

func (pfs *PhysicalFileSystem) Open(path string) (io.ReadCloser, error)

Open opens a file for reading

func (*PhysicalFileSystem) ReadFile

func (pfs *PhysicalFileSystem) ReadFile(path string) ([]byte, error)

ReadFile reads the entire file content

type Source

type Source struct {
	Kind SourceKind
	Path string

	// Writable marks this source as the writable overlay. At most one source
	// may be writable and it must be the top (highest-priority) layer and a
	// SourceLooseDir.
	Writable bool

	// Label overrides the FileLayer.Source label reported for this source. When
	// empty, a sensible default is chosen (the directory base name, or
	// "Physical Filesystem" for loose files inside a context directory).
	Label string
}

Source describes one layer in a VFS stack.

type SourceKind

type SourceKind int

SourceKind identifies how a layer source is loaded.

const (
	// SourceContextDir is a game-install directory: its archives are loaded in
	// extension priority order, then its loose physical files are overlaid.
	SourceContextDir SourceKind = iota
	// SourceArchive is a single archive file.
	SourceArchive
	// SourceLooseDir is a plain directory of loose files (no archives), such as
	// a workspace's writable work folder.
	SourceLooseDir
)

type VirtualFileSystem

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

VirtualFileSystem provides a layered view of archive and physical files.

Files are resolved through an ordered stack of sources (see NewLayered). Each file carries one FileLayer per source that contains it; the layer with the highest load sequence (the top-most source) is the active version.

func NewLayered

func NewLayered(sources []Source, config *Config) (*VirtualFileSystem, error)

NewLayered creates a virtual filesystem from an ordered stack of sources. sources[0] is the highest-priority (top) layer; later entries are lower priority. Files present in more than one source resolve to the top-most one.

A single writable SourceLooseDir may be supplied as sources[0] to make the VFS support copy-on-write edits (see WriteFile/EnsureLocal/Remove).

func NewVirtualFileSystem

func NewVirtualFileSystem(basePath string, config *Config) (*VirtualFileSystem, error)

NewVirtualFileSystem creates a read-only virtual filesystem over a single directory (its archives plus loose physical files). It is a thin wrapper over NewLayered for backward compatibility.

func (*VirtualFileSystem) Archives

func (vfs *VirtualFileSystem) Archives() []string

Archives returns information about loaded archives

func (*VirtualFileSystem) Close

func (vfs *VirtualFileSystem) Close() error

Close closes all open archives

func (*VirtualFileSystem) DirectoryStats

func (vfs *VirtualFileSystem) DirectoryStats(dirPath string) map[string]interface{}

DirectoryStats returns statistics for a specific directory

func (*VirtualFileSystem) EnsureLocal

func (vfs *VirtualFileSystem) EnsureLocal(path string) error

EnsureLocal guarantees that an existing file has a writable copy in the work folder (copy-on-write), so subsequent edits land in the overlay. It is a no-op if the file is already local, and errors if the file does not exist.

func (*VirtualFileSystem) Exists

func (vfs *VirtualFileSystem) Exists(path string) bool

Exists checks if a file or directory exists

func (*VirtualFileSystem) GetFileLayers

func (vfs *VirtualFileSystem) GetFileLayers(path string) []FileLayer

GetFileLayers returns all layers containing this file, ordered by priority (index 0 = highest priority = the active version).

func (*VirtualFileSystem) GetMD5

func (vfs *VirtualFileSystem) GetMD5(path string) (string, bool)

GetMD5 returns the MD5 hash for a file if it has been calculated Returns (hash, true) if available, ("", false) if not yet calculated

func (*VirtualFileSystem) IsDir

func (vfs *VirtualFileSystem) IsDir(path string) bool

IsDir checks if a path is a directory

func (*VirtualFileSystem) IsLocal

func (vfs *VirtualFileSystem) IsLocal(path string) bool

IsLocal reports whether a path is backed by the writable overlay layer (either net-new or an override of a base-layer file).

func (*VirtualFileSystem) List

func (vfs *VirtualFileSystem) List() []string

List returns all files in the VFS

func (*VirtualFileSystem) ListDir

func (vfs *VirtualFileSystem) ListDir(dir string) ([]string, error)

ListDir returns files in a specific directory

func (*VirtualFileSystem) LocalLayerInfo

func (vfs *VirtualFileSystem) LocalLayerInfo(path string) (hasLocal bool, layers int)

LocalLayerInfo reports whether the path has a copy in the writable layer (i.e. Remove would succeed) and how many layers carry it in total. A deletable file with more than one layer is an OVERRIDE — removing it reverts to the base version rather than erasing the path.

func (*VirtualFileSystem) Open

func (vfs *VirtualFileSystem) Open(path string) (io.ReadCloser, error)

Open opens a file for reading

func (*VirtualFileSystem) ReadFile

func (vfs *VirtualFileSystem) ReadFile(path string) ([]byte, error)

ReadFile reads an entire file into memory

func (*VirtualFileSystem) ReadFileFromSource

func (vfs *VirtualFileSystem) ReadFileFromSource(path, sourceName string) ([]byte, error)

ReadFileFromSource reads a file from a specific source layer. sourceName can be the physical/overlay label or an archive name like "totala1.hpi".

func (*VirtualFileSystem) RecursiveDirectoryStats

func (vfs *VirtualFileSystem) RecursiveDirectoryStats(dirPath string) map[string]interface{}

RecursiveDirectoryStats returns statistics for a directory and all subdirectories

func (*VirtualFileSystem) Remove

func (vfs *VirtualFileSystem) Remove(path string) error

Remove deletes a path from the writable overlay. Per the no-whiteout rule:

  • a net-new local file is removed entirely;
  • an override reverts to the underlying base version;
  • a file that exists only in a read-only base layer cannot be removed.

func (*VirtualFileSystem) SetMetricsCallback

func (vfs *VirtualFileSystem) SetMetricsCallback(callback func(bytes int64))

SetMetricsCallback sets a callback function for tracking bytes read

func (*VirtualFileSystem) ShouldExclude

func (vfs *VirtualFileSystem) ShouldExclude(filePath string, isDir bool) bool

ShouldExclude checks if a file/directory should be excluded based on config

func (*VirtualFileSystem) Stat

func (vfs *VirtualFileSystem) Stat(path string) (*FileInfo, error)

Stat returns information about a file

func (*VirtualFileSystem) Stats

func (vfs *VirtualFileSystem) Stats() map[string]interface{}

Stats returns statistics about the VFS

func (*VirtualFileSystem) Walk

func (vfs *VirtualFileSystem) Walk(fn func(path string, info *FileInfo) error) error

Walk walks the entire filesystem tree

func (*VirtualFileSystem) WriteFile

func (vfs *VirtualFileSystem) WriteFile(path string, data []byte) error

WriteFile writes data to the writable overlay layer, overriding any lower-layer version of the same path. It fails if the VFS is read-only.

type WritableFileSystem

type WritableFileSystem interface {
	FileSystem

	// WriteFile writes data to the writable overlay, overriding any lower-layer
	// version of the same path. Fails if the filesystem is read-only.
	WriteFile(path string, data []byte) error

	// Remove deletes a path from the writable overlay: a net-new local file is
	// removed, an override reverts to the base version, and a base-only file
	// cannot be removed.
	Remove(path string) error

	// EnsureLocal copies an existing file into the writable overlay so that
	// later edits are local (copy-on-write). No-op if already local.
	EnsureLocal(path string) error

	// IsLocal reports whether a path is backed by the writable overlay layer.
	IsLocal(path string) bool
}

WritableFileSystem is a FileSystem with a writable overlay layer, used by editing workspaces. Writes land in a local work folder layered on top of one or more read-only base layers (copy-on-write).

Jump to

Keyboard shortcuts

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