张兴洋
2 years ago
commit
c0328b5e1a
4 changed files with 569 additions and 0 deletions
@ -0,0 +1,2 @@ |
|||
/target |
|||
.vscode |
@ -0,0 +1,238 @@ |
|||
# This file is automatically @generated by Cargo. |
|||
# It is not intended for manual editing. |
|||
version = 3 |
|||
|
|||
[[package]] |
|||
name = "atty" |
|||
version = "0.2.14" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" |
|||
dependencies = [ |
|||
"hermit-abi", |
|||
"libc", |
|||
"winapi", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "autocfg" |
|||
version = "1.1.0" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" |
|||
|
|||
[[package]] |
|||
name = "bitflags" |
|||
version = "1.3.2" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" |
|||
|
|||
[[package]] |
|||
name = "clap" |
|||
version = "3.1.8" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c" |
|||
dependencies = [ |
|||
"atty", |
|||
"bitflags", |
|||
"clap_derive", |
|||
"indexmap", |
|||
"lazy_static", |
|||
"os_str_bytes", |
|||
"strsim", |
|||
"termcolor", |
|||
"textwrap", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "clap_derive" |
|||
version = "3.1.7" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" |
|||
dependencies = [ |
|||
"heck", |
|||
"proc-macro-error", |
|||
"proc-macro2", |
|||
"quote", |
|||
"syn", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "fcp" |
|||
version = "0.1.0" |
|||
dependencies = [ |
|||
"clap", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "hashbrown" |
|||
version = "0.11.2" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" |
|||
|
|||
[[package]] |
|||
name = "heck" |
|||
version = "0.4.0" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" |
|||
|
|||
[[package]] |
|||
name = "hermit-abi" |
|||
version = "0.1.19" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" |
|||
dependencies = [ |
|||
"libc", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "indexmap" |
|||
version = "1.8.1" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" |
|||
dependencies = [ |
|||
"autocfg", |
|||
"hashbrown", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "lazy_static" |
|||
version = "1.4.0" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" |
|||
|
|||
[[package]] |
|||
name = "libc" |
|||
version = "0.2.121" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" |
|||
|
|||
[[package]] |
|||
name = "memchr" |
|||
version = "2.4.1" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" |
|||
|
|||
[[package]] |
|||
name = "os_str_bytes" |
|||
version = "6.0.0" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" |
|||
dependencies = [ |
|||
"memchr", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "proc-macro-error" |
|||
version = "1.0.4" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" |
|||
dependencies = [ |
|||
"proc-macro-error-attr", |
|||
"proc-macro2", |
|||
"quote", |
|||
"syn", |
|||
"version_check", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "proc-macro-error-attr" |
|||
version = "1.0.4" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" |
|||
dependencies = [ |
|||
"proc-macro2", |
|||
"quote", |
|||
"version_check", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "proc-macro2" |
|||
version = "1.0.36" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" |
|||
dependencies = [ |
|||
"unicode-xid", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "quote" |
|||
version = "1.0.17" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" |
|||
dependencies = [ |
|||
"proc-macro2", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "strsim" |
|||
version = "0.10.0" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" |
|||
|
|||
[[package]] |
|||
name = "syn" |
|||
version = "1.0.90" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f" |
|||
dependencies = [ |
|||
"proc-macro2", |
|||
"quote", |
|||
"unicode-xid", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "termcolor" |
|||
version = "1.1.3" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" |
|||
dependencies = [ |
|||
"winapi-util", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "textwrap" |
|||
version = "0.15.0" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" |
|||
|
|||
[[package]] |
|||
name = "unicode-xid" |
|||
version = "0.2.2" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" |
|||
|
|||
[[package]] |
|||
name = "version_check" |
|||
version = "0.9.4" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" |
|||
|
|||
[[package]] |
|||
name = "winapi" |
|||
version = "0.3.9" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" |
|||
dependencies = [ |
|||
"winapi-i686-pc-windows-gnu", |
|||
"winapi-x86_64-pc-windows-gnu", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "winapi-i686-pc-windows-gnu" |
|||
version = "0.4.0" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" |
|||
|
|||
[[package]] |
|||
name = "winapi-util" |
|||
version = "0.1.5" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" |
|||
dependencies = [ |
|||
"winapi", |
|||
] |
|||
|
|||
[[package]] |
|||
name = "winapi-x86_64-pc-windows-gnu" |
|||
version = "0.4.0" |
|||
source = "registry+https://github.com/rust-lang/crates.io-index" |
|||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" |
@ -0,0 +1,9 @@ |
|||
[package] |
|||
name = "fcp" |
|||
version = "0.1.0" |
|||
edition = "2021" |
|||
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
|||
|
|||
[dependencies] |
|||
clap = { version = "3.1.8", features = ["derive"] } |
@ -0,0 +1,320 @@ |
|||
// Note: this requires the `derive` feature
|
|||
|
|||
extern crate clap; |
|||
|
|||
use clap::Parser; |
|||
use std::fs; |
|||
use std::path::{Path, PathBuf}; |
|||
// use std::ffi::OsStr;
|
|||
use std::fs::File; |
|||
use std::io::prelude::*; |
|||
use std::process::Command; |
|||
/// Create Compose project from template
|
|||
#[derive(Parser, Debug)] |
|||
#[clap(author, version, about, long_about = None)] |
|||
struct Args { |
|||
/// Name of your project. It's be converted to lowercases as part of project package name.
|
|||
#[clap(short, long)] |
|||
name: String, |
|||
/// organization of your project, should be like com.fcp. It'll be used as part of project package name.
|
|||
#[clap(short, long, default_value = "com.fcp")] |
|||
organization: String, |
|||
/// Path of your template, default is ./template
|
|||
#[clap(short, long, default_value = "./template")] |
|||
template: String, |
|||
/// Path of your output project, default is current folder.
|
|||
#[clap(short, long, default_value = ".")] |
|||
destination: String, |
|||
} |
|||
|
|||
fn main() { |
|||
let args = Args::parse(); |
|||
|
|||
let name_lowercase = args.name.to_lowercase(); |
|||
let template_path = args.template; |
|||
let destination_path = args.destination + "/" + &args.name; |
|||
let package = args.organization + "." + &name_lowercase; |
|||
|
|||
// print!("hello project {} {}", name_lowercase, args.org);
|
|||
let template_dir = Path::new(&template_path); |
|||
let destination_dir = Path::new(&destination_path); |
|||
|
|||
if destination_dir.exists() { |
|||
let dir = &destination_dir.to_str(); |
|||
|
|||
println!("destination folder {:?} already exsit", dir); |
|||
|
|||
return; |
|||
} |
|||
|
|||
if !template_dir.exists() { |
|||
let dir = &template_dir.to_str(); |
|||
println!("template folder {:?} not exsit", dir); |
|||
|
|||
return; |
|||
} |
|||
let result = copy_dir_all(template_dir, &destination_dir); |
|||
|
|||
match result { |
|||
Ok(_) => { |
|||
println!("project copied!!!") |
|||
} |
|||
Err(_) => {} |
|||
} |
|||
|
|||
let package_dir = package.replace(".", "/"); |
|||
|
|||
println!("creating android test folder..."); |
|||
let android_test_folder = format!("{}/app/src/androidTest/java", &destination_path); |
|||
let path_android_test = format!("{}/{}", &android_test_folder, &package_dir); |
|||
let android_test_dir_result = fs::create_dir_all(Path::new(&path_android_test)); |
|||
println!( |
|||
"crate android test folder result {:?} ", |
|||
android_test_dir_result |
|||
); |
|||
|
|||
// let catalog_path = format!("{}/androidVersionCatalog", &destination_path);
|
|||
// let _ = fs::create_dir_all(Path::new(&catalog_path));
|
|||
|
|||
println!("creating source folder..."); |
|||
let folder_test = format!("{}/app/src/test/java", &destination_path); |
|||
let path_test = format!("{}/{}", &folder_test, &package_dir); |
|||
let test_dir_result = fs::create_dir_all(Path::new(&path_test)); |
|||
println!("crate unit test folder result {:?} ", test_dir_result); |
|||
|
|||
println!("creating source folder..."); |
|||
let java_folder = format!("{}/app/src/main/java", &destination_path); |
|||
let path_source = format!("{}/{}", &java_folder, &package_dir); |
|||
let source_dir_result = fs::create_dir_all(Path::new(&path_source)); |
|||
|
|||
println!("crate source folder result {:?} ", source_dir_result); |
|||
|
|||
println!("moving source files..."); |
|||
let source_dir = format!("{}/source", java_folder); |
|||
let source_dir = Path::new(&source_dir); |
|||
let _r = copy_and_remove(&source_dir, &path_source); |
|||
|
|||
let source_dir = format!("{}/source", &android_test_folder); |
|||
let source_dir = Path::new(&source_dir); |
|||
let _r = copy_and_remove(&source_dir, &path_android_test); |
|||
|
|||
let source_dir = format!("{}/source", &folder_test); |
|||
let source_dir = Path::new(&source_dir); |
|||
let _r = copy_and_remove(&source_dir, &path_test); |
|||
|
|||
println!("source files moved"); |
|||
|
|||
println!("replacing placeholders..."); |
|||
let _r = replace_placeholders(destination_dir, &package, &args.name, &name_lowercase); |
|||
|
|||
println!("placeholders replaced..."); |
|||
|
|||
println!("integrating version catalog..."); |
|||
let which_shell = if cfg!(target_os = "windows") { |
|||
"powershell" |
|||
} else { |
|||
"sh" |
|||
}; |
|||
let _ = format!("cannot enter path {}", destination_path); |
|||
// let _ = Command::new(&which_shell)
|
|||
// .arg("cd")
|
|||
// .arg(&destination_path)
|
|||
// .status()
|
|||
// .expect(&err);
|
|||
|
|||
let _ = Command::new(&which_shell) |
|||
.current_dir(Path::new(&destination_path)) |
|||
.arg("git") |
|||
.arg("init") |
|||
.status() |
|||
.expect("cannot add init git"); |
|||
|
|||
|
|||
// let _ = Command::new(&which_shell)
|
|||
// .current_dir(Path::new(&destination_path))
|
|||
// .arg("git")
|
|||
// .arg("config")
|
|||
// .arg("core.filemode=false")
|
|||
// .status()
|
|||
// .expect("cannot add init git");
|
|||
|
|||
// let _ = Command::new(&which_shell)
|
|||
// .current_dir(Path::new(&destination_path))
|
|||
// .arg("git")
|
|||
// .arg("rm")
|
|||
// .arg("-r")
|
|||
// .arg("--cached")
|
|||
// .arg("androidVersionCatalog")
|
|||
// .status()
|
|||
// .expect("cannot remove cached dir");
|
|||
|
|||
let _ = Command::new(&which_shell) |
|||
.current_dir(Path::new(&destination_path)) |
|||
.arg("git") |
|||
.arg("submodule") |
|||
.arg("add") |
|||
.arg("http://git.cnyanglao.com:6666/JarvanMo/AndroidVersionCatalog.git") |
|||
.arg("androidVersionCatalog") |
|||
.status() |
|||
.expect("cannot add submodule"); |
|||
|
|||
|
|||
// keytool -genkeypair -alias $formatted_project_name -keyalg RSA -keypass $key_pass -storepass $stor_epass -keysize 2048 -keystore $jks_file_name -validity 18250
|
|||
|
|||
let alias = format!("-alias {}", args.name); |
|||
let key_pass = format!("-keypass {}123456", name_lowercase); |
|||
let store_pass = format!("-storepass {}123456", name_lowercase); |
|||
let keystore = format!("-keystore {}/app/{}.jks", &destination_path, name_lowercase); |
|||
// println!("--> {} {} {} {}", alias, key_pass, store_pass, keystore);
|
|||
let _ = Command::new(&which_shell) |
|||
.arg("keytool") |
|||
.arg("-genkeypair") |
|||
.arg(alias) |
|||
.arg("-keyalg RSA") |
|||
.arg(key_pass) |
|||
.arg(store_pass) |
|||
.arg("-keysize 2048") |
|||
.arg(keystore) |
|||
.arg("-validity 18250") |
|||
.status(); |
|||
// let output = String::from_utf8(output.stdout);
|
|||
// println!("craete jks {:?}", output.unwrap());
|
|||
println!("finished!!!") |
|||
} |
|||
|
|||
pub fn copy_dir_all<U: AsRef<Path>, V: AsRef<Path>>(from: U, to: V) -> Result<(), std::io::Error> { |
|||
let mut stack = Vec::new(); |
|||
stack.push(PathBuf::from(from.as_ref())); |
|||
|
|||
let output_root = PathBuf::from(to.as_ref()); |
|||
let input_root = PathBuf::from(from.as_ref()).components().count(); |
|||
|
|||
while let Some(working_path) = stack.pop() { |
|||
println!("process: {:?}", &working_path); |
|||
|
|||
// Generate a relative path
|
|||
let src: PathBuf = working_path.components().skip(input_root).collect(); |
|||
|
|||
// Create a destination if missing
|
|||
let dest = if src.components().count() == 0 { |
|||
output_root.clone() |
|||
} else { |
|||
output_root.join(&src) |
|||
}; |
|||
if fs::metadata(&dest).is_err() { |
|||
println!(" mkdir: {:?}", dest); |
|||
fs::create_dir_all(&dest)?; |
|||
} |
|||
|
|||
for entry in fs::read_dir(working_path)? { |
|||
let entry = entry?; |
|||
let path = entry.path(); |
|||
if path.is_dir() { |
|||
stack.push(path); |
|||
} else { |
|||
match path.file_name() { |
|||
Some(filename) => { |
|||
let dest_path = dest.join(filename); |
|||
println!(" copy: {:?} -> {:?}", &path, &dest_path); |
|||
fs::copy(&path, &dest_path)?; |
|||
} |
|||
None => { |
|||
println!("failed: {:?}", path); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
Ok(()) |
|||
} |
|||
|
|||
fn copy_and_remove<U: AsRef<Path>, V: AsRef<Path>>(from: U, to: V) -> Result<(), std::io::Error> { |
|||
let result = copy_dir_all(&from, to); |
|||
|
|||
match result { |
|||
Ok(_) => { |
|||
let result = fs::remove_dir_all(from); |
|||
match result { |
|||
Ok(_) => Ok(()), |
|||
Err(e) => Err(e), |
|||
} |
|||
} |
|||
Err(e) => Err(e), |
|||
} |
|||
} |
|||
|
|||
pub fn replace_placeholders<U: AsRef<Path>>( |
|||
from: U, |
|||
package: &str, |
|||
project_name: &str, |
|||
project_name_lowercase: &String, |
|||
) -> Result<(), std::io::Error> { |
|||
const PLACEHOLDER_PACKAGE: &str = "###package###"; |
|||
const PLACEHOLDER_PROJECTNAME: &str = "###ProjectName###"; |
|||
const PLACEHOLDER_STORE_FILE: &str = "###StoreFile###"; |
|||
const PLACEHOLDER_STORE_PASSWORD: &str = "###StorePassword###"; |
|||
const PLACEHOLDER_KEY_ALIAS: &str = "###KeyAlias###"; |
|||
const PLACEHOLDER_KEY_PASSWORD: &str = "###KeyPassword###"; |
|||
|
|||
let mut stack = Vec::new(); |
|||
stack.push(PathBuf::from(from.as_ref())); |
|||
|
|||
while let Some(working_path) = stack.pop() { |
|||
println!("replacing: {:?}", &working_path); |
|||
|
|||
for entry in fs::read_dir(working_path)? { |
|||
let entry = entry?; |
|||
let path = entry.path(); |
|||
if path.is_dir() { |
|||
stack.push(path); |
|||
} else { |
|||
match path.file_name() { |
|||
Some(file_name) => { |
|||
if file_name.to_str().unwrap_or("").contains(".kt") |
|||
|| file_name.to_str().unwrap_or("").contains(".kts") |
|||
|| file_name.to_str().unwrap_or("").contains(".xml") |
|||
|| file_name.to_str().unwrap_or("").contains(".gradle") |
|||
{ |
|||
let content = fs::read_to_string(&path).unwrap(); |
|||
let content = content |
|||
.replace(PLACEHOLDER_PACKAGE, package) |
|||
.replace( |
|||
PLACEHOLDER_STORE_FILE, |
|||
&format!("{}.jks", project_name_lowercase), |
|||
) |
|||
.replace( |
|||
PLACEHOLDER_STORE_PASSWORD, |
|||
&format!("{}123456", project_name_lowercase), |
|||
) |
|||
.replace(PLACEHOLDER_KEY_ALIAS, project_name_lowercase) |
|||
.replace( |
|||
PLACEHOLDER_KEY_PASSWORD, |
|||
&format!("{}123456", project_name_lowercase), |
|||
) |
|||
.replace(PLACEHOLDER_PROJECTNAME, project_name); |
|||
let mut file = File::create(path).unwrap(); |
|||
file.write(content.as_bytes()).unwrap(); |
|||
} |
|||
// let suffix = path.file_stem().unwrap();
|
|||
// println!("file name--> {:?} -- {:?}",filename.to_str(),suffix.to_str())
|
|||
|
|||
// println!("file name--> {:?}",filename.to_str())
|
|||
} |
|||
None => { |
|||
println!("failed: {:?}", path); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
Ok(()) |
|||
} |
|||
|
|||
// fn get_extension_from_filename(filename: &str) -> Option<&str> {
|
|||
// Path::new(filename)
|
|||
// .extension()
|
|||
// .and_then(OsStr::to_str)
|
|||
|
|||
// }
|
Loading…
Reference in new issue