From b895827155d92d94d2c7972e1b294850f7261604 Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Thu, 5 Sep 2024 15:53:06 -0400 Subject: [PATCH 1/3] Renaming our dependencies field to make immediate dependencies by default --- crates/turborepo-lib/src/query.rs | 8 ++++---- .../integration/tests/command-query.t | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/crates/turborepo-lib/src/query.rs b/crates/turborepo-lib/src/query.rs index 64faef1a059f2..bbfd7b6f97a7f 100644 --- a/crates/turborepo-lib/src/query.rs +++ b/crates/turborepo-lib/src/query.rs @@ -319,7 +319,7 @@ impl Package { } /// The upstream packages that have this package as a direct dependency - async fn immediate_dependents(&self) -> Result, Error> { + async fn dependents(&self) -> Result, Error> { let node: PackageNode = PackageNode::Workspace(self.name.clone()); Ok(self .run @@ -335,7 +335,7 @@ impl Package { } /// The downstream packages that directly depend on this package - async fn immediate_dependencies(&self) -> Result, Error> { + async fn dependencies(&self) -> Result, Error> { let node: PackageNode = PackageNode::Workspace(self.name.clone()); Ok(self .run @@ -351,7 +351,7 @@ impl Package { } /// The downstream packages that depend on this package, transitively - async fn dependents(&self) -> Result, Error> { + async fn transitive_dependents(&self) -> Result, Error> { let node: PackageNode = PackageNode::Workspace(self.name.clone()); Ok(self @@ -368,7 +368,7 @@ impl Package { } /// The upstream packages that this package depends on, transitively - async fn dependencies(&self) -> Result, Error> { + async fn transitive_dependencies(&self) -> Result, Error> { let node: PackageNode = PackageNode::Workspace(self.name.clone()); Ok(self diff --git a/turborepo-tests/integration/tests/command-query.t b/turborepo-tests/integration/tests/command-query.t index 36721a091ca4f..4dc6c9c2621ad 100644 --- a/turborepo-tests/integration/tests/command-query.t +++ b/turborepo-tests/integration/tests/command-query.t @@ -74,6 +74,23 @@ Get dependencies of `my-app` "packages": [ { "dependencies": [ + { + "name": "util" + } + ] + } + ] + } + } + +Get transitive dependencies of `my-app` + $ ${TURBO} query "query { packages(filter: { equal: { field: NAME, value: \"my-app\" } }) { transitiveDependencies { name } } }" | jq + WARNING query command is experimental and may change in the future + { + "data": { + "packages": [ + { + "transitiveDependencies": [ { "name": "//" }, From 8998e89f458c3e63ea3f86e7a2f636e565ebe432 Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Thu, 5 Sep 2024 16:06:39 -0400 Subject: [PATCH 2/3] Renaming because transitive is too math-y --- crates/turborepo-lib/src/query.rs | 8 ++++---- turborepo-tests/integration/tests/command-query.t | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/turborepo-lib/src/query.rs b/crates/turborepo-lib/src/query.rs index bbfd7b6f97a7f..cbefc1752e068 100644 --- a/crates/turborepo-lib/src/query.rs +++ b/crates/turborepo-lib/src/query.rs @@ -350,8 +350,8 @@ impl Package { .collect()) } - /// The downstream packages that depend on this package, transitively - async fn transitive_dependents(&self) -> Result, Error> { + /// The downstream packages that depend on this package, indirectly + async fn indirect_dependents(&self) -> Result, Error> { let node: PackageNode = PackageNode::Workspace(self.name.clone()); Ok(self @@ -367,8 +367,8 @@ impl Package { .collect()) } - /// The upstream packages that this package depends on, transitively - async fn transitive_dependencies(&self) -> Result, Error> { + /// The upstream packages that this package depends on, indirectly + async fn indirect_dependencies(&self) -> Result, Error> { let node: PackageNode = PackageNode::Workspace(self.name.clone()); Ok(self diff --git a/turborepo-tests/integration/tests/command-query.t b/turborepo-tests/integration/tests/command-query.t index 4dc6c9c2621ad..14e991642508a 100644 --- a/turborepo-tests/integration/tests/command-query.t +++ b/turborepo-tests/integration/tests/command-query.t @@ -83,14 +83,14 @@ Get dependencies of `my-app` } } -Get transitive dependencies of `my-app` - $ ${TURBO} query "query { packages(filter: { equal: { field: NAME, value: \"my-app\" } }) { transitiveDependencies { name } } }" | jq +Get the indirect dependencies of `my-app` + $ ${TURBO} query "query { packages(filter: { equal: { field: NAME, value: \"my-app\" } }) { indirectDependencies { name } } }" | jq WARNING query command is experimental and may change in the future { "data": { "packages": [ { - "transitiveDependencies": [ + "indirectDependencies": [ { "name": "//" }, From 9074391d0bdf1a658b0203bb83099f0ed4a66621 Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Mon, 9 Sep 2024 13:09:40 -0400 Subject: [PATCH 3/3] Renaming query --- crates/turborepo-lib/src/query.rs | 168 ++++++++++++++---- .../integration/tests/command-query.t | 27 ++- 2 files changed, 154 insertions(+), 41 deletions(-) diff --git a/crates/turborepo-lib/src/query.rs b/crates/turborepo-lib/src/query.rs index cbefc1752e068..9d6341adc8d4f 100644 --- a/crates/turborepo-lib/src/query.rs +++ b/crates/turborepo-lib/src/query.rs @@ -44,40 +44,56 @@ struct Package { } impl Package { - fn immediate_dependents_count(&self) -> usize { + fn direct_dependents_count(&self) -> usize { self.run .pkg_dep_graph() .immediate_ancestors(&PackageNode::Workspace(self.name.clone())) .map_or(0, |pkgs| pkgs.len()) } - fn immediate_dependencies_count(&self) -> usize { + fn direct_dependencies_count(&self) -> usize { self.run .pkg_dep_graph() .immediate_dependencies(&PackageNode::Workspace(self.name.clone())) .map_or(0, |pkgs| pkgs.len()) } - fn dependent_count(&self) -> usize { + fn indirect_dependents_count(&self) -> usize { let node: PackageNode = PackageNode::Workspace(self.name.clone()); - self.run.pkg_dep_graph().ancestors(&node).len() + self.run.pkg_dep_graph().ancestors(&node).len() - self.direct_dependents_count() } - fn dependency_count(&self) -> usize { + fn indirect_dependencies_count(&self) -> usize { let node: PackageNode = PackageNode::Workspace(self.name.clone()); - self.run.pkg_dep_graph().dependencies(&node).len() + self.run.pkg_dep_graph().dependencies(&node).len() - self.direct_dependencies_count() + } + + fn all_dependents_count(&self) -> usize { + self.run + .pkg_dep_graph() + .ancestors(&PackageNode::Workspace(self.name.clone())) + .len() + } + + fn all_dependencies_count(&self) -> usize { + self.run + .pkg_dep_graph() + .dependencies(&PackageNode::Workspace(self.name.clone())) + .len() } } #[derive(Enum, Copy, Clone, Eq, PartialEq, Debug)] enum PackageFields { Name, - DependencyCount, - DependentCount, - ImmediateDependentCount, - ImmediateDependencyCount, + DirectDependencyCount, + DirectDependentCount, + IndirectDependentCount, + IndirectDependencyCount, + AllDependentCount, + AllDependencyCount, } #[derive(InputObject)] @@ -107,29 +123,41 @@ impl PackagePredicate { fn check_equals(pkg: &Package, field: &PackageFields, value: &Any) -> bool { match (field, &value.0) { (PackageFields::Name, Value::String(name)) => pkg.name.as_ref() == name, - (PackageFields::DependencyCount, Value::Number(n)) => { + (PackageFields::DirectDependencyCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.dependency_count() == n as usize + pkg.direct_dependencies_count() == n as usize } - (PackageFields::DependentCount, Value::Number(n)) => { + (PackageFields::DirectDependentCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.dependent_count() == n as usize + pkg.direct_dependents_count() == n as usize } - (PackageFields::ImmediateDependentCount, Value::Number(n)) => { + (PackageFields::IndirectDependentCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.immediate_dependents_count() == n as usize + pkg.indirect_dependents_count() == n as usize } - (PackageFields::ImmediateDependencyCount, Value::Number(n)) => { + (PackageFields::IndirectDependencyCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.immediate_dependencies_count() == n as usize + pkg.indirect_dependencies_count() == n as usize + } + (PackageFields::AllDependentCount, Value::Number(n)) => { + let Some(n) = n.as_u64() else { + return false; + }; + pkg.all_dependents_count() == n as usize + } + (PackageFields::AllDependencyCount, Value::Number(n)) => { + let Some(n) = n.as_u64() else { + return false; + }; + pkg.all_dependencies_count() == n as usize } _ => false, } @@ -137,29 +165,41 @@ impl PackagePredicate { fn check_greater_than(pkg: &Package, field: &PackageFields, value: &Any) -> bool { match (field, &value.0) { - (PackageFields::DependencyCount, Value::Number(n)) => { + (PackageFields::DirectDependencyCount, Value::Number(n)) => { + let Some(n) = n.as_u64() else { + return false; + }; + pkg.direct_dependencies_count() > n as usize + } + (PackageFields::DirectDependentCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.dependency_count() > n as usize + pkg.direct_dependents_count() > n as usize } - (PackageFields::DependentCount, Value::Number(n)) => { + (PackageFields::IndirectDependentCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.dependent_count() > n as usize + pkg.indirect_dependents_count() > n as usize } - (PackageFields::ImmediateDependentCount, Value::Number(n)) => { + (PackageFields::IndirectDependencyCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.immediate_dependents_count() > n as usize + pkg.indirect_dependencies_count() > n as usize } - (PackageFields::ImmediateDependencyCount, Value::Number(n)) => { + (PackageFields::AllDependentCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.immediate_dependencies_count() > n as usize + pkg.all_dependents_count() > n as usize + } + (PackageFields::AllDependencyCount, Value::Number(n)) => { + let Some(n) = n.as_u64() else { + return false; + }; + pkg.all_dependencies_count() > n as usize } _ => false, } @@ -167,29 +207,41 @@ impl PackagePredicate { fn check_less_than(pkg: &Package, field: &PackageFields, value: &Any) -> bool { match (field, &value.0) { - (PackageFields::DependencyCount, Value::Number(n)) => { + (PackageFields::DirectDependencyCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.dependency_count() < n as usize + pkg.direct_dependencies_count() < n as usize } - (PackageFields::DependentCount, Value::Number(n)) => { + (PackageFields::DirectDependentCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.dependent_count() < n as usize + pkg.direct_dependents_count() < n as usize } - (PackageFields::ImmediateDependentCount, Value::Number(n)) => { + (PackageFields::IndirectDependentCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.immediate_dependents_count() < n as usize + pkg.indirect_dependents_count() < n as usize } - (PackageFields::ImmediateDependencyCount, Value::Number(n)) => { + (PackageFields::IndirectDependencyCount, Value::Number(n)) => { let Some(n) = n.as_u64() else { return false; }; - pkg.immediate_dependencies_count() < n as usize + pkg.indirect_dependencies_count() < n as usize + } + (PackageFields::AllDependentCount, Value::Number(n)) => { + let Some(n) = n.as_u64() else { + return false; + }; + pkg.all_dependents_count() < n as usize + } + (PackageFields::AllDependencyCount, Value::Number(n)) => { + let Some(n) = n.as_u64() else { + return false; + }; + pkg.all_dependencies_count() < n as usize } _ => false, } @@ -319,7 +371,7 @@ impl Package { } /// The upstream packages that have this package as a direct dependency - async fn dependents(&self) -> Result, Error> { + async fn direct_dependents(&self) -> Result, Error> { let node: PackageNode = PackageNode::Workspace(self.name.clone()); Ok(self .run @@ -331,11 +383,12 @@ impl Package { run: self.run.clone(), name: package.as_package_name().clone(), }) + .sorted_by(|a, b| a.name.cmp(&b.name)) .collect()) } /// The downstream packages that directly depend on this package - async fn dependencies(&self) -> Result, Error> { + async fn direct_dependencies(&self) -> Result, Error> { let node: PackageNode = PackageNode::Workspace(self.name.clone()); Ok(self .run @@ -347,18 +400,55 @@ impl Package { run: self.run.clone(), name: package.as_package_name().clone(), }) + .sorted_by(|a, b| a.name.cmp(&b.name)) + .collect()) + } + + async fn all_dependents(&self) -> Result, Error> { + let node: PackageNode = PackageNode::Workspace(self.name.clone()); + Ok(self + .run + .pkg_dep_graph() + .ancestors(&node) + .iter() + .map(|package| Package { + run: self.run.clone(), + name: package.as_package_name().clone(), + }) + .sorted_by(|a, b| a.name.cmp(&b.name)) + .collect()) + } + + async fn all_dependencies(&self) -> Result, Error> { + let node: PackageNode = PackageNode::Workspace(self.name.clone()); + Ok(self + .run + .pkg_dep_graph() + .dependencies(&node) + .iter() + .map(|package| Package { + run: self.run.clone(), + name: package.as_package_name().clone(), + }) + .sorted_by(|a, b| a.name.cmp(&b.name)) .collect()) } /// The downstream packages that depend on this package, indirectly async fn indirect_dependents(&self) -> Result, Error> { let node: PackageNode = PackageNode::Workspace(self.name.clone()); + let immediate_dependents = self + .run + .pkg_dep_graph() + .immediate_ancestors(&node) + .ok_or_else(|| Error::PackageNotFound(self.name.clone()))?; Ok(self .run .pkg_dep_graph() .ancestors(&node) .iter() + .filter(|package| !immediate_dependents.contains(*package)) .map(|package| Package { run: self.run.clone(), name: package.as_package_name().clone(), @@ -370,12 +460,18 @@ impl Package { /// The upstream packages that this package depends on, indirectly async fn indirect_dependencies(&self) -> Result, Error> { let node: PackageNode = PackageNode::Workspace(self.name.clone()); + let immediate_dependencies = self + .run + .pkg_dep_graph() + .immediate_dependencies(&node) + .ok_or_else(|| Error::PackageNotFound(self.name.clone()))?; Ok(self .run .pkg_dep_graph() .dependencies(&node) .iter() + .filter(|package| !immediate_dependencies.contains(*package)) .map(|package| Package { run: self.run.clone(), name: package.as_package_name().clone(), diff --git a/turborepo-tests/integration/tests/command-query.t b/turborepo-tests/integration/tests/command-query.t index 14e991642508a..9d1842ee72488 100644 --- a/turborepo-tests/integration/tests/command-query.t +++ b/turborepo-tests/integration/tests/command-query.t @@ -37,7 +37,7 @@ Query packages with equals filter } Query packages that have at least one dependent package - $ ${TURBO} query "query { packages(filter: { greaterThan: { field: DEPENDENT_COUNT, value: 0 } }) { name } }" | jq + $ ${TURBO} query "query { packages(filter: { greaterThan: { field: DIRECT_DEPENDENT_COUNT, value: 0 } }) { name } }" | jq WARNING query command is experimental and may change in the future { "data": { @@ -50,13 +50,13 @@ Query packages that have at least one dependent package } Get dependents of `util` - $ ${TURBO} query "query { packages(filter: { equal: { field: NAME, value: \"util\" } }) { dependents { name } } }" | jq + $ ${TURBO} query "query { packages(filter: { equal: { field: NAME, value: \"util\" } }) { directDependents { name } } }" | jq WARNING query command is experimental and may change in the future { "data": { "packages": [ { - "dependents": [ + "directDependents": [ { "name": "my-app" } @@ -67,13 +67,13 @@ Get dependents of `util` } Get dependencies of `my-app` - $ ${TURBO} query "query { packages(filter: { equal: { field: NAME, value: \"my-app\" } }) { dependencies { name } } }" | jq + $ ${TURBO} query "query { packages(filter: { equal: { field: NAME, value: \"my-app\" } }) { directDependencies { name } } }" | jq WARNING query command is experimental and may change in the future { "data": { "packages": [ { - "dependencies": [ + "directDependencies": [ { "name": "util" } @@ -91,6 +91,23 @@ Get the indirect dependencies of `my-app` "packages": [ { "indirectDependencies": [ + { + "name": "//" + } + ] + } + ] + } + } + +Get all dependencies of `my-app` + $ ${TURBO} query "query { packages(filter: { equal: { field: NAME, value: \"my-app\" } }) { allDependencies { name } } }" | jq + WARNING query command is experimental and may change in the future + { + "data": { + "packages": [ + { + "allDependencies": [ { "name": "//" },