OXYGENHUB

oxy show lists modified files in its summary 0912a0337a95

The summary above a change's diff listed tree operations only, so a file
whose lines were edited appeared only further down, as its --- header,
and looked as if it had not been committed. Every edited file without a
tree operation now has an M line, and a rename shows its full new path.

closes #14
Author
Andy McCall @andymccall <[email protected]>
When
· 2026-09-28 23:06 UTC
Signature
✔ signed by Andy McCall
Hash
0912a0337a955864e1038da409ef794f111dd80f7fc7b050c989c74d588a4600
Depends on
75167672ebcd 982864068a59
Depended on by
nothing yet
In bookmarks
agents-in-readme 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.1.0 v0.10.0 v0.11.0 v0.2.0 v0.3.0 v0.3.1 v0.4.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, 2 files

Browse the tree at this change

modified crates/oxy-core/src/repo/snapshot.rs +19 −2
…
1821 unchanged lines
1822 1822
                ));
1823 1823
            }
1824 1824
            TreeOp::RemoveNode { node, .. } => out.push_str(&format!("D {}\n", path_of(node))),
1825 -
            TreeOp::Move { node, name, .. } => {
1826 -
                out.push_str(&format!("R {} -> {}\n", path_of(node), name))
1825 +
            TreeOp::Move {
1826 +
                node, parent, name, ..
1827 +
            } => {
1828 +
                let to = if parent.is_root() {
1829 +
                    name.clone()
1830 +
                } else {
1831 +
                    format!("{}/{name}", path_of(parent))
1832 +
                };
1833 +
                out.push_str(&format!("R {} -> {to}\n", path_of(node)))
1827 1834
            }
1828 1835
            TreeOp::SetMode { node, mode, .. } => {
1829 1836
                out.push_str(&format!(
…
3 unchanged lines
1833 1840
                    mode.opaque
1834 1841
                ));
1835 1842
            }
1843 +
        }
1844 +
    }
1845 +
    // Every other file the change edits is modified: the summary names
1846 +
    // every path it touches, not only those with a tree operation.
1847 +
    let with_op: HashSet<NodeId> = change.tree_ops.iter().map(|o| o.node()).collect();
1848 +
    let mut listed: HashSet<NodeId> = HashSet::new();
1849 +
    for e in &change.edits {
1850 +
        let n = e.node();
1851 +
        if !with_op.contains(&n) && listed.insert(n) {
1852 +
            out.push_str(&format!("M {}\n", path_of(&n)));
1836 1853
        }
1837 1854
    }
1838 1855
    let mut last_node: Option<NodeId> = None;
…
152 unchanged lines
modified crates/oxy-core/src/repo/tests.rs +6 −1
…
133 unchanged lines
134 134
    assert_eq!(log[2].hash, h1);
135 135
    let d = repo.describe_change(&h2).unwrap();
136 136
    assert!(d.contains("D README.md"), "{d}");
137 +
    assert!(
138 +
        d.lines()
139 +
            .any(|l| l.starts_with("M ") && l.ends_with("main.rs")),
140 +
        "a modified file is in the summary too: {d}"
141 +
    );
137 142
    assert!(d.contains("+    println!(\"hi\");"), "{d}");
138 143
    assert!(d.contains("-fn main() {}"), "{d}");
139 144
…
2522 unchanged lines
2662 2667
        &repo.load_state(&[h1]).unwrap(),
2663 2668
        &repo.load_state(&[h1]).unwrap().materialize()
2664 2669
    )
2665 -
    .contains("R "));
2670 +
    .contains("R src/old.rs -> lib/new.rs"));
2666 2671
    // A fresh checkout reproduces the tree.
2667 2672
    let other = tempfile::tempdir().unwrap();
2668 2673
    let clone = Repo::clone(&root.to_string_lossy(), other.path()).unwrap();
…
1202 unchanged lines