store: centralize Fruix path naming

This commit is contained in:
2026-04-05 08:58:40 +02:00
parent 9dae4e5c84
commit 4975084baa
5 changed files with 109 additions and 22 deletions

View File

@@ -197,6 +197,51 @@ So if you come from Guix, assume that Fruix now has:
- explicit generation metadata roots
- a real but still modest installed-system switch/rollback UX
## 7. Fruix keeps Guix-like store semantics, but not Guix/Nix hash-prefix machinery exactly
Fruix still uses immutable store paths under:
- `/frx/store`
and it still treats a store path as a deployment identity boundary.
But Fruix now intentionally differs from Guix/Nix in how the visible store-path prefix is constructed.
Current Fruix policy is:
- centralize store-path naming behind shared helpers
- hash a small semantic identity record rather than copying Nix's historical path-hash formula exactly
- include at least:
- object kind
- logical/display name
- output name
- payload or manifest identity
- hash-scheme version marker
- truncate the visible SHA-256 prefix to **160 bits**
- render that visible prefix as **40 hex characters**
Why Fruix does this instead of copying Guix/Nix exactly:
- the main goal was shorter store prefixes, not Nix compatibility for its own sake
- distinct outputs should have distinct identities because `out`, `lib`, `debug`, and `doc` are semantically different artifacts
- Fruix wanted one central policy point that can be swapped later without touching every materializer again
- Fruix did **not** want to inherit Nix's legacy details unless they provide clear value here
- custom base32 alphabet and bit ordering
- compressed/XOR-folded path hashes
- exact historical `output:out` / `source` path-hash conventions
So compared with Guix:
- the important semantic property is the same:
- different store objects should get different immutable identities
- the exact printable prefix algorithm is intentionally simpler in Fruix today
For Guix-familiar operators, the practical takeaway is:
- still think of `/frx/store/...` paths as immutable deployment identities
- do **not** assume Fruix store prefixes are byte-for-byte comparable to Guix/Nix ones
- expect Fruix to prefer a simpler, centralized naming policy unless exact Guix/Nix behavior becomes necessary later
## Where Fruix is intentionally trying to improve on Guix's representation
Fruix is not trying to improve on Guix's core semantics. Guix already got those right.

View File

@@ -364,11 +364,11 @@
(cached (hash-ref cache cache-key #f)))
(if cached
cached
(let* ((hash (sha256-string manifest))
(output-path (string-append store-dir "/" hash "-"
(freebsd-package-name prepared-package)
(let* ((display-name (string-append (freebsd-package-name prepared-package)
"-"
(freebsd-package-version prepared-package))))
(freebsd-package-version prepared-package)))
(output-path (make-store-path store-dir display-name manifest
#:kind 'freebsd-package)))
(unless (file-exists? output-path)
(case (freebsd-package-build-system prepared-package)
((copy-build-system)
@@ -454,8 +454,9 @@
(define* (materialize-prefix source-path name version store-dir #:key (extra-files '()))
(let* ((manifest (prefix-manifest-string source-path extra-files))
(hash (sha256-string manifest))
(output-path (string-append store-dir "/" hash "-" name "-" version)))
(display-name (string-append name "-" version))
(output-path (make-store-path store-dir display-name manifest
#:kind 'prefix)))
(unless (file-exists? output-path)
(mkdir-p output-path)
(for-each (lambda (entry)

View File

@@ -172,9 +172,10 @@
"\n")
"\nreferences=\n"
(string-join references "\n")))
(hash (sha256-string manifest))
(closure-path (string-append store-dir "/" hash "-fruix-system-"
(operating-system-host-name os))))
(display-name (string-append "fruix-system-"
(operating-system-host-name os)))
(closure-path (make-store-path store-dir display-name manifest
#:kind 'operating-system)))
(unless (file-exists? closure-path)
(mkdir-p closure-path)
(mkdir-p (string-append closure-path "/boot/kernel"))
@@ -870,9 +871,10 @@
"\nstore-items=\n"
(string-join store-items "\n")
"\n"))
(hash (sha256-string manifest))
(image-store-path (string-append store-dir "/" hash "-fruix-bhyve-image-"
(display-name (string-append "fruix-bhyve-image-"
(operating-system-host-name os)))
(image-store-path (make-store-path store-dir display-name manifest
#:kind 'bhyve-image))
(disk-image (string-append image-store-path "/disk.img"))
(esp-image (string-append image-store-path "/esp.img"))
(root-image (string-append image-store-path "/root.ufs")))
@@ -1024,9 +1026,10 @@
"\ninstall-metadata=\n"
(object->string install-metadata)
"\n"))
(hash (sha256-string manifest))
(image-store-path (string-append store-dir "/" hash "-fruix-installer-image-"
(display-name (string-append "fruix-installer-image-"
(operating-system-host-name installer-os)))
(image-store-path (make-store-path store-dir display-name manifest
#:kind 'installer-image))
(disk-image (string-append image-store-path "/disk.img"))
(esp-image (string-append image-store-path "/esp.img"))
(root-image (string-append image-store-path "/root.ufs")))
@@ -1329,9 +1332,10 @@
"\ninstall-metadata=\n"
(object->string install-metadata)
"\n"))
(hash (sha256-string manifest))
(iso-store-path (string-append store-dir "/" hash "-fruix-installer-iso-"
(display-name (string-append "fruix-installer-iso-"
(operating-system-host-name installer-os)))
(iso-store-path (make-store-path store-dir display-name manifest
#:kind 'installer-iso))
(iso-image (string-append iso-store-path "/installer.iso"))
(boot-efi-image (string-append iso-store-path "/efiboot.img"))
(root-image (string-append iso-store-path "/root.img")))

View File

@@ -150,9 +150,10 @@
(effective-source (assoc-ref resolution 'effective-source))
(identity (assoc-ref resolution 'identity))
(manifest (freebsd-source-manifest source effective-source identity))
(hash (sha256-string manifest))
(output-path (string-append store-dir "/" hash "-freebsd-source-"
(display-name (string-append "freebsd-source-"
(safe-name-fragment (freebsd-source-name source))))
(output-path (make-store-path store-dir display-name manifest
#:kind 'freebsd-source))
(info-file (string-append output-path "/.freebsd-source-info.scm"))
(cache-path (assoc-ref resolution 'cache-path))
(populate-tree (assoc-ref resolution 'populate-tree)))

View File

@@ -14,6 +14,8 @@
safe-command-output
write-file
sha256-string
store-hash-string
make-store-path
file-hash
directory-entries
path-signature
@@ -68,6 +70,40 @@
(write-file tmp text)
(command-output "sha256" "-q" tmp)))
(define store-hash-visible-length 40)
(define store-hash-scheme-version "1")
(define (store-identity-field value)
(cond ((symbol? value)
(symbol->string value))
((string? value)
value)
(else
(object->string value))))
(define* (store-hash-string payload #:key (kind 'item) name (output "out"))
(let* ((identity `((scheme . "fruix-store-path")
(version . ,store-hash-scheme-version)
(kind . ,(store-identity-field kind))
(name . ,(store-identity-field (or name "")))
(output . ,(store-identity-field output))
(payload . ,payload)))
(digest (sha256-string (object->string identity))))
(string-take digest store-hash-visible-length)))
(define* (make-store-path store-dir display-name payload
#:key
(kind 'item)
name
(output "out"))
(string-append store-dir "/"
(store-hash-string payload
#:kind kind
#:name (or name display-name)
#:output output)
"-"
display-name))
(define (file-hash path)
(command-output "sha256" "-q" path))