Rename host library to master throughout
The two libraries are now "master" and "slave" everywhere: UI text, API JSON fields (master_root, rel_master, master_size, ...), Go identifiers, database columns, quality verdicts, quarantine subfolders and docs. Existing databases are upgraded by a new migration that renames the columns in place and rewrites stored "host" values, so pairs, history, cached verdicts and restorable quarantine entries carry over. Network "host" usages (SplitHostPort, the Origin/Host check) are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d06b6d546d
commit
5b088bb4a6
19 files changed
+339
-326
No files matched your search
+55
-55
@@ -96,7 +96,7 @@ func (s *Store) PruneSessions(ctx context.Context) {
|
||||
type Pair struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
HostRoot string `json:"host_root"`
|
||||
MasterRoot string `json:"master_root"`
|
||||
SlaveRoot string `json:"slave_root"`
|
||||
QuarantineDir string `json:"quarantine_dir"`
|
||||
Extensions []string `json:"extensions"`
|
||||
@@ -110,7 +110,7 @@ type Pair struct {
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
|
||||
const pairCols = `id, name, host_root, slave_root, quarantine_dir, extensions, auto_link_identical,
|
||||
const pairCols = `id, name, master_root, slave_root, quarantine_dir, extensions, auto_link_identical,
|
||||
scan_interval_minutes, retention_days, settle_minutes, last_scan_at, last_scan_error, last_scan_warnings, created_at`
|
||||
|
||||
type scanner interface{ Scan(...any) error }
|
||||
@@ -119,7 +119,7 @@ func scanPair(r scanner) (Pair, error) {
|
||||
var p Pair
|
||||
var exts, warns string
|
||||
var last sql.NullInt64
|
||||
err := r.Scan(&p.ID, &p.Name, &p.HostRoot, &p.SlaveRoot, &p.QuarantineDir, &exts, &p.AutoLinkIdentical,
|
||||
err := r.Scan(&p.ID, &p.Name, &p.MasterRoot, &p.SlaveRoot, &p.QuarantineDir, &exts, &p.AutoLinkIdentical,
|
||||
&p.ScanIntervalMinutes, &p.RetentionDays, &p.SettleMinutes, &last, &p.LastScanError, &warns, &p.CreatedAt)
|
||||
if err != nil {
|
||||
return p, err
|
||||
@@ -163,10 +163,10 @@ func (s *Store) Pair(ctx context.Context, id int64) (Pair, error) {
|
||||
func (s *Store) SavePair(ctx context.Context, p *Pair) error {
|
||||
exts := strings.Join(p.Extensions, ",")
|
||||
if p.ID == 0 {
|
||||
res, err := s.DB.ExecContext(ctx, `INSERT INTO pairs (name, host_root, slave_root, quarantine_dir, extensions,
|
||||
res, err := s.DB.ExecContext(ctx, `INSERT INTO pairs (name, master_root, slave_root, quarantine_dir, extensions,
|
||||
auto_link_identical, scan_interval_minutes, retention_days, settle_minutes, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
p.Name, p.HostRoot, p.SlaveRoot, p.QuarantineDir, exts, p.AutoLinkIdentical,
|
||||
p.Name, p.MasterRoot, p.SlaveRoot, p.QuarantineDir, exts, p.AutoLinkIdentical,
|
||||
p.ScanIntervalMinutes, p.RetentionDays, p.SettleMinutes, now())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -174,10 +174,10 @@ func (s *Store) SavePair(ctx context.Context, p *Pair) error {
|
||||
p.ID, _ = res.LastInsertId()
|
||||
return nil
|
||||
}
|
||||
_, err := s.DB.ExecContext(ctx, `UPDATE pairs SET name = ?, host_root = ?, slave_root = ?, quarantine_dir = ?,
|
||||
_, err := s.DB.ExecContext(ctx, `UPDATE pairs SET name = ?, master_root = ?, slave_root = ?, quarantine_dir = ?,
|
||||
extensions = ?, auto_link_identical = ?, scan_interval_minutes = ?, retention_days = ?, settle_minutes = ?
|
||||
WHERE id = ?`,
|
||||
p.Name, p.HostRoot, p.SlaveRoot, p.QuarantineDir, exts, p.AutoLinkIdentical,
|
||||
p.Name, p.MasterRoot, p.SlaveRoot, p.QuarantineDir, exts, p.AutoLinkIdentical,
|
||||
p.ScanIntervalMinutes, p.RetentionDays, p.SettleMinutes, p.ID)
|
||||
return err
|
||||
}
|
||||
@@ -214,7 +214,7 @@ const (
|
||||
StatusError = "error" // cannot be linked (e.g. other filesystem)
|
||||
)
|
||||
|
||||
// Match kinds (how the host candidate was found).
|
||||
// Match kinds (how the master candidate was found).
|
||||
const (
|
||||
KindPath = "path" // identical relative path
|
||||
KindPathCase = "path_case" // relative path differs only by case
|
||||
@@ -225,36 +225,36 @@ const (
|
||||
)
|
||||
|
||||
type Match struct {
|
||||
ID int64 `json:"id"`
|
||||
PairID int64 `json:"pair_id"`
|
||||
RelSlave string `json:"rel_slave"`
|
||||
RelHost string `json:"rel_host"`
|
||||
Kind string `json:"kind"`
|
||||
Status string `json:"status"`
|
||||
HostIno uint64 `json:"-"`
|
||||
HostSize int64 `json:"host_size"`
|
||||
HostMtime int64 `json:"host_mtime"`
|
||||
SlaveIno uint64 `json:"-"`
|
||||
SlaveSize int64 `json:"slave_size"`
|
||||
SlaveMtime int64 `json:"slave_mtime"`
|
||||
HostProbe json.RawMessage `json:"host_probe,omitempty"`
|
||||
SlaveProbe json.RawMessage `json:"slave_probe,omitempty"`
|
||||
Verdict json.RawMessage `json:"verdict,omitempty"`
|
||||
Note string `json:"note"`
|
||||
Ignored bool `json:"ignored"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
ID int64 `json:"id"`
|
||||
PairID int64 `json:"pair_id"`
|
||||
RelSlave string `json:"rel_slave"`
|
||||
RelMaster string `json:"rel_master"`
|
||||
Kind string `json:"kind"`
|
||||
Status string `json:"status"`
|
||||
MasterIno uint64 `json:"-"`
|
||||
MasterSize int64 `json:"master_size"`
|
||||
MasterMtime int64 `json:"master_mtime"`
|
||||
SlaveIno uint64 `json:"-"`
|
||||
SlaveSize int64 `json:"slave_size"`
|
||||
SlaveMtime int64 `json:"slave_mtime"`
|
||||
MasterProbe json.RawMessage `json:"master_probe,omitempty"`
|
||||
SlaveProbe json.RawMessage `json:"slave_probe,omitempty"`
|
||||
Verdict json.RawMessage `json:"verdict,omitempty"`
|
||||
Note string `json:"note"`
|
||||
Ignored bool `json:"ignored"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
|
||||
const matchCols = `id, pair_id, rel_slave, rel_host, kind, status, host_ino, host_size, host_mtime,
|
||||
slave_ino, slave_size, slave_mtime, host_probe, slave_probe, verdict, note, ignored, updated_at`
|
||||
const matchCols = `id, pair_id, rel_slave, rel_master, kind, status, master_ino, master_size, master_mtime,
|
||||
slave_ino, slave_size, slave_mtime, master_probe, slave_probe, verdict, note, ignored, updated_at`
|
||||
|
||||
func scanMatch(r scanner) (Match, error) {
|
||||
var m Match
|
||||
var hp, sp, v string
|
||||
err := r.Scan(&m.ID, &m.PairID, &m.RelSlave, &m.RelHost, &m.Kind, &m.Status, &m.HostIno, &m.HostSize, &m.HostMtime,
|
||||
&m.SlaveIno, &m.SlaveSize, &m.SlaveMtime, &hp, &sp, &v, &m.Note, &m.Ignored, &m.UpdatedAt)
|
||||
if hp != "" {
|
||||
m.HostProbe = json.RawMessage(hp)
|
||||
var mp, sp, v string
|
||||
err := r.Scan(&m.ID, &m.PairID, &m.RelSlave, &m.RelMaster, &m.Kind, &m.Status, &m.MasterIno, &m.MasterSize, &m.MasterMtime,
|
||||
&m.SlaveIno, &m.SlaveSize, &m.SlaveMtime, &mp, &sp, &v, &m.Note, &m.Ignored, &m.UpdatedAt)
|
||||
if mp != "" {
|
||||
m.MasterProbe = json.RawMessage(mp)
|
||||
}
|
||||
if sp != "" {
|
||||
m.SlaveProbe = json.RawMessage(sp)
|
||||
@@ -321,7 +321,7 @@ func (s *Store) Matches(ctx context.Context, pairID int64, f MatchFilter) ([]Mat
|
||||
args = append(args, f.Status)
|
||||
}
|
||||
if f.Query != "" {
|
||||
where = append(where, "(rel_slave LIKE ? ESCAPE '\\' OR rel_host LIKE ? ESCAPE '\\')")
|
||||
where = append(where, "(rel_slave LIKE ? ESCAPE '\\' OR rel_master LIKE ? ESCAPE '\\')")
|
||||
q := "%" + strings.NewReplacer(`\`, `\\`, `%`, `\%`, `_`, `\_`).Replace(f.Query) + "%"
|
||||
args = append(args, q, q)
|
||||
}
|
||||
@@ -370,16 +370,16 @@ func (s *Store) IdenticalIDs(ctx context.Context, pairID int64) ([]int64, error)
|
||||
|
||||
func (s *Store) UpsertMatch(ctx context.Context, m *Match) error {
|
||||
nullable := func(r json.RawMessage) string { return string(r) }
|
||||
_, err := s.DB.ExecContext(ctx, `INSERT INTO matches (pair_id, rel_slave, rel_host, kind, status, host_ino, host_size,
|
||||
host_mtime, slave_ino, slave_size, slave_mtime, host_probe, slave_probe, verdict, note, ignored, updated_at)
|
||||
_, err := s.DB.ExecContext(ctx, `INSERT INTO matches (pair_id, rel_slave, rel_master, kind, status, master_ino, master_size,
|
||||
master_mtime, slave_ino, slave_size, slave_mtime, master_probe, slave_probe, verdict, note, ignored, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(pair_id, rel_slave) DO UPDATE SET rel_host = excluded.rel_host, kind = excluded.kind,
|
||||
status = excluded.status, host_ino = excluded.host_ino, host_size = excluded.host_size,
|
||||
host_mtime = excluded.host_mtime, slave_ino = excluded.slave_ino, slave_size = excluded.slave_size,
|
||||
slave_mtime = excluded.slave_mtime, host_probe = excluded.host_probe, slave_probe = excluded.slave_probe,
|
||||
ON CONFLICT(pair_id, rel_slave) DO UPDATE SET rel_master = excluded.rel_master, kind = excluded.kind,
|
||||
status = excluded.status, master_ino = excluded.master_ino, master_size = excluded.master_size,
|
||||
master_mtime = excluded.master_mtime, slave_ino = excluded.slave_ino, slave_size = excluded.slave_size,
|
||||
slave_mtime = excluded.slave_mtime, master_probe = excluded.master_probe, slave_probe = excluded.slave_probe,
|
||||
verdict = excluded.verdict, note = excluded.note, ignored = excluded.ignored, updated_at = excluded.updated_at`,
|
||||
m.PairID, m.RelSlave, m.RelHost, m.Kind, m.Status, m.HostIno, m.HostSize, m.HostMtime, m.SlaveIno, m.SlaveSize,
|
||||
m.SlaveMtime, nullable(m.HostProbe), nullable(m.SlaveProbe), nullable(m.Verdict), m.Note, m.Ignored, now())
|
||||
m.PairID, m.RelSlave, m.RelMaster, m.Kind, m.Status, m.MasterIno, m.MasterSize, m.MasterMtime, m.SlaveIno, m.SlaveSize,
|
||||
m.SlaveMtime, nullable(m.MasterProbe), nullable(m.SlaveProbe), nullable(m.Verdict), m.Note, m.Ignored, now())
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -409,12 +409,12 @@ func (s *Store) SetIgnored(ctx context.Context, id int64, ignored bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkedHostPaths returns host paths already linked into the slave under prefix.
|
||||
func (s *Store) LinkedHostPaths(ctx context.Context, pairID int64, prefix string) ([]string, error) {
|
||||
q := `SELECT rel_host FROM matches WHERE pair_id = ? AND status = 'linked'`
|
||||
// LinkedMasterPaths returns master paths already linked into the slave under prefix.
|
||||
func (s *Store) LinkedMasterPaths(ctx context.Context, pairID int64, prefix string) ([]string, error) {
|
||||
q := `SELECT rel_master FROM matches WHERE pair_id = ? AND status = 'linked'`
|
||||
args := []any{pairID}
|
||||
if prefix != "" {
|
||||
q += ` AND rel_host LIKE ? ESCAPE '\'`
|
||||
q += ` AND rel_master LIKE ? ESCAPE '\'`
|
||||
args = append(args, strings.NewReplacer(`\`, `\\`, `%`, `\%`, `_`, `\_`).Replace(prefix)+"/%")
|
||||
}
|
||||
rows, err := s.DB.QueryContext(ctx, q, args...)
|
||||
@@ -479,7 +479,7 @@ type Operation struct {
|
||||
ID int64 `json:"id"`
|
||||
PairID int64 `json:"pair_id"`
|
||||
Action string `json:"action"`
|
||||
RelHost string `json:"rel_host"`
|
||||
RelMaster string `json:"rel_master"`
|
||||
RelSlave string `json:"rel_slave"`
|
||||
RelNew string `json:"rel_new"`
|
||||
QuarantinePath string `json:"quarantine_path"`
|
||||
@@ -498,10 +498,10 @@ type Operation struct {
|
||||
|
||||
// Operation actions.
|
||||
const (
|
||||
ActLink = "link" // slave replaced by hardlink of host
|
||||
ActPromote = "promote" // host replaced by slave's file, then linked
|
||||
ActBuild = "build" // host file linked into the slave (fresh library)
|
||||
ActRemove = "remove" // slave hardlink removed (host copy kept)
|
||||
ActLink = "link" // slave replaced by hardlink of master
|
||||
ActPromote = "promote" // master replaced by slave's file, then linked
|
||||
ActBuild = "build" // master file linked into the slave (fresh library)
|
||||
ActRemove = "remove" // slave hardlink removed (master copy kept)
|
||||
)
|
||||
|
||||
// Operation statuses.
|
||||
@@ -513,13 +513,13 @@ const (
|
||||
OpInterrupted = "interrupted"
|
||||
)
|
||||
|
||||
const opCols = `id, pair_id, action, rel_host, rel_slave, rel_new, quarantine_path, quarantine_side, tmp_path, bytes,
|
||||
const opCols = `id, pair_id, action, rel_master, rel_slave, rel_new, quarantine_path, quarantine_side, tmp_path, bytes,
|
||||
dry_run, trigger, status, error, created_at, finished_at, undone_at, purged_at`
|
||||
|
||||
func scanOp(r scanner) (Operation, error) {
|
||||
var o Operation
|
||||
var fin, und, pur sql.NullInt64
|
||||
err := r.Scan(&o.ID, &o.PairID, &o.Action, &o.RelHost, &o.RelSlave, &o.RelNew, &o.QuarantinePath, &o.QuarantineSide,
|
||||
err := r.Scan(&o.ID, &o.PairID, &o.Action, &o.RelMaster, &o.RelSlave, &o.RelNew, &o.QuarantinePath, &o.QuarantineSide,
|
||||
&o.TmpPath, &o.Bytes, &o.DryRun, &o.Trigger, &o.Status, &o.Error, &o.CreatedAt, &fin, &und, &pur)
|
||||
if fin.Valid {
|
||||
o.FinishedAt = &fin.Int64
|
||||
@@ -535,10 +535,10 @@ func scanOp(r scanner) (Operation, error) {
|
||||
|
||||
func (s *Store) CreateOp(ctx context.Context, o *Operation) error {
|
||||
o.CreatedAt = now()
|
||||
res, err := s.DB.ExecContext(ctx, `INSERT INTO operations (pair_id, action, rel_host, rel_slave, rel_new, quarantine_path,
|
||||
res, err := s.DB.ExecContext(ctx, `INSERT INTO operations (pair_id, action, rel_master, rel_slave, rel_new, quarantine_path,
|
||||
quarantine_side, tmp_path, bytes, dry_run, trigger, status, error, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
o.PairID, o.Action, o.RelHost, o.RelSlave, o.RelNew, o.QuarantinePath, o.QuarantineSide, o.TmpPath, o.Bytes,
|
||||
o.PairID, o.Action, o.RelMaster, o.RelSlave, o.RelNew, o.QuarantinePath, o.QuarantineSide, o.TmpPath, o.Bytes,
|
||||
o.DryRun, o.Trigger, o.Status, o.Error, o.CreatedAt)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in new issue
Block a user