OXYGENHUB

Tests: browse's clones never see another test's OXY_TOKEN 19c71c828f86

private_repositories_and_push_tokens set OXY_TOKEN for the whole process
around one clone, and create_push_and_browse, running beside it, now and
then cloned with it: 'unknown token' (gate, 2026-10-16) and 'not unbound'
(Flow run 330's test-postgres). Every clone in browse.rs, and that
variable's setting, now hold one lock.

Closes #247
Author
Andy McCall @andymccall <[email protected]>
via
agent Claude Code <[email protected]> · delegate for changes, until 2026-11-13 19:00Z · key ea5f78160088
When
· 2026-10-17 01:20 UTC
Signature
✔ signed by Claude Code
Hash
19c71c828f86cc7dbcdd8d0c8d34d9f470b90a45d4bc384686498305b0f6b33e
Depends on
d23464c0ac60
Depended on by
nothing yet
In bookmarks
api-unknown-fields cancel-landed-runs diffusion-pin-bookmark draft-ready main oh-comment-body-file proposal-list-fast
In tags
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
6 atoms, 0 tree operations, 1 file

Browse the tree at this change

modified crates/hub/tests/browse.rs +19 −6
…
34 unchanged lines
35 35
    _dir: tempfile::TempDir,
36 36
}
37 37
38 +
/// Held by every clone here and while OXY_TOKEN is set: the variable is the
39 +
/// whole process's, and a clone in another test sent it (oxygenhub#247).
40 +
static ENV: std::sync::Mutex<()> = std::sync::Mutex::new(());
41 +
42 +
fn clone(url: &str, dir: &Path) -> Result<Repo, oxy_core::repo::RepoError> {
43 +
    let _env = ENV.lock().unwrap_or_else(|p| p.into_inner());
44 +
    Repo::clone(url, dir)
45 +
}
46 +
38 47
async fn hub(push_tokens: Vec<String>) -> Hub {
39 48
    hermetic();
40 49
    let dir = tempfile::tempdir().unwrap();
…
27 unchanged lines
68 77
    // The hosted repository is unbound until the first push, so it cannot
69 78
    // be cloned yet: start locally and push, as moving an existing
70 79
    // repository to the hub does.
71 -
    assert!(Repo::clone(url, &work.join("early")).err().unwrap().to_string().contains("unbound"));
80 +
    assert!(clone(url, &work.join("early")).err().unwrap().to_string().contains("unbound"));
72 81
    let mut client = Repo::init(work).unwrap();
73 82
    // A signing identity, so changes and the tag travel signed.
74 83
    client.create_identity("Test Author", "[email protected]", oxy_core::repo::IdentityScope::User).unwrap();
…
15 unchanged lines
90 99
    let results = client.push_bookmark("origin", "feature", false).unwrap();
91 100
    assert!(results.iter().all(|r| r.ok), "{results:?}");
92 101
    // Bound now: a clone shares the id.
93 -
    let clone = Repo::clone(url, &work.join("clone")).unwrap();
102 +
    let clone = clone(url, &work.join("clone")).unwrap();
94 103
    assert_eq!(clone.id().unwrap(), client.id().unwrap());
95 104
    (client, c1.to_hex(), c2.to_hex())
96 105
}
…
100 unchanged lines
197 206
    // The private one is invisible on pages and to anonymous clients.
198 207
    assert_eq!(get(&h.app, "/andy/priv").await.0, StatusCode::NOT_FOUND);
199 208
    assert!(!page(&h.app, "/").await.contains("priv"));
200 -
    assert!(Repo::clone(&format!("{}/andy/priv", h.base), &tempfile::tempdir().unwrap().path().join("x")).is_err());
209 +
    assert!(clone(&format!("{}/andy/priv", h.base), &tempfile::tempdir().unwrap().path().join("x")).is_err());
201 210
    // Anonymous push to the public one is refused; with the token it lands.
202 211
    let work = tempfile::tempdir().unwrap();
203 212
    let mut client = Repo::init(work.path()).unwrap();
…
6 unchanged lines
210 219
    assert!(client.push("origin", false).unwrap().iter().all(|r| r.ok));
211 220
    // With the token, the private repository can be cloned too.
212 221
    let priv_dir = tempfile::tempdir().unwrap();
213 -
    std::env::set_var("OXY_TOKEN", "s3cret");
214 -
    let ok = Repo::clone(&format!("{}/andy/priv", h.base), &priv_dir.path().join("p")).is_ok();
215 -
    std::env::remove_var("OXY_TOKEN");
222 +
    let ok = {
223 +
        let _env = ENV.lock().unwrap_or_else(|p| p.into_inner());
224 +
        std::env::set_var("OXY_TOKEN", "s3cret");
225 +
        let ok = Repo::clone(&format!("{}/andy/priv", h.base), &priv_dir.path().join("p")).is_ok();
226 +
        std::env::remove_var("OXY_TOKEN");
227 +
        ok
228 +
    };
216 229
    assert!(ok, "a token reads a private repository until accounts exist");
217 230
    // The pushes log shows the accepted update; the front page shows activity.
218 231
    tokio::time::sleep(std::time::Duration::from_millis(100)).await;
…
3 unchanged lines