Skip to content

Commit 34afd73

Browse files
milesjclaude
andauthored
internal: Rename frozen lockfiles to immutable. (#1098)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 84860e5 commit 34afd73

10 files changed

Lines changed: 47 additions & 41 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
- Signature files may contain multiple binary signatures, multiple signatures in one armored block, or multiple concatenated armored blocks. Verification succeeds when any signature matches a trusted key.
3636
- GPG verification streams the artifact from disk in a blocking worker and records only the verified signer fingerprint and artifact SHA256 in lockfiles, instead of the armored public keyring.
3737
- **Lockfiles**
38-
- Added a `--frozen-lockfile` flag to `proto install` (and a `PROTO_FROZEN_LOCKFILE` environment variable) that treats the lockfile as read-only. Versions are resolved from existing lockfile records, and the lockfile is never created, updated, or pruned.
38+
- Added an `--immutable-lockfile` flag to `proto install` (and a `PROTO_IMMUTABLE_LOCKFILE` environment variable) that treats the lockfile as read-only. Versions are resolved from existing lockfile records, and the lockfile is never created, updated, or pruned.
3939
- If a tool being installed has no matching record, the install fails instead of resolving a fresh version, which is useful for reproducible installs in CI.
4040
- This flag cannot be combined with `--update-lockfile` or `--pin`.
4141
- Updated `proto pin` and `proto unpin` to always keep the lockfile of the modified config in sync, even when another config (like an environment config) takes precedence for the tool.

crates/cli/src/commands/install.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@ pub struct InstallArgs {
5050

5151
#[arg(
5252
long,
53-
env = "PROTO_FROZEN_LOCKFILE",
53+
env = "PROTO_IMMUTABLE_LOCKFILE",
5454
group = "lockfile-mode",
5555
conflicts_with = "pin",
5656
help = "Error if the lockfile is missing a record or would be modified"
5757
)]
58-
pub frozen_lockfile: bool,
58+
pub immutable_lockfile: bool,
5959

6060
#[arg(long, help = "Pin the resolved version to .prototools")]
6161
pub pin: Option<Option<PinLocation>>,
@@ -174,8 +174,8 @@ pub async fn install_one(
174174

175175
// Don't resolve the version from a lockfile
176176
spec.resolve_from_lockfile = !args.update_lockfile;
177-
spec.update_lockfile = !args.internal && !args.frozen_lockfile;
178-
spec.frozen = args.frozen_lockfile;
177+
spec.update_lockfile = !args.internal && !args.immutable_lockfile;
178+
spec.immutable = args.immutable_lockfile;
179179

180180
// Load config including global versions,
181181
// so that our requirements can be satisfied
@@ -225,9 +225,9 @@ pub async fn install_one(
225225
let outcome = result?;
226226
let tool = workflow.tool;
227227

228-
// Reconcile lockfiles by removing orphaned records, unless frozen, as
228+
// Reconcile lockfiles by removing orphaned records, unless immutable, as
229229
// pruning would modify the lockfile
230-
if !args.internal && !args.frozen_lockfile {
230+
if !args.internal && !args.immutable_lockfile {
231231
Locker::prune_orphaned_records(&session.env)?;
232232
}
233233

@@ -336,8 +336,8 @@ async fn install_all(session: ProtoSession, args: InstallArgs) -> SessionResult
336336

337337
let mut spec = version.clone();
338338
spec.resolve_from_lockfile = !args.update_lockfile;
339-
spec.update_lockfile = !args.internal && !args.frozen_lockfile;
340-
spec.frozen = args.frozen_lockfile;
339+
spec.update_lockfile = !args.internal && !args.immutable_lockfile;
340+
spec.immutable = args.immutable_lockfile;
341341

342342
let tool_context = tool.context.clone();
343343
let topo_graph = topo_graph.clone();
@@ -448,9 +448,9 @@ async fn install_all(session: ProtoSession, args: InstallArgs) -> SessionResult
448448

449449
workflow_manager.stop_rendering().await?;
450450

451-
// Reconcile lockfiles by removing orphaned records, unless frozen, as
451+
// Reconcile lockfiles by removing orphaned records, unless immutable, as
452452
// pruning would modify the lockfile
453-
if !args.internal && !args.frozen_lockfile {
453+
if !args.internal && !args.immutable_lockfile {
454454
Locker::prune_orphaned_records(&session.env)?;
455455
}
456456

crates/cli/src/commands/run.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ pub async fn run(session: ProtoSession, mut args: RunArgs) -> SessionResult {
446446
resolve_from_manifest: false,
447447
resolve_from_lockfile: false,
448448
update_lockfile: false,
449-
frozen: false,
449+
immutable: false,
450450
}),
451451
..Default::default()
452452
},

crates/cli/tests/install_all_lockfile_test.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ version = "4.5.15"
320320
);
321321
}
322322

