This repository has no description
1use std::path::Path;
2use std::sync::atomic::AtomicBool;
3
4use knot_git::ArchiveFormat;
5use knot_types::Oid;
6
7mod common;
8use common::{commit_file, contains, git_ok as git, seeded};
9
10fn archive_without_isolation(bare_path: &Path, head: Oid) -> Vec<u8> {
11 let permissive = gix::open_opts(bare_path, gix::open::Options::default()).unwrap();
12 let tree = permissive
13 .find_object(head.object_id())
14 .unwrap()
15 .peel_to_tree()
16 .unwrap();
17 let (stream, _index) = permissive.worktree_stream(tree.id).unwrap();
18 let mut out = std::io::Cursor::new(Vec::new());
19 permissive
20 .worktree_archive(
21 stream,
22 &mut out,
23 gix::progress::Discard,
24 &AtomicBool::new(false),
25 gix_archive::Options {
26 format: gix_archive::Format::Tar,
27 tree_prefix: None,
28 modification_time: 0,
29 },
30 )
31 .unwrap();
32 out.into_inner()
33}
34
35#[test]
36fn a_filter_driver_pulled_in_by_an_include_never_runs_for_a_served_archive() {
37 let (_scan, work_dir, layout, did) = seeded();
38 let work = work_dir.path();
39 let bare_path = layout.repo_path(&did).unwrap();
40 std::fs::write(work.join(".gitattributes"), "payload.txt filter=knotpwn\n").unwrap();
41 commit_file(work, "payload.txt", "kelp\n", "seed");
42 git(work, &["push", "-q", bare_path.to_str().unwrap(), "main"]);
43 let head = Oid::from_hex(&git(work, &["rev-parse", "HEAD"])).unwrap();
44
45 let ambient = tempfile::tempdir().unwrap();
46 let driver = ambient.path().join("driver.cfg");
47 std::fs::write(
48 &driver,
49 "[filter \"knotpwn\"]\n\tsmudge = sed s/kelp/pwned/\n\trequired = true\n",
50 )
51 .unwrap();
52 let config_path = bare_path.join("config");
53 let local = std::fs::read_to_string(&config_path).unwrap();
54 std::fs::write(
55 &config_path,
56 format!("{local}[include]\n\tpath = {}\n", driver.display()),
57 )
58 .unwrap();
59
60 let via_git = knot_fixtures::command(&bare_path)
61 .args(["archive", "--format=tar", "main"])
62 .output()
63 .unwrap();
64 assert!(
65 via_git.status.success(),
66 "git archive failed:\n{}",
67 String::from_utf8_lossy(&via_git.stderr)
68 );
69 assert!(
70 contains(&via_git.stdout, b"pwned"),
71 "git archived with the include in place and its output has no pwned in it, so the driver \
72 never ran"
73 );
74 assert!(
75 contains(&archive_without_isolation(&bare_path, head), b"pwned"),
76 "gix archived the same repo under default permissions and its output has no pwned in it, \
77 so worktree_stream no longer applies filters"
78 );
79
80 let bare = layout.open(&did).unwrap();
81 let tree = bare.peel_to_tree(head).unwrap();
82 let mut out = std::io::Cursor::new(Vec::new());
83 bare.write_archive(tree, ArchiveFormat::Tar, None, &mut out)
84 .unwrap();
85 let served = out.into_inner();
86
87 assert!(
88 std::fs::read_to_string(&config_path)
89 .unwrap()
90 .contains("[include]"),
91 "opening the repo rewrote its config and removed the include, so gix never read the \
92 driver definition for the archive below"
93 );
94 assert!(
95 contains(&served, b"kelp"),
96 "the served archive contains the blob as it was pushed"
97 );
98 assert!(
99 !contains(&served, b"pwned"),
100 "the knot ran a filter driver defined by config outside the repository"
101 );
102}