Repository navigation
Record the units a layer carries, so a child can subtract them - #8
Merged
Merged
Conversation
A component can be handed to fab as a unit: a directory under the product's
UNIT_DIRS with a plan, an overlay, a conf script and a removelist. fab
resolves and applies it, and a layer built that way is the same layer, which
the Keel decision 0010 experiment measured. bt-layer did not know units
exist, and that is what stopped a component from moving out of the shared
tree.
A child layer works out what it has to do by subtracting what the parent
recorded. A unit appeared in no manifest field, so a child could not subtract
a component its parent had already applied, and would apply the overlay again
and re-run the conf script. conf/mysql does ln -s /etc/init.d/mysql under
bash -e and fails with "File exists" the second time, so the second layer of
a stack simply did not build. That is the LAMP case, not a distant one.
Two fields, alongside the two pairs that are already there:
units every component the finished layer carries as a unit, as
name@version sorted by name, or none
build_units the units this build applied: default without a parent, else
the difference, or none
units is cumulative: the parent's record merged with this build's own. The
common_* fields are cumulative too, but only because a child recipe includes
its parent's makefile fragments; here bt-layer keeps it so on purpose,
because a child that carries no database content of its own still sits on the
database and its own child has to know that.
A version comes from the first of three sources that answers: a version file,
the pin an assembly step writes; the unit's own git HEAD, but only when the
directory is the top of that work tree, so the commit of an enclosing product
repository is never passed off as the component's; otherwise a digest of the
directory's content, so a scratch or assembled unit still has an identity and
two different contents never record the same version.
A unit the parent applied at another version fails the build instead of being
applied. A conf script runs once, so there is no move from one version of a
component to another inside a child layer, and the parent is the thing to
rebuild. bt-layer also refuses a unit directory carrying none of the four
inputs, and one whose conf is not executable, which fab skips without a word.
The applied set is passed to fab as UNITS, the variable keel-linux/fab pull
request 4 added. A parent manifest written before these fields existed reads
as none through the new layer_manifest_opt, so older layers stay usable as
parents; keel reads a manifest by its required keys and round-trips the rest,
so the two fields need no change there.
tests/layer covers the ten new functions and six builds: a rootfs layer with
a unit, a child that composes the same unit, a child that adds one, a child
with none of its own, a version conflict and a conf fab would skip. Coverage
99 percent (layer-lib 331 of 332, bt-layer 110 of 111), gate 99.
This was referenced Sep 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prerequisite of Keel decision 0010: nothing migrates out of the shared tree until
bt-layerrecords units in the layer manifest.A component handed to fab as a unit (a directory under
UNIT_DIRSwith a plan, an overlay, a conf script and a removelist) appeared in no manifest field. A child layer computes what to apply by subtracting what the parent recorded, so it could not subtract the component and would re-apply the overlay and re-run the conf script.conf/mysqldoesln -s /etc/init.d/mysqlunderbash -eand fails with "File exists" the second time, so the second layer of the stack did not build at all. That is the LAMP case.The two fields
unitsname@versionsorted by name, ornonebuild_unitsdefaultwithout a parent, else the difference, ornoneunitsis cumulative, the parent's record merged with this build's own. Thecommon_*fields are cumulative too, but only because a child recipe includes its parent's makefile fragments; here it is kept so deliberately, because a child that carries no database content of its own still sits on the database and its own child has to know that.The subtraction rule
build_unitsis the recipe's own units minus the parent's, matched by name. Same name and same version means the parent already applied it, so it is skipped. Same name at a different version fails the build: a conf script runs once, so there is no move from one version of a component to another inside a child layer, and the parent is the thing to rebuild.Versions
The first of three sources that answers: a
versionfile (the pin an assembly step writes); the unit's own git HEAD, but only when the directory is the top of that work tree, so the commit of an enclosing product repository is never passed off as the component's; otherwise a digest of the directory content, so an assembled or scratch unit still has an identity.Compatibility
The applied set reaches fab as
UNITS, added in Keel-Linux/fab#4. A parent manifest written before these fields existed reads asnonethrough the newlayer_manifest_opt.keelvalidates a manifest by its required keys and round-trips the rest, so both fields passkeel verifyandkeel pulluntouched, and manifests without them still validate; checked againstkeel/layers/manifest.pyon this host.Test plan
tests/layer: ten new functions and six builds (a rootfs layer with a unit, a child composing the same unit, a child adding one, a child with none of its own, a version conflict, aconffab would skip, and a parent manifest older than the fields).tests/coverage.sh 99:bin/layer-lib331 of 332,bt-layer110 of 111, both 99 percent; the other four files 100 percent. Gate 99.keelloads, validates and byte-identically round-trips a manifest carrying both fields, and still validates one without them.