use std::path::Path;
use std::process::Command;
use std::sync::Arc;
use std::time::Duration;
use git_checks_core::Commit;
use git_workarea::{CommitId, GitContext};
use crate::actions::reformat::*;
use crate::host::{HostedProject, HostingService, MergeRequest};
use crate::tests::mock::{AsUser, MockData, MockDataBuilder, MockMergeRequest, MockService};
use crate::tests::utils::test_workspace_dir;
const REPO_NAME: &str = "base";
const MR_NO_ATTRS_ID: u64 = 0;
const MR_NO_CHANGE_ID: u64 = 1;
const MR_REWRITE_ID: u64 = 2;
const MR_REWRITE_MERGES_ID: u64 = 3;
const MR_REWRITE_FAIL_ID: u64 = 4;
const MR_REWRITE_DELETE_ID: u64 = 5;
const MR_REWRITE_UNTRACKED_ID: u64 = 6;
const MR_REWRITE_MANUAL_ID: u64 = 7;
const MR_EMPTY_ID: u64 = 8;
const MR_REWRITE_REMOVE_ID: u64 = 9;
const MR_REWRITE_MANUAL_REMOVE_ID: u64 = 10;
const MR_TIMEOUT_ID: u64 = 11;
const MR_REWRITE_REPO_PARENT_ID: u64 = 12;
const MR_REWRITE_IGNORED_ID: u64 = 13;
const MR_WITH_ARG_ID: u64 = 14;
const MR_WITH_SUBMODULE_ID: u64 = 15;
const MR_WITH_SYMLINK_ID: u64 = 16;
const MR_NO_HISTORY_ID: u64 = 16;
const MR_NO_SOURCE_ID: u64 = 17;
const COMMIT_NO_ATTRS: &str = "b9f9ba95441fc06f7e0c99032508b76fe5c8fa53";
const COMMIT_NO_CHANGE: &str = "7b5fcacdff4947cf501929dbc76d17654ca4343a";
const COMMIT_REWRITE: &str = "391992dbe37f2d4a3792430fe64874f744c4fbe6";
const COMMIT_REWRITE_MERGES: &str = "811418bb4004d1949d0057a832ee5e35ca01efca";
const COMMIT_REWRITE_FAIL: &str = "6137ad841169bdcd82dea88f7ff31ca8fdc4bc72";
const COMMIT_REWRITE_DELETE: &str = "d42d39e413d1944d4ad7394796c22d6aeb2818c4";
const COMMIT_REWRITE_UNTRACKED: &str = "d4159cc5fd9d1bfa8b8b8ad7a7ace2464f6a59f6";
const COMMIT_REWRITE_MANUAL: &str = "ab7200256e78d4ae8e0a4ac807d6e048623f1e10";
const COMMIT_EMPTY: &str = "f0a00a83187dc8c8f41675874f9e207290d9c24d";
const COMMIT_REWRITE_REMOVE: &str = "59764e7f7c8057c141a2f532437b5cf93d3ca257";
const COMMIT_REWRITE_MANUAL_REMOVE: &str = "67719629fc90b2d2a8350c10ebd789810b8c9479";
const COMMIT_TIMEOUT: &str = "b7d30c687a0272b36df44614de3438efa726278e";
const COMMIT_REWRITE_REPO_PARENT: &str = "7e09019e55e42bed1083bf0bea2240774cf66fe1";
const COMMIT_REWRITE_IGNORED: &str = "0355324224afe9a6b85798c5fb7720bcc8c6175e";
const COMMIT_WITH_ARG: &str = "abd5443b496e816c0a005d261d075d375a4b8c8f";
const COMMIT_WITH_SUBMODULE: &str = "cc7a8f5614560334170e416be4d93d95a6814c1f";
const COMMIT_WITH_SYMLINK: &str = "46f6cdae30bf4ae7f5d1be7fe63926eaf118aa4a";
const COMMIT_NO_HISTORY: &str = "1da7f0e3f3f5f6948835aa4f77a2ee2c2ae43854";
const COMMIT_NO_SOURCE: &str = "7189cf557ba2c7c61881ff8669158710b94d8df1";
const BASE: &str = "58b2dee73ab6e6b1f3587b41d0ccdbe2ded785dd";
const UNRELATED_COMMIT: &str = "1da7f0e3f3f5f6948835aa4f77a2ee2c2ae43854";
fn git_context(workspace_path: &Path) -> (GitContext, GitContext) {
let origindir = workspace_path.join("origin");
let clone = Command::new("git")
.arg("clone")
.arg("--bare")
.arg(concat!(env!("CARGO_MANIFEST_DIR"), "/../.git"))
.arg(&origindir)
.output()
.unwrap();
if !clone.status.success() {
panic!(
"origin clone failed: {}",
String::from_utf8_lossy(&clone.stderr),
);
}
let forkdir = workspace_path.join("fork");
let clone = Command::new("git")
.arg("clone")
.arg("--bare")
.arg(&origindir)
.arg(&forkdir)
.output()
.unwrap();
if !clone.status.success() {
panic!(
"fork clone failed: {}",
String::from_utf8_lossy(&clone.stderr),
);
}
let mirrordir = workspace_path.join("mirror");
let clone = Command::new("git")
.arg("clone")
.arg("--bare")
.arg(&origindir)
.arg(&mirrordir)
.output()
.unwrap();
if !clone.status.success() {
panic!(
"mirror clone failed: {}",
String::from_utf8_lossy(&clone.stderr),
);
}
let gitdir = workspace_path.join("git");
let clone = Command::new("git")
.arg("clone")
.arg("--bare")
.arg(origindir)
.arg(&gitdir)
.output()
.unwrap();
if !clone.status.success() {
panic!(
"working clone failed: {}",
String::from_utf8_lossy(&clone.stderr),
);
}
let gitctx = GitContext::new(gitdir);
let remote_add = gitctx
.git()
.arg("remote")
.arg("add")
.arg("fork")
.arg(&forkdir)
.output()
.unwrap();
if !remote_add.status.success() {
panic!(
"adding the fork as a remote failed: {}",
String::from_utf8_lossy(&remote_add.stderr),
);
}
let remote_add = gitctx
.git()
.arg("remote")
.arg("add")
.arg("mirror")
.arg(&mirrordir)
.output()
.unwrap();
if !remote_add.status.success() {
panic!(
"adding the mirror as a remote failed: {}",
String::from_utf8_lossy(&remote_add.stderr),
);
}
let forkctx = GitContext::new(forkdir);
let remote_add = forkctx
.git()
.arg("remote")
.arg("add")
.arg("mirror")
.arg(&mirrordir)
.output()
.unwrap();
if !remote_add.status.success() {
panic!(
"adding the mirror as a remote failed: {}",
String::from_utf8_lossy(&remote_add.stderr),
);
}
(gitctx, forkctx)
}
fn formatter_path(kind: &str) -> String {
format!("{}/test/format.{}", env!("CARGO_MANIFEST_DIR"), kind)
}
fn create_formatter(kind: &str) -> Result<Formatter, FormatterError> {
Formatter::new(kind, formatter_path(kind))
}
fn create_reformat(git: &GitContext, service: &Arc<MockService>) -> Reformat {
let project = HostedProject {
name: REPO_NAME.into(),
service: Arc::clone(service) as Arc<dyn HostingService>,
};
let mut reformat = Reformat::new(git.clone(), project);
let mut simple_formatter = create_formatter("simple").unwrap();
simple_formatter.add_config_files(["format-config"].iter().cloned());
let untracked_formatter = create_formatter("untracked").unwrap();
let delete_formatter = create_formatter("delete").unwrap();
let mut timeout_formatter = create_formatter("timeout").unwrap();
timeout_formatter.with_timeout(Duration::from_secs(1));
let with_arg_formatter = create_formatter("with_arg").unwrap();
let formatters = [
simple_formatter,
untracked_formatter,
delete_formatter,
timeout_formatter,
with_arg_formatter,
];
reformat.add_formatters(formatters);
reformat
}
fn prepare_fork(git: &GitContext, mr: &MergeRequest) {
let update_ref = git
.git()
.arg("update-ref")
.arg(format!("refs/heads/{}", mr.source_branch))
.arg(mr.commit.id.as_str())
.output()
.unwrap();
if !update_ref.status.success() {
panic!(
"failed to update the ref for the fork: {}",
String::from_utf8_lossy(&update_ref.stderr),
);
}
let push_mirror = git
.git()
.arg("push")
.arg("mirror")
.arg(&mr.source_branch)
.output()
.unwrap();
if !push_mirror.status.success() {
panic!(
"failed to push to the mirror: {}",
String::from_utf8_lossy(&push_mirror.stderr),
);
}
}
fn check_fork(git: &GitContext, commit: &CommitId) -> CommitId {
let rev_parse = git
.git()
.arg("rev-parse")
.arg(commit.as_str())
.output()
.unwrap();
if !rev_parse.status.success() {
panic!(
"failed to read the ref for the topic from the fork: {}",
String::from_utf8_lossy(&rev_parse.stderr),
);
}
CommitId::new(String::from_utf8_lossy(&rev_parse.stdout).trim())
}
fn check_file_contents(git: &GitContext, commit: &CommitId, file: &str, expected: &str) {
let ls_tree = git
.git()
.arg("ls-tree")
.arg(commit.as_str())
.arg(file)
.output()
.unwrap();
if !ls_tree.status.success() {
panic!(
"failed to run ls-tree on commit {} for the file {}: {}",
commit,
file,
String::from_utf8_lossy(&ls_tree.stderr),
);
}
let ls_tree_output = String::from_utf8_lossy(&ls_tree.stdout);
if ls_tree_output.is_empty() {
panic!(
"no output from ls-tree on commit {} for the file {}",
commit, file,
);
}
let blob = ls_tree_output.split_whitespace().nth(2).unwrap();
let cat_file = git
.git()
.arg("cat-file")
.arg("blob")
.arg(blob)
.output()
.unwrap();
if !cat_file.status.success() {
panic!(
"failed to get the contents of the blob {}: {}",
blob,
String::from_utf8_lossy(&cat_file.stderr),
);
}
assert_eq!(String::from_utf8_lossy(&cat_file.stdout), expected);
}
fn file_exists(git: &GitContext, commit: &CommitId, file: &str) -> bool {
let ls_tree = git
.git()
.arg("ls-tree")
.arg(commit.as_str())
.arg(file)
.output()
.unwrap();
if !ls_tree.status.success() {
panic!(
"failed to run ls-tree on commit {} for the file {}: {}",
commit,
file,
String::from_utf8_lossy(&ls_tree.stderr),
);
}
!ls_tree.stdout.is_empty()
}
#[test]
fn test_reformat_format_empty_kind() {
let err = Formatter::new(
"",
concat!(env!("CARGO_MANIFEST_DIR"), "/test/format.simple"),
)
.unwrap_err();
if let FormatterError::EmptyKind {} = err {
} else {
panic!("unexpected error: {:?}", err);
}
}
#[test]
fn test_reformat_format_no_exist() {
let kind = "no-exist";
let err = create_formatter(kind).unwrap_err();
if let FormatterError::MissingFormatter {
formatter,
} = err
{
assert_eq!(formatter, Path::new(&formatter_path(kind)));
} else {
panic!("unexpected error: {:?}", err);
}
}
fn reformat_service_builder() -> MockDataBuilder {
let base = MockData::repo(REPO_NAME);
let fork = MockData::forked_repo("fork", &base);
let user = MockData::user("user");
let mut builder = MockData::builder();
builder
.add_merge_request(MockMergeRequest::new(
MR_NO_ATTRS_ID,
&user,
COMMIT_NO_ATTRS,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_NO_CHANGE_ID,
&user,
COMMIT_NO_CHANGE,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_REWRITE_ID,
&user,
COMMIT_REWRITE,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_REWRITE_MERGES_ID,
&user,
COMMIT_REWRITE_MERGES,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_REWRITE_FAIL_ID,
&user,
COMMIT_REWRITE_FAIL,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_REWRITE_DELETE_ID,
&user,
COMMIT_REWRITE_DELETE,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_REWRITE_UNTRACKED_ID,
&user,
COMMIT_REWRITE_UNTRACKED,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_REWRITE_MANUAL_ID,
&user,
COMMIT_REWRITE_MANUAL,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_EMPTY_ID,
&user,
COMMIT_EMPTY,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_REWRITE_REMOVE_ID,
&user,
COMMIT_REWRITE_REMOVE,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_REWRITE_MANUAL_REMOVE_ID,
&user,
COMMIT_REWRITE_MANUAL_REMOVE,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_TIMEOUT_ID,
&user,
COMMIT_TIMEOUT,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_REWRITE_REPO_PARENT_ID,
&user,
COMMIT_REWRITE_REPO_PARENT,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_REWRITE_IGNORED_ID,
&user,
COMMIT_REWRITE_IGNORED,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_WITH_ARG_ID,
&user,
COMMIT_WITH_ARG,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_WITH_SUBMODULE_ID,
&user,
COMMIT_WITH_SUBMODULE,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_WITH_SYMLINK_ID,
&user,
COMMIT_WITH_SYMLINK,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_NO_HISTORY_ID,
&user,
COMMIT_NO_HISTORY,
&base,
&fork,
))
.add_merge_request(MockMergeRequest::new(
MR_NO_SOURCE_ID,
&user,
COMMIT_NO_SOURCE,
&base,
None,
))
.add_project(base)
.add_project(fork)
.add_user(user);
builder
}
fn reformat_service() -> Arc<MockService> {
let builder = reformat_service_builder();
builder.service()
}
fn reformat_service_as_user(as_user: AsUser) -> Arc<MockService> {
let mut builder = reformat_service_builder();
if let AsUser::Mirror(ref m) = as_user {
builder.add_project(MockData::repo(m));
}
builder.as_user(as_user);
builder.service()
}
#[test]
fn test_reformat_no_attrs() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_NO_ATTRS_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}
#[test]
fn test_reformat_no_change() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_NO_CHANGE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}
#[test]
fn test_reformat_pass_simple() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_REWRITE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
let cur_parent = check_fork(
&fork_ctx,
&CommitId::new(format!("refs/heads/{}~", mr.source_branch)),
);
let old_parent = check_fork(&fork_ctx, &CommitId::new(format!("{}~", mr.commit.id)));
assert_eq!(cur_parent, old_parent);
check_file_contents(
&fork_ctx,
&cur_head,
"bad.simple.txt",
"This is a well-formatted file.\n",
);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source repository and \
reset your local branch to continue with further development on the reformatted commits.",
);
}
#[test]
fn test_reformat_pass_simple_remove_manual() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_REWRITE_MANUAL_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
let cur_parent = check_fork(
&fork_ctx,
&CommitId::new(format!("refs/heads/{}~", mr.source_branch)),
);
let old_grandparent = check_fork(&fork_ctx, &CommitId::new(format!("{}~~", mr.commit.id)));
assert_eq!(cur_parent, old_grandparent);
check_file_contents(
&fork_ctx,
&cur_head,
"bad.simple.txt",
"This is a well-formatted file.\n",
);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source repository and \
reset your local branch to continue with further development on the reformatted \
commits.\n\
\n\
The following commits were empty after reformatting and removed from the history: \
ab7200256e78d4ae8e0a4ac807d6e048623f1e10.",
);
}
#[test]
fn test_reformat_pass_simple_keep_empty() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_EMPTY_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}
#[test]
fn test_reformat_pass_simple_remove_formatted_file() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_REWRITE_REMOVE_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
let cur_tree = check_fork(&fork_ctx, &CommitId::new(format!("{cur_head}^{{tree}}")));
let old_tree = check_fork(
&fork_ctx,
&CommitId::new(format!("{}^{{tree}}", mr.commit.id)),
);
assert_eq!(cur_tree, old_tree);
assert!(!file_exists(&fork_ctx, &cur_head, "bad.simple.txt"));
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source repository and \
reset your local branch to continue with further development on the reformatted commits.",
);
}
#[test]
fn test_reformat_pass_simple_reformat_ignored_file() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_REWRITE_IGNORED_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
check_file_contents(
&fork_ctx,
&cur_head,
"bad.simple.txt",
"This is a well-formatted file.\n",
);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source \
repository and reset your local branch to continue with further development on \
the reformatted commits.",
);
}
#[test]
fn test_reformat_repo_pass_simple_reformat_ignored_file() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_REWRITE_IGNORED_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_repo(&mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
check_file_contents(
&fork_ctx,
&cur_head,
"bad.simple.txt",
"This is a well-formatted file.\n",
);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source \
repository and reset your local branch to continue with further development on \
the reformatted commits.",
);
}
#[test]
fn test_reformat_pass_simple_keep_manual_extra() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_REWRITE_MANUAL_REMOVE_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
check_file_contents(
&fork_ctx,
&cur_head,
"bad.simple.txt",
"This is a well-formatted file.\n",
);
assert!(!file_exists(&fork_ctx, &cur_head, "ok.txt"));
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source repository and \
reset your local branch to continue with further development on the reformatted commits.",
);
}
#[test]
fn test_reformat_pass_merges() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_REWRITE_MERGES_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
let old_commit = Commit::new(&ctx, &mr.commit.id).unwrap();
let new_commit = Commit::new(&ctx, &cur_head).unwrap();
assert_eq!(old_commit.parents.len(), 2);
assert_eq!(new_commit.parents.len(), 2);
check_file_contents(
&fork_ctx,
&cur_head,
"bad.simple.txt",
"This is a well-formatted file.\n",
);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source repository and \
reset your local branch to continue with further development on the reformatted commits.",
);
}
#[test]
fn test_reformat_fail_reformat() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_REWRITE_FAIL_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let err = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap_err();
if let ReformatError::ReformatFailed {
commit,
paths,
} = err
{
assert_eq!(commit, mr.commit.id);
itertools::assert_equal(paths, ["bad.simple.txt", "fail.simple.txt"].iter().copied());
} else {
panic!("unexpected error: {:?}", err);
}
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"Failed to format the following files in 6137ad841169bdcd82dea88f7ff31ca8fdc4bc72:\n\n - \
`bad.simple.txt`\n - `fail.simple.txt`",
);
}
#[test]
fn test_reformat_fail_deleted() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_REWRITE_DELETE_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let err = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap_err();
if let ReformatError::DisallowedFiles {
commit,
reason,
paths,
} = err
{
assert_eq!(commit, mr.commit.id);
assert_eq!(reason, DisallowedFilesReason::Deleted);
itertools::assert_equal(paths, ["bad.delete.txt"].iter().copied());
} else {
panic!("unexpected error: {:?}", err);
}
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"The following paths were deleted while formatting \
d42d39e413d1944d4ad7394796c22d6aeb2818c4:\n\n - `bad.delete.txt`",
);
}
#[test]
fn test_reformat_fail_untracked() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_REWRITE_UNTRACKED_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let err = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap_err();
if let ReformatError::DisallowedFiles {
commit,
reason,
paths,
} = err
{
assert_eq!(commit, mr.commit.id);
assert_eq!(reason, DisallowedFilesReason::Created);
itertools::assert_equal(paths, ["untracked"].iter().copied());
} else {
panic!("unexpected error: {:?}", err);
}
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"The following untracked paths were created while formatting \
d4159cc5fd9d1bfa8b8b8ad7a7ace2464f6a59f6:\n\n - `untracked`",
);
}
#[test]
fn test_reformat_fail_timeout() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_TIMEOUT_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let err = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap_err();
if let ReformatError::ReformatFailed {
commit,
paths,
} = err
{
assert_eq!(commit, mr.commit.id);
itertools::assert_equal(paths, ["timeout.txt"].iter().copied());
} else {
panic!("unexpected error: {:?}", err);
}
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"Failed to format the following files in b7d30c687a0272b36df44614de3438efa726278e:\n\n - \
`timeout.txt`",
);
}
#[test]
fn test_reformat_fail_push() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_REWRITE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let update_ref = fork_ctx
.git()
.arg("update-ref")
.arg(format!("refs/heads/{}", mr.source_branch))
.arg(UNRELATED_COMMIT)
.output()
.unwrap();
if !update_ref.status.success() {
panic!(
"failed to update the ref for the fork: {}",
String::from_utf8_lossy(&update_ref.stderr),
);
}
let err = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap_err();
if let ReformatError::PushFailed {
url,
output,
} = err
{
assert_eq!(url, "fork");
assert!(!output.is_empty());
} else {
panic!("unexpected error: {:?}", err);
}
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(mr_comments[0], "Failed to push the reformatted branch.");
}
#[test]
fn test_reformat_fail_push_as_user() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let mut reformat = create_reformat(&ctx, &service);
reformat.push_as(PushAs::Author);
let mr = service.merge_request(REPO_NAME, MR_REWRITE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let update_ref = fork_ctx
.git()
.arg("update-ref")
.arg(format!("refs/heads/{}", mr.source_branch))
.arg(UNRELATED_COMMIT)
.output()
.unwrap();
if !update_ref.status.success() {
panic!(
"failed to update the ref for the fork: {}",
String::from_utf8_lossy(&update_ref.stderr),
);
}
let err = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap_err();
if let ReformatError::RepoAsUserUnsupported = err {
} else {
panic!("unexpected error: {:?}", err);
}
assert_eq!(service.remaining_data(), 0);
}
#[test]
fn test_reformat_fail_push_as_user_err() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service_as_user(AsUser::Error);
let mut reformat = create_reformat(&ctx, &service);
reformat.push_as(PushAs::Author);
let mr = service.merge_request(REPO_NAME, MR_REWRITE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let update_ref = fork_ctx
.git()
.arg("update-ref")
.arg(format!("refs/heads/{}", mr.source_branch))
.arg(UNRELATED_COMMIT)
.output()
.unwrap();
if !update_ref.status.success() {
panic!(
"failed to update the ref for the fork: {}",
String::from_utf8_lossy(&update_ref.stderr),
);
}
let err = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap_err();
if let ReformatError::RepoForUser {
repo,
user,
source,
} = err
{
assert_eq!(repo.url, "fork");
assert_eq!(user.handle, "user");
assert_eq!(format!("{source}"), "host error: rejecting as user views");
} else {
panic!("unexpected error: {:?}", err);
}
assert_eq!(service.remaining_data(), 0);
}
#[test]
fn test_reformat_push_as_user_redirect() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service_as_user(AsUser::Mirror("mirror".into()));
let mut reformat = create_reformat(&ctx, &service);
reformat.push_as(PushAs::Author);
let mr = service.merge_request(REPO_NAME, MR_REWRITE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let update_ref = fork_ctx
.git()
.arg("update-ref")
.arg(format!("refs/heads/{}", mr.source_branch))
.arg(UNRELATED_COMMIT)
.output()
.unwrap();
if !update_ref.status.success() {
panic!(
"failed to update the ref for the fork: {}",
String::from_utf8_lossy(&update_ref.stderr),
);
}
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source repository and \
reset your local branch to continue with further development on the reformatted commits.",
);
}
#[test]
fn test_reformat_fail_push_without_push() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let mut reformat = create_reformat(&ctx, &service);
reformat.push_as(None);
let mr = service.merge_request(REPO_NAME, MR_REWRITE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let update_ref = fork_ctx
.git()
.arg("update-ref")
.arg(format!("refs/heads/{}", mr.source_branch))
.arg(UNRELATED_COMMIT)
.output()
.unwrap();
if !update_ref.status.success() {
panic!(
"failed to update the ref for the fork: {}",
String::from_utf8_lossy(&update_ref.stderr),
);
}
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
assert_eq!(service.remaining_data(), 0);
}
#[test]
fn test_reformat_fail_push_no_rewrite() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_NO_ATTRS_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let update_ref = fork_ctx
.git()
.arg("update-ref")
.arg(format!("refs/heads/{}", mr.source_branch))
.arg(UNRELATED_COMMIT)
.output()
.unwrap();
if !update_ref.status.success() {
panic!(
"failed to update the ref for the fork: {}",
String::from_utf8_lossy(&update_ref.stderr),
);
}
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}
#[test]
fn test_reformat_root_commit() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_NO_HISTORY_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}
#[test]
fn test_reformat_repo_no_change() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_NO_CHANGE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_repo(&mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}
#[test]
fn test_reformat_repo_pass_simple() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_REWRITE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_repo(&mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
let cur_parent = check_fork(
&fork_ctx,
&CommitId::new(format!("refs/heads/{}~", mr.source_branch)),
);
let old_parent = check_fork(&fork_ctx, &CommitId::new(format!("{}~", mr.commit.id)));
assert_eq!(cur_parent, old_parent);
check_file_contents(
&fork_ctx,
&cur_head,
"bad.simple.txt",
"This is a well-formatted file.\n",
);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source repository and \
reset your local branch to continue with further development on the reformatted commits.",
);
}
#[test]
fn test_reformat_repo_pass_simple_only_head() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_REWRITE_REPO_PARENT_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_repo(&mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
let cur_parent = check_fork(
&fork_ctx,
&CommitId::new(format!("refs/heads/{}~", mr.source_branch)),
);
let old_parent = check_fork(&fork_ctx, &CommitId::new(format!("{}~", mr.commit.id)));
assert_eq!(cur_parent, old_parent);
check_file_contents(
&fork_ctx,
&cur_head,
"bad.simple.txt",
"This is a well-formatted file.\n",
);
check_file_contents(
&fork_ctx,
&CommitId::new(format!("{cur_head}~")),
"bad.simple.txt",
"This is a poorly-formatted file.\n",
);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source repository and \
reset your local branch to continue with further development on the reformatted commits.",
);
}
#[test]
fn test_reformat_repo_fail_push() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_REWRITE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let update_ref = fork_ctx
.git()
.arg("update-ref")
.arg(format!("refs/heads/{}", mr.source_branch))
.arg(UNRELATED_COMMIT)
.output()
.unwrap();
if !update_ref.status.success() {
panic!(
"failed to update the ref for the fork: {}",
String::from_utf8_lossy(&update_ref.stderr),
);
}
let err = reformat.reformat_repo(&mr).unwrap_err();
if let ReformatError::PushFailed {
url,
output,
} = err
{
assert_eq!(url, "fork");
assert!(!output.is_empty());
} else {
panic!("unexpected error: {:?}", err);
}
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(mr_comments[0], "Failed to push the reformatted branch.");
}
#[test]
fn test_reformat_repo_fail_push_no_rewrite() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_NO_ATTRS_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let update_ref = fork_ctx
.git()
.arg("update-ref")
.arg(format!("refs/heads/{}", mr.source_branch))
.arg(UNRELATED_COMMIT)
.output()
.unwrap();
if !update_ref.status.success() {
panic!(
"failed to update the ref for the fork: {}",
String::from_utf8_lossy(&update_ref.stderr),
);
}
let cur_head = reformat.reformat_repo(&mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}
#[test]
fn test_reformat_repo_merge() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_REWRITE_MERGES_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let err = reformat.reformat_repo(&mr).unwrap_err();
if let ReformatError::MergeCommit {} = err {
} else {
panic!("unexpected error: {:?}", err);
}
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"The repository cannot be reformatted using a merge commit. Please use a non-merge \
commit.",
);
}
#[test]
fn test_reformat_repo_root() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_NO_HISTORY_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_repo(&mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}
#[test]
fn test_reformat_deleted_source() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_NO_SOURCE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let err = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap_err();
if let ReformatError::InaccessibleSource {} = err {
} else {
panic!("unexpected error: {:?}", err);
}
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"The source repository is not accessible. Has it been deleted or is it a private \
repository?",
);
}
#[test]
fn test_reformat_repo_deleted_source() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_NO_SOURCE_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let err = reformat.reformat_repo(&mr).unwrap_err();
if let ReformatError::InaccessibleSource {} = err {
} else {
panic!("unexpected error: {:?}", err);
}
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"The source repository is not accessible. Has it been deleted or is it a private \
repository?",
);
}
#[test]
fn test_reformat_with_args() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_WITH_ARG_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_mr(&CommitId::new(BASE), &mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
check_file_contents(
&fork_ctx,
&cur_head,
"with-arg.txt",
"This file is bad because it says AAvalue like a pirate.\n",
);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source \
repository and reset your local branch to continue with further development on \
the reformatted commits.",
);
}
#[test]
fn test_reformat_repo_with_args() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service.merge_request(REPO_NAME, MR_WITH_ARG_ID).unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_repo(&mr).unwrap();
assert_ne!(cur_head, mr.commit.id);
check_file_contents(
&fork_ctx,
&cur_head,
"with-arg.txt",
"This file is bad because it says AAvalue like a pirate.\n",
);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic has been reformatted and pushed; please fetch from the source \
repository and reset your local branch to continue with further development on \
the reformatted commits.",
);
}
#[test]
fn test_reformat_with_submodule() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_WITH_SUBMODULE_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_repo(&mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}
#[test]
fn test_reformat_repo_with_submodule() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_WITH_SUBMODULE_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_repo(&mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}
#[test]
fn test_reformat_with_symlink() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_WITH_SYMLINK_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_repo(&mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}
#[test]
fn test_reformat_repo_with_symlink() {
let tempdir = test_workspace_dir();
let (ctx, fork_ctx) = git_context(tempdir.path());
let service = reformat_service();
let reformat = create_reformat(&ctx, &service);
let mr = service
.merge_request(REPO_NAME, MR_WITH_SYMLINK_ID)
.unwrap();
prepare_fork(&fork_ctx, &mr);
let cur_head = reformat.reformat_repo(&mr).unwrap();
assert_eq!(cur_head, mr.commit.id);
let mr_comments = service.mr_comments(mr.id);
assert_eq!(service.remaining_data(), 0);
assert_eq!(mr_comments.len(), 1);
assert_eq!(
mr_comments[0],
"This topic is clean and required no reformatting.",
);
}