diff --git a/src/args.rs b/src/args.rs index 6423ac8..65ac4c4 100644 --- a/src/args.rs +++ b/src/args.rs @@ -7,6 +7,7 @@ use std::path::PathBuf; #[value(rename_all = "lowercase")] pub enum TargetLanguage { C, + UC, CCpp, Cpp, Rust, @@ -19,6 +20,10 @@ pub enum Platform { Native, Zephyr, RP2040, + LF3PI, + FlexPRET, + Patmos, + RIOT, } #[derive(clap::ValueEnum, Clone, Copy, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)] diff --git a/src/main.rs b/src/main.rs index 9715753..39830b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use std::process::Command; use std::{env, io}; use clap::Parser; -use git2::Repository; +use git2::{BranchType, ObjectType, Repository}; use liblingo::args::InitArgs; use liblingo::args::{BuildArgs, Command as ConsoleCommand, CommandLineArgs}; @@ -13,14 +13,7 @@ use liblingo::backends::{BatchBuildResults, BuildCommandOptions, CommandSpec}; use liblingo::package::tree::GitLock; use liblingo::package::{Config, ConfigFile}; use liblingo::util::errors::{BuildResult, LingoError}; -use liblingo::{GitCloneCapability, GitCloneError, GitUrl, WhichCapability, WhichError}; - -fn do_repo_clone(url: GitUrl, into: &std::path::Path) -> Result<(), GitCloneError> { - Repository::clone(url.into(), into).map_or_else( - |err: git2::Error| Err(GitCloneError(format!("{}", err))), - |_| Ok(()), - ) -} +use liblingo::{GitCloneAndCheckoutCap, GitCloneError, GitUrl, WhichCapability, WhichError}; fn do_which(cmd: &str) -> Result { which::which(cmd).map_err(|err| match err { @@ -42,18 +35,30 @@ fn do_clone_and_checkout( let mut git_rev = None; if let Some(git_lock) = git_tag { - let name = match git_lock { - GitLock::Tag(tag) => tag, - GitLock::Branch(branch) => branch, - GitLock::Rev(rev) => rev, + let (object, reference) = match git_lock { + GitLock::Tag(tag) => repo + .revparse_ext(&tag) + .map_err(|e| GitCloneError(format!("cannot parse rev {e}")))?, + GitLock::Branch(branch) => { + let reference = repo + .find_branch(&branch, BranchType::Remote) + .map_err(|_| GitCloneError("cannot find branch".to_string()))? + .into_reference(); + ( + reference + .peel(ObjectType::Any) + .map_err(|_| GitCloneError("cannot peel object".to_string()))?, + Some(reference), + ) + } + GitLock::Rev(rev) => repo + .revparse_ext(&rev) + .map_err(|e| GitCloneError(format!("cannot parse rev {e}")))?, }; + repo.checkout_tree(&object, None) + .map_err(|e| GitCloneError(format!("cannot checkout rev {e}")))?; // TODO: this produces hard to debug output - let (object, reference) = repo - .revparse_ext(&name) - .map_err(|_| GitCloneError("cannot parse rev".to_string()))?; - repo.checkout_tree(&object, None) - .map_err(|_| GitCloneError("cannot checkout rev".to_string()))?; match reference { // gref is an actual reference like branches or tags @@ -100,7 +105,7 @@ fn main() { &mut wrapped_config, args.command, Box::new(do_which), - Box::new(do_repo_clone), + Box::new(do_clone_and_checkout), ); match result { @@ -145,7 +150,7 @@ fn execute_command<'a>( config: &'a mut Option, command: ConsoleCommand, _which_capability: WhichCapability, - git_clone_capability: GitCloneCapability, + git_clone_capability: GitCloneAndCheckoutCap, ) -> CommandResult<'a> { match (config, command) { (_, ConsoleCommand::Init(init_config)) => { @@ -174,7 +179,7 @@ fn execute_command<'a>( } } -fn do_init(init_config: InitArgs, git_clone_capability: &GitCloneCapability) -> BuildResult { +fn do_init(init_config: InitArgs, git_clone_capability: &GitCloneAndCheckoutCap) -> BuildResult { let initial_config = ConfigFile::new_for_init_task(&init_config)?; initial_config.write(Path::new("./Lingo.toml"))?; initial_config.setup_example( diff --git a/src/package/mod.rs b/src/package/mod.rs index a138206..e6f4c6b 100644 --- a/src/package/mod.rs +++ b/src/package/mod.rs @@ -17,11 +17,13 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{env, fmt, io}; +use crate::args::TargetLanguage::UC; use crate::args::{ BuildSystem, BuildSystem::{CMake, LFC}, InitArgs, Platform, TargetLanguage, }; +use crate::package::tree::GitLock; use crate::package::{ target_properties::{ AppTargetProperties, AppTargetPropertiesFile, LibraryTargetProperties, @@ -33,7 +35,7 @@ use crate::util::{ analyzer, copy_recursively, errors::{BuildResult, LingoError}, }; -use crate::{FsReadCapability, GitCloneCapability, GitUrl, WhichCapability}; +use crate::{FsReadCapability, GitCloneAndCheckoutCap, GitUrl, WhichCapability}; /// place where are the build artifacts will be dropped pub const OUTPUT_DIRECTORY: &str = "build"; @@ -404,10 +406,23 @@ impl ConfigFile { Ok(()) } - fn setup_template_repo(&self, url: &str, clone: &GitCloneCapability) -> BuildResult { + fn setup_template_repo( + &self, + url: &str, + target_language: TargetLanguage, + clone: &GitCloneAndCheckoutCap, + ) -> BuildResult { let dir = tempdir()?; let tmp_path = dir.path(); - clone(GitUrl::from(url), tmp_path)?; + + let git_rev = if target_language == UC { + Some(GitLock::Branch("origin/reactor-uc".to_string())) + } else { + None + }; + + clone(GitUrl::from(url), tmp_path, git_rev)?; + // Copy the cloned template repo into the project directory copy_recursively(tmp_path, Path::new("."))?; // Remove temporary folder @@ -416,34 +431,57 @@ impl ConfigFile { } // Sets up a LF project with Zephyr as the target platform. - fn setup_zephyr(&self, clone: &GitCloneCapability) -> BuildResult { - let url = "https://github.com/lf-lang/lf-west-template"; - self.setup_template_repo(url, clone)?; + fn clone_and_clean( + &self, + url: &str, + target_language: TargetLanguage, + clone: &GitCloneAndCheckoutCap, + ) -> BuildResult { + self.setup_template_repo(url, target_language, clone)?; remove_file(".gitignore")?; remove_dir_all(Path::new(".git"))?; Ok(()) } - // Sets up a LF project with RP2040 MCU as the target platform. - // Initializes a repo using the lf-pico-template - fn setup_rp2040(&self, clone: &GitCloneCapability) -> BuildResult { - let url = "https://github.com/lf-lang/lf-pico-template"; - // leave git artifacts - self.setup_template_repo(url, clone)?; - Ok(()) - } - pub fn setup_example( &self, platform: Platform, target_language: TargetLanguage, - git_clone_capability: &GitCloneCapability, + git_clone_capability: &GitCloneAndCheckoutCap, ) -> BuildResult { if is_valid_location_for_project(Path::new(".")) { match platform { Platform::Native => self.setup_native(target_language), - Platform::Zephyr => self.setup_zephyr(git_clone_capability), - Platform::RP2040 => self.setup_rp2040(git_clone_capability), + Platform::Zephyr => self.clone_and_clean( + "https://github.com/lf-lang/lf-west-template", + target_language, + git_clone_capability, + ), + Platform::RP2040 => self.clone_and_clean( + "https://github.com/lf-lang/lf-pico-template", + target_language, + git_clone_capability, + ), + Platform::LF3PI => self.clone_and_clean( + "https://github.com/lf-lang/lf-3pi-template", + target_language, + git_clone_capability, + ), + Platform::FlexPRET => self.clone_and_clean( + "https://github.com/lf-lang/lf-flexpret-template", + target_language, + git_clone_capability, + ), + Platform::Patmos => self.clone_and_clean( + "https://github.com/lf-lang/lf-patmos-template", + target_language, + git_clone_capability, + ), + Platform::RIOT => self.clone_and_clean( + "https://github.com/lf-lang/lf-riot-template", + target_language, + git_clone_capability, + ), } } else { Err(Box::new(LingoError::InvalidProjectLocation(