Help us shape the future of Go! Take the 2026 Go Developer Survey

lastgood

package
v0.1.2234 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package lastgood keeps the last good generation of magpie's own state files (accounts, sign-ins, providers, settings) and reads it back when the file itself can't be read.

A Windows machine that went down mid-write left logins.json and plugin-auth.json at their full length with every byte zero (#1505). magpie then read no accounts, and its next write made that final. Here a file that is there but not valid is unknown, never empty: before each write the file there now is kept as <file>.bak when it is valid, or copied aside as <file>.bad-<time> when it isn't, and a read of a file that isn't valid gives the .bak's contents instead, noted for the GUI and the log.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnreadable = errors.New("unreadable")

ErrUnreadable is a file that is there but neither it nor its .bak is valid: unknown, never empty.

Functions

func Bak

func Bak(path string) string

Bak is where path's last good generation is kept.

func Fallback

func Fallback(path string, bad []byte, valid Valid) ([]byte, error)

Fallback is Read for a caller that read path itself and found bad (its contents, or nil when only its parse said so): the .bak's contents when they are valid, noted, else an *UnreadableError.

func Into added in v0.1.1247

func Into[T any](b []byte) bool

Into is a file that unmarshals into a T: what a reader that takes any other file as empty can read. `[]` is valid JSON but not a map, so a reader of a map would see nothing in it.

func JSON

func JSON(b []byte) bool

JSON is a file that holds one JSON value: a file of zero bytes, empty or whitespace only, or cut short is not.

func Keep

func Keep(path string, valid Valid, perm fs.FileMode) error

Keep is called before path is replaced, under the lock its writer holds: the file there now, when valid, becomes the last good generation, path.bak, written to the disk before path is; one that isn't valid is copied aside (path.bad-<time>) and the .bak left as it is, so a file that can't be read is never written over before a copy of it is kept. A file not there needs neither. An error stops the write: the file there couldn't be read, or a bad one couldn't be kept.

func KeepBad

func KeepBad(path string, b []byte) (string, error)

KeepBad copies b, path's contents that aren't valid, aside as path.bad-<time> and gives that name. Two bad files within one second are both kept (.bad-<time>-2, …); the same bad bytes kept already, under any time, are not kept again.

func KeepUnparsed added in v0.1.1247

func KeepUnparsed(path string, parses Valid) error

KeepUnparsed is called before path is written over, by a writer whose reader takes a file that doesn't parse (parses false) as empty: such a file is copied aside (KeepBad) first, so the write of what was read as empty doesn't lose what it held. A file not there, or empty, needs nothing. An error stops the write: the file there couldn't be read, or couldn't be kept.

func Noted

func Noted(path, why string)

Noted records a recovery another process made (the plugin host's of plugin-auth.json).

func Read

func Read(path string, valid Valid) ([]byte, error)

Read gives path's contents when they are valid. A file there that isn't gives its .bak's contents, when that is valid, and the recovery is noted (Recovered). A file not there is fs.ErrNotExist, its .bak not looked at: a crash leaves a file renamed over as it was or as it became, never gone, so one gone was removed on purpose. Anything else is an *UnreadableError, or the error that stopped the read.

func Reset

func Reset()

Reset forgets the notes; for tests.

Types

type Note

type Note struct {
	File string    `json:"file"` // the file's name: logins.json
	Path string    `json:"path"`
	Why  string    `json:"why"` // what was wrong with it
	Bak  time.Time `json:"bak"` // when the .bak was written
	At   time.Time `json:"at"`
}

A Note is one file read back from its last good generation.

func Recovered

func Recovered() []Note

Recovered are the files read back from their last good generation since magpie started, for the GUI to tell the user.

type UnreadableError

type UnreadableError struct {
	Path string
	Err  error
}

UnreadableError says which file, and why it didn't read.

func (*UnreadableError) Error

func (e *UnreadableError) Error() string

func (*UnreadableError) Unwrap

func (e *UnreadableError) Unwrap() []error

type Valid

type Valid func(b []byte) bool

Valid is whether b is a good copy of a file's contents.

Jump to

Keyboard shortcuts

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