Add --proxy and --no-proxy global flags to control HTTP/HTTPS proxy usage for all network operations (SDK installs, FTC SDK clone/fetch, Android SDK download). Proxy resolution priority: 1. --no-proxy → go direct, ignore everything 2. --proxy <url> → use the specified proxy 3. HTTPS_PROXY / HTTP_PROXY env vars (auto-detected) 4. Nothing → go direct Key implementation details: - reqwest client is always built through ProxyConfig::client() rather than Client::new(), so --no-proxy actively suppresses env-var auto-detection instead of just being a no-op. - git2/libgit2 has its own HTTP transport that doesn't use reqwest. GitProxyGuard is an RAII guard that temporarily sets/clears the HTTPS_PROXY env vars around clone and fetch operations, then restores the previous state on drop. This avoids mutating ~/.gitconfig. - Gradle wrapper reads HTTPS_PROXY natively; no programmatic intervention needed. - All network failure paths now print offline/air-gapped installation instructions automatically, covering manual SDK installs and Gradle distribution download. Closes: v1.1.0 proxy support milestone
105 lines
4.4 KiB
Rust
105 lines
4.4 KiB
Rust
use anyhow::{Result, bail};
|
|
use std::path::PathBuf;
|
|
use colored::*;
|
|
|
|
use crate::sdk::SdkConfig;
|
|
use crate::sdk::proxy::ProxyConfig;
|
|
use crate::project::ProjectBuilder;
|
|
|
|
pub fn create_project(
|
|
name: &str,
|
|
ftc_sdk: Option<&str>,
|
|
android_sdk: Option<&str>,
|
|
_proxy: &ProxyConfig,
|
|
) -> Result<()> {
|
|
// _proxy is threaded through here so future flows (e.g. auto-install on
|
|
// missing SDK) can use it without changing the call site in main.
|
|
// Validate project name
|
|
if name.is_empty() {
|
|
bail!("Project name cannot be empty");
|
|
}
|
|
|
|
if !name.chars().all(|c| c.is_alphanumeric() || c == '-' || c == '_') {
|
|
bail!("Project name must contain only alphanumeric characters, hyphens, and underscores");
|
|
}
|
|
|
|
let project_path = PathBuf::from(name);
|
|
|
|
// Check if project already exists
|
|
if project_path.exists() {
|
|
bail!(
|
|
"{}\n\nDirectory already exists: {}\n\nTo upgrade: weevil upgrade {}",
|
|
"Project Already Exists".red().bold(),
|
|
project_path.display(),
|
|
name
|
|
);
|
|
}
|
|
|
|
println!("{}", format!("Creating FTC project: {}", name).bright_green().bold());
|
|
println!();
|
|
|
|
// Check system health FIRST
|
|
println!("{}", "Checking system prerequisites...".bright_yellow());
|
|
let health = crate::commands::doctor::check_system_health()?;
|
|
|
|
if !health.is_healthy() {
|
|
println!();
|
|
println!("{}", "═══════════════════════════════════════════════════════════".bright_red());
|
|
println!("{}", " ✗ System Setup Required".bright_red().bold());
|
|
println!("{}", "═══════════════════════════════════════════════════════════".bright_red());
|
|
println!();
|
|
println!("{}", "Missing required components:".bright_yellow().bold());
|
|
|
|
if !health.java_ok {
|
|
println!(" {} Java JDK", "✗".red());
|
|
}
|
|
if !health.ftc_sdk_ok {
|
|
println!(" {} FTC SDK", "✗".red());
|
|
}
|
|
if !health.android_sdk_ok {
|
|
println!(" {} Android SDK", "✗".red());
|
|
}
|
|
|
|
println!();
|
|
println!("{}", "Before creating a project, you need to set up your development environment.".bright_yellow());
|
|
println!();
|
|
println!("{}", "Run this command to install required components:".bright_yellow().bold());
|
|
println!(" {}", "weevil setup".bright_cyan());
|
|
println!();
|
|
println!("{}", "Then try creating your project again:".bright_yellow().bold());
|
|
println!(" {}", format!("weevil new {}", name).bright_cyan());
|
|
println!();
|
|
|
|
bail!("System setup required");
|
|
}
|
|
|
|
println!("{} All prerequisites met", "✓".green());
|
|
println!();
|
|
|
|
// Setup or verify SDK configuration
|
|
let sdk_config = SdkConfig::with_paths(ftc_sdk, android_sdk)?;
|
|
|
|
println!("{}", "Creating project structure...".bright_yellow());
|
|
|
|
// Build the project
|
|
let builder = ProjectBuilder::new(name, &sdk_config)?;
|
|
builder.create(&project_path, &sdk_config)?;
|
|
|
|
println!();
|
|
println!("{}", "═══════════════════════════════════════════════════════════".bright_green());
|
|
println!("{}", format!(" ✓ Project Created: {}", name).bright_green().bold());
|
|
println!("{}", "═══════════════════════════════════════════════════════════".bright_green());
|
|
println!();
|
|
println!("FTC SDK: {}", sdk_config.ftc_sdk_path.display());
|
|
println!("Version: {}", crate::sdk::ftc::get_version(&sdk_config.ftc_sdk_path).unwrap_or_else(|_| "unknown".to_string()));
|
|
println!();
|
|
println!("{}", "Next steps:".bright_yellow().bold());
|
|
println!(" 1. {}", format!("cd {}", name).bright_cyan());
|
|
println!(" 2. Review README.md for project structure");
|
|
println!(" 3. Start coding in src/main/java/robot/");
|
|
println!(" 4. Run tests: {}", "./gradlew test".bright_cyan());
|
|
println!(" 5. Deploy to robot: {}", format!("weevil deploy {}", name).bright_cyan());
|
|
println!();
|
|
|
|
Ok(())
|
|
} |