323-
mod frozen {
323+
mod immutable {
324324
use super::*;
325325

326326
fn create_sandbox() -> ProtoSandbox {
@@ -379,7 +379,7 @@ version = "{version}"
379379

380380
sandbox
381381
.run_bin(|cmd| {
382-
cmd.arg("install").arg("--frozen-lockfile");
382+
cmd.arg("install").arg("--immutable-lockfile");
383383
})
384384
.success();
385385

@@ -398,7 +398,7 @@ version = "{version}"
398398
}
399399

400400
#[test]
401-
fn doesnt_prune_orphans_when_frozen() {
401+
fn doesnt_prune_orphans_when_immutable() {
402402
let sandbox = create_sandbox();
403403
sandbox.create_file(
404404
".protolock",
@@ -413,7 +413,7 @@ version = "{version}"
413413

414414
sandbox
415415
.run_bin(|cmd| {
416-
cmd.arg("install").arg("--frozen-lockfile");
416+
cmd.arg("install").arg("--immutable-lockfile");
417417
})
418418
.success();
419419

@@ -433,7 +433,7 @@ version = "{version}"
433433

434434
sandbox
435435
.run_bin(|cmd| {
436-
cmd.arg("install").arg("--frozen-lockfile");
436+
cmd.arg("install").arg("--immutable-lockfile");
437437
})
438438
.failure();
439439

crates/cli/tests/install_one_lockfile_test.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,7 @@ version = "1.0.0"
10261026
}
10271027
}
10281028

1029-
mod frozen {
1029+
mod immutable {
10301030
use super::*;
10311031

10321032
fn create_record(spec: &str, version: &str) -> String {
@@ -1053,7 +1053,7 @@ version = "{version}"
10531053
cmd.arg("install")
10541054
.arg("protostar")
10551055
.arg("5.0.0")
1056-
.arg("--frozen-lockfile");
1056+
.arg("--immutable-lockfile");
10571057
})
10581058
.success();
10591059

@@ -1076,13 +1076,13 @@ version = "{version}"
10761076
let sandbox = create_proto_sandbox("lockfile");
10771077
sandbox.create_file(".protolock", create_record("^5.10", "5.10.10"));
10781078

1079-
// 5.10.15 is the latest, but the frozen record pins 5.10.10
1079+
// 5.10.15 is the latest, but the immutable record pins 5.10.10
10801080
let assert = sandbox
10811081
.run_bin(|cmd| {
10821082
cmd.arg("install")
10831083
.arg("protostar")
10841084
.arg("^5.10")
1085-
.arg("--frozen-lockfile");
1085+
.arg("--immutable-lockfile");
10861086
})
10871087
.success();
10881088

@@ -1101,11 +1101,11 @@ version = "{version}"
11011101
cmd.arg("install")
11021102
.arg("protostar")
11031103
.arg("5.0.0")
1104-
.arg("--frozen-lockfile");
1104+
.arg("--immutable-lockfile");
11051105
})
11061106
.failure();
11071107

1108-
assert.stderr(predicate::str::contains("Lockfile is frozen"));
1108+
assert.stderr(predicate::str::contains("Lockfile is immutable"));
11091109

11101110
// Nothing was written to the lockfile
11111111
assert!(!sandbox.path().join(".protolock").exists());
@@ -1123,11 +1123,11 @@ version = "{version}"
11231123
cmd.arg("install")
11241124
.arg("protostar")
11251125
.arg("5.10.0")
1126-
.arg("--frozen-lockfile");
1126+
.arg("--immutable-lockfile");
11271127
})
11281128
.failure();
11291129

1130-
assert.stderr(predicate::str::contains("Lockfile is frozen"));
1130+
assert.stderr(predicate::str::contains("Lockfile is immutable"));
11311131

11321132
// And the existing record was left untouched
11331133
let lockfile = ProtoLock::load(sandbox.path().join(".protolock")).unwrap();
@@ -1146,7 +1146,7 @@ version = "{version}"
11461146
cmd.arg("install")
11471147
.arg("protostar")
11481148
.arg("5.0.0")
1149-
.arg("--frozen-lockfile")
1149+
.arg("--immutable-lockfile")
11501150
.arg("--update-lockfile");
11511151
})
11521152
.failure()
@@ -1162,7 +1162,7 @@ version = "{version}"
11621162
cmd.arg("install")
11631163
.arg("protostar")
11641164
.arg("5.0.0")
1165-
.arg("--frozen-lockfile")
1165+
.arg("--immutable-lockfile")
11661166
.arg("--pin");
11671167
})
11681168
.failure()

