cat: say -r CHANGE reads the change's dependency closure b0a0c9afae2d
oxy cat -r CHANGE reads the change and what it depends on, not the
bookmark it is on, so a file only later changes touched is absent or
older. --help says so, and a file missing there but on the bookmark now
gets an error naming the closure and suggesting -r BOOKMARK or --at-op.
closes #76
Author Andy McCall @andymccall <[email protected] >
When 1 month ago · 2026-10-05 18:24 UTC
Signature ✔ signed by Andy McCall
Hash b0a0c9afae2d5c2af470c2ce8a932d5e7438b2416e7bcc929214d0c873f17938
Depends on c6aa5bd9d1c8 ee06a6c557b7 fce44ae9ad29
Depended on by nothing yet
In bookmarks bare-hashes carried-not-removed carry-identical doctor-trust identical-sides keyless-tags main merge-remote-bookmark only-help-103 paths-for-resolutions-and-amend push-notes show-stat subrepo-pin-state switch-says
In tags v0.10.0 v0.11.0 v0.4.1 v0.4.2 v0.4.3 v0.4.4 v0.4.5 v0.4.6 v0.5.0 v0.5.1 v0.6.0 v0.7.0 v0.8.0 v0.9.0
Edits 6 atoms, 0 tree operations, 3 files
Browse the tree at this change
docs/guide.md src/cli/mod.rs src/cli/workspace.rs
modified
docs/guide.md
+4 −2
…
411 unchanged lines
412
412
`diff`, `hunks`, `blame`, `resolve`, `op log`, `bookmark list`, `remote list`,
413
413
`fetch`, `pull`, `push`, `submodule status`, `bisect status`, `verify`,
414
414
`policy show`, `root`, `version`). `oxy cat PATH -r CHANGE` prints a file as
415
-
it was, `oxy discard PATH..` restores files to the base, and `oxy hunks`
416
-
numbers the working copy's hunks for `commit --hunks` and `discard --hunks`.
415
+
it was in that change's dependency closure ( the change and what it depends
416
+
on; `-r BOOKMARK` or a tag reads the whole state), `oxy discard PATH..`
417
+
restores files to the base, and `oxy hunks` numbers the working copy's hunks
418
+
for `commit --hunks` and `discard --hunks`.
417
419
418
420
## 18. If something looks wrong
419
421
…
10 unchanged lines
modified
src/cli/mod.rs
+3 −1
…
130 unchanged lines
131
131
/// Print a file as it is in a state (default: the working copy's base)
132
132
Cat {
133
133
path: String,
134
-
/// A change, bookmark, or tag
134
+
/// A bookmark or tag (its state), or a change: a change means its
135
+
/// dependency closure, the change and what it depends on, so files
136
+
/// only later changes touched are absent or at older versions
135
137
#[arg(short = 'r', long)]
136
138
change: Option<String>,
137
139
},
…
547 unchanged lines
modified
src/cli/workspace.rs
+21 −1
…
415 unchanged lines
416
416
pub fn cat(path: &str, change: Option<&str>) -> Result<i32> {
417
417
let repo = open()?;
418
418
let heads = change.map(|c| repo.resolve_heads(c)).transpose()?;
419
-
let bytes = repo.file_at(path, heads.as_deref())?;
419
+
let bytes = match repo.file_at(path, heads.as_deref()) {
420
+
Ok(b) => b,
421
+
// -r CHANGE reads that change's dependency closure, not the
422
+
// bookmark it is on: say so when the bookmark has the file
423
+
// (oxygen#76).
424
+
Err(e) => match change {
425
+
Some(c)
426
+
if !repo.view()?.bookmarks.contains_key(c)
427
+
&& repo.tag_heads(c)?.is_none()
428
+
&& repo.file_at(path, None).is_ok() =>
429
+
{
430
+
anyhow::bail!(
431
+
"{path} is not in {c}'s dependency closure (the change and what it \
432
+
depends on); it is on the bookmark: try -r {}, or --at-op OP for the \
433
+
state at an operation",
434
+
repo.config.bookmark
435
+
)
436
+
}
437
+
_ => return Err(e.into()),
438
+
},
439
+
};
420
440
use std::io::Write as _;
421
441
std::io::stdout().write_all(&bytes)?;
422
442
Ok(0)
…
549 unchanged lines