git-ents.gitmain
⌘K
foforge
worktree_update.rs101 lines · 4.0 KB · rusthistorycomment on this file
1//! `roots.worktree-update`: `git ents setup` sets
2//! `receive.denyCurrentBranch=updateInstead` on the local repository, so
3//! the integration-test-harness case — an external push landing on this
4//! repository's own checked-out branch — also updates the working tree,
5//! rather than the ordinary git behavior of refusing such a push outright.
6
7#![allow(clippy::expect_used, reason = "integration test")]
8
9mod common;
10
11use std::path::Path;
12use std::process::Command;
13
14use git_ents::commands;
15use git_ents::root::LocalRoot;
16
17fn git(dir: &Path, args: &[&str]) -> std::process::Output {
18 Command::new("git")
19 .arg("-C")
20 .arg(dir)
21 .args(args)
22 .env("GIT_AUTHOR_NAME", "test")
23 .env("GIT_AUTHOR_EMAIL", "test@ents.test")
24 .env("GIT_COMMITTER_NAME", "test")
25 .env("GIT_COMMITTER_EMAIL", "test@ents.test")
26 .env("GIT_CONFIG_GLOBAL", "/dev/null")
27 .env("GIT_CONFIG_SYSTEM", "/dev/null")
28 .env_remove("HOME")
29 .output()
30 .expect("git runs")
31}
32
33/// After `git ents setup`, an external push into this repository's own
34/// checked-out branch both succeeds and updates the working tree —
35/// `receive.denyCurrentBranch=updateInstead` in effect
36/// (`roots.worktree-update`).
37// @relation(roots.worktree-update, scope=function, role=Verifies)
38#[test]
39fn setup_lets_a_harness_push_update_the_checked_out_branch() {
40 let origin_dir = tempfile::tempdir().expect("tempdir");
41 let init = git(origin_dir.path(), &["init", "-q", "-b", "main"]);
42 assert!(init.status.success(), "{init:?}");
43 std::fs::write(origin_dir.path().join("file.txt"), "before\n").expect("write");
44 let add = git(origin_dir.path(), &["add", "-A"]);
45 assert!(add.status.success());
46 let commit = git(origin_dir.path(), &["commit", "-q", "-m", "before"]);
47 assert!(commit.status.success(), "{commit:?}");
48
49 // `git ents setup` is what this test exercises: it must record
50 // `receive.denyCurrentBranch=updateInstead` on `origin_dir`'s own
51 // config. An explicit `--key` sidesteps `resolve_key_path`'s
52 // ambient-fallback resolution (`user.signingkey`, `~/.ssh/id_ed25519`)
53 // entirely, keeping this test isolated from whatever the machine
54 // running it happens to have configured globally, without mutating
55 // process environment (`unsafe_code` is workspace-forbidden even in
56 // tests).
57 let key_path = common::write_key_in(origin_dir.path(), 30);
58 let root = LocalRoot::open(origin_dir.path()).expect("opens");
59 commands::setup::run(&root, Some(key_path)).expect("configures the repo");
60
61 let config = git(origin_dir.path(), &["config", "receive.denyCurrentBranch"]);
62 assert_eq!(
63 String::from_utf8_lossy(&config.stdout).trim(),
64 "updateInstead",
65 "{config:?}"
66 );
67
68 // An external clone pushes a change directly onto `main` — the
69 // integration-test-harness case `roots.worktree-update` names.
70 let clone_dir = tempfile::tempdir().expect("tempdir");
71 let clone = git(
72 clone_dir.path(),
73 &[
74 "clone",
75 "--quiet",
76 origin_dir.path().to_str().expect("utf8"),
77 ".",
78 ],
79 );
80 assert!(clone.status.success(), "{clone:?}");
81 std::fs::write(clone_dir.path().join("file.txt"), "after\n").expect("write");
82 let add = git(clone_dir.path(), &["add", "-A"]);
83 assert!(add.status.success());
84 let commit = git(clone_dir.path(), &["commit", "-q", "-m", "after"]);
85 assert!(commit.status.success(), "{commit:?}");
86
87 let push = git(clone_dir.path(), &["push", "origin", "main"]);
88 assert!(
89 push.status.success(),
90 "a push into the checked-out branch must be accepted, not refused: {push:?}"
91 );
92
93 // The working tree on `origin_dir` reflects the push, not just its
94 // ref — this is the "also updates the working tree" half of
95 // `updateInstead`, distinct from an ordinary bare remote.
96 let updated = std::fs::read_to_string(origin_dir.path().join("file.txt")).expect("read");
97 assert_eq!(
98 updated, "after\n",
99 "the checked-out working tree must update"
100 );
101}