224 lines
6.0 KiB
Rust
224 lines
6.0 KiB
Rust
//! Copyright (c) 2022-2026 GitDataAi All rights reserved.
|
|
|
|
use gitks::bare::GitBare;
|
|
use gitks::server::GitksService;
|
|
|
|
#[allow(dead_code)]
|
|
pub fn setup_service(dir: &std::path::Path) -> GitksService {
|
|
GitksService::new(dir.to_path_buf())
|
|
}
|
|
|
|
pub fn run_git(work_dir: &std::path::Path, args: &[&str]) -> duct::Expression {
|
|
duct::cmd("git", {
|
|
let work_str = work_dir.to_string_lossy().into_owned();
|
|
let mut v: Vec<String> = vec!["-C".into(), work_str];
|
|
v.extend(args.iter().map(|s| s.to_string()));
|
|
v
|
|
})
|
|
.env("GIT_AUTHOR_NAME", "Test")
|
|
.env("GIT_AUTHOR_EMAIL", "test@example.com")
|
|
.env("GIT_COMMITTER_NAME", "Test")
|
|
.env("GIT_COMMITTER_EMAIL", "test@example.com")
|
|
}
|
|
|
|
pub fn run(work_dir: &std::path::Path, args: &[&str]) {
|
|
let result = run_git(work_dir, args)
|
|
.stdout_capture()
|
|
.stderr_capture()
|
|
.unchecked()
|
|
.run()
|
|
.unwrap();
|
|
assert!(
|
|
result.status.success(),
|
|
"git {} failed: {}",
|
|
args.join(" "),
|
|
String::from_utf8_lossy(&result.stderr)
|
|
);
|
|
}
|
|
|
|
pub fn setup_bare_repo() -> (tempfile::TempDir, GitBare) {
|
|
let dir = tempfile::tempdir().expect("create temp dir");
|
|
let bare_dir = dir.path().join("test-repo");
|
|
|
|
duct::cmd(
|
|
"git",
|
|
["init", "--bare", bare_dir.to_string_lossy().as_ref()],
|
|
)
|
|
.run()
|
|
.expect("git init --bare");
|
|
|
|
let work_dir = dir.path().join("work");
|
|
duct::cmd(
|
|
"git",
|
|
[
|
|
"clone",
|
|
bare_dir.to_string_lossy().as_ref(),
|
|
work_dir.to_string_lossy().as_ref(),
|
|
],
|
|
)
|
|
.run()
|
|
.expect("clone");
|
|
|
|
run(&work_dir, &["checkout", "-b", "main"]);
|
|
|
|
std::fs::write(work_dir.join("README.md"), "# Test\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "initial commit"]);
|
|
|
|
run(&work_dir, &["branch", "feature"]);
|
|
|
|
std::fs::write(work_dir.join("src.txt"), "source\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "second commit"]);
|
|
|
|
std::fs::write(work_dir.join("README.md"), "# Test\n\nUpdated.\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "third commit"]);
|
|
|
|
std::fs::create_dir_all(work_dir.join("src/lib")).unwrap();
|
|
std::fs::write(work_dir.join("src/lib/mod.rs"), "pub fn hello() {}\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "add nested file"]);
|
|
|
|
run(&work_dir, &["tag", "v0.1.0"]);
|
|
|
|
run(
|
|
&work_dir,
|
|
&["push", "-f", "origin", "main:main", "feature:feature"],
|
|
);
|
|
run(
|
|
&work_dir,
|
|
&["push", "-f", "origin", "refs/tags/v0.1.0:refs/tags/v0.1.0"],
|
|
);
|
|
|
|
duct::cmd(
|
|
"git",
|
|
[
|
|
"--git-dir",
|
|
bare_dir.to_string_lossy().as_ref(),
|
|
"symbolic-ref",
|
|
"HEAD",
|
|
"refs/heads/main",
|
|
],
|
|
)
|
|
.run()
|
|
.expect("set HEAD to main");
|
|
|
|
(dir, GitBare::new(bare_dir))
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn setup_bare_repo_with_conflict() -> (tempfile::TempDir, GitBare) {
|
|
let dir = tempfile::tempdir().expect("create temp dir");
|
|
let bare_dir = dir.path().join("test-repo");
|
|
|
|
duct::cmd(
|
|
"git",
|
|
["init", "--bare", bare_dir.to_string_lossy().as_ref()],
|
|
)
|
|
.run()
|
|
.expect("git init --bare");
|
|
|
|
let work_dir = dir.path().join("work");
|
|
duct::cmd(
|
|
"git",
|
|
[
|
|
"clone",
|
|
bare_dir.to_string_lossy().as_ref(),
|
|
work_dir.to_string_lossy().as_ref(),
|
|
],
|
|
)
|
|
.run()
|
|
.expect("clone");
|
|
|
|
run(&work_dir, &["checkout", "-b", "main"]);
|
|
std::fs::write(work_dir.join("file.txt"), "base content\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "base commit"]);
|
|
|
|
run(&work_dir, &["checkout", "-b", "branch-a"]);
|
|
std::fs::write(work_dir.join("file.txt"), "branch A content\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "branch A change"]);
|
|
|
|
run(&work_dir, &["checkout", "main"]);
|
|
run(&work_dir, &["checkout", "-b", "branch-b"]);
|
|
std::fs::write(work_dir.join("file.txt"), "branch B content\n").unwrap();
|
|
run(&work_dir, &["add", "."]);
|
|
run(&work_dir, &["commit", "-m", "branch B change"]);
|
|
|
|
run(
|
|
&work_dir,
|
|
&[
|
|
"push",
|
|
"-f",
|
|
"origin",
|
|
"main:main",
|
|
"branch-a:branch-a",
|
|
"branch-b:branch-b",
|
|
],
|
|
);
|
|
|
|
duct::cmd(
|
|
"git",
|
|
[
|
|
"--git-dir",
|
|
bare_dir.to_string_lossy().as_ref(),
|
|
"symbolic-ref",
|
|
"HEAD",
|
|
"refs/heads/main",
|
|
],
|
|
)
|
|
.run()
|
|
.expect("set HEAD to main");
|
|
|
|
(dir, GitBare::new(bare_dir))
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn get_oid(gb: &GitBare, rev: &str) -> String {
|
|
let output = std::process::Command::new("git")
|
|
.args([
|
|
"--git-dir",
|
|
gb.bare_dir.to_string_lossy().as_ref(),
|
|
"rev-parse",
|
|
rev,
|
|
])
|
|
.output()
|
|
.expect("git rev-parse");
|
|
assert!(output.status.success(), "git rev-parse {rev} failed");
|
|
String::from_utf8_lossy(&output.stdout).trim().to_string()
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn get_main_oid(gb: &GitBare) -> String {
|
|
get_oid(gb, "refs/heads/main")
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn get_feature_oid(gb: &GitBare) -> String {
|
|
get_oid(gb, "refs/heads/feature")
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn oid_selector(hex: &str) -> Option<gitks::pb::ObjectSelector> {
|
|
Some(gitks::pb::ObjectSelector {
|
|
selector: Some(gitks::pb::object_selector::Selector::Oid(gitks::pb::Oid {
|
|
hex: hex.to_string(),
|
|
value: vec![],
|
|
format: 0,
|
|
})),
|
|
})
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn rev_selector(rev: &str) -> Option<gitks::pb::ObjectSelector> {
|
|
Some(gitks::pb::ObjectSelector {
|
|
selector: Some(gitks::pb::object_selector::Selector::Revision(
|
|
gitks::pb::ObjectName {
|
|
revision: rev.to_string(),
|
|
},
|
|
)),
|
|
})
|
|
}
|