Complete Windows compatibility overhaul with robust cross-platform SDK management. This release candidate establishes feature freeze for the 1.0.0 release. Key improvements: - Fixed Android SDK installation on Windows * Use cmd.exe wrapper for sdkmanager.bat with piped stdin * Properly reorganize cmdline-tools directory structure * Write license acceptances synchronously to avoid hangs - Fixed FTC SDK configuration * Auto-generate local.properties with Android SDK path * Escape backslashes in Kotlin build.gradle.kts strings * Support both new installs and upgrades via ensure_local_properties() - Enhanced Windows console output * Enable ANSI color support via enable_ansi_support crate * Maintain color compatibility across Windows versions - Improved error handling and debugging * Added comprehensive logging throughout SDK installation * Better context messages for troubleshooting failures Cross-platform testing verified on: - Windows 11 with Eclipse Adoptium JDK 21 - Linux (existing support maintained) Breaking changes: None This RC introduces feature freeze - subsequent 1.0.x releases will be bug fixes only. New features deferred to 1.1.0. Closes Windows compatibility milestone.
136 lines
4.1 KiB
Rust
136 lines
4.1 KiB
Rust
use std::path::Path;
|
|
use anyhow::{Result, Context};
|
|
use git2::Repository;
|
|
use colored::*;
|
|
use std::fs;
|
|
|
|
const FTC_SDK_URL: &str = "https://github.com/FIRST-Tech-Challenge/FtcRobotController.git";
|
|
const FTC_SDK_VERSION: &str = "v10.1.1";
|
|
|
|
pub fn install(sdk_path: &Path, android_sdk_path: &Path) -> Result<()> {
|
|
if sdk_path.exists() {
|
|
println!("{} FTC SDK already installed at: {}",
|
|
"✓".green(),
|
|
sdk_path.display()
|
|
);
|
|
// Make sure local.properties exists even if SDK was already installed
|
|
create_local_properties(sdk_path, android_sdk_path)?;
|
|
return check_version(sdk_path);
|
|
}
|
|
|
|
println!("{}", "Installing FTC SDK...".bright_yellow());
|
|
println!("Cloning from: {}", FTC_SDK_URL);
|
|
println!("Version: {}", FTC_SDK_VERSION);
|
|
|
|
// Clone the repository
|
|
let repo = Repository::clone(FTC_SDK_URL, sdk_path)
|
|
.context("Failed to clone FTC SDK")?;
|
|
|
|
// Checkout specific version
|
|
let obj = repo.revparse_single(FTC_SDK_VERSION)?;
|
|
repo.checkout_tree(&obj, None)?;
|
|
repo.set_head_detached(obj.id())?;
|
|
|
|
// Create local.properties with Android SDK path
|
|
create_local_properties(sdk_path, android_sdk_path)?;
|
|
|
|
println!("{} FTC SDK installed successfully", "✓".green());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn create_local_properties(sdk_path: &Path, android_sdk_path: &Path) -> Result<()> {
|
|
// Convert path to use forward slashes (works on both Windows and Unix)
|
|
let android_sdk_str = android_sdk_path
|
|
.display()
|
|
.to_string()
|
|
.replace("\\", "/");
|
|
|
|
let local_properties = format!("sdk.dir={}\n", android_sdk_str);
|
|
|
|
let properties_path = sdk_path.join("local.properties");
|
|
fs::write(&properties_path, local_properties)
|
|
.context("Failed to create local.properties")?;
|
|
|
|
println!("{} Created local.properties with Android SDK path", "✓".green());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn check_version(sdk_path: &Path) -> Result<()> {
|
|
let repo = Repository::open(sdk_path)?;
|
|
|
|
// Get current HEAD
|
|
let head = repo.head()?;
|
|
let commit = head.peel_to_commit()?;
|
|
|
|
// Try to find a tag for this commit
|
|
let tag_names = repo.tag_names(None)?;
|
|
let tags: Vec<_> = tag_names
|
|
.iter()
|
|
.filter_map(|t| t)
|
|
.collect();
|
|
|
|
println!("Current version: {}",
|
|
tags.first()
|
|
.map(|t| t.to_string())
|
|
.unwrap_or_else(|| format!("{}", commit.id()))
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn update(sdk_path: &Path) -> Result<()> {
|
|
println!("{}", "Updating FTC SDK...".bright_yellow());
|
|
|
|
let repo = Repository::open(sdk_path)
|
|
.context("FTC SDK not found or not a git repository")?;
|
|
|
|
// Fetch latest
|
|
let mut remote = repo.find_remote("origin")?;
|
|
remote.fetch(&["refs/tags/*:refs/tags/*"], None, None)?;
|
|
|
|
// Checkout latest version
|
|
let obj = repo.revparse_single(FTC_SDK_VERSION)?;
|
|
repo.checkout_tree(&obj, None)?;
|
|
repo.set_head_detached(obj.id())?;
|
|
|
|
println!("{} FTC SDK updated to {}", "✓".green(), FTC_SDK_VERSION);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn verify(sdk_path: &Path) -> Result<()> {
|
|
if !sdk_path.exists() {
|
|
anyhow::bail!("FTC SDK not found at: {}", sdk_path.display());
|
|
}
|
|
|
|
// Check for essential directories
|
|
let team_code = sdk_path.join("TeamCode");
|
|
let ftc_robot_controller = sdk_path.join("FtcRobotController");
|
|
|
|
if !team_code.exists() || !ftc_robot_controller.exists() {
|
|
anyhow::bail!("FTC SDK incomplete: missing essential directories");
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn get_version(sdk_path: &Path) -> Result<String> {
|
|
let repo = Repository::open(sdk_path)?;
|
|
let head = repo.head()?;
|
|
let commit = head.peel_to_commit()?;
|
|
|
|
// Try to find a tag
|
|
let tags = repo.tag_names(None)?;
|
|
for tag in tags.iter().flatten() {
|
|
let tag_ref = repo.find_reference(&format!("refs/tags/{}", tag))?;
|
|
if let Ok(tag_commit) = tag_ref.peel_to_commit() {
|
|
if tag_commit.id() == commit.id() {
|
|
return Ok(tag.to_string());
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(format!("commit-{}", &commit.id().to_string()[..8]))
|
|
} |