diff --git a/src/cli/clone.rs b/src/cli/clone.rs index a97dfa6a..56d9288e 100644 --- a/src/cli/clone.rs +++ b/src/cli/clone.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use anyhow::{bail, Context}; @@ -51,6 +51,13 @@ impl CloneCommand { name ); } + if Path::new(&folder).exists() { + bail!( + "Directory '{}' already exists. \ + Remove it or use --path to specify a different location.", + folder + ); + } println!("Using folder: {folder}"); PathBuf::from(folder) } @@ -68,21 +75,20 @@ impl CloneCommand { init.run()?; - let project_path = path.join("default.project.json5"); - let syncback = SyncbackCommand { - project: project_path, + project: PathBuf::from("default.project.json5"), input: PathBuf::from("Project.rbxl"), download: Some(self.placeid), list: false, dry_run: false, interactive: false, incremental: false, + working_dir: path.clone(), }; syncback.run(global)?; - // Commit the full project (init + syncback) in one shot + // Commit syncback result if !skip_git { let _ = Command::new("git") .args(["add", "."]) @@ -92,7 +98,7 @@ impl CloneCommand { .status(); let _ = Command::new("git") - .args(["commit", "-m", "init"]) + .args(["commit", "-m", "syncback"]) .current_dir(&path) .stdout(Stdio::null()) .stderr(Stdio::null()) diff --git a/src/cli/syncback.rs b/src/cli/syncback.rs index bf607c99..7bab7d50 100644 --- a/src/cli/syncback.rs +++ b/src/cli/syncback.rs @@ -74,14 +74,28 @@ pub struct SyncbackCommand { /// project layout that exactly matches the input file, removing any orphaned files. #[clap(long, short = 'n')] pub incremental: bool, + + /// Base directory for resolving relative paths (project, input). + /// Defaults to the current working directory. + #[clap(long, hide = true, default_value = ".")] + pub working_dir: PathBuf, } impl SyncbackCommand { pub fn run(&self, global: GlobalOptions) -> anyhow::Result<()> { - let path_old = resolve_path(&self.project); + let base = resolve_path(&self.working_dir); + let path_old = if self.project.is_absolute() { + self.project.clone() + } else { + base.join(&self.project) + }; // Determine if we need to download the input file - let resolved_input = resolve_path(&self.input); + let resolved_input = if self.input.is_absolute() { + self.input.clone() + } else { + base.join(&self.input) + }; let _temp_file: Option; // Track if we should delete the input file after successful syncback // (when using default Project.rbxl and file exists locally) @@ -111,11 +125,11 @@ impl SyncbackCommand { _temp_file = None; // If using default input path, mark for deletion after success delete_input_after_syncback = if self.input.as_os_str() == "Project.rbxl" { - Some(resolved_input.clone().into_owned()) + Some(resolved_input.clone()) } else { None }; - resolved_input.into_owned() + resolved_input } None => { // No --download flag, input file doesn't exist: auto-download diff --git a/src/syncback/mod.rs b/src/syncback/mod.rs index 9a7c17ea..33f9cc6d 100644 --- a/src/syncback/mod.rs +++ b/src/syncback/mod.rs @@ -113,8 +113,13 @@ pub fn syncback_loop_with_stats( // TODO: Add a better way to tell if the root of a project is a directory let skip_pruning = if let Some(path) = &project.tree.path { + let resolved = if path.path().is_absolute() { + path.path().to_path_buf() + } else { + project.folder_location().join(path.path()) + }; let middleware = - Middleware::middleware_for_path(vfs, &project.sync_rules, path.path()).unwrap(); + Middleware::middleware_for_path(vfs, &project.sync_rules, &resolved).unwrap(); if let Some(middleware) = middleware { middleware.is_dir() } else { diff --git a/tests/rojo_test/internable.rs b/tests/rojo_test/internable.rs index f5ab9a4c..a409071e 100644 --- a/tests/rojo_test/internable.rs +++ b/tests/rojo_test/internable.rs @@ -38,7 +38,10 @@ impl Internable for ReadResponse<'_> { redactions.intern(root_id); let root_instance = self.instances.get(&root_id).unwrap(); - intern_variant_refs(redactions, root_instance.properties.values().map(|v| v.as_ref())); + intern_variant_refs( + redactions, + root_instance.properties.values().map(|v| v.as_ref()), + ); for &child_id in root_instance.children.iter() { self.intern(redactions, child_id);