OXYGENHUB

Pin oxygen with the Linux-scale work; read change metadata alone df15b74774ca

oxygen 397d9f98: the working-copy lock, change skeletons in history-only
loads, metadata-only change reads, shared line buffers, faster graphs.
Nothing on the wire changes.

Where the hub only lists a change's message or dependencies (push
reports, the issue chain, file history's states, Flow's check that a
change is known) it now reads its metadata (Store::get_change_meta), and
where it needs only the nodes a change touches (a file's history, a
directory's newest changes) its skeleton: neither reads the change's
text.

closes #58
Author
Andy McCall @andymccall <[email protected]>
When
· 2026-09-30 00:05 UTC
Signature
✔ signed by Andy McCall
Hash
df15b74774ca5bc2a21596eef9d70be392e4517c948b8af98000f4ac48223d92
Depends on
18e381ea88c2 380996db84e5 38833ed78707 3d3d29fbcb00 42fa95540468 4f6925337848 6ae41081ccd3 9ff27da517fe b19606f28101 d23464c0ac60
Depended on by
7c36794d3630
In bookmarks
api-unknown-fields cancel-landed-runs clear-waiting close-proposal-140 diffusion-pin-bookmark draft-ready image-check job-waits main oh-comment-body-file proposal-list-fast run-one-job wiki-says-so
In tags
v0.1.0 v0.2.0 v0.3.0 v0.3.1 v0.4.0 v0.4.1 v0.4.2 v0.5.0 v0.5.1 v0.5.2 v0.6.0 v0.6.1 v0.7.0 v0.8.0 v0.9.0 v0.9.1 v0.9.11 v0.9.15 v0.9.16 v0.9.19 v0.9.2 v0.9.20 v0.9.21 v0.9.22 v0.9.23 v0.9.24 v0.9.3 v0.9.4 v0.9.5 v0.9.6 v0.9.7 v0.9.8 v0.9.9
Edits
12 atoms, 0 tree operations, 5 files

Browse the tree at this change

modified crates/hub/src/flow.rs +1 −1
…
72 unchanged lines
73 73
    }
74 74
    let h = ChangeHash::from_hex(change.trim().trim_start_matches('#')).ok_or("give the full hash of a change")?;
75 75
    let repo = RepoName::new(&row.owner, &row.name).ok_or("bad repository name")?;
76 -
    let known = app.repos.read(&repo, move |r, _| Ok(r.store().get_change(&h).is_ok())).await.map_err(|e| e.to_string())?;
76 +
    let known = app.repos.read(&repo, move |r, _| Ok(r.store().get_change_meta(&h).is_ok())).await.map_err(|e| e.to_string())?;
77 77
    if !known {
78 78
        return Err(format!("no change {} in this repository", &change.trim()[..12.min(change.trim().len())]));
79 79
    }
…
591 unchanged lines
modified crates/hub/src/protocol.rs +3 −1
…
199 unchanged lines
200 200
        } else {
201 201
            self.repos
202 202
                .open(&parsed)
203 -
                .map(|r| report.imported.iter().filter_map(|h| r.store().get_change(h).ok().map(|c| (h.to_hex(), c.message))).collect())
203 +
                .map(|r| {
204 +
                    report.imported.iter().filter_map(|h| r.store().get_change_meta(h).ok().map(|c| (h.to_hex(), c.message))).collect()
205 +
                })
204 206
                .unwrap_or_default()
205 207
        };
206 208
        let messages: Vec<(String, String)> = if bookmarks.contains(&row.default_bookmark) { imported.clone() } else { vec![] };
…
69 unchanged lines
modified crates/hub/src/repos/view.rs +5 −4
…
313 unchanged lines
314 314
                .state
315 315
                .changes()
316 316
                .filter(|(h, _)| {
317 +
                    // The skeleton says which nodes a change touches, without its text.
317 318
                    repo.store()
318 -
                        .get_change(h)
319 -
                        .map(|c| c.tree_ops.iter().any(|o| o.node() == node) || c.edits.iter().any(|x| x.node() == node))
319 +
                        .get_change_lazy(h)
320 +
                        .map(|(c, _)| c.tree_ops.iter().any(|o| o.node() == node) || c.edits.iter().any(|x| x.node() == node))
320 321
                        .unwrap_or(false)
321 322
                })
322 323
                .map(|(h, m)| (*h, m.clone()))
…
399 unchanged lines
722 723
    // Newest change touching each node, from one pass over the log.
723 724
    let mut newest: HashMap<oxy_core::ids::NodeId, (ChangeHash, u64)> = HashMap::new();
724 725
    for e in repo.log_of(state) {
725 -
        let Ok(c) = repo.store().get_change(&e.hash) else { continue };
726 +
        let Ok((c, _)) = repo.store().get_change_lazy(&e.hash) else { continue };
726 727
        let when = e.change.hlc.wall_ms;
727 728
        for node in c.tree_ops.iter().map(|o| o.node()).chain(c.edits.iter().map(|x| x.node())) {
728 729
            newest.entry(node).or_insert((e.hash, when));
…
41 unchanged lines
770 771
    let lines = blame_cached(repo, cache, &heads, path)?;
771 772
    let mut before = HashMap::new();
772 773
    for l in &lines {
773 -
        before.entry(l.hash).or_insert_with(|| repo.store().get_change(&l.hash).ok().and_then(|c| state_spec(&c.deps)));
774 +
        before.entry(l.hash).or_insert_with(|| repo.store().get_change_meta(&l.hash).ok().and_then(|c| state_spec(&c.deps)));
774 775
    }
775 776
    Ok(Blame { file, lines, before })
776 777
}
…
600 unchanged lines
modified crates/hub/src/web/chain.rs +1 −1
…
47 unchanged lines
48 48
                        .map(|hs| {
49 49
                            hs.iter()
50 50
                                .filter_map(|h| oxy_core::hash::ChangeHash::from_hex(h))
51 -
                                .filter_map(|h| r.store().get_change(&h).ok().map(|c| c.message))
51 +
                                .filter_map(|h| r.store().get_change_meta(&h).ok().map(|c| c.message))
52 52
                                .collect()
53 53
                        })
54 54
                        .collect())
…
20 unchanged lines
replaced deps/oxygenflow +0 −0

No line changes.