这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions crates/turborepo-filewatch/src/package_watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,13 +449,15 @@ impl Subscriber {
tracing::debug!("handling change to workspace {path_workspace}");
let package_json = path_workspace.join_component("package.json");
let turbo_json = path_workspace.join_component("turbo.json");
let turbo_jsonc = path_workspace.join_component("turbo.jsonc");

let (package_exists, turbo_exists) = join!(
let (package_exists, turbo_json_exists, turbo_jsonc_exists) = join!(
// It's possible that an IO error could occur other than the file not existing, but
// we will treat it like the file doesn't exist. It's possible we'll need to
// revisit this, depending on what kind of errors occur.
tokio::fs::try_exists(&package_json).map(|result| result.unwrap_or(false)),
tokio::fs::try_exists(&turbo_json)
tokio::fs::try_exists(&turbo_json),
tokio::fs::try_exists(&turbo_jsonc)
);

changed |= if package_exists {
Expand All @@ -464,7 +466,14 @@ impl Subscriber {
path_workspace.to_owned(),
WorkspaceData {
package_json,
turbo_json: turbo_exists.unwrap_or_default().then_some(turbo_json),
turbo_json: turbo_json_exists
.unwrap_or_default()
.then_some(turbo_json)
.or_else(|| {
turbo_jsonc_exists
.unwrap_or_default()
.then_some(turbo_jsonc)
}),
},
)
.is_none()
Expand Down
7 changes: 2 additions & 5 deletions crates/turborepo-lib/src/commands/login/manual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,8 @@ pub async fn login_manual(base: &mut CommandBase, force: bool) -> Result<(), Err
// update global config with token
write_token(base, token)?;
// ensure api url & team id/slug are present in turbo.json
write_remote(
&base.root_turbo_json_path(),
api_client.base_url(),
team_identifier,
)?;
let turbo_json_path = base.root_turbo_json_path()?;
write_remote(&turbo_json_path, api_client.base_url(), team_identifier)?;
Ok(())
}

Expand Down
24 changes: 22 additions & 2 deletions crates/turborepo-lib/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
cli,
config::{ConfigurationOptions, Error as ConfigError, TurborepoConfigBuilder},
opts::Opts,
turbo_json::{CONFIG_FILE, CONFIG_FILE_JSONC},
Args,
};

Expand Down Expand Up @@ -139,8 +140,27 @@ impl CommandBase {
fn root_package_json_path(&self) -> AbsoluteSystemPathBuf {
self.repo_root.join_component("package.json")
}
fn root_turbo_json_path(&self) -> AbsoluteSystemPathBuf {
self.repo_root.join_component("turbo.json")
fn root_turbo_json_path(&self) -> Result<AbsoluteSystemPathBuf, ConfigError> {
let turbo_json_path = self.repo_root.join_component(CONFIG_FILE);
let turbo_jsonc_path = self.repo_root.join_component(CONFIG_FILE_JSONC);

let turbo_json_exists = turbo_json_path.exists();
let turbo_jsonc_exists = turbo_jsonc_path.exists();

if turbo_json_exists && turbo_jsonc_exists {
return Err(ConfigError::MultipleTurboConfigs {
directory: self.repo_root.to_string(),
});
}

if turbo_json_exists {
Ok(turbo_json_path)
} else if turbo_jsonc_exists {
Ok(turbo_jsonc_path)
} else {
Ok(turbo_json_path) // Default to turbo.json path even if it doesn't
// exist
}
}

pub fn api_auth(&self) -> Result<Option<APIAuth>, ConfigError> {
Expand Down
119 changes: 99 additions & 20 deletions crates/turborepo-lib/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use turborepo_repository::package_graph::PackageName;
pub use crate::turbo_json::{RawTurboJson, UIMode};
use crate::{
cli::{EnvMode, LogOrder},
turbo_json::CONFIG_FILE,
turbo_json::{CONFIG_FILE, CONFIG_FILE_JSONC},
};

#[derive(Debug, Error, Diagnostic)]
Expand Down Expand Up @@ -74,10 +74,15 @@ pub enum Error {
#[error(transparent)]
PackageJson(#[from] turborepo_repository::package_json::Error),
#[error(
"Could not find turbo.json.\nFollow directions at https://turbo.build/repo/docs to create \
"Could not find turbo.json or turbo.jsonc.\nFollow directions at https://turbo.build/repo/docs to create \
one."
)]
NoTurboJSON,
#[error(
"Found both turbo.json and turbo.jsonc in the same directory: {directory}\nRemove either \
turbo.json or turbo.jsonc so there is only one."
)]
MultipleTurboConfigs { directory: String },
#[error(transparent)]
SerdeJson(#[from] serde_json::Error),
#[error(transparent)]
Expand Down Expand Up @@ -396,10 +401,29 @@ impl ConfigurationOptions {
self.run_summary.unwrap_or_default()
}

pub fn root_turbo_json_path(&self, repo_root: &AbsoluteSystemPath) -> AbsoluteSystemPathBuf {
self.root_turbo_json_path
.clone()
.unwrap_or_else(|| repo_root.join_component(CONFIG_FILE))
pub fn root_turbo_json_path(
&self,
repo_root: &AbsoluteSystemPath,
) -> Result<AbsoluteSystemPathBuf, Error> {
if let Some(path) = &self.root_turbo_json_path {
return Ok(path.clone());
}

// Check if both files exist
let turbo_json_path = repo_root.join_component(CONFIG_FILE);
let turbo_jsonc_path = repo_root.join_component(CONFIG_FILE_JSONC);
let turbo_json_exists = turbo_json_path.try_exists()?;
let turbo_jsonc_exists = turbo_jsonc_path.try_exists()?;

match (turbo_json_exists, turbo_jsonc_exists) {
(true, true) => Err(Error::MultipleTurboConfigs {
directory: repo_root.to_string(),
}),
(true, false) => Ok(turbo_json_path),
(false, true) => Ok(turbo_jsonc_path),
// Default to turbo.json if neither exists
(false, false) => Ok(turbo_json_path),
}
}

pub fn allow_no_turbo_json(&self) -> bool {
Expand Down Expand Up @@ -450,16 +474,6 @@ impl TurborepoConfigBuilder {
self
}

// Getting all of the paths.
#[allow(dead_code)]
fn root_package_json_path(&self) -> AbsoluteSystemPathBuf {
self.repo_root.join_component("package.json")
}
#[allow(dead_code)]
fn root_turbo_json_path(&self) -> AbsoluteSystemPathBuf {
self.repo_root.join_component("turbo.json")
}

fn get_environment(&self) -> HashMap<OsString, OsString> {
self.environment
.clone()
Expand Down Expand Up @@ -517,9 +531,12 @@ mod test {
use tempfile::TempDir;
use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf};

use crate::config::{
ConfigurationOptions, TurborepoConfigBuilder, DEFAULT_API_URL, DEFAULT_LOGIN_URL,
DEFAULT_TIMEOUT,
use crate::{
config::{
ConfigurationOptions, TurborepoConfigBuilder, DEFAULT_API_URL, DEFAULT_LOGIN_URL,
DEFAULT_TIMEOUT,
},
turbo_json::{CONFIG_FILE, CONFIG_FILE_JSONC},
};

#[test]
Expand All @@ -542,7 +559,7 @@ mod test {
})
.unwrap();
assert_eq!(
defaults.root_turbo_json_path(repo_root),
defaults.root_turbo_json_path(repo_root).unwrap(),
repo_root.join_component("turbo.json")
)
}
Expand Down Expand Up @@ -635,4 +652,66 @@ mod test {
assert!(!config.preflight());
assert_eq!(config.timeout(), 123);
}

#[test]
fn test_multiple_turbo_configs() {
let tmp_dir = TempDir::new().unwrap();
let repo_root = AbsoluteSystemPath::from_std_path(tmp_dir.path()).unwrap();

// Create both turbo.json and turbo.jsonc
let turbo_json_path = repo_root.join_component(CONFIG_FILE);
let turbo_jsonc_path = repo_root.join_component(CONFIG_FILE_JSONC);

turbo_json_path.create_with_contents("{}").unwrap();
turbo_jsonc_path.create_with_contents("{}").unwrap();

// Test ConfigurationOptions.root_turbo_json_path
let config = ConfigurationOptions::default();
let result = config.root_turbo_json_path(repo_root);
assert!(result.is_err());
}

#[test]
fn test_only_turbo_json() {
let tmp_dir = TempDir::new().unwrap();
let repo_root = AbsoluteSystemPath::from_std_path(tmp_dir.path()).unwrap();

// Create only turbo.json
let turbo_json_path = repo_root.join_component(CONFIG_FILE);
turbo_json_path.create_with_contents("{}").unwrap();

// Test ConfigurationOptions.root_turbo_json_path
let config = ConfigurationOptions::default();
let result = config.root_turbo_json_path(repo_root);

assert_eq!(result.unwrap(), turbo_json_path);
}

#[test]
fn test_only_turbo_jsonc() {
let tmp_dir = TempDir::new().unwrap();
let repo_root = AbsoluteSystemPath::from_std_path(tmp_dir.path()).unwrap();

// Create only turbo.jsonc
let turbo_jsonc_path = repo_root.join_component(CONFIG_FILE_JSONC);
turbo_jsonc_path.create_with_contents("{}").unwrap();

// Test ConfigurationOptions.root_turbo_json_path
let config = ConfigurationOptions::default();
let result = config.root_turbo_json_path(repo_root);

assert_eq!(result.unwrap(), turbo_jsonc_path);
}

#[test]
fn test_no_turbo_config() {
let tmp_dir = TempDir::new().unwrap();
let repo_root = AbsoluteSystemPath::from_std_path(tmp_dir.path()).unwrap();

// Test ConfigurationOptions.root_turbo_json_path
let config = ConfigurationOptions::default();
let result = config.root_turbo_json_path(repo_root);

assert_eq!(result.unwrap(), repo_root.join_component(CONFIG_FILE));
}
}
5 changes: 3 additions & 2 deletions crates/turborepo-lib/src/config/turbo_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<'a> ResolvedConfigurationOptions for TurboJsonReader<'a> {
&self,
existing_config: &ConfigurationOptions,
) -> Result<ConfigurationOptions, Error> {
let turbo_json_path = existing_config.root_turbo_json_path(self.repo_root);
let turbo_json_path = existing_config.root_turbo_json_path(self.repo_root)?;
let turbo_json = RawTurboJson::read(self.repo_root, &turbo_json_path).or_else(|e| {
if let Error::Io(e) = &e {
if matches!(e.kind(), std::io::ErrorKind::NotFound) {
Expand All @@ -72,6 +72,7 @@ mod test {
use tempfile::tempdir;

use super::*;
use crate::turbo_json::CONFIG_FILE;

#[test]
fn test_reads_from_default() {
Expand All @@ -82,7 +83,7 @@ mod test {
..Default::default()
};
repo_root
.join_component("turbo.json")
.join_component(CONFIG_FILE)
.create_with_contents(
serde_json::to_string_pretty(&serde_json::json!({
"daemon": false
Expand Down
21 changes: 13 additions & 8 deletions crates/turborepo-lib/src/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
},
config::ConfigurationOptions,
run::task_id::TaskId,
turbo_json::UIMode,
turbo_json::{UIMode, CONFIG_FILE},
Args,
};

Expand Down Expand Up @@ -287,7 +287,10 @@ pub enum ResolvedLogPrefix {

impl<'a> From<OptsInputs<'a>> for RepoOpts {
fn from(inputs: OptsInputs<'a>) -> Self {
let root_turbo_json_path = inputs.config.root_turbo_json_path(inputs.repo_root);
let root_turbo_json_path = inputs
.config
.root_turbo_json_path(inputs.repo_root)
.unwrap_or_else(|_| inputs.repo_root.join_component(CONFIG_FILE));
let allow_no_package_manager = inputs.config.allow_no_package_manager();
let allow_no_turbo_json = inputs.config.allow_no_turbo_json();

Expand Down Expand Up @@ -553,7 +556,7 @@ mod test {
commands::CommandBase,
config::ConfigurationOptions,
opts::{Opts, RunCacheOpts, ScopeOpts},
turbo_json::UIMode,
turbo_json::{UIMode, CONFIG_FILE},
Args,
};

Expand Down Expand Up @@ -694,7 +697,9 @@ mod test {
.map(|(base, head)| (Some(base), Some(head))),
};
let config = ConfigurationOptions::default();
let root_turbo_json_path = config.root_turbo_json_path(&AbsoluteSystemPathBuf::default());
let root_turbo_json_path = config
.root_turbo_json_path(&AbsoluteSystemPathBuf::default())
.unwrap_or_else(|_| AbsoluteSystemPathBuf::default().join_component(CONFIG_FILE));

let opts = Opts {
repo_opts: RepoOpts {
Expand Down Expand Up @@ -801,11 +806,11 @@ mod test {
let tmpdir = TempDir::new()?;
let repo_root = AbsoluteSystemPathBuf::try_from(tmpdir.path())?;

repo_root
.join_component("turbo.json")
.create_with_contents(serde_json::to_string_pretty(&serde_json::json!({
repo_root.join_component(CONFIG_FILE).create_with_contents(
serde_json::to_string_pretty(&serde_json::json!({
"remoteCache": { "enabled": true }
}))?)?;
}))?,
)?;

let mut args = Args::default();
args.command = Some(Command::Run {
Expand Down
12 changes: 7 additions & 5 deletions crates/turborepo-lib/src/run/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,19 +383,21 @@ impl RunBuilder {
let task_access = TaskAccess::new(self.repo_root.clone(), async_cache.clone(), &scm);
task_access.restore_config().await;

let root_turbo_json_path = self.opts.repo_opts.root_turbo_json_path.clone();

let turbo_json_loader = if task_access.is_enabled() {
TurboJsonLoader::task_access(
self.repo_root.clone(),
self.opts.repo_opts.root_turbo_json_path.clone(),
root_turbo_json_path.clone(),
root_package_json.clone(),
)
} else if is_single_package {
TurboJsonLoader::single_package(
self.repo_root.clone(),
self.opts.repo_opts.root_turbo_json_path.clone(),
root_turbo_json_path.clone(),
root_package_json.clone(),
)
} else if !self.opts.repo_opts.root_turbo_json_path.exists() &&
} else if !root_turbo_json_path.exists() &&
// Infer a turbo.json if allowing no turbo.json is explicitly allowed or if MFE configs are discovered
(self.opts.repo_opts.allow_no_turbo_json || micro_frontend_configs.is_some())
{
Expand All @@ -407,14 +409,14 @@ impl RunBuilder {
} else if let Some(micro_frontends) = &micro_frontend_configs {
TurboJsonLoader::workspace_with_microfrontends(
self.repo_root.clone(),
self.opts.repo_opts.root_turbo_json_path.clone(),
root_turbo_json_path.clone(),
pkg_dep_graph.packages(),
micro_frontends.clone(),
)
} else {
TurboJsonLoader::workspace(
self.repo_root.clone(),
self.opts.repo_opts.root_turbo_json_path.clone(),
root_turbo_json_path.clone(),
pkg_dep_graph.packages(),
)
};
Expand Down
4 changes: 3 additions & 1 deletion crates/turborepo-lib/src/run/watch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ impl WatchClient {
let signal = get_signal()?;
let handler = SignalHandler::new(signal);

if base.opts.repo_opts.root_turbo_json_path != base.repo_root.join_component(CONFIG_FILE) {
// Check if the turbo.json path is the standard one
let standard_path = base.repo_root.join_component(CONFIG_FILE);
if base.opts.repo_opts.root_turbo_json_path != standard_path {
return Err(Error::NonStandardTurboJsonPath(
base.opts.repo_opts.root_turbo_json_path.to_string(),
));
Expand Down
Loading
Loading