feat: Weevil v1.0.0-beta1 - FTC Project Generator
Cross-platform tool for generating clean, testable FTC robot projects without editing the SDK installation. Features: - Standalone project generation with proper separation from SDK - Per-project SDK configuration via .weevil.toml - Local unit testing support (no robot required) - Cross-platform build/deploy scripts (Linux/macOS/Windows) - Project upgrade system preserving user code - Configuration management commands - Comprehensive test suite (11 passing tests) - Zero-warning builds Architecture: - Pure Rust implementation with embedded Gradle wrapper - Projects use deployToSDK task to copy code to FTC SDK TeamCode - Git-ready projects with automatic initialization - USB and WiFi deployment with auto-detection Commands: - weevil new <name> - Create new project - weevil upgrade <path> - Update project infrastructure - weevil config <path> - View/modify project configuration - weevil sdk status/install/update - Manage SDKs Addresses the core problem: FTC's SDK structure forces students to edit framework internals instead of separating concerns like industry standard practices. Weevil enables proper software engineering workflows for robotics education.
This commit is contained in:
112
src/sdk/ftc.rs
Normal file
112
src/sdk/ftc.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
use std::path::Path;
|
||||
use anyhow::{Result, Context};
|
||||
use git2::Repository;
|
||||
use colored::*;
|
||||
|
||||
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) -> Result<()> {
|
||||
if sdk_path.exists() {
|
||||
println!("{} FTC SDK already installed at: {}",
|
||||
"✓".green(),
|
||||
sdk_path.display()
|
||||
);
|
||||
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())?;
|
||||
|
||||
println!("{} FTC SDK installed successfully", "✓".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]))
|
||||
}
|
||||
Reference in New Issue
Block a user