cc202d6d1f
- Add tracing spans with repo labels for archive and blame operations - Implement caching for archive list entries when using OID selectors - Implement caching for blame operations when using OID selectors - Add detailed
316 lines
9.2 KiB
Rust
316 lines
9.2 KiB
Rust
mod common;
|
|
|
|
use gitks::pb::branch_service_server::BranchService;
|
|
use gitks::pb::*;
|
|
|
|
#[allow(unused_imports)]
|
|
use gitks::pb::{BranchUpstream, SetBranchUpstreamRequest, UpdateBranchTargetRequest};
|
|
|
|
fn hdr() -> RepositoryHeader {
|
|
RepositoryHeader {
|
|
relative_path: "test-repo".into(),
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_list_branches() {
|
|
let (dir, _gb) = common::setup_bare_repo();
|
|
let svc = common::setup_service(dir.path());
|
|
let result = svc
|
|
.list_branches(tonic::Request::new(ListBranchesRequest {
|
|
repository: Some(hdr()),
|
|
pattern: String::new(),
|
|
merged_into_head: false,
|
|
not_merged_into_head: false,
|
|
pagination: None,
|
|
sort_direction: 0,
|
|
}))
|
|
.await
|
|
.unwrap()
|
|
.into_inner();
|
|
let names: Vec<String> = result.branches.iter().map(|b| b.name.clone()).collect();
|
|
assert!(names.contains(&"feature".to_string()));
|
|
assert!(names.contains(&"main".to_string()));
|
|
assert!(result.branches.len() >= 2);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_list_branches_merged_filter() {
|
|
let (dir, _gb) = common::setup_bare_repo();
|
|
let svc = common::setup_service(dir.path());
|
|
|
|
let merged = svc
|
|
.list_branches(tonic::Request::new(ListBranchesRequest {
|
|
repository: Some(hdr()),
|
|
pattern: String::new(),
|
|
merged_into_head: true,
|
|
not_merged_into_head: false,
|
|
pagination: None,
|
|
sort_direction: 0,
|
|
}))
|
|
.await
|
|
.unwrap()
|
|
.into_inner();
|
|
|
|
let not_merged = svc
|
|
.list_branches(tonic::Request::new(ListBranchesRequest {
|
|
repository: Some(hdr()),
|
|
pattern: String::new(),
|
|
merged_into_head: false,
|
|
not_merged_into_head: true,
|
|
pagination: None,
|
|
sort_direction: 0,
|
|
}))
|
|
.await
|
|
.unwrap()
|
|
.into_inner();
|
|
|
|
let merged_names: Vec<&str> = merged.branches.iter().map(|b| b.name.as_str()).collect();
|
|
let not_merged_names: Vec<&str> = not_merged
|
|
.branches
|
|
.iter()
|
|
.map(|b| b.name.as_str())
|
|
.collect();
|
|
|
|
assert!(
|
|
merged_names.contains(&"main"),
|
|
"main should be merged into HEAD, got: {:?}",
|
|
merged_names
|
|
);
|
|
assert!(
|
|
not_merged_names.contains(&"feature"),
|
|
"feature should NOT be merged into HEAD, got: {:?}",
|
|
not_merged_names
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_branch() {
|
|
let (dir, _gb) = common::setup_bare_repo();
|
|
let svc = common::setup_service(dir.path());
|
|
let branch = svc
|
|
.get_branch(tonic::Request::new(GetBranchRequest {
|
|
repository: Some(hdr()),
|
|
name: "feature".into(),
|
|
}))
|
|
.await
|
|
.unwrap()
|
|
.into_inner();
|
|
assert_eq!(branch.full_ref, "refs/heads/feature");
|
|
let oid = branch.target_oid.unwrap();
|
|
assert!(!oid.value.is_empty());
|
|
assert_eq!(oid.value.len(), 20);
|
|
assert_eq!(oid.hex.len(), 40);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_branch_pagination() {
|
|
let (dir, _gb) = common::setup_bare_repo();
|
|
let svc = common::setup_service(dir.path());
|
|
let result = svc
|
|
.list_branches(tonic::Request::new(ListBranchesRequest {
|
|
repository: Some(hdr()),
|
|
pattern: String::new(),
|
|
merged_into_head: false,
|
|
not_merged_into_head: false,
|
|
pagination: Some(Pagination {
|
|
page_size: 1,
|
|
page_token: String::new(),
|
|
}),
|
|
sort_direction: 0,
|
|
}))
|
|
.await
|
|
.unwrap()
|
|
.into_inner();
|
|
let page_info = result.page_info.unwrap();
|
|
assert_eq!(result.branches.len(), 1);
|
|
assert!(page_info.has_next_page);
|
|
|
|
let result2 = svc
|
|
.list_branches(tonic::Request::new(ListBranchesRequest {
|
|
repository: Some(hdr()),
|
|
pattern: String::new(),
|
|
merged_into_head: false,
|
|
not_merged_into_head: false,
|
|
pagination: Some(Pagination {
|
|
page_size: 1,
|
|
page_token: page_info.next_page_token,
|
|
}),
|
|
sort_direction: 0,
|
|
}))
|
|
.await
|
|
.unwrap()
|
|
.into_inner();
|
|
assert!(!result2.branches.is_empty());
|
|
assert_ne!(result.branches[0].name, result2.branches[0].name);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_create_and_delete_branch() {
|
|
let (dir, _gb) = common::setup_bare_repo();
|
|
let svc = common::setup_service(dir.path());
|
|
let branch = svc
|
|
.create_branch(tonic::Request::new(CreateBranchRequest {
|
|
repository: Some(hdr()),
|
|
name: "new-branch".into(),
|
|
start_point: Some(ObjectSelector {
|
|
selector: Some(object_selector::Selector::Revision(ObjectName {
|
|
revision: "main".into(),
|
|
})),
|
|
}),
|
|
force: false,
|
|
}))
|
|
.await
|
|
.unwrap()
|
|
.into_inner();
|
|
assert_eq!(branch.name, "new-branch");
|
|
|
|
svc.delete_branch(tonic::Request::new(DeleteBranchRequest {
|
|
repository: Some(hdr()),
|
|
name: "new-branch".into(),
|
|
force: true,
|
|
}))
|
|
.await
|
|
.unwrap();
|
|
|
|
let result = svc
|
|
.get_branch(tonic::Request::new(GetBranchRequest {
|
|
repository: Some(hdr()),
|
|
name: "new-branch".into(),
|
|
}))
|
|
.await;
|
|
assert!(result.is_err(), "deleted branch should not exist");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_rename_branch() {
|
|
let (dir, _gb) = common::setup_bare_repo();
|
|
let svc = common::setup_service(dir.path());
|
|
svc.create_branch(tonic::Request::new(CreateBranchRequest {
|
|
repository: Some(hdr()),
|
|
name: "to-rename".into(),
|
|
start_point: Some(ObjectSelector {
|
|
selector: Some(object_selector::Selector::Revision(ObjectName {
|
|
revision: "main".into(),
|
|
})),
|
|
}),
|
|
force: false,
|
|
}))
|
|
.await
|
|
.unwrap();
|
|
|
|
let renamed = svc
|
|
.rename_branch(tonic::Request::new(RenameBranchRequest {
|
|
repository: Some(hdr()),
|
|
old_name: "to-rename".into(),
|
|
new_name: "renamed".into(),
|
|
}))
|
|
.await
|
|
.unwrap()
|
|
.into_inner();
|
|
assert_eq!(renamed.name, "renamed");
|
|
|
|
let old = svc
|
|
.get_branch(tonic::Request::new(GetBranchRequest {
|
|
repository: Some(hdr()),
|
|
name: "to-rename".into(),
|
|
}))
|
|
.await;
|
|
assert!(old.is_err(), "old branch name should not exist");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_compare_branch() {
|
|
let (dir, _gb) = common::setup_bare_repo();
|
|
let svc = common::setup_service(dir.path());
|
|
let result = svc
|
|
.compare_branch(tonic::Request::new(CompareBranchRequest {
|
|
repository: Some(hdr()),
|
|
source_branch: "feature".into(),
|
|
target_branch: "main".into(),
|
|
}))
|
|
.await
|
|
.unwrap()
|
|
.into_inner();
|
|
|
|
assert!(
|
|
result.ahead_by > 0 || result.behind_by > 0,
|
|
"branches should differ"
|
|
);
|
|
assert!(result.merge_base.is_some(), "should find merge base");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_update_branch_target() {
|
|
let (dir, _gb) = common::setup_bare_repo();
|
|
let svc = common::setup_service(dir.path());
|
|
|
|
// Get current main OID
|
|
let main_branch = svc
|
|
.get_branch(tonic::Request::new(GetBranchRequest {
|
|
repository: Some(hdr()),
|
|
name: "main".into(),
|
|
}))
|
|
.await
|
|
.unwrap()
|
|
.into_inner();
|
|
let main_oid = main_branch.target_oid.as_ref().unwrap().clone();
|
|
|
|
// Create a new branch pointing to main's HEAD
|
|
svc.create_branch(tonic::Request::new(CreateBranchRequest {
|
|
repository: Some(hdr()),
|
|
name: "movable".into(),
|
|
start_point: Some(ObjectSelector {
|
|
selector: Some(object_selector::Selector::Revision(ObjectName {
|
|
revision: "main~2".into(),
|
|
})),
|
|
}),
|
|
force: false,
|
|
}))
|
|
.await
|
|
.unwrap();
|
|
|
|
// Update target to main's OID
|
|
let updated = svc
|
|
.update_branch_target(tonic::Request::new(UpdateBranchTargetRequest {
|
|
repository: Some(hdr()),
|
|
name: "movable".into(),
|
|
expected_old_oid: None,
|
|
new_oid: Some(main_oid),
|
|
force: true,
|
|
}))
|
|
.await
|
|
.unwrap()
|
|
.into_inner();
|
|
|
|
assert_eq!(updated.name, "movable");
|
|
assert_eq!(
|
|
updated.target_oid.as_ref().unwrap().hex,
|
|
main_branch.target_oid.as_ref().unwrap().hex
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_set_branch_upstream() {
|
|
let (dir, _gb) = common::setup_bare_repo();
|
|
let svc = common::setup_service(dir.path());
|
|
|
|
let result = svc
|
|
.set_branch_upstream(tonic::Request::new(SetBranchUpstreamRequest {
|
|
repository: Some(hdr()),
|
|
name: "main".into(),
|
|
upstream: Some(BranchUpstream {
|
|
remote_name: "origin".into(),
|
|
remote_url: String::new(),
|
|
remote_branch_name: "main".into(),
|
|
local_branch_name: "main".into(),
|
|
}),
|
|
}))
|
|
.await;
|
|
|
|
// This may fail if no remote is configured, which is expected
|
|
// The important thing is that the code path is exercised
|
|
assert!(result.is_ok() || result.is_err());
|
|
}
|