Documentation
¶
Index ¶
- Constants
- Variables
- func AddRemapRule(ctx context.Context, db *sql.DB, q *dbq.Queries, itemID int64, ruleType string, ...) (position int64, err error)
- func CheckTargetCanBeDisabled(t dbq.Target, u TargetUsage) error
- func ClearRemapConfig(ctx context.Context, db *sql.DB, q *dbq.Queries, itemID int64) (cleared bool, err error)
- func CopyDeployRules(ctx context.Context, db *sql.DB, q *dbq.Queries, srcItemID, dstItemID int64) (skipBackup, writeOnce int, err error)
- func CopyRemapConfig(ctx context.Context, db *sql.DB, q *dbq.Queries, srcItemID, dstItemID int64) (copied int, err error)
- func CopySkipBackupPatterns(ctx context.Context, db *sql.DB, q *dbq.Queries, srcItemID, dstItemID int64) (copied int, err error)
- func CopyWriteOncePatterns(ctx context.Context, db *sql.DB, q *dbq.Queries, srcItemID, dstItemID int64) (copied int, err error)
- func CurrentSchemaVersion(ctx context.Context, db *sql.DB) (int64, error)
- func DSN(path string, readOnly bool) string
- func EnabledTargets(targets []dbq.Target) []dbq.Target
- func EnsureDBExists() error
- func EnsureRemapConfig(ctx context.Context, qtx *dbq.Queries, itemID int64) (int64, error)
- func EnsureTargetEnabled(t dbq.Target) error
- func FormatNotesLines(notes string) string
- func FullSelector(storeID, storeGameID, instanceID string) string
- func GooseProvider(db *sql.DB) (*goose.Provider, error)
- func IsBinaryContent(data []byte) bool
- func IsForeignKeyConstraint(err error) bool
- func IsTriggerConstraint(err error) bool
- func IsUniqueConstraint(err error) bool
- func LatestSchemaVersion() (int64, error)
- func MigrateDB(ctx context.Context, db *sql.DB) error
- func NormalizeStoreID(s string) string
- func NotesTextFromArg(arg string, stdin io.Reader) (string, error)
- func ParseInt64(s string) (int64, bool)
- func ParseSelector(s string) (storeID, storeGameID, instanceID string, err error)
- func ResolveEnabledProfileVersionArg(ctx context.Context, q *dbq.Queries, gi dbq.GameInstall, profile *dbq.Profile, ...) (int64, error)
- func ResolveModFileVersionArg(ctx context.Context, q *dbq.Queries, gi dbq.GameInstall, arg string) (dbq.GetModFileVersionByIDRow, error)
- func ResolveModPageArg(ctx context.Context, q *dbq.Queries, gi dbq.GameInstall, arg string) (dbq.GetModPageByIDForGameRow, error)
- func ResolveProfileItemByVersion(ctx context.Context, profile *dbq.Profile, q *dbq.Queries, versionID int64) (int64, error)
- func ResolveTarget(targets []dbq.Target, requested string) (dbq.Target, error)
- func RewriteProfilePriorities(ctx context.Context, qtx *dbq.Queries, profileID int64, ...) error
- func SetProfileItemEnabled(ctx context.Context, profile *dbq.Profile, q *dbq.Queries, versionID int64, ...) (changed bool, err error)
- func SetupDB() (*sql.DB, error)
- func SetupDBReadOnly() (*sql.DB, error)
- func ShortSelector(storeID, storeGameID, instanceID string) string
- func TargetEnabled(t dbq.Target) bool
- type RefreshChange
- type RefreshChangeKind
- type RefreshResult
- type SqliteStore
- type TargetUsage
Constants ¶
const DB_PRAGMAS = "?_foreign_keys=ON&_journal_mode=WAL&_synchronous=NORMAL"
DB_PRAGMAS are the connection parameters for a read-write database: foreign keys enforced, write-ahead logging and synchronous NORMAL. The driver runs each of them as a PRAGMA when a connection is opened.
const DB_PRAGMAS_READONLY = "?_foreign_keys=ON&mode=ro"
DB_PRAGMAS_READONLY are the connection parameters for a read-only database. There is deliberately no journal mode: a read-only connection can't change it, and asking for WAL on a database that is stored in rollback-journal mode fails with "attempt to write a readonly database". That is exactly how the databases inside an export are stored, since VACUUM INTO writes them that way.
const DefaultTargetName = "game_dir"
DefaultTargetName is the target used when a command isn't told which one to use.
Variables ¶
var Migrations embed.FS
Functions ¶
func AddRemapRule ¶
func AddRemapRule(ctx context.Context, db *sql.DB, q *dbq.Queries, itemID int64, ruleType string, intVal sql.NullInt64, textVal sql.NullString, overridePos int64) (position int64, err error)
AddRemapRule adds a single remap rule to the config for a profile item, creating the config if it does not exist yet. The position is auto-assigned as MAX(position)+1 unless overridePos is >= 0. It returns the position the rule was added at.
func CheckTargetCanBeDisabled ¶ added in v0.8.0
func CheckTargetCanBeDisabled(t dbq.Target, u TargetUsage) error
CheckTargetCanBeDisabled returns an error explaining why an enabled target can't be disabled: it still has installed files, profile items or overrides pointing at it, or it is the last enabled target.
func ClearRemapConfig ¶
func ClearRemapConfig(ctx context.Context, db *sql.DB, q *dbq.Queries, itemID int64) (cleared bool, err error)
ClearRemapConfig deletes all remap rules for a profile item's config and removes the config itself, leaving remap_config_id NULL on the profile item. No-op if the profile item has no remap config. It reports whether there was a config to clear.
func CopyDeployRules ¶ added in v0.6.0
func CopyDeployRules(ctx context.Context, db *sql.DB, q *dbq.Queries, srcItemID, dstItemID int64) (skipBackup, writeOnce int, err error)
CopyDeployRules copies skip-backup and write-once patterns from one profile item to another. If the destination already has patterns of either kind they are replaced. If the source has no patterns for a given kind that kind is a no-op. It returns the number of patterns copied for each kind.
func CopyRemapConfig ¶
func CopyRemapConfig(ctx context.Context, db *sql.DB, q *dbq.Queries, srcItemID, dstItemID int64) (copied int, err error)
CopyRemapConfig copies remap rules from one profile item to another within the same profile. If the destination already has a config its rules are replaced. If the source has no config this is a no-op. It returns the number of rules copied.
func CopySkipBackupPatterns ¶ added in v0.6.0
func CopySkipBackupPatterns(ctx context.Context, db *sql.DB, q *dbq.Queries, srcItemID, dstItemID int64) (copied int, err error)
CopySkipBackupPatterns copies skip-backup patterns from one profile item to another within the same profile. If the destination already has patterns they are replaced. If the source has no patterns this is a no-op. It returns the number of patterns copied.
func CopyWriteOncePatterns ¶ added in v0.6.0
func CopyWriteOncePatterns(ctx context.Context, db *sql.DB, q *dbq.Queries, srcItemID, dstItemID int64) (copied int, err error)
CopyWriteOncePatterns copies write-once patterns from one profile item to another within the same profile. If the destination already has patterns they are replaced. If the source has no patterns this is a no-op. It returns the number of patterns copied.
func CurrentSchemaVersion ¶ added in v0.8.0
CurrentSchemaVersion returns the version of the latest migration that has been applied to db. This is what the database itself is at, which is not necessarily the latest migration this build of modctl knows about: a new database reports 0 and one that has not been migrated since an upgrade reports its older version.
func DSN ¶ added in v0.8.0
DSN returns the connection string for the SQLite database at path, which every database open in modctl should use rather than building its own.
It is a file: URI with an escaped path. With a plain path the driver cuts the query string off before SQLite sees it, which silently drops mode=ro (the connection stays writable), and a path that contains a '?' is cut short at it. The read-only variant is described at DB_PRAGMAS_READONLY.
func EnabledTargets ¶ added in v0.8.0
EnabledTargets returns the enabled subset of targets, preserving order.
func EnsureDBExists ¶
func EnsureDBExists() error
EnsureDBExists verifies that the configured database file exists and is a regular file. If not, it returns a user-friendly error.
func EnsureRemapConfig ¶
EnsureRemapConfig returns the existing remap_config_id for a profile item, or creates a new one and links it to the profile item within the provided transaction if none exists yet.
func EnsureTargetEnabled ¶ added in v0.8.0
EnsureTargetEnabled returns an error if the target is disabled.
func FormatNotesLines ¶ added in v0.8.0
FormatNotesLines renders freeform notes for display under a "notes:" label. A single line stays on the label's line; multi-line notes start on the next line, indented, so they read as one block.
func FullSelector ¶
FullSelector always includes the instance (even if it's "default").
Example: steam:1091500#default
func IsBinaryContent ¶ added in v0.6.0
IsBinaryContent reports whether data appears to be binary by scanning for null bytes in the first 8KB, matching the heuristic used by Git and other tools.
func IsForeignKeyConstraint ¶ added in v0.8.0
IsForeignKeyConstraint reports whether err is SQLite complaining that a FOREIGN KEY constraint would have been violated: a row that refers to something that isn't there, or the deletion of something that is still referred to.
func IsTriggerConstraint ¶ added in v0.8.0
IsTriggerConstraint reports whether err is a trigger of ours stopping the statement with RAISE(ABORT, ...) and the like.
func IsUniqueConstraint ¶ added in v0.8.0
IsUniqueConstraint reports whether err is SQLite complaining that a UNIQUE constraint (or unique index) would have been violated. A PRIMARY KEY violation is a different error and is not matched.
func LatestSchemaVersion ¶ added in v0.8.0
LatestSchemaVersion returns the version of the latest migration known to this build of modctl: the highest version among the embedded migrations. It does not look at any database, so it is the version a database ends up at once it has been fully migrated, and what a bundle's schema version has to be compared against to tell whether this build can import it.
func NormalizeStoreID ¶ added in v0.8.0
NormalizeStoreID normalizes a store id the way store ids are stored and compared: trimmed and lowercased. Store ids are meant to be stable identifiers like "steam", so we normalize them to avoid surprising mismatches.
func NotesTextFromArg ¶ added in v0.8.0
NotesTextFromArg returns the notes text given as a command argument. If the argument is "-" the text is read from stdin instead. Trailing newlines are trimmed so that piped input doesn't store them; everything else, including interior newlines and surrounding spaces, is kept exactly as given.
func ParseInt64 ¶
func ParseSelector ¶
ParseSelector parses either: - store:game - store:game#instance
If instance is omitted, it returns instanceID="default".
func ResolveEnabledProfileVersionArg ¶ added in v0.7.1
func ResolveEnabledProfileVersionArg(ctx context.Context, q *dbq.Queries, gi dbq.GameInstall, profile *dbq.Profile, arg string) (int64, error)
ResolveEnabledProfileVersionArg resolves a mod file version argument for a command that acts on the enabled version of a mod in a profile (e.g., disable). It behaves like ResolveModFileVersionArg except that when the argument is a mod page name matching several versions, the candidates are narrowed to the versions that are enabled in the given profile:
- exactly one enabled version: that version is returned
- several enabled versions: an error listing only those is returned
- none enabled: resolution falls back to ResolveModFileVersionArg so the usual not-in-profile/already-disabled/ambiguity handling applies
func ResolveModFileVersionArg ¶
func ResolveModFileVersionArg(ctx context.Context, q *dbq.Queries, gi dbq.GameInstall, arg string) (dbq.GetModFileVersionByIDRow, error)
ResolveModFileVersionArg resolves a mod file version argument for the given game install. Accepts:
- a numeric ID (fast path, unambiguous)
- a mod page name (case-insensitive; errors if ambiguous, listing all candidates with their numeric IDs)
func ResolveModPageArg ¶
func ResolveModPageArg(ctx context.Context, q *dbq.Queries, gi dbq.GameInstall, arg string) (dbq.GetModPageByIDForGameRow, error)
ResolveModPageArg resolves a mod page argument for the given game install. Accepts:
- a numeric ID (fast path, unambiguous)
- a mod page name (case-insensitive; errors if ambiguous, listing all candidates with their numeric IDs)
func ResolveProfileItemByVersion ¶
func ResolveProfileItemByVersion(ctx context.Context, profile *dbq.Profile, q *dbq.Queries, versionID int64) (int64, error)
ResolveProfileItemByVersion looks up a profile item by mod file version ID within a profile, returning a clean error if the version is not in the profile.
func ResolveTarget ¶ added in v0.8.0
ResolveTarget picks the install target for a command from the targets of a game install. A requested name must exist and be enabled. With no name the default target (game_dir) is used if it is enabled; if it isn't, the only enabled target is used, and it is an error to have to guess between several.
func RewriteProfilePriorities ¶
func RewriteProfilePriorities( ctx context.Context, qtx *dbq.Queries, profileID int64, items []dbq.ListProfileItemsForOrderRow, start, step int64, ) error
RewriteProfilePriorities rewrites priorities for the given ordered items.
It is safe under UNIQUE(profile_id, priority) because it first shifts all existing priorities out of the way by an offset, then assigns final values.
start is the first priority value to assign (for compact: 1). step is the increment between consecutive priorities (for compact: 1; for --multiple N: N).
func SetProfileItemEnabled ¶
func SetProfileItemEnabled(ctx context.Context, profile *dbq.Profile, q *dbq.Queries, versionID int64, enabled bool) (changed bool, err error)
SetProfileItemEnabled enables or disables the profile item for a mod file version. It reports whether anything changed: false means the item was already in the requested state.
func SetupDBReadOnly ¶
func ShortSelector ¶
ShortSelector includes the instance only if it isn't "default".
Example: steam:1091500 Example: steam:1091500#library_2
func TargetEnabled ¶ added in v0.8.0
TargetEnabled reports whether the target takes part in planning.
Types ¶
type RefreshChange ¶ added in v0.8.0
type RefreshChange struct {
Name string
Kind RefreshChangeKind
}
RefreshChange is what a refresh found out about one install.
type RefreshChangeKind ¶ added in v0.8.0
type RefreshChangeKind int
RefreshChangeKind says what a refresh found out about an install.
const ( RefreshNew RefreshChangeKind = iota // seen for the first time RefreshReturned // was missing and has come back RefreshUpdated // seen again, as before RefreshMissing // was present and has gone )
type RefreshResult ¶ added in v0.2.0
type RefreshResult struct {
New []string // display names of newly discovered installs
Updated []string // display names of installs seen again (already present)
Returned []string // display names of installs that were missing and came back
Missing []string // display names of installs that disappeared
Skipped []string // display names of installs that were filtered out
// Warnings are the non-fatal problems found along the way, in the order
// they were found.
Warnings []string
// Changes is what happened to each install, in the order to show them:
// the installs that disappeared first, then the ones that were found.
Changes []RefreshChange
}
func ScanStores ¶
ScanStores rescans every enabled store and updates the game installs in the database. It prints nothing: what it found is in the result. If it fails part way, the result still holds the warnings found up to then.
type SqliteStore ¶ added in v0.2.0
A custom goose store to let us override the schema migrations table to use more idiomatic sqlite
func (*SqliteStore) CreateVersionTable ¶ added in v0.2.0
type TargetUsage ¶ added in v0.8.0
type TargetUsage struct {
InstalledFiles int64 // files recorded as installed through the target
ProfileItems int64 // profile items deploying to the target
Overrides int64 // overrides defined for the target
EnabledTargets int64 // enabled targets for the game install, counting this one
}
TargetUsage describes what still depends on a target.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package extractor handles extraction of mod archives to a staging directory and deployment of files into the game target directory.
|
Package extractor handles extraction of mod archives to a staging directory and deployment of files into the game target directory. |
|
Package lock provides per-game-install exclusive locking for apply and unapply operations.
|
Package lock provides per-game-install exclusive locking for apply and unapply operations. |
|
Package patchapply applies structured patch entries to ini, yaml, and json files.
|
Package patchapply applies structured patch entries to ini, yaml, and json files. |
|
Package planner computes the desired file state for a profile apply or unapply.
|
Package planner computes the desired file state for a profile apply or unapply. |
|
Package remap implements the remap rule engine for modctl.
|
Package remap implements the remap rule engine for modctl. |
|
Package style holds how modctl looks in a terminal, so that no command formats its own output:
|
Package style holds how modctl looks in a terminal, so that no command formats its own output: |
|
Package updatechain works out where a file stands against the updates that Nexus Mods knows about for its mod: whether something newer has replaced it, and whether that newer file has already been imported.
|
Package updatechain works out where a file stands against the updates that Nexus Mods knows about for its mod: whether something newer has replaced it, and whether that newer file has already been imported. |