-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Support for Submodule Versioning #23
Changes from 13 commits
c7197c1
761a583
e7247ec
b1d0520
f7ad9e4
ea2884f
da3a7b4
043f387
7f9d730
0d4e1ef
4fdaa93
30d74d2
fd0925d
0dd1bb5
111b54e
f5ba079
0e92ea6
dc059b8
b79c25b
c6f8ba9
386a08e
59f6c35
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[submodule "test-child-repo"] | ||
path = test-child-repo | ||
url = [email protected]:baxterjo/test-child-repo.git | ||
[submodule "test_outer_directory/test-child-repo"] | ||
path = test_outer_directory/test-child-repo | ||
url = [email protected]:baxterjo/test-child-repo.git |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,165 @@ | ||||||||||||||||||||||||||||||||||||||
extern crate proc_macro; | ||||||||||||||||||||||||||||||||||||||
use crate::canonicalize_path; | ||||||||||||||||||||||||||||||||||||||
use crate::git_dependencies; | ||||||||||||||||||||||||||||||||||||||
use crate::utils::run_git; | ||||||||||||||||||||||||||||||||||||||
use proc_macro2::{Span, TokenStream as TokenStream2}; | ||||||||||||||||||||||||||||||||||||||
use quote::{quote, ToTokens}; | ||||||||||||||||||||||||||||||||||||||
use std::ffi::OsStr; | ||||||||||||||||||||||||||||||||||||||
use std::path::Path; | ||||||||||||||||||||||||||||||||||||||
use std::process::Command; | ||||||||||||||||||||||||||||||||||||||
use syn::{ | ||||||||||||||||||||||||||||||||||||||
bracketed, | ||||||||||||||||||||||||||||||||||||||
parse::{Parse, ParseStream}, | ||||||||||||||||||||||||||||||||||||||
punctuated::Punctuated, | ||||||||||||||||||||||||||||||||||||||
token::{Comma, Eq}, | ||||||||||||||||||||||||||||||||||||||
Expr, Ident, LitStr, | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
macro_rules! error { | ||||||||||||||||||||||||||||||||||||||
($($args:tt)*) => { | ||||||||||||||||||||||||||||||||||||||
syn::Error::new(Span::call_site(), format!($($args)*)) | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
#[derive(Default)] | ||||||||||||||||||||||||||||||||||||||
pub(crate) struct GitModArgs { | ||||||||||||||||||||||||||||||||||||||
args: Option<Punctuated<LitStr, Comma>>, | ||||||||||||||||||||||||||||||||||||||
prefix: Option<LitStr>, | ||||||||||||||||||||||||||||||||||||||
suffix: Option<LitStr>, | ||||||||||||||||||||||||||||||||||||||
fallback: Option<Expr>, | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
impl Parse for GitModArgs { | ||||||||||||||||||||||||||||||||||||||
fn parse(input: ParseStream) -> syn::Result<Self> { | ||||||||||||||||||||||||||||||||||||||
let mut result = GitModArgs::default(); | ||||||||||||||||||||||||||||||||||||||
loop { | ||||||||||||||||||||||||||||||||||||||
if input.is_empty() { | ||||||||||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
let ident: Ident = input.parse()?; | ||||||||||||||||||||||||||||||||||||||
let _: Eq = input.parse()?; | ||||||||||||||||||||||||||||||||||||||
let check_dup = |dup: bool| { | ||||||||||||||||||||||||||||||||||||||
if dup { | ||||||||||||||||||||||||||||||||||||||
Err(error!("`{} = ` can only appear once", ident)) | ||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||
Ok(()) | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
match ident.to_string().as_str() { | ||||||||||||||||||||||||||||||||||||||
"args" => { | ||||||||||||||||||||||||||||||||||||||
check_dup(result.args.is_some())?; | ||||||||||||||||||||||||||||||||||||||
let content; | ||||||||||||||||||||||||||||||||||||||
bracketed!(content in input); | ||||||||||||||||||||||||||||||||||||||
result.args = Some(Punctuated::parse_terminated(&content)?); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
"prefix" => { | ||||||||||||||||||||||||||||||||||||||
check_dup(result.prefix.is_some())?; | ||||||||||||||||||||||||||||||||||||||
result.prefix = Some(input.parse()?); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
"suffix" => { | ||||||||||||||||||||||||||||||||||||||
check_dup(result.suffix.is_some())?; | ||||||||||||||||||||||||||||||||||||||
result.suffix = Some(input.parse()?); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
"fallback" => { | ||||||||||||||||||||||||||||||||||||||
check_dup(result.fallback.is_some())?; | ||||||||||||||||||||||||||||||||||||||
result.fallback = Some(input.parse()?); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
x => Err(error!("Unexpected argument name `{}`", x))?, | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
if input.is_empty() { | ||||||||||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
let _: Comma = input.parse()?; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
Ok(result) | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
pub(crate) fn git_version_modules_impl(args: GitModArgs) -> syn::Result<TokenStream2> { | ||||||||||||||||||||||||||||||||||||||
let modules = match get_modules() { | ||||||||||||||||||||||||||||||||||||||
Ok(x) => x, | ||||||||||||||||||||||||||||||||||||||
Err(err) => return Err(error!("{}", err)), | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
let mut describe_paths: Vec<(String, String)> = vec![]; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
for path in modules.into_iter() { | ||||||||||||||||||||||||||||||||||||||
baxterjo marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||
let path_obj = Path::new(&path); | ||||||||||||||||||||||||||||||||||||||
let path_obj = canonicalize_path(path_obj)?; | ||||||||||||||||||||||||||||||||||||||
describe_paths.push((path, path_obj)); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
let git_describe_args = args.args.map_or_else( | ||||||||||||||||||||||||||||||||||||||
|| vec!["--always".to_string(), "--dirty=-modified".to_string()], | ||||||||||||||||||||||||||||||||||||||
|list| list.iter().map(|x| x.value()).collect(), | ||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
let prefix = match args.prefix { | ||||||||||||||||||||||||||||||||||||||
Some(x) => x.value(), | ||||||||||||||||||||||||||||||||||||||
_ => "".to_string(), | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
let suffix = match args.suffix { | ||||||||||||||||||||||||||||||||||||||
Some(x) => x.value(), | ||||||||||||||||||||||||||||||||||||||
_ => "".to_string(), | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
match describe_modules(describe_paths, &git_describe_args, prefix, suffix) { | ||||||||||||||||||||||||||||||||||||||
Ok(result) => { | ||||||||||||||||||||||||||||||||||||||
let dependencies = git_dependencies()?; | ||||||||||||||||||||||||||||||||||||||
let (paths, versions) = result; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
Ok(quote!({ | ||||||||||||||||||||||||||||||||||||||
#dependencies; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
[#((#paths, #versions)),*] | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
})) | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
Err(_) if args.fallback.is_some() => Ok(args.fallback.to_token_stream()), | ||||||||||||||||||||||||||||||||||||||
Err(e) => Err(error!("{}", e)), | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// Run `git submodule foreach` command to discover submodules in the project. | ||||||||||||||||||||||||||||||||||||||
fn get_modules() -> Result<Vec<String>, String> { | ||||||||||||||||||||||||||||||||||||||
let mut args: Vec<String> = "submodule foreach --quiet --recursive" | ||||||||||||||||||||||||||||||||||||||
.to_string() | ||||||||||||||||||||||||||||||||||||||
.split(' ') | ||||||||||||||||||||||||||||||||||||||
.map(|x| x.to_string()) | ||||||||||||||||||||||||||||||||||||||
.collect(); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
args.push("echo $displaypath".to_string()); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
let result = run_git("git submodule", Command::new("git").args(args))?; | ||||||||||||||||||||||||||||||||||||||
Comment on lines
+127
to
+135
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lemme check real quick. Edit: Yep! It works. The shell that executes the command must be implemented by git. Tested on Powershell and Command Prompt There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok :) |
||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
Ok(result.split('\n').map(|x| x.to_string()).collect()) | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// Run `git describe` for each submodule to | ||||||||||||||||||||||||||||||||||||||
fn describe_modules<I, S>( | ||||||||||||||||||||||||||||||||||||||
paths: Vec<(String, String)>, | ||||||||||||||||||||||||||||||||||||||
describe_args: I, | ||||||||||||||||||||||||||||||||||||||
prefix: String, | ||||||||||||||||||||||||||||||||||||||
suffix: String, | ||||||||||||||||||||||||||||||||||||||
) -> Result<(Vec<String>, Vec<String>), String> | ||||||||||||||||||||||||||||||||||||||
where | ||||||||||||||||||||||||||||||||||||||
I: IntoIterator<Item = S> + Clone, | ||||||||||||||||||||||||||||||||||||||
S: AsRef<OsStr>, | ||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||
let mut paths_out: Vec<String> = vec![]; | ||||||||||||||||||||||||||||||||||||||
let mut versions: Vec<String> = vec![]; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
for (rel_path, abs_path) in paths.into_iter() { | ||||||||||||||||||||||||||||||||||||||
let result = run_git( | ||||||||||||||||||||||||||||||||||||||
"git describe", | ||||||||||||||||||||||||||||||||||||||
Command::new("git") | ||||||||||||||||||||||||||||||||||||||
.current_dir(abs_path) | ||||||||||||||||||||||||||||||||||||||
.arg("describe") | ||||||||||||||||||||||||||||||||||||||
.args(describe_args.clone()), | ||||||||||||||||||||||||||||||||||||||
)?; | ||||||||||||||||||||||||||||||||||||||
paths_out.push(rel_path); | ||||||||||||||||||||||||||||||||||||||
versions.push(format!("{}{}{}", prefix, result, suffix)) | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
Ok((paths_out, versions)) | ||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be nice to set up a custom testing repo for this instead of adding submodules. But I will take care of this part, since I also think they should be in the same organization :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed submodules and added more effective test. Also fixed some issues that popped up when this macro is ran in a project with no submodules.