//! A command-line tool for creating large scale changes in the Android tree. mod cli; mod repo;
usecrate::cli::args::{Cli, Commands, CommitArgs, Granularity, UploadArgs}; usecrate::repo::runner::{
add_all_git_files, add_git_file, command_exists, commit_git_files, find_project_for_branch,
get_repo_status, git_checkout_new_branch, start_repo_branch, upload_repo_branch,
}; use clap::Parser; use std::collections::HashMap; use std::env; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::process::Command;
fn main() { let cli = Cli::parse();
if !command_exists("repo") {
eprintln!("Error: 'repo' command not found. Please make sure it is in your PATH.");
std::process::exit(1);
} if !command_exists("git") {
eprintln!("Error: 'git' command not found. Please make sure it is in your PATH.");
std::process::exit(1);
}
/// Prompts the user for confirmation to run a command. pubfn prompt_for_confirmation(command: &str) -> bool {
print!("About to run: `{}`. Continue? [y/N] ", command);
io::stdout().flush().unwrap(); letmut input = String::new();
io::stdin().read_line(&mut input).expect("Failed to read line");
input.trim().eq_ignore_ascii_case("y")
}
fn handle_upload(args: &UploadArgs, interactive: bool, verbose: bool) { let android_build_top =
env::var("ANDROID_BUILD_TOP").expect("ANDROID_BUILD_TOP environment variable not set.");
if verbose {
println!("[VERBOSE] ANDROID_BUILD_TOP is: {}", android_build_top);
}
iflet Some(project_path) = find_project_for_branch(&args.branch, &android_build_top) {
println!("Found branch {} in project: {}", args.branch, project_path); let full_project_path = Path::new(&android_build_top).join(project_path);
upload_repo_branch(&args.topic, &args.hashtag, &full_project_path, interactive, args.yes);
} else {
eprintln!("Error: Branch '{}' not found in any project.", args.branch);
std::process::exit(1);
}
}
fn handle_commit(args: &CommitArgs, interactive: bool, verbose: bool) { let android_build_top =
env::var("ANDROID_BUILD_TOP").expect("ANDROID_BUILD_TOP environment variable not set.");
if verbose {
println!("[VERBOSE] ANDROID_BUILD_TOP is: {}", android_build_top);
}
let (dirty_projects_on_branches, dirty_projects_no_branch) =
get_dirty_projects(&android_build_top);
if !dirty_projects_on_branches.is_empty() {
eprintln!("Error: The following dirty projects are already on a branch. Please checkout the tip-of-tree branch before proceeding:"); for (project, _) in dirty_projects_on_branches {
eprintln!(" - {}", project);
}
std::process::exit(1);
}
if args.dry_run {
println!("-- DRY RUN --\n"); if dirty_projects_no_branch.is_empty() {
println!("No dirty projects found."); return;
}
for (project_path, files) in &dirty_projects_no_branch { let num_commits = process_project(
project_path,
files,
&android_build_top,
args, "<dry-run>",
interactive, true, // dry_run = true
);
total_commits += num_commits;
commits_per_repo.push((project_path.clone(), num_commits));
}
println!("\n-- SUMMARY --");
println!("Total projects to be modified: {}", total_repos);
println!("Total commits to be created: {}", total_commits); if !commits_per_repo.is_empty() {
println!("\nCommits per project:"); for (project_path, commits) in commits_per_repo {
println!(" - {}: {}", project_path, commits);
}
}
} else { let message = match &args.message {
Some(m) => m.clone(),
None => { let temp_file_path = Path::new(&android_build_top).join(".LSC_COMMIT_MSG.tmp");
fs::write(&temp_file_path, "").expect("Unable to create temp commit message file.");
let editor = env::var("EDITOR").unwrap_or_else(|_| "vim".to_string());
Command::new(editor).arg(&temp_file_path).status().expect("Failed to open editor.");
let commit_message = fs::read_to_string(&temp_file_path)
.expect("Unable to read commit message from file.");
fs::remove_file(&temp_file_path)
.expect("Unable to remove temp commit message file.");
if commit_message.trim().is_empty() {
eprintln!("Error: Commit message is empty. Aborting.");
std::process::exit(1);
}
commit_message
}
};
for (project_path, files) in dirty_projects_no_branch { let _ = process_project(
&project_path,
&files,
&android_build_top,
args,
&message,
interactive,
args.dry_run,
);
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.