crates/cli/tests/plugins_test.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use starbase_utils::envx;
1212
use std::env;
1313
use std::fs;
1414
use std::path::PathBuf;
15+
use std::time::Duration;
1516

1617
fn create_empty_proto_sandbox_with_tools(ext: &str) -> ProtoSandbox {
1718
let sandbox = create_empty_proto_sandbox();
@@ -483,7 +484,12 @@ mod plugins {
483484

484485
sandbox
485486
.run_bin(|cmd| {
486-
cmd.arg("install").arg("swift");
487+
// The Swift archive is ~1GB; downloading, verifying, and
488+
// unpacking it can exceed the default sandbox timeout.
489+
// Keep this below nextest's 480s terminate threshold.
490+
cmd.arg("install")
491+
.arg("swift")
492+
.timeout(Duration::from_mins(7));
487493
})
488494
.success();
489495

crates/core/src/flow/lock.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ use version_spec::{UnresolvedVersionSpec, VersionSpec};
1414
// [x] validate lock record
1515
// [x] create lockfile if it does not exist
1616
// [x] error if spec/req is not found in lockfile
17-
// [x] frozen lockfiles
17+
// [x] immutable lockfiles
1818
// [x] orphan pruning
1919
// [x] install one
2020
// [x] resolve version from lockfile
2121
// [x] validate lock record
22-
// [x] frozen lockfiles
22+
// [x] immutable lockfiles
2323
// [x] orphan pruning
2424
// [x] install one version
2525
// [x] don't resolve version from lockfile
2626
// [x] validate lock record
27-
// [x] frozen lockfiles
27+
// [x] immutable lockfiles
2828
// [x] orphan pruning
2929
// [x] uninstall
3030
// [x] remove from lockfile

crates/core/src/flow/lock_error.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,15 @@ pub enum ProtoLockError {
4646
},
4747

4848
#[diagnostic(
49-
code(proto::install::frozen_lockfile),
50-
help = "Run `proto install` without `--frozen-lockfile` to populate the lockfile, then commit the changes."
49+
code(proto::install::immutable_lockfile),
50+
help = "Run `proto install` without `--immutable-lockfile` to populate the lockfile, then commit the changes."
5151
)]
5252
#[error(
53-
"Lockfile is frozen, but is missing a record for {} {}. The lockfile is either not enabled or out of date.",
53+
"Lockfile is immutable, but is missing a record for {} {}. The lockfile is either not enabled or out of date.",
5454
.tool.style(Style::Id),
5555
.spec.style(Style::Hash),
5656
)]
57-
FrozenMissingRecord { tool: String, spec: String },
57+
ImmutableMissingRecord { tool: String, spec: String },
5858

5959
#[diagnostic(code(proto::install::mismatched_arch))]
6060
#[error(

crates/core/src/flow/resolve.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,12 @@ impl<'tool> Resolver<'tool> {
145145
spec.version_locked = Some(record);
146146
candidate = version.to_unresolved_spec();
147147
}
148-
// When frozen, the lockfile is authoritative and must already
148+
// When immutable, the lockfile is authoritative and must already
149149
// contain a record for the requested specification. Resolving a
150150
// fresh version would require writing to the lockfile, so error
151151
// instead of silently falling through to remote resolution
152-
else if spec.frozen {
153-
return Err(ProtoLockError::FrozenMissingRecord {
152+
else if spec.immutable {
153+
return Err(ProtoLockError::ImmutableMissingRecord {
154154
tool: self.tool.get_name().to_owned(),
155155
spec: spec.req.to_string(),
156156
}

crates/core/src/tool_spec.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ pub struct ToolSpec {
2727
/// Update the lockfile when applicable?
2828
pub update_lockfile: bool,
2929

30-
/// Treat the lockfile as frozen (read-only)? When enabled, the version
30+
/// Treat the lockfile as immutable (read-only)? When enabled, the version
3131
/// must resolve from an existing lockfile record, and the lockfile is
3232
/// never created or modified. If a matching record does not exist, an
3333
/// error is raised instead of resolving a fresh version.
34-
pub frozen: bool,
34+
pub immutable: bool,
3535
}
3636

3737
impl ToolSpec {
@@ -90,7 +90,7 @@ impl Default for ToolSpec {
9090
resolve_from_lockfile: true,
9191
resolve_from_manifest: true,
9292
update_lockfile: true,
93-
frozen: false,
93+
immutable: false,
9494
}
9595
}
9696
}

0 commit comments

Comments
 (0)