Skip to content

Commit

Permalink
Add tests for git_submodule_versions!().
Browse files Browse the repository at this point in the history
  • Loading branch information
de-vri-es committed Dec 11, 2023
1 parent 14f3942 commit 4f513fc
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 58 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ git-version-macro = { version = "=0.3.8", path = "git-version-macro" }
[workspace]
resolver = "2"
members = ["git-version-macro"]

[dev-dependencies]
assert2 = "0.3.11"
tempfile = "3.8.1"
28 changes: 17 additions & 11 deletions git-version-macro/src/describe_submodules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ impl Parse for GitModArgs {
}
}

pub(crate) fn git_module_versions_impl(args: GitModArgs) -> syn::Result<TokenStream2> {
let mut modules = match get_modules() {
pub(crate) fn git_submodule_versions_impl(args: GitModArgs) -> syn::Result<TokenStream2> {
let mut modules = match get_submodules() {
Ok(x) => x,
Err(err) => return Err(error!("{}", err)),
};
Expand Down Expand Up @@ -106,24 +106,30 @@ pub(crate) fn git_module_versions_impl(args: GitModArgs) -> syn::Result<TokenStr
};
let fallback = args.fallback.map(|x| x.value());

match describe_modules(describe_paths, &git_describe_args, prefix, suffix, fallback) {
match describe_submodules(describe_paths, &git_describe_args, prefix, suffix, fallback) {
Ok(result) => {
let dependencies = git_dependencies()?;
let (paths, versions) = result;

Ok(quote!({
#dependencies;

[#((#paths, #versions)),*]

}))
// Ensure that the type of the empty array is still known to the compiler.
if paths.is_empty() {
Ok(quote!({
#dependencies;
[("", ""); 0]
}))
} else {
Ok(quote!({
#dependencies;
[#((#paths, #versions)),*]
}))
}
}
Err(e) => Err(error!("{}", e)),
}
}

/// Run `git submodule foreach` command to discover submodules in the project.
fn get_modules() -> Result<Vec<String>, String> {
fn get_submodules() -> Result<Vec<String>, String> {
let mut args: Vec<String> = "submodule foreach --quiet --recursive"
.to_string()
.split(' ')
Expand All @@ -138,7 +144,7 @@ fn get_modules() -> Result<Vec<String>, String> {
}

/// Run `git describe` for each submodule to get the git version with the specified args.
fn describe_modules<I, S>(
fn describe_submodules<I, S>(
paths: Vec<(String, String)>,
describe_args: I,
prefix: String,
Expand Down
4 changes: 2 additions & 2 deletions git-version-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,10 @@ fn git_version_impl(args: Args) -> syn::Result<TokenStream2> {
/// const MODULE_VERSIONS: [(&str, &str), N] = git_version_modules!(prefix = "git:", fallback = "unknown");
/// ```
#[proc_macro]
pub fn git_module_versions(input: TokenStream) -> TokenStream {
pub fn git_submodule_versions(input: TokenStream) -> TokenStream {
let args = syn::parse_macro_input!(input as describe_submodules::GitModArgs);

let tokens = match describe_submodules::git_module_versions_impl(args) {
let tokens = match describe_submodules::git_submodule_versions_impl(args) {
Ok(x) => x,
Err(e) => e.to_compile_error(),
};
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
//! These macros do not depend on libgit, but simply uses the `git` binary directly.
//! So you must have `git` installed somewhere in your `PATH`.

pub use git_version_macro::{git_module_versions, git_version};
pub use git_version_macro::{git_submodule_versions, git_version};

/// Run `git describe` at compile time with custom flags.
///
Expand Down
101 changes: 57 additions & 44 deletions tests/version.rs
Original file line number Diff line number Diff line change
@@ -1,55 +1,68 @@
use git_version::{git_describe, git_module_versions, git_version};
use std::path::PathBuf;

use assert2::{assert, let_assert};
use git_version::{git_describe, git_submodule_versions, git_version};

#[test]
fn git_describe_is_right() {
let vec = std::process::Command::new("git")
let output = std::process::Command::new("git")
.args(["describe", "--always", "--dirty=-modified"])
.output()
.expect("failed to execute git")
.stdout;
let name = std::str::from_utf8(&vec[..vec.len() - 1]).expect("non-utf8 error?!");
println!("name = {}", name);
println!("GIT_VERSION = {}", git_version!(args = ["--always", "--dirty=-modified"]));
assert_eq!(git_version!(args = ["--always", "--dirty=-modified"]), name);
assert_eq!(git_describe!("--always", "--dirty=-modified"), name);
assert_eq!(git_version!(prefix = "[", suffix = "]"), format!("[{}]", name));

let_assert!(Ok(name) = std::str::from_utf8(&output));
let name = name.trim();
assert!(git_version!(args = ["--always", "--dirty=-modified"]) == name);
assert!(git_describe!("--always", "--dirty=-modified") == name);
assert!(git_version!(prefix = "[", suffix = "]") == format!("[{}]", name));
assert!(git_submodule_versions!() == []);
}

#[test]
fn test_modules_macro_gives_expected_output() {
let vec = std::process::Command::new("git")
.args(["submodule", "foreach", "--quiet", "--recursive", "echo $displaypath"])
.output()
.expect("failed to execute git")
.stdout;
let mut submodules: Vec<String> = String::from_utf8(vec)
.expect("Failed to gather submodules for test")
.trim_end()
.to_string()
.split("\n")
.map(|str| str.to_string())
.collect();

submodules.retain(|path| path != "");

let mut expected_result: Vec<(String, String)> = vec![];
for submodule in submodules.into_iter() {
let abs_path = std::fs::canonicalize(submodule.clone()).expect("Failed to canonicalize submodule path in test");
let vec = std::process::Command::new("git")
.current_dir(abs_path)
.args(["describe", "--always", "--dirty=-modified"])
.output()
.expect("failed to execute git")
.stdout;
let name = std::str::from_utf8(&vec[..vec.len() - 1]).expect("non-utf8 error?!");
expected_result.push((submodule.clone(), name.to_string()))
}

let boxed_slice: Box<[(&str, &str)]> = expected_result
.iter()
.map(|(path, version)| (path.as_str(), version.as_str()))
.collect::<Vec<(&str, &str)>>()
.into_boxed_slice();

assert_eq!(*boxed_slice, git_module_versions!(args = ["--always", "--dirty=-modified"]));
fn test_in_external_clone() {
let_assert!(Ok(tempdir) = tempfile::tempdir());
let_assert!(Some(project_dir) = std::env::var_os("CARGO_MANIFEST_DIR"));
let_assert!(Ok(project_dir) = PathBuf::from(project_dir).canonicalize());
let_assert!(Ok(target_dir) = PathBuf::from(env!("CARGO_TARGET_TMPDIR")).canonicalize());
let target_dir = target_dir.join("tests_target");

let_assert!(Ok(result) = std::process::Command::new("git")
.arg("clone")
.arg("-b")
.arg("test-root")
.arg(&project_dir)
.arg(tempdir.path())
.status()
);
assert!(result.success(), "git clone: {result:?}");

let_assert!(Ok(result) = std::process::Command::new("git")
.current_dir(&tempdir)
.arg("-c")
.arg("protocol.file.allow=always")
.arg("submodule")
.arg("update")
.arg("--init")
.status()
);
assert!(result.success(), "git submodule update --init: {result:?}");

let_assert!(Ok(result) = std::process::Command::new("cargo")
.current_dir(&tempdir)
.arg("add")
.arg("--path")
.arg(&project_dir)
.status()
);
assert!(result.success(), "cargo test: {result:?}");

let_assert!(Ok(result) = std::process::Command::new("cargo")
.current_dir(&tempdir)
.arg("test")
.arg("--target-dir")
.arg(target_dir)
.status()
);
assert!(result.success(), "cargo test: {result:?}");
}

0 comments on commit 4f513fc

Please sign in to comment.