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

fingerprint

package
v0.7.1 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package fingerprint records the state a sync reconciled, so the next sync can tell whether anything changed.

New digests the state into a Fingerprint; Fingerprinter is the seam that generates, reads and writes one, with FileFingerprinter keeping the record in a file. The package knows nothing about projects: callers describe their state as Params.

Index

Examples

Constants

View Source
const FileName = ".gotools.fingerprint"

FileName is the record's file inside the directory a FileFingerprinter is built for.

Variables

View Source
var ErrNone = errors.New("no fingerprint recorded")

ErrNone is returned by Read when nothing has been written.

Functions

func FileDigest

func FileDigest(path string) (string, error)

FileDigest is the hex SHA-256 of the file at path.

Types

type File

type File struct {
	Path   string // where it is, as the caller names it
	Digest string // hex SHA-256 of its content
}

File is one file a fingerprint covers, by what it holds.

type FileFingerprinter

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

FileFingerprinter is the Fingerprinter that generates with New and keeps the record in one file.

func NewFile

func NewFile(dir string) FileFingerprinter

NewFile returns a Fingerprinter that records in FileName inside dir. It touches nothing until Write.

func (FileFingerprinter) Generate

func (FileFingerprinter) Generate(params Params) Fingerprint

Generate implements Fingerprinter.

func (FileFingerprinter) Read

func (f FileFingerprinter) Read() (Fingerprint, error)

Read implements Fingerprinter.

func (FileFingerprinter) Write

func (f FileFingerprinter) Write(fp Fingerprint) error

Write implements Fingerprinter. The record is written to a temporary file and renamed, so a reader never sees a partial one.

type Fingerprint

type Fingerprint struct {
	Digest       string // hex SHA-256 of the tool list and the files
	Strategy     string
	GoVersion    string
	ModulePrefix string
}

Fingerprint is a deterministic digest of Params. Any change to the state yields a different value. It is comparable: two fingerprints are equal when every field is.

func New

func New(params Params) Fingerprint

New digests params. The result does not depend on the order of params.Tools or params.Files.

func Parse

func Parse(s string) (Fingerprint, error)

Parse reads the form String writes.

Example

The recorded form is digest|strategy|go version|module prefix.

package main

import (
	"fmt"

	"github.com/piusalfred/gotools/internal/fingerprint"
)

func main() {
	f, err := fingerprint.Parse("abc123|split|1.27|github.com/acme/tools\n")

	fmt.Println(f.Strategy, f.GoVersion, f.ModulePrefix, err)
	fmt.Println(f)

}
Output:
split 1.27 github.com/acme/tools <nil>
abc123|split|1.27|github.com/acme/tools

func (Fingerprint) String

func (f Fingerprint) String() string

String is the recorded form: digest|strategy|go version|module prefix.

type Fingerprinter

type Fingerprinter interface {
	// Generate is the fingerprint of params. It is deterministic and does not
	// depend on the order of params.Tools.
	Generate(params Params) Fingerprint
	// Read is the fingerprint last written, or ErrNone. Any other error means
	// the record is unreadable or malformed; callers treat that as "does not
	// match".
	Read() (Fingerprint, error)
	// Write records f atomically.
	Write(f Fingerprint) error
}

Fingerprinter generates and records a fingerprint.

Example

A sync generates the fingerprint of the state it is about to reconcile and compares it with the recorded one. A match means nothing changed.

package main

import (
	"fmt"
	"os"

	"github.com/piusalfred/gotools/internal/fingerprint"
)

func main() {
	dir, _ := os.MkdirTemp("", "fingerprint-example")
	defer os.RemoveAll(dir)

	var fp fingerprint.Fingerprinter = fingerprint.NewFile(dir)

	params := fingerprint.Params{
		Tools:     []fingerprint.Tool{{Name: "gofumpt", Source: "go", Package: "mvdan.cc/gofumpt", Version: "v0.9.2"}},
		Strategy:  "split",
		GoVersion: "1.27",
	}

	_, err := fp.Read()
	fmt.Println("before the first sync:", err)

	// ... reconcile the tools, then record the state ...
	if err := fp.Write(fp.Generate(params)); err != nil {
		fmt.Println(err)
	}

	recorded, _ := fp.Read()
	fmt.Println("unchanged:", recorded == fp.Generate(params))

	params.Tools[0].Version = "v0.9.3"
	fmt.Println("after an upgrade:", recorded == fp.Generate(params))

}
Output:
before the first sync: no fingerprint recorded
unchanged: true
after an upgrade: false

type Params

type Params struct {
	Tools []Tool
	// Files are the files the state lives in. A change to one, or a file
	// added or removed, changes the fingerprint, so a hand edit is seen.
	Files        []File
	Strategy     string
	GoVersion    string
	ModulePrefix string
}

Params is what a fingerprint covers.

type Tool

type Tool struct {
	Name    string
	Source  string
	Package string
	Version string
}

Tool is one tool a fingerprint covers.

Jump to

Keyboard shortcuts

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