mod common;
use assert_cmd::prelude::*;
use common::dircat_cmd;
use predicates::prelude::*;
use std::fs;
use tempfile::{tempdir, TempDir};
fn setup_local_git_repo() -> Result<TempDir, Box<dyn std::error::Error>> {
let temp_dir = tempdir()?;
let repo_path = temp_dir.path();
let repo = git2::Repository::init(repo_path)?;
fs::write(repo_path.join("README.md"), "# Test Repo")?;
fs::create_dir_all(repo_path.join("src"))?;
fs::write(repo_path.join("src/main.rs"), "fn main() {}")?;
fs::write(repo_path.join(".gitignore"), "*.log")?;
fs::create_dir_all(repo_path.join("data"))?;
fs::write(repo_path.join("data/app.log"), "some log data")?;
fs::write(repo_path.join("uncommitted.txt"), "do not include")?;
let mut index = repo.index()?;
index.add_path(std::path::Path::new("README.md"))?;
index.add_path(std::path::Path::new("src/main.rs"))?;
index.add_path(std::path::Path::new(".gitignore"))?;
index.add_path(std::path::Path::new("data/app.log"))?;
index.write()?;
let oid = index.write_tree()?;
let tree = repo.find_tree(oid)?;
let signature = git2::Signature::now("Test User", "test@example.com")?;
repo.commit(
Some("HEAD"), &signature, &signature, "Initial commit", &tree, &[], )?;
Ok(temp_dir)
}
fn setup_local_git_repo_with_tags() -> Result<TempDir, Box<dyn std::error::Error>> {
let temp_dir = tempdir()?;
let repo_path = temp_dir.path();
let repo = git2::Repository::init(repo_path)?;
let signature = git2::Signature::now("Test User", "test@example.com")?;
fs::write(repo_path.join("README.md"), "# Test Repo v1")?;
fs::write(repo_path.join(".gitignore"), "*.log")?;
let mut index = repo.index()?;
index.add_path(std::path::Path::new("README.md"))?;
index.add_path(std::path::Path::new(".gitignore"))?;
index.write()?;
let oid_v1 = index.write_tree()?;
let tree_v1 = repo.find_tree(oid_v1)?;
let commit_v1_oid = repo.commit(
Some("HEAD"),
&signature,
&signature,
"Initial commit (v1)",
&tree_v1,
&[],
)?;
let commit_v1 = repo.find_commit(commit_v1_oid)?;
repo.tag(
"v1.0",
commit_v1.as_object(),
&signature,
"Tagging version 1.0",
false,
)?;
fs::create_dir_all(repo_path.join("src"))?;
fs::write(repo_path.join("src/main.rs"), "fn main() {} // v2")?;
index.add_path(std::path::Path::new("src/main.rs"))?;
index.write()?;
let oid_v2 = index.write_tree()?;
let tree_v2 = repo.find_tree(oid_v2)?;
repo.commit(
Some("HEAD"),
&signature,
&signature,
"Second commit (v2)",
&tree_v2,
&[&commit_v1],
)?;
Ok(temp_dir)
}
#[test]
fn test_git_local_repository_input() -> Result<(), Box<dyn std::error::Error>> {
let source_repo_dir = setup_local_git_repo()?;
let repo_path_str = source_repo_dir.path().to_str().unwrap();
#[cfg(windows)]
let repo_url = format!("file:///{}", repo_path_str.replace('\\', "/"));
#[cfg(not(windows))]
let repo_url = format!("file://{}", repo_path_str);
let temp_cache = tempdir()?;
dircat_cmd()
.arg(&repo_url) .env("DIRCAT_TEST_CACHE_DIR", temp_cache.path())
.assert()
.success()
.stdout(predicate::str::contains("## File: README.md"))
.stdout(predicate::str::contains("# Test Repo"))
.stdout(predicate::str::contains("## File: src/main.rs"))
.stdout(predicate::str::contains("fn main() {}"))
.stdout(predicate::str::contains("## File: data/app.log").not())
.stdout(predicate::str::contains("## File: uncommitted.txt").not());
Ok(())
}
#[test]
#[ignore = "requires network access and is slow"]
fn test_git_remote_repository_input() -> Result<(), Box<dyn std::error::Error>> {
let repo_url = "https://github.com/git-fixtures/basic";
dircat_cmd()
.arg(repo_url)
.assert()
.success()
.stdout(predicate::str::contains("## File: CHANGELOG"))
.stdout(predicate::str::contains("Initial changelog"))
.stdout(predicate::str::contains("## File: LICENSE"))
.stdout(predicate::str::contains("Copyright (c) 2015 Tyba"))
.stdout(predicate::str::contains("## File: go/example.go"))
.stdout(predicate::str::contains("package harvesterd"));
Ok(())
}
#[test]
#[ignore = "requires network access and is slow"]
fn test_git_remote_github_folder_url_input() -> Result<(), Box<dyn std::error::Error>> {
let repo_folder_url = "https://github.com/git-fixtures/basic/tree/master/go";
dircat_cmd()
.arg(repo_folder_url)
.assert()
.success()
.stdout(predicate::str::contains("## File: example.go"))
.stdout(predicate::str::contains("package harvesterd"))
.stdout(predicate::str::contains("## File: CHANGELOG").not())
.stdout(predicate::str::contains("## File: LICENSE").not());
Ok(())
}
#[test]
fn test_git_clone_specific_tag() -> Result<(), Box<dyn std::error::Error>> {
let source_repo_dir = setup_local_git_repo_with_tags()?;
let repo_path_str = source_repo_dir.path().to_str().unwrap();
#[cfg(windows)]
let repo_url = format!("file:///{}", repo_path_str.replace('\\', "/"));
#[cfg(not(windows))]
let repo_url = format!("file://{}", repo_path_str);
let temp_cache = tempdir()?;
dircat_cmd()
.arg(&repo_url)
.arg("--git-branch") .arg("v1.0")
.env("DIRCAT_TEST_CACHE_DIR", temp_cache.path())
.assert()
.success()
.stdout(predicate::str::contains("## File: README.md"))
.stdout(predicate::str::contains("# Test Repo v1"))
.stdout(predicate::str::contains("## File: src/main.rs").not())
.stdout(predicate::str::contains("fn main() {} // v2").not());
Ok(())
}