From 1173102be67fe2958bb91aa16bfe2e6598ee558c Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Wed, 5 Feb 2025 15:20:52 -0500 Subject: [PATCH 1/8] Trying out a turbo clone mvp --- crates/turborepo-lib/src/cli/error.rs | 2 ++ crates/turborepo-lib/src/cli/mod.rs | 24 +++++++++++-- crates/turborepo-lib/src/commands/clone.rs | 42 ++++++++++++++++++++++ crates/turborepo-lib/src/commands/mod.rs | 1 + crates/turborepo-scm/src/clone.rs | 40 +++++++++++++++++++++ crates/turborepo-scm/src/git.rs | 23 +++++++++++- crates/turborepo-scm/src/lib.rs | 1 + 7 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 crates/turborepo-lib/src/commands/clone.rs create mode 100644 crates/turborepo-scm/src/clone.rs diff --git a/crates/turborepo-lib/src/cli/error.rs b/crates/turborepo-lib/src/cli/error.rs index ef1df55fedf9e..a60e8c9496363 100644 --- a/crates/turborepo-lib/src/cli/error.rs +++ b/crates/turborepo-lib/src/cli/error.rs @@ -26,6 +26,8 @@ pub enum Error { #[error(transparent)] Boundaries(#[from] crate::boundaries::Error), #[error(transparent)] + Clone(#[from] crate::commands::clone::Error), + #[error(transparent)] Path(#[from] turbopath::PathError), #[error(transparent)] #[diagnostic(transparent)] diff --git a/crates/turborepo-lib/src/cli/mod.rs b/crates/turborepo-lib/src/cli/mod.rs index 4b1ee799da6a5..86494a79141ae 100644 --- a/crates/turborepo-lib/src/cli/mod.rs +++ b/crates/turborepo-lib/src/cli/mod.rs @@ -28,8 +28,8 @@ use turborepo_ui::{ColorConfig, GREY}; use crate::{ cli::error::print_potential_tasks, commands::{ - bin, boundaries, config, daemon, generate, info, link, login, logout, ls, prune, query, - run, scan, telemetry, unlink, CommandBase, + bin, boundaries, clone, config, daemon, generate, info, link, login, logout, ls, prune, + query, run, scan, telemetry, unlink, CommandBase, }, get_version, run::watch::WatchClient, @@ -588,6 +588,15 @@ pub enum Command { #[clap(short = 'F', long, group = "scope-filter-group")] filter: Vec, }, + #[clap(hide = true)] + Clone { + url: String, + dir: Option, + #[clap(long, conflicts_with = "local")] + ci: bool, + #[clap(long, conflicts_with = "ci")] + local: bool, + }, /// Generate the autocompletion script for the specified shell Completion { shell: Shell }, /// Runs the Turborepo background daemon @@ -1389,6 +1398,17 @@ pub async fn run( Ok(boundaries::run(base, event).await?) } + Command::Clone { + url, + dir, + ci, + local, + } => { + let event = CommandEventBuilder::new("clone").with_parent(&root_telemetry); + event.track_call(); + let base = CommandBase::new(cli_args.clone(), repo_root, version, color_config)?; + Ok(clone::run(base, event, url, dir.as_deref(), *ci, *local)?) + } #[allow(unused_variables)] Command::Daemon { command, idle_time } => { let event = CommandEventBuilder::new("daemon").with_parent(&root_telemetry); diff --git a/crates/turborepo-lib/src/commands/clone.rs b/crates/turborepo-lib/src/commands/clone.rs new file mode 100644 index 0000000000000..8dbacf6f91200 --- /dev/null +++ b/crates/turborepo-lib/src/commands/clone.rs @@ -0,0 +1,42 @@ +use thiserror::Error; +use turborepo_ci::is_ci; +use turborepo_scm::{clone::CloneMode, SCM}; +use turborepo_telemetry::events::command::CommandEventBuilder; + +use crate::commands::CommandBase; + +#[derive(Debug, Error)] +pub enum Error { + #[error("failed to find git binary")] + GitBinaryNotFound, + + #[error("failed to clone repository")] + SCM(#[from] turborepo_scm::Error), +} + +pub fn run( + base: CommandBase, + _telemetry: CommandEventBuilder, + url: &str, + dir: Option<&str>, + ci: bool, + local: bool, +) -> Result { + let clone_mode = if ci { + CloneMode::CI + } else if local { + CloneMode::Local + } else if is_ci() { + CloneMode::CI + } else { + CloneMode::Local + }; + + let SCM::Git(git) = SCM::new(&base.repo_root) else { + return Err(Error::GitBinaryNotFound); + }; + + git.clone(url, dir, None, clone_mode)?; + + Ok(0) +} diff --git a/crates/turborepo-lib/src/commands/mod.rs b/crates/turborepo-lib/src/commands/mod.rs index 4acee04c53f0b..efe48d781bf43 100644 --- a/crates/turborepo-lib/src/commands/mod.rs +++ b/crates/turborepo-lib/src/commands/mod.rs @@ -15,6 +15,7 @@ use crate::{ pub(crate) mod bin; pub(crate) mod boundaries; +pub(crate) mod clone; pub(crate) mod config; pub(crate) mod daemon; pub(crate) mod generate; diff --git a/crates/turborepo-scm/src/clone.rs b/crates/turborepo-scm/src/clone.rs new file mode 100644 index 0000000000000..a051728e9ef3f --- /dev/null +++ b/crates/turborepo-scm/src/clone.rs @@ -0,0 +1,40 @@ +use crate::{Error, Git}; + +pub enum CloneMode { + /// Cloning locally, do a blobless clone (good UX and reasonably fast) + Local, + /// Cloning on CI, do a treeless clone (worse UX but fastest) + CI, +} + +impl Git { + pub fn clone( + &self, + url: &str, + dir: Option<&str>, + branch: Option<&str>, + mode: CloneMode, + ) -> Result<(), Error> { + let mut args = vec!["clone"]; + if let Some(branch) = branch { + args.push("--branch"); + args.push(branch); + } + match mode { + CloneMode::Local => { + args.push("--filter=blob:none"); + } + CloneMode::CI => { + args.push("--filter=tree:0"); + } + } + args.push(url); + if let Some(dir) = dir { + args.push(dir); + } + + self.spawn_git_command(&args, "")?; + + Ok(()) + } +} diff --git a/crates/turborepo-scm/src/git.rs b/crates/turborepo-scm/src/git.rs index c9f57e454f4d8..d2c3f0c3e8490 100644 --- a/crates/turborepo-scm/src/git.rs +++ b/crates/turborepo-scm/src/git.rs @@ -323,7 +323,28 @@ impl Git { Ok(files) } - fn execute_git_command(&self, args: &[&str], pathspec: &str) -> Result, Error> { + pub fn spawn_git_command(&self, args: &[&str], pathspec: &str) -> Result<(), Error> { + let mut command = Command::new(self.bin.as_std_path()); + command + .args(args) + .current_dir(&self.root) + .env("GIT_OPTIONAL_LOCKS", "0"); + + if !pathspec.is_empty() { + command.arg("--").arg(pathspec); + } + + let output = command.spawn()?.wait_with_output()?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + Err(Error::Git(stderr, Backtrace::capture())) + } else { + Ok(()) + } + } + + pub fn execute_git_command(&self, args: &[&str], pathspec: &str) -> Result, Error> { let mut command = Command::new(self.bin.as_std_path()); command .args(args) diff --git a/crates/turborepo-scm/src/lib.rs b/crates/turborepo-scm/src/lib.rs index 88399aaa4a402..0db5cf35088a1 100644 --- a/crates/turborepo-scm/src/lib.rs +++ b/crates/turborepo-scm/src/lib.rs @@ -19,6 +19,7 @@ use thiserror::Error; use tracing::debug; use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, PathError, RelativeUnixPathBuf}; +pub mod clone; pub mod git; mod hash_object; mod ls_tree; From 79de69a8d4a178d1f4635d7e41a86a436a177517 Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Wed, 5 Feb 2025 15:32:47 -0500 Subject: [PATCH 2/8] Add depth flag --- crates/turborepo-lib/src/cli/mod.rs | 13 ++++++++++++- crates/turborepo-lib/src/commands/clone.rs | 3 ++- crates/turborepo-scm/src/clone.rs | 8 +++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/crates/turborepo-lib/src/cli/mod.rs b/crates/turborepo-lib/src/cli/mod.rs index 86494a79141ae..2340be489ad70 100644 --- a/crates/turborepo-lib/src/cli/mod.rs +++ b/crates/turborepo-lib/src/cli/mod.rs @@ -596,6 +596,8 @@ pub enum Command { ci: bool, #[clap(long, conflicts_with = "ci")] local: bool, + #[clap(long)] + depth: Option, }, /// Generate the autocompletion script for the specified shell Completion { shell: Shell }, @@ -1403,11 +1405,20 @@ pub async fn run( dir, ci, local, + depth, } => { let event = CommandEventBuilder::new("clone").with_parent(&root_telemetry); event.track_call(); let base = CommandBase::new(cli_args.clone(), repo_root, version, color_config)?; - Ok(clone::run(base, event, url, dir.as_deref(), *ci, *local)?) + Ok(clone::run( + base, + event, + url, + dir.as_deref(), + *ci, + *local, + *depth, + )?) } #[allow(unused_variables)] Command::Daemon { command, idle_time } => { diff --git a/crates/turborepo-lib/src/commands/clone.rs b/crates/turborepo-lib/src/commands/clone.rs index 8dbacf6f91200..af1f057f63cc3 100644 --- a/crates/turborepo-lib/src/commands/clone.rs +++ b/crates/turborepo-lib/src/commands/clone.rs @@ -21,6 +21,7 @@ pub fn run( dir: Option<&str>, ci: bool, local: bool, + depth: Option, ) -> Result { let clone_mode = if ci { CloneMode::CI @@ -36,7 +37,7 @@ pub fn run( return Err(Error::GitBinaryNotFound); }; - git.clone(url, dir, None, clone_mode)?; + git.clone(url, dir, None, clone_mode, depth)?; Ok(0) } diff --git a/crates/turborepo-scm/src/clone.rs b/crates/turborepo-scm/src/clone.rs index a051728e9ef3f..8a6dd7d08e794 100644 --- a/crates/turborepo-scm/src/clone.rs +++ b/crates/turborepo-scm/src/clone.rs @@ -7,6 +7,10 @@ pub enum CloneMode { CI, } +// Provide a sane maximum depth for cloning. If a user needs more history than +// this, they can override or fetch it themselves. +const MAX_CLONE_DEPTH: usize = 64; + impl Git { pub fn clone( &self, @@ -14,8 +18,10 @@ impl Git { dir: Option<&str>, branch: Option<&str>, mode: CloneMode, + depth: Option, ) -> Result<(), Error> { - let mut args = vec!["clone"]; + let depth = depth.unwrap_or(MAX_CLONE_DEPTH).to_string(); + let mut args = vec!["clone", "--depth", &depth]; if let Some(branch) = branch { args.push("--branch"); args.push(branch); From fb227d4eaf3ac8e787a9e3bd7a81ba3c1f7579c6 Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Wed, 12 Feb 2025 12:22:46 -0500 Subject: [PATCH 3/8] Trying to do some testing for clone. Refactored the git interface after finding bugs via tests --- crates/turborepo-lib/src/cli/mod.rs | 5 +- crates/turborepo-lib/src/commands/clone.rs | 34 +++++++++----- crates/turborepo-lib/src/diagnostics.rs | 4 +- crates/turborepo-scm/src/clone.rs | 46 ++++++++++++++++++- crates/turborepo-scm/src/git.rs | 31 ++----------- crates/turborepo-scm/src/lib.rs | 16 ++++--- crates/turborepo-scm/src/ls_tree.rs | 4 +- crates/turborepo-scm/src/package_deps.rs | 4 +- crates/turborepo-scm/src/status.rs | 4 +- .../integration/tests/clone/basic-monorepo.t | 19 ++++++++ .../integration/tests/clone/new-repo.t | 27 +++++++++++ 11 files changed, 137 insertions(+), 57 deletions(-) create mode 100644 turborepo-tests/integration/tests/clone/basic-monorepo.t create mode 100644 turborepo-tests/integration/tests/clone/new-repo.t diff --git a/crates/turborepo-lib/src/cli/mod.rs b/crates/turborepo-lib/src/cli/mod.rs index 2340be489ad70..4e5f86ae30946 100644 --- a/crates/turborepo-lib/src/cli/mod.rs +++ b/crates/turborepo-lib/src/cli/mod.rs @@ -1371,7 +1371,6 @@ pub async fn run( }; cli_args.command = Some(command); - cli_args.cwd = Some(repo_root.as_path().to_owned()); let root_telemetry = GenericEventBuilder::new(); root_telemetry.track_start(); @@ -1409,9 +1408,9 @@ pub async fn run( } => { let event = CommandEventBuilder::new("clone").with_parent(&root_telemetry); event.track_call(); - let base = CommandBase::new(cli_args.clone(), repo_root, version, color_config)?; + Ok(clone::run( - base, + cwd, event, url, dir.as_deref(), diff --git a/crates/turborepo-lib/src/commands/clone.rs b/crates/turborepo-lib/src/commands/clone.rs index af1f057f63cc3..e3d8c05eb65a3 100644 --- a/crates/turborepo-lib/src/commands/clone.rs +++ b/crates/turborepo-lib/src/commands/clone.rs @@ -1,21 +1,26 @@ +use std::env::current_dir; + +use camino::Utf8Path; use thiserror::Error; +use turbopath::AbsoluteSystemPathBuf; use turborepo_ci::is_ci; -use turborepo_scm::{clone::CloneMode, SCM}; +use turborepo_scm::clone::{CloneMode, Git}; use turborepo_telemetry::events::command::CommandEventBuilder; -use crate::commands::CommandBase; - #[derive(Debug, Error)] pub enum Error { - #[error("failed to find git binary")] - GitBinaryNotFound, + #[error("path is not valid UTF-8")] + Path(#[from] camino::FromPathBufError), + + #[error(transparent)] + Turbopath(#[from] turbopath::PathError), #[error("failed to clone repository")] SCM(#[from] turborepo_scm::Error), } pub fn run( - base: CommandBase, + cwd: Option<&Utf8Path>, _telemetry: CommandEventBuilder, url: &str, dir: Option<&str>, @@ -23,6 +28,16 @@ pub fn run( local: bool, depth: Option, ) -> Result { + // We do *not* want to use the repo root but the actual, literal cwd for clone + let cwd = if let Some(cwd) = cwd { + cwd.to_owned() + } else { + current_dir() + .expect("could not get current directory") + .try_into()? + }; + let abs_cwd = AbsoluteSystemPathBuf::from_cwd(cwd)?; + let clone_mode = if ci { CloneMode::CI } else if local { @@ -33,11 +48,8 @@ pub fn run( CloneMode::Local }; - let SCM::Git(git) = SCM::new(&base.repo_root) else { - return Err(Error::GitBinaryNotFound); - }; - - git.clone(url, dir, None, clone_mode, depth)?; + let git = Git::find()?; + git.clone(url, abs_cwd, dir, None, clone_mode, depth)?; Ok(0) } diff --git a/crates/turborepo-lib/src/diagnostics.rs b/crates/turborepo-lib/src/diagnostics.rs index de836c04e17f7..a3a2330055339 100644 --- a/crates/turborepo-lib/src/diagnostics.rs +++ b/crates/turborepo-lib/src/diagnostics.rs @@ -11,7 +11,7 @@ use tokio::{ }; use turbo_updater::check_for_updates; use turbopath::AbsoluteSystemPathBuf; -use turborepo_scm::Git; +use turborepo_scm::GitRepo; use crate::{ commands::{ @@ -157,7 +157,7 @@ impl Diagnostic for GitDaemonDiagnostic { // get the current setting let stdout = Stdio::piped(); - let Ok(git_path) = Git::find_bin() else { + let Ok(git_path) = GitRepo::find_bin() else { return Err("git not found"); }; diff --git a/crates/turborepo-scm/src/clone.rs b/crates/turborepo-scm/src/clone.rs index 8a6dd7d08e794..8d0c1dcb8981a 100644 --- a/crates/turborepo-scm/src/clone.rs +++ b/crates/turborepo-scm/src/clone.rs @@ -1,4 +1,8 @@ -use crate::{Error, Git}; +use std::{backtrace::Backtrace, process::Command}; + +use turbopath::AbsoluteSystemPathBuf; + +use crate::{Error, GitRepo}; pub enum CloneMode { /// Cloning locally, do a blobless clone (good UX and reasonably fast) @@ -11,10 +15,48 @@ pub enum CloneMode { // this, they can override or fetch it themselves. const MAX_CLONE_DEPTH: usize = 64; +/// A wrapper around the git binary that is not tied to a specific repo. +pub struct Git { + bin: AbsoluteSystemPathBuf, +} + impl Git { + pub fn find() -> Result { + Ok(Self { + bin: GitRepo::find_bin()?, + }) + } + + pub fn spawn_git_command( + &self, + cwd: &AbsoluteSystemPathBuf, + args: &[&str], + pathspec: &str, + ) -> Result<(), Error> { + let mut command = Command::new(self.bin.as_std_path()); + command + .args(args) + .current_dir(cwd) + .env("GIT_OPTIONAL_LOCKS", "0"); + + if !pathspec.is_empty() { + command.arg("--").arg(pathspec); + } + + let output = command.spawn()?.wait_with_output()?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + Err(Error::Git(stderr, Backtrace::capture())) + } else { + Ok(()) + } + } + pub fn clone( &self, url: &str, + cwd: AbsoluteSystemPathBuf, dir: Option<&str>, branch: Option<&str>, mode: CloneMode, @@ -39,7 +81,7 @@ impl Git { args.push(dir); } - self.spawn_git_command(&args, "")?; + self.spawn_git_command(&cwd, &args, "")?; Ok(()) } diff --git a/crates/turborepo-scm/src/git.rs b/crates/turborepo-scm/src/git.rs index d2c3f0c3e8490..923d0c1f6e1e7 100644 --- a/crates/turborepo-scm/src/git.rs +++ b/crates/turborepo-scm/src/git.rs @@ -14,7 +14,7 @@ use turbopath::{ }; use turborepo_ci::Vendor; -use crate::{Error, Git, SCM}; +use crate::{Error, GitRepo, SCM}; #[derive(Debug, PartialEq, Eq)] pub struct InvalidRange { @@ -170,7 +170,7 @@ impl CIEnv { } } -impl Git { +impl GitRepo { fn get_current_branch(&self) -> Result { let output = self.execute_git_command(&["branch", "--show-current"], "")?; let output = String::from_utf8(output)?; @@ -323,27 +323,6 @@ impl Git { Ok(files) } - pub fn spawn_git_command(&self, args: &[&str], pathspec: &str) -> Result<(), Error> { - let mut command = Command::new(self.bin.as_std_path()); - command - .args(args) - .current_dir(&self.root) - .env("GIT_OPTIONAL_LOCKS", "0"); - - if !pathspec.is_empty() { - command.arg("--").arg(pathspec); - } - - let output = command.spawn()?.wait_with_output()?; - - if !output.status.success() { - let stderr = String::from_utf8_lossy(&output.stderr).to_string(); - Err(Error::Git(stderr, Backtrace::capture())) - } else { - Ok(()) - } - } - pub fn execute_git_command(&self, args: &[&str], pathspec: &str) -> Result, Error> { let mut command = Command::new(self.bin.as_std_path()); command @@ -452,7 +431,7 @@ mod tests { use super::{previous_content, CIEnv, InvalidRange}; use crate::{ git::{GitHubCommit, GitHubEvent}, - Error, Git, SCM, + Error, GitRepo, SCM, }; fn setup_repository( @@ -1065,7 +1044,7 @@ mod tests { repo.branch(branch, &commit, true).unwrap(); }); - let thing = Git::find(&root).unwrap(); + let thing = GitRepo::find(&root).unwrap(); let actual = thing.resolve_base(target_branch, CIEnv::none()).ok(); assert_eq!(actual.as_deref(), expected); @@ -1301,7 +1280,7 @@ mod tests { Err(VarError::NotPresent) }; - let actual = Git::get_github_base_ref(CIEnv { + let actual = GitRepo::get_github_base_ref(CIEnv { is_github_actions: test_case.env.is_github_actions, github_base_ref: test_case.env.github_base_ref, github_event_path: temp_file diff --git a/crates/turborepo-scm/src/lib.rs b/crates/turborepo-scm/src/lib.rs index 0db5cf35088a1..c06aec27bbddc 100644 --- a/crates/turborepo-scm/src/lib.rs +++ b/crates/turborepo-scm/src/lib.rs @@ -172,7 +172,7 @@ pub(crate) fn wait_for_success( } #[derive(Debug, Clone)] -pub struct Git { +pub struct GitRepo { root: AbsoluteSystemPathBuf, bin: AbsoluteSystemPathBuf, } @@ -185,7 +185,7 @@ enum GitError { Root(AbsoluteSystemPathBuf, Error), } -impl Git { +impl GitRepo { fn find(path_in_repo: &AbsoluteSystemPath) -> Result { // If which produces an invalid absolute path, it's not an execution error, it's // a programming error. We expect it to always give us an absolute path @@ -237,17 +237,19 @@ fn find_git_root(turbo_root: &AbsoluteSystemPath) -> Result SCM { - Git::find(path_in_repo).map(SCM::Git).unwrap_or_else(|e| { - debug!("{}, continuing with manual hashing", e); - SCM::Manual - }) + GitRepo::find(path_in_repo) + .map(SCM::Git) + .unwrap_or_else(|e| { + debug!("{}, continuing with manual hashing", e); + SCM::Manual + }) } pub fn is_manual(&self) -> bool { diff --git a/crates/turborepo-scm/src/ls_tree.rs b/crates/turborepo-scm/src/ls_tree.rs index 0c2415bf90c60..d6dfbef594cc8 100644 --- a/crates/turborepo-scm/src/ls_tree.rs +++ b/crates/turborepo-scm/src/ls_tree.rs @@ -6,9 +6,9 @@ use std::{ use nom::Finish; use turbopath::{AbsoluteSystemPathBuf, RelativeUnixPathBuf}; -use crate::{wait_for_success, Error, Git, GitHashes}; +use crate::{wait_for_success, Error, GitHashes, GitRepo}; -impl Git { +impl GitRepo { #[tracing::instrument(skip(self))] pub fn git_ls_tree(&self, root_path: &AbsoluteSystemPathBuf) -> Result { let mut hashes = GitHashes::new(); diff --git a/crates/turborepo-scm/src/package_deps.rs b/crates/turborepo-scm/src/package_deps.rs index 85fba9051d467..b1090a6b50852 100644 --- a/crates/turborepo-scm/src/package_deps.rs +++ b/crates/turborepo-scm/src/package_deps.rs @@ -8,7 +8,7 @@ use turborepo_telemetry::events::task::{FileHashMethod, PackageTaskEventBuilder} #[cfg(feature = "git2")] use crate::hash_object::hash_objects; -use crate::{Error, Git, GitHashes, SCM}; +use crate::{Error, GitHashes, GitRepo, SCM}; pub const INPUT_INCLUDE_DEFAULT_FILES: &str = "$TURBO_DEFAULT$"; @@ -112,7 +112,7 @@ impl SCM { } } -impl Git { +impl GitRepo { fn get_package_file_hashes>( &self, turbo_root: &AbsoluteSystemPath, diff --git a/crates/turborepo-scm/src/status.rs b/crates/turborepo-scm/src/status.rs index ee42ca96286f0..cf609b4a09d60 100644 --- a/crates/turborepo-scm/src/status.rs +++ b/crates/turborepo-scm/src/status.rs @@ -9,9 +9,9 @@ use std::{ use nom::Finish; use turbopath::{AbsoluteSystemPath, RelativeUnixPathBuf}; -use crate::{wait_for_success, Error, Git, GitHashes}; +use crate::{wait_for_success, Error, GitRepo, GitHashes}; -impl Git { +impl GitRepo { #[tracing::instrument(skip(self, root_path, hashes))] pub(crate) fn append_git_status( &self, diff --git a/turborepo-tests/integration/tests/clone/basic-monorepo.t b/turborepo-tests/integration/tests/clone/basic-monorepo.t new file mode 100644 index 0000000000000..93e11e4484072 --- /dev/null +++ b/turborepo-tests/integration/tests/clone/basic-monorepo.t @@ -0,0 +1,19 @@ +Setup + $ . ${TESTDIR}/../../../helpers/setup_integration_test.sh + + $ git config uploadpack.allowFilter true + $ cd .. +Make sure we allow partial clones + +Do a blobless clone + $ ${TURBO} clone file://$(pwd)/basic-monorepo.t basic-monorepo-blobless --local + Cloning into 'basic-monorepo-blobless'... + $ cd basic-monorepo-blobless + $ ${TURBO} build > /dev/null 2>&1 + $ cd .. + +Do a treeless clone + $ ${TURBO} clone file://$(pwd)/basic-monorepo.t basic-monorepo-treeless --local + Cloning into 'basic-monorepo-treeless'... + $ cd basic-monorepo-treeless + $ ${TURBO} build > /dev/null 2>&1 \ No newline at end of file diff --git a/turborepo-tests/integration/tests/clone/new-repo.t b/turborepo-tests/integration/tests/clone/new-repo.t new file mode 100644 index 0000000000000..e3fa26e81d950 --- /dev/null +++ b/turborepo-tests/integration/tests/clone/new-repo.t @@ -0,0 +1,27 @@ +Setup + $ . ${TESTDIR}/../../helpers/setup.sh + +Create a repo + $ mkdir my-repo + $ cd my-repo + $ git init --quiet + $ echo "Hello World" > README.md + $ git add README.md + $ git commit -m "Initial commit" --quiet + +Make sure we allow partial clones + $ git config uploadpack.allowFilter true + $ cd .. + +Clone repo with `--ci` + $ ${TURBO} clone file://$(pwd)/my-repo my-repo-treeless --ci + $ cd my-repo-treeless +Assert it's a treeless clone + $ git config remote.origin.partialclonefilter + $ cd .. + +Clone repo with `--local` + $ ${TURBO} clone file://$(pwd)/my-repo my-repo-blobless --local + $ cd my-repo-blobless +Assert it's a blobless clone + $ git config remote.origin.partialclonefilter From 4171726dc2c6176552e2457df544ccc1c91d7685 Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Wed, 12 Feb 2025 12:24:49 -0500 Subject: [PATCH 4/8] Remove unused parameter --- crates/turborepo-lib/src/cli/mod.rs | 10 +--------- crates/turborepo-lib/src/commands/clone.rs | 1 - 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/crates/turborepo-lib/src/cli/mod.rs b/crates/turborepo-lib/src/cli/mod.rs index 4e5f86ae30946..21c4b305d8f75 100644 --- a/crates/turborepo-lib/src/cli/mod.rs +++ b/crates/turborepo-lib/src/cli/mod.rs @@ -1409,15 +1409,7 @@ pub async fn run( let event = CommandEventBuilder::new("clone").with_parent(&root_telemetry); event.track_call(); - Ok(clone::run( - cwd, - event, - url, - dir.as_deref(), - *ci, - *local, - *depth, - )?) + Ok(clone::run(cwd, url, dir.as_deref(), *ci, *local, *depth)?) } #[allow(unused_variables)] Command::Daemon { command, idle_time } => { diff --git a/crates/turborepo-lib/src/commands/clone.rs b/crates/turborepo-lib/src/commands/clone.rs index e3d8c05eb65a3..c6e02a7258d01 100644 --- a/crates/turborepo-lib/src/commands/clone.rs +++ b/crates/turborepo-lib/src/commands/clone.rs @@ -21,7 +21,6 @@ pub enum Error { pub fn run( cwd: Option<&Utf8Path>, - _telemetry: CommandEventBuilder, url: &str, dir: Option<&str>, ci: bool, From 74edcdf2e0ef846aaf40af458b8ddea0a73ba685 Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Wed, 12 Feb 2025 12:28:40 -0500 Subject: [PATCH 5/8] Fix clippy --- crates/turborepo-lib/src/commands/clone.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/turborepo-lib/src/commands/clone.rs b/crates/turborepo-lib/src/commands/clone.rs index c6e02a7258d01..cb93aee95d76d 100644 --- a/crates/turborepo-lib/src/commands/clone.rs +++ b/crates/turborepo-lib/src/commands/clone.rs @@ -5,7 +5,6 @@ use thiserror::Error; use turbopath::AbsoluteSystemPathBuf; use turborepo_ci::is_ci; use turborepo_scm::clone::{CloneMode, Git}; -use turborepo_telemetry::events::command::CommandEventBuilder; #[derive(Debug, Error)] pub enum Error { @@ -16,7 +15,7 @@ pub enum Error { Turbopath(#[from] turbopath::PathError), #[error("failed to clone repository")] - SCM(#[from] turborepo_scm::Error), + Scm(#[from] turborepo_scm::Error), } pub fn run( From b8423eac88dcb3f8d2b9b4466edcadd4e8cf396c Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Tue, 4 Mar 2025 12:09:13 -0500 Subject: [PATCH 6/8] Fix test --- turborepo-tests/integration/tests/clone/new-repo.t | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/turborepo-tests/integration/tests/clone/new-repo.t b/turborepo-tests/integration/tests/clone/new-repo.t index e3fa26e81d950..7f02c9b165ead 100644 --- a/turborepo-tests/integration/tests/clone/new-repo.t +++ b/turborepo-tests/integration/tests/clone/new-repo.t @@ -1,5 +1,5 @@ Setup - $ . ${TESTDIR}/../../helpers/setup.sh + $ . ${TESTDIR}/../../../helpers/setup.sh Create a repo $ mkdir my-repo @@ -15,13 +15,17 @@ Make sure we allow partial clones Clone repo with `--ci` $ ${TURBO} clone file://$(pwd)/my-repo my-repo-treeless --ci + Cloning into 'my-repo-treeless'... $ cd my-repo-treeless Assert it's a treeless clone $ git config remote.origin.partialclonefilter + tree:0 $ cd .. Clone repo with `--local` $ ${TURBO} clone file://$(pwd)/my-repo my-repo-blobless --local + Cloning into 'my-repo-blobless'... $ cd my-repo-blobless Assert it's a blobless clone $ git config remote.origin.partialclonefilter + blob:none From 421f850e27fbeca32e8969e359488cdd3eaba4f5 Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Tue, 4 Mar 2025 12:21:55 -0500 Subject: [PATCH 7/8] Fix format --- crates/turborepo-scm/src/status.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/turborepo-scm/src/status.rs b/crates/turborepo-scm/src/status.rs index cf609b4a09d60..c8384060ce909 100644 --- a/crates/turborepo-scm/src/status.rs +++ b/crates/turborepo-scm/src/status.rs @@ -9,7 +9,7 @@ use std::{ use nom::Finish; use turbopath::{AbsoluteSystemPath, RelativeUnixPathBuf}; -use crate::{wait_for_success, Error, GitRepo, GitHashes}; +use crate::{wait_for_success, Error, GitHashes, GitRepo}; impl GitRepo { #[tracing::instrument(skip(self, root_path, hashes))] From e8953295f4d5560997de35f5d6080d558c545e7f Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Tue, 4 Mar 2025 13:57:34 -0500 Subject: [PATCH 8/8] Fix test --- turborepo-tests/integration/tests/clone/new-repo.t | 2 ++ 1 file changed, 2 insertions(+) diff --git a/turborepo-tests/integration/tests/clone/new-repo.t b/turborepo-tests/integration/tests/clone/new-repo.t index 7f02c9b165ead..203cf661addb8 100644 --- a/turborepo-tests/integration/tests/clone/new-repo.t +++ b/turborepo-tests/integration/tests/clone/new-repo.t @@ -7,6 +7,8 @@ Create a repo $ git init --quiet $ echo "Hello World" > README.md $ git add README.md + $ git config user.email "test@example.com" + $ git config user.name "Test" $ git commit -m "Initial commit" --quiet Make sure we allow partial clones