Skip to content

Commit 0a8f780

Browse files
committed
Add affected.
1 parent 63ea21f commit 0a8f780

7 files changed

Lines changed: 88 additions & 11 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/affected/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ clap = { workspace = true }
1919
miette = { workspace = true }
2020
rustc-hash = { workspace = true }
2121
serde = { workspace = true }
22+
starbase_utils = { workspace = true }
2223
tracing = { workspace = true }
2324

2425
[dev-dependencies]

crates/affected/src/affected_tracker.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use moon_project::Project;
66
use moon_task::{Target, Task, TaskOptionRunInCI};
77
use moon_workspace_graph::{GraphConnections, WorkspaceGraph};
88
use rustc_hash::{FxHashMap, FxHashSet};
9+
use starbase_utils::fs;
910
use std::fmt;
1011
use std::sync::Arc;
1112
use tracing::{debug, trace};
@@ -361,7 +362,25 @@ impl AffectedTracker {
361362
let globset = task.create_globset()?;
362363

363364
for file in self.touched_files.iter() {
364-
if task.input_files.contains_key(file) || globset.matches(file.as_str()) {
365+
let mut affected = false;
366+
367+
if let Some(params) = task.input_files.get(file) {
368+
affected = match &params.content {
369+
Some(matcher) => {
370+
let content =
371+
fs::read_file(file.to_logical_path(&self.workspace_graph.root))?;
372+
373+
matcher.is_match(&content)
374+
}
375+
None => true,
376+
};
377+
}
378+
379+
if !affected {
380+
affected = globset.matches(file.as_str());
381+
}
382+
383+
if affected {
365384
return Ok(Some(AffectedBy::TouchedFile(file.to_owned())));
366385
}
367386
}

crates/affected/tests/__fixtures__/tasks/base/moon.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ tasks:
99
by-file:
1010
inputs:
1111
- 'file.txt'
12+
by-file-match:
13+
inputs:
14+
- file: 'file.txt'
15+
content: 'ba(r|z)'
1216
by-glob:
1317
inputs:
1418
- '*.txt'

crates/affected/tests/affected_tracker_test.rs

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,24 @@ use moon_env_var::GlobalEnvBag;
44
use moon_task::Target;
55
use moon_test_utils2::{WorkspaceGraph, WorkspaceMocker};
66
use rustc_hash::{FxHashMap, FxHashSet};
7-
use starbase_sandbox::create_sandbox;
7+
use starbase_sandbox::{Sandbox, create_sandbox};
88

9-
async fn build_graph(fixture: &str) -> WorkspaceGraph {
9+
async fn build_graph_with_sandbox(fixture: &str) -> (WorkspaceGraph, Sandbox) {
1010
let sandbox = create_sandbox(fixture);
1111

12-
WorkspaceMocker::new(sandbox.path())
13-
.with_default_projects()
14-
.with_global_envs()
15-
.with_inherited_tasks()
16-
.mock_workspace_graph()
17-
.await
12+
(
13+
WorkspaceMocker::new(sandbox.path())
14+
.with_default_projects()
15+
.with_global_envs()
16+
.with_inherited_tasks()
17+
.mock_workspace_graph()
18+
.await,
19+
sandbox,
20+
)
21+
}
22+
23+
async fn build_graph(fixture: &str) -> WorkspaceGraph {
24+
build_graph_with_sandbox(fixture).await.0
1825
}
1926

2027
mod affected_projects {
@@ -454,6 +461,44 @@ mod affected_tasks {
454461
);
455462
}
456463

464+
#[tokio::test]
465+
async fn affected_by_file_if_content_matches() {
466+
let (workspace_graph, sandbox) = build_graph_with_sandbox("tasks").await;
467+
sandbox.create_file("base/file.txt", "bar");
468+
469+
let touched_files = FxHashSet::from_iter(["base/file.txt".into()]);
470+
471+
let mut tracker = AffectedTracker::new(workspace_graph.into(), touched_files);
472+
tracker
473+
.track_tasks_by_target(&[Target::parse("base:by-file-match").unwrap()])
474+
.unwrap();
475+
let affected = tracker.build();
476+
477+
assert_eq!(
478+
affected.tasks,
479+
FxHashMap::from_iter([(
480+
Target::parse("base:by-file-match").unwrap(),
481+
create_state_from_file("base/file.txt")
482+
)])
483+
);
484+
}
485+
486+
#[tokio::test]
487+
async fn not_affected_by_file_if_content_doesnt_match() {
488+
let (workspace_graph, sandbox) = build_graph_with_sandbox("tasks").await;
489+
sandbox.create_file("base/file.txt", "foo");
490+
491+
let touched_files = FxHashSet::from_iter(["base/file.txt".into()]);
492+
493+
let mut tracker = AffectedTracker::new(workspace_graph.into(), touched_files);
494+
tracker
495+
.track_tasks_by_target(&[Target::parse("base:by-file-match").unwrap()])
496+
.unwrap();
497+
let affected = tracker.build();
498+
499+
assert!(affected.tasks.is_empty());
500+
}
501+
457502
#[tokio::test]
458503
async fn affected_by_glob() {
459504
let workspace_graph = build_graph("tasks").await;

crates/workspace-graph/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use moon_common::Id;
55
use moon_project_graph::{Project, ProjectGraph};
66
use moon_task_graph::{Target, Task, TaskGraph};
77
use scc::HashMap;
8+
use std::path::PathBuf;
89
use std::{path::Path, sync::Arc};
910

1011
pub use moon_graph_utils::*;
@@ -15,6 +16,7 @@ pub use moon_task_graph as tasks;
1516
pub struct WorkspaceGraph {
1617
pub projects: Arc<ProjectGraph>,
1718
pub tasks: Arc<TaskGraph>,
19+
pub root: PathBuf,
1820

1921
/// Cache of query results, mapped by query input to project IDs.
2022
project_query_cache: HashMap<String, Arc<Vec<Id>>>,
@@ -24,10 +26,11 @@ pub struct WorkspaceGraph {
2426
}
2527

2628
impl WorkspaceGraph {
27-
pub fn new(projects: Arc<ProjectGraph>, tasks: Arc<TaskGraph>) -> Self {
29+
pub fn new(projects: Arc<ProjectGraph>, tasks: Arc<TaskGraph>, root: PathBuf) -> Self {
2830
Self {
2931
projects,
3032
tasks,
33+
root,
3134
project_query_cache: HashMap::default(),
3235
task_query_cache: HashMap::default(),
3336
}

crates/workspace/src/workspace_builder.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,11 @@ impl<'app> WorkspaceBuilder<'app> {
273273
Arc::clone(&project_graph),
274274
));
275275

276-
Ok(WorkspaceGraph::new(project_graph, task_graph))
276+
Ok(WorkspaceGraph::new(
277+
project_graph,
278+
task_graph,
279+
context.workspace_root.to_path_buf(),
280+
))
277281
}
278282

279283
/// Load a single project by ID or alias into the graph.

0 commit comments

Comments
 (0)