deb: rework build sessions into immutable per-build records
The single mutable session per identity loses the last-good state: a failed run after a good one adopts the session in place and leaves only the failed state behind, so "continue from the last success" was impossible. Each build now records an immutable record under /var/tmp/pkh/sessions/<slug>/<id>/ (chroot, tree-upper, journal, manifest), and --incremental forks a NEW record — a full copy of the base's chroot and, at the same changelog version, its staged artifacts — under the base's flock, never mutating the base itself. Selection picks the newest successful record of the identity among the last five usable, falling back to the newest when none succeeded, and --incremental <id> pins an exact record (failed ones allowed: their environment may be fine). The lifecycle is strict keep-iff-incremental: plain runs build in a throwaway record discarded on success, failure and interrupt alike (the SIGINT cleanup hook follows the same policy), while --incremental records are always kept. Each identity keeps its newest five records; pkh prune's 7-day sweep and orphaned-lock cleanup follow the nested layout. --resume and --keep are removed (no aliases): their adoption-in-place and keep-on-success semantics are exactly what the record model replaces. pkh deb list shows id, outcome, tree version, fork lineage and age. README rewritten around the record workflow.
This commit is contained in:
+20
-26
@@ -365,25 +365,21 @@ fn main() {
|
||||
.long_help("Change build mode [local]\nDefault will chose depending on other parameters, don't provide if unsure"))
|
||||
.arg(arg!(-j --jobs <jobs> "Number of parallel build jobs (default: number of CPUs available in the build context)").required(false))
|
||||
.arg(
|
||||
clap::Arg::new("resume")
|
||||
.long("resume")
|
||||
clap::Arg::new("incremental")
|
||||
.long("incremental")
|
||||
.value_name("ID")
|
||||
.num_args(0..=1)
|
||||
.require_equals(false)
|
||||
.default_missing_value("")
|
||||
.help("Resume a previous build session: reuse the chroot, build dependencies and build artifacts")
|
||||
.long_help("Resume a previous build session of this tree: the prepared chroot and installed build dependencies are reused, and the build continues in the staged tree (make recompiles only what changed).\nWithout a value, the newest session of this tree is adopted; with an ID (as shown by 'pkh deb list'), that exact session.\nA plain build never reuses a session: everything is rechecked from scratch."),
|
||||
.help("Incremental build: fork a previous build record of this target and keep the result")
|
||||
.long_help("Incremental build: fork a previous build record of this target — its prepared chroot and installed build dependencies are copied into a new record, and at the same changelog version its build artifacts too (make recompiles only what changed).\nWithout a value, the newest successful record of the target (among the last five usable) is the base; with an ID (as shown by 'pkh deb list'), that exact record — a failed one is fine if its environment is.\nEvery --incremental run keeps its record, success or failure, so the next one can fork it; a plain 'pkh deb' is fully ephemeral (nothing is kept, even on failure or interrupt)."),
|
||||
)
|
||||
.arg(arg!(--keep "Keep the build session after a successful build (for a later --resume)")
|
||||
.long_help("Keep the build session after a successful build, so a later 'pkh deb --resume' can iterate on it (e.g. after editing sources).\nWithout it, a successful build consumes the session (failures and interrupts always keep it)."))
|
||||
.arg(arg!(--incremental "Reuse a previous build session of this target (like --resume) and keep the session even on success; the next --incremental build reuses the chroot, build deps and objects")
|
||||
.required(false))
|
||||
.arg(arg!(--verbose "Show raw tool output instead of the live build view").required(false)
|
||||
.long_help("Show raw tool output instead of the live build view.\nAlso implied by RUST_LOG=debug for pkh's own logs."))
|
||||
.subcommand(
|
||||
Command::new("list")
|
||||
.about("List the resumable build sessions recorded from this tree")
|
||||
.long_about("List the resumable build sessions recorded from this tree, one per target (series/arch), with the id to pass to 'pkh deb --resume <id>'.\nRead-only: never builds or removes anything ('pkh prune' removes old sessions)."),
|
||||
.about("List the build records recorded from this tree")
|
||||
.long_about("List the build records recorded from this tree, with their outcome, version, fork lineage and the id to pass to 'pkh deb --incremental <id>'.\nRead-only: never builds or removes anything (only the last five records per target are kept, 'pkh prune' removes the ones older than a week)."),
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
@@ -891,9 +887,8 @@ fn main() {
|
||||
Some(("deb", sub_matches)) => {
|
||||
let cwd = current_dir_or_exit();
|
||||
|
||||
// `pkh deb list`: read-only listing of the resumable build
|
||||
// sessions recorded from this tree; never touches the build
|
||||
// machinery.
|
||||
// `pkh deb list`: read-only listing of the build records
|
||||
// recorded from this tree; never touches the build machinery.
|
||||
if let Some(("list", _)) = sub_matches.subcommand() {
|
||||
let tree = cwd.canonicalize().unwrap_or(cwd.clone());
|
||||
let rows = pkh::deb::session::list_for_tree(&tree);
|
||||
@@ -939,18 +934,18 @@ fn main() {
|
||||
})
|
||||
});
|
||||
|
||||
// Session handling: --resume [<id>], --incremental and --keep
|
||||
// (see the deb subcommand help). --incremental adopts the newest
|
||||
// session when no explicit --resume ID is given, and always adds
|
||||
// keep so the session survives success.
|
||||
let incremental = sub_matches.get_flag("incremental");
|
||||
let resume = match sub_matches.get_one::<String>("resume").map(String::as_str) {
|
||||
Some("") => pkh::deb::SessionResume::Latest,
|
||||
Some(id) => pkh::deb::SessionResume::Id(id.to_string()),
|
||||
None if incremental => pkh::deb::SessionResume::Latest,
|
||||
None => pkh::deb::SessionResume::Fresh,
|
||||
// Incremental request: `--incremental` (no value) forks the
|
||||
// auto-selected base, `--incremental <id>` that exact record;
|
||||
// without the flag the run is fully ephemeral (see the deb
|
||||
// subcommand help).
|
||||
let incremental = match sub_matches
|
||||
.get_one::<String>("incremental")
|
||||
.map(String::as_str)
|
||||
{
|
||||
Some("") => pkh::deb::Incremental::Auto,
|
||||
Some(id) => pkh::deb::Incremental::Id(id.to_string()),
|
||||
None => pkh::deb::Incremental::Off,
|
||||
};
|
||||
let keep_session = sub_matches.get_flag("keep") || incremental;
|
||||
|
||||
// Live build view, unless --verbose (DebUi additionally disables
|
||||
// itself when stdout is not a terminal)
|
||||
@@ -976,8 +971,7 @@ fn main() {
|
||||
ppa,
|
||||
inject,
|
||||
jobs,
|
||||
resume,
|
||||
keep_session,
|
||||
incremental,
|
||||
view,
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user