Skip to content

Commit fe86401

Browse files
feat(blazebuild): task graph
1 parent f4c92b4 commit fe86401

File tree

4 files changed

+94
-7
lines changed

4 files changed

+94
-7
lines changed

blazebuild/src/main/typescript/core/Blaze.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class Blaze {
1919
this.taskManager,
2020
this.projectManager
2121
];
22-
22+
private _taskNames: string[] = [];
2323
private static _instance: Blaze;
2424

2525
private constructor() {
@@ -35,6 +35,10 @@ class Blaze {
3535
return this._instance;
3636
}
3737

38+
public get taskNames() {
39+
return this._taskNames;
40+
}
41+
3842
public async boot() {
3943
process.on("uncaughtException", error => {
4044
IO.fatal(error);
@@ -65,11 +69,11 @@ class Blaze {
6569
IO.fatal(error);
6670
}
6771

68-
const taskNames =
72+
this._taskNames =
6973
process.argv.length >= 3 ? process.argv.slice(2) : [Blaze.defaultTaskName];
7074

7175
try {
72-
for (const taskName of taskNames) {
76+
for (const taskName of this._taskNames) {
7377
await this.taskManager.executeTask(taskName);
7478
}
7579
} catch (error) {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import IO from "../../io/IO";
2+
import AbstractTask from "../../tasks/AbstractTask";
3+
import { Task } from "../../tasks/Task";
4+
import { TaskAction } from "../../tasks/TaskAction";
5+
6+
@Task({
7+
description: "Graphs the project's dependencies.",
8+
group: "Help"
9+
})
10+
class GraphTask extends AbstractTask {
11+
@TaskAction
12+
public override async run() {
13+
this.blaze.taskNames.shift();
14+
const taskName = this.blaze.taskNames.shift();
15+
16+
if (!taskName) {
17+
IO.fatal("No task specified. Please specify a task to graph.");
18+
}
19+
20+
const graph = await this.blaze.taskManager.getTaskGraph(taskName);
21+
console.log("\n" + (await graph.toString()));
22+
}
23+
}
24+
25+
export default GraphTask;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import chalk from "chalk";
2+
import Blaze from "../core/Blaze";
3+
import type { TaskDetails } from "./TaskManager";
4+
5+
class TaskGraph {
6+
public readonly taskDetails: TaskDetails<unknown>;
7+
8+
public constructor(task: TaskDetails<unknown>) {
9+
this.taskDetails = task;
10+
}
11+
12+
public async toString() {
13+
const dependenciesOutput = await this.internalToString(this.taskDetails, 1);
14+
return `${chalk.bold(dependenciesOutput === "" ? "-" : "+")} ${this.taskDetails.options?.name ?? this.taskDetails.task.name}\n${dependenciesOutput.trimEnd()}`;
15+
}
16+
17+
private async internalToString(
18+
taskDetails: TaskDetails<unknown>,
19+
tabs = 0,
20+
visited = new Map<string, number>()
21+
) {
22+
const taskManager = Blaze.getInstance().taskManager;
23+
let output = "";
24+
25+
for (const dependency of await taskManager.getTaskDependencies(
26+
taskDetails.task,
27+
undefined,
28+
false
29+
)) {
30+
const dependenciesOutput = await this.internalToString(dependency, tabs + 1, visited);
31+
const name = dependency.options?.name ?? dependency.task.name;
32+
const appearance = visited.get(name) ?? 0;
33+
output += `${`${chalk.gray.dim("|")} `.repeat(tabs)}${chalk.bold(dependenciesOutput === "" ? "-" : "+")} ${name}${appearance === 0 ? "" : ` ${chalk.white.dim(`[${appearance}]`)}`}\n`;
34+
output += dependenciesOutput;
35+
visited.set(name, appearance + 1);
36+
}
37+
38+
return output;
39+
}
40+
}
41+
42+
export default TaskGraph;

blazebuild/src/main/typescript/tasks/TaskManager.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,22 @@ import type Blaze from "../core/Blaze";
55
import Manager from "../core/Manager";
66
import TaskNotFoundError from "../errors/TaskNotFoundError";
77
import BuildTask from "../framework/tasks/BuildTask";
8+
import GraphTask from "../framework/tasks/GraphTask";
89
import TasksTask from "../framework/tasks/TasksTask";
910
import IO from "../io/IO";
1011
import type { FileResolvable } from "../types/file";
1112
import type { Awaitable } from "../types/utils";
1213
import AbstractTask, { type TaskResolvable } from "./AbstractTask";
1314
import { ActionlessTask } from "./ActionlessTask";
1415
import { TASK_DEPENDENCY_GENERATOR_METADATA_KEY } from "./TaskDependencyGenerator";
16+
import TaskGraph from "./TaskGraph";
1517
import { TaskOutputGenerator } from "./TaskOutputGenerator";
1618

1719
class TaskManager extends Manager {
1820
private static readonly builtInTasks: Array<new (blaze: Blaze) => AbstractTask<any>> = [
1921
TasksTask,
20-
BuildTask
22+
BuildTask,
23+
GraphTask
2124
];
2225
private readonly tasks = new Map<string, TaskDetails<any>>();
2326
private readonly classToTaskMap = new Map<typeof AbstractTask<any>, TaskDetails<any>>();
@@ -76,7 +79,10 @@ class TaskManager extends Manager {
7679
throw new Error("Invalid arguments passed to register method");
7780
}
7881

79-
public named<T extends AbstractTask<any>>(name: string, options: TaskRegisterOptions<unknown, T>) {
82+
public named<T extends AbstractTask<any>>(
83+
name: string,
84+
options: TaskRegisterOptions<unknown, T>
85+
) {
8086
const task = this.resolveTask(name);
8187

8288
task.options = {
@@ -302,7 +308,8 @@ class TaskManager extends Manager {
302308

303309
public async getTaskDependencies(
304310
taskResolvable: string | AbstractTask<any>,
305-
set = new Set<TaskDetails<unknown>>()
311+
set = new Set<TaskDetails<unknown>>(),
312+
deep = true
306313
) {
307314
const { task, options } = this.resolveTask(
308315
typeof taskResolvable === "string"
@@ -321,7 +328,11 @@ class TaskManager extends Manager {
321328

322329
for (const dependency of [...dependencies, ...(options?.dependsOn ?? [])]) {
323330
const details: TaskDetails<unknown> = this.blaze.taskManager.resolveTask(dependency);
324-
await this.getTaskDependencies(details.task, set);
331+
332+
if (deep) {
333+
await this.getTaskDependencies(details.task, set);
334+
}
335+
325336
set.add(details);
326337
}
327338

@@ -431,6 +442,11 @@ class TaskManager extends Manager {
431442
public getActionableTaskCount() {
432443
return this.upToDateTasks.size + this.executedTasks.size;
433444
}
445+
446+
public async getTaskGraph<T>(resolvable: TaskResolvable<T>) {
447+
const taskDetails = this.resolveTask(resolvable);
448+
return new TaskGraph(taskDetails);
449+
}
434450
}
435451

436452
export type TaskRegisterOptions<R, T extends AbstractTask<R> = AbstractTask<R>> = {

0 commit comments

Comments
 (0)