teapot 3.6.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/context/getting-started.md +139 -0
- data/context/index.yaml +13 -0
- data/lib/teapot/command/build.rb +10 -3
- data/lib/teapot/command/clean.rb +2 -0
- data/lib/teapot/command/clone.rb +7 -0
- data/lib/teapot/command/create.rb +7 -0
- data/lib/teapot/command/fetch.rb +7 -0
- data/lib/teapot/command/list.rb +6 -0
- data/lib/teapot/command/selection.rb +7 -0
- data/lib/teapot/command/status.rb +9 -0
- data/lib/teapot/command/visualize.rb +153 -27
- data/lib/teapot/command.rb +16 -0
- data/lib/teapot/configuration.rb +17 -1
- data/lib/teapot/context.rb +13 -0
- data/lib/teapot/definition.rb +10 -0
- data/lib/teapot/loader.rb +27 -0
- data/lib/teapot/package.rb +21 -0
- data/lib/teapot/project.rb +11 -0
- data/lib/teapot/select.rb +15 -0
- data/lib/teapot/target.rb +8 -0
- data/lib/teapot/version.rb +2 -1
- data/lib/teapot.rb +0 -4
- data/readme.md +8 -118
- data/releases.md +4 -0
- data.tar.gz.sig +0 -0
- metadata +19 -15
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6fb45edfbd49bfea6e78038ec74bd4473be5a2f716edd0391907acf66d5a740c
|
|
4
|
+
data.tar.gz: 61012b133dc05dbd9fd5e240964313f387592361e08394c2602c024606f65d48
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d1dfddcdc2485c1911367892d4be722a74c2aa2a5f2cc0943ad9b914896ec648b1276d8582cf4225f2ff864c8f8c7a5a9f1fff134c10bb1407abaae7c8ee933c
|
|
7
|
+
data.tar.gz: 39c8e42658208e0499fd22b0951e75218725622bcf83690b3290f230f1e5e7c710a6f0db1776036bd2b51b4108fc3ee9eef9b1ac8e65566385ba1677449204dd
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
This guide explains how to use `teapot` to manage cross-platform project dependencies and build systems.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Ensure that you already have a working install of Ruby 2.0.0+ and run the following to install `teapot`:
|
|
8
|
+
|
|
9
|
+
~~~ bash
|
|
10
|
+
$ gem install teapot
|
|
11
|
+
~~~
|
|
12
|
+
|
|
13
|
+
## Create Project
|
|
14
|
+
|
|
15
|
+
Firstly, create your project by running:
|
|
16
|
+
|
|
17
|
+
~~~ bash
|
|
18
|
+
$ teapot create "My Project" https://github.com/kurocha generate-project
|
|
19
|
+
$ cd my-project
|
|
20
|
+
~~~
|
|
21
|
+
|
|
22
|
+
You will be asked to merge the project file. At present, merge tools are not very good and thus you may need to take a moment to review the changes. You want to keep most of the original file, but you would like to add the `define_target` blocks which are being added.
|
|
23
|
+
|
|
24
|
+
In the resulting project directory that has been created, you can see the list of dependencies:
|
|
25
|
+
|
|
26
|
+
~~~ bash
|
|
27
|
+
$ teapot list
|
|
28
|
+
... lots of output ...
|
|
29
|
+
~~~
|
|
30
|
+
|
|
31
|
+
To only see things exported by your current project, you can run:
|
|
32
|
+
|
|
33
|
+
~~~ bash
|
|
34
|
+
$ teapot list root
|
|
35
|
+
Package root (from /private/tmp/my-project):
|
|
36
|
+
#<Teapot::Project "my-project">
|
|
37
|
+
My Project description.
|
|
38
|
+
- Summary: A brief one line summary of the project.
|
|
39
|
+
- License: MIT License
|
|
40
|
+
- Version: 0.1.0
|
|
41
|
+
- Author: Samuel Williams <samuel.williams@oriontransfer.co.nz>
|
|
42
|
+
#<Teapot::Target "my-project-library">
|
|
43
|
+
- depends on "Build/Files"
|
|
44
|
+
- depends on "Build/Clang"
|
|
45
|
+
- depends on :platform
|
|
46
|
+
- depends on "Language/C++14" {:private=>true}
|
|
47
|
+
- provides "Library/MyProject"
|
|
48
|
+
#<Teapot::Target "my-project-test">
|
|
49
|
+
- depends on "Library/UnitTest"
|
|
50
|
+
- depends on "Library/MyProject"
|
|
51
|
+
- provides "Test/MyProject"
|
|
52
|
+
#<Teapot::Target "my-project-executable">
|
|
53
|
+
- depends on "Build/Files"
|
|
54
|
+
- depends on "Build/Clang"
|
|
55
|
+
- depends on :platform
|
|
56
|
+
- depends on "Language/C++14" {:private=>true}
|
|
57
|
+
- depends on "Library/MyProject"
|
|
58
|
+
- provides "Executable/MyProject"
|
|
59
|
+
#<Teapot::Target "my-project-run">
|
|
60
|
+
- depends on "Executable/MyProject"
|
|
61
|
+
- provides "Run/MyProject"
|
|
62
|
+
#<Teapot::Configuration "development" visibility=private>
|
|
63
|
+
- references root from /private/tmp/my-project
|
|
64
|
+
- clones platforms from https://github.com/kurocha/platforms
|
|
65
|
+
- clones unit-test from https://github.com/kurocha/unit-test
|
|
66
|
+
- clones generate-cpp-class from https://github.com/kurocha/generate-cpp-class
|
|
67
|
+
- clones generate-project from https://github.com/kurocha/generate-project
|
|
68
|
+
- clones variants from https://github.com/kurocha/variants
|
|
69
|
+
- clones platform-darwin-osx from https://github.com/kurocha/platform-darwin-osx
|
|
70
|
+
- clones platform-darwin-ios from https://github.com/kurocha/platform-darwin-ios
|
|
71
|
+
- clones build-clang from https://github.com/kurocha/build-clang
|
|
72
|
+
- clones build-darwin from https://github.com/kurocha/build-darwin
|
|
73
|
+
- clones build-files from https://github.com/kurocha/build-files
|
|
74
|
+
- clones streams from https://github.com/kurocha/streams
|
|
75
|
+
- clones generate-template from https://github.com/kurocha/generate-template
|
|
76
|
+
#<Teapot::Configuration "my-project" visibility=public>
|
|
77
|
+
- references root from /private/tmp/my-project
|
|
78
|
+
~~~
|
|
79
|
+
|
|
80
|
+
## Run Tests
|
|
81
|
+
|
|
82
|
+
Testing is a good idea, and teapot supports test driven development.
|
|
83
|
+
|
|
84
|
+
~~~ bash
|
|
85
|
+
$ teapot Test/MyProject
|
|
86
|
+
~~~
|
|
87
|
+
|
|
88
|
+
### Wildcard Targets
|
|
89
|
+
|
|
90
|
+
To run all tests:
|
|
91
|
+
|
|
92
|
+
~~~ bash
|
|
93
|
+
$ teapot "Test/*"
|
|
94
|
+
~~~
|
|
95
|
+
|
|
96
|
+
Provided you are using an environment that supports sanitizers, you can test more thoroughly using:
|
|
97
|
+
|
|
98
|
+
~~~ bash
|
|
99
|
+
$ teapot "Test/*" variant-sanitize
|
|
100
|
+
~~~
|
|
101
|
+
|
|
102
|
+
## Run Project
|
|
103
|
+
|
|
104
|
+
We can now build and run the project executable:
|
|
105
|
+
|
|
106
|
+
~~~ bash
|
|
107
|
+
$ teapot Run/MyProject
|
|
108
|
+
I'm a little teapot,
|
|
109
|
+
Short and stout,
|
|
110
|
+
Here is my handle (one hand on hip),
|
|
111
|
+
Here is my spout (other arm out with elbow and wrist bent).
|
|
112
|
+
When I get all steamed up,
|
|
113
|
+
Hear me shout,
|
|
114
|
+
Tip me over and pour me out! (lean over toward spout)
|
|
115
|
+
|
|
116
|
+
~
|
|
117
|
+
___^___ __
|
|
118
|
+
.- / \./ /
|
|
119
|
+
/ / _/
|
|
120
|
+
\__| |
|
|
121
|
+
\_______/
|
|
122
|
+
~~~
|
|
123
|
+
|
|
124
|
+
The resulting executables and libraries will be framework dependent, but are typically located in:
|
|
125
|
+
|
|
126
|
+
~~~ bash
|
|
127
|
+
$ cd teapot/platforms/development/$PLATFORM-debug/bin
|
|
128
|
+
$ ./$PROJECT_NAME
|
|
129
|
+
~~~
|
|
130
|
+
|
|
131
|
+
## Cloning Project
|
|
132
|
+
|
|
133
|
+
You can clone another project which will fetch all dependencies:
|
|
134
|
+
|
|
135
|
+
~~~ bash
|
|
136
|
+
$ teapot clone https://github.com/kurocha/tagged-format
|
|
137
|
+
$ cd tagged-format
|
|
138
|
+
$ teapot build Executable/TaggedFormat
|
|
139
|
+
~~~
|
data/context/index.yaml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Automatically generated context index for Utopia::Project guides.
|
|
2
|
+
# Do not edit then files in this directory directly, instead edit the guides and then run `bake utopia:project:agent:context:update`.
|
|
3
|
+
---
|
|
4
|
+
description: Teapot is a tool for managing cross-platform builds.
|
|
5
|
+
metadata:
|
|
6
|
+
documentation_uri: https://ioquatix.github.io/teapot/
|
|
7
|
+
funding_uri: https://github.com/sponsors/ioquatix
|
|
8
|
+
source_code_uri: https://github.com/ioquatix/teapot
|
|
9
|
+
files:
|
|
10
|
+
- path: getting-started.md
|
|
11
|
+
title: Getting Started
|
|
12
|
+
description: This guide explains how to use `teapot` to manage cross-platform project
|
|
13
|
+
dependencies and build systems.
|
data/lib/teapot/command/build.rb
CHANGED
|
@@ -9,20 +9,25 @@ require "build/controller"
|
|
|
9
9
|
|
|
10
10
|
module Teapot
|
|
11
11
|
module Command
|
|
12
|
+
# Raised when the build fails.
|
|
12
13
|
class BuildFailedError < StandardError
|
|
13
14
|
end
|
|
14
15
|
|
|
16
|
+
# A command to build targets in the project.
|
|
15
17
|
class Build < Selection
|
|
16
18
|
self.description = "Build the specified target."
|
|
17
19
|
|
|
18
20
|
options do
|
|
19
21
|
option "-j/-l/--limit <n>", "Limit the build to <n> concurrent processes.", type: Integer
|
|
20
22
|
option "-c/--continuous", "Run the build graph continually (experimental)."
|
|
23
|
+
option "--show-dependencies", "Show task dependencies for debugging."
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
many :targets, "Build these targets, or use them to help the dependency resolution process."
|
|
24
27
|
split :argv, "Arguments passed to child process(es) of build if any."
|
|
25
28
|
|
|
29
|
+
# Build the selected targets or default build targets, resolving dependencies and executing the build controller.
|
|
30
|
+
# @returns [Build::Dependency::Chain] The dependency chain.
|
|
26
31
|
def call
|
|
27
32
|
context = parent.context
|
|
28
33
|
|
|
@@ -36,8 +41,8 @@ module Teapot
|
|
|
36
41
|
chain = selection.chain
|
|
37
42
|
environment = context.configuration.environment
|
|
38
43
|
|
|
39
|
-
controller = ::Build::Controller.
|
|
40
|
-
|
|
44
|
+
controller = ::Build::Controller.build(limit: @options[:limit]) do |builder|
|
|
45
|
+
builder.add_chain(chain, self.argv, environment)
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
walker = nil
|
|
@@ -45,7 +50,7 @@ module Teapot
|
|
|
45
50
|
# We need to catch interrupt here, and exit with the correct exit code:
|
|
46
51
|
begin
|
|
47
52
|
controller.run do |walker|
|
|
48
|
-
|
|
53
|
+
show_dependencies(walker) if @options[:show_dependencies]
|
|
49
54
|
|
|
50
55
|
# Only run once is asked:
|
|
51
56
|
unless @options[:continuous]
|
|
@@ -65,6 +70,8 @@ module Teapot
|
|
|
65
70
|
return chain
|
|
66
71
|
end
|
|
67
72
|
|
|
73
|
+
# Display task dependencies for debugging, showing which tasks generate which outputs.
|
|
74
|
+
# @parameter walker [Build::Walker] The build walker.
|
|
68
75
|
def show_dependencies(walker)
|
|
69
76
|
outputs = {}
|
|
70
77
|
|
data/lib/teapot/command/clean.rb
CHANGED
|
@@ -7,9 +7,11 @@ require "samovar"
|
|
|
7
7
|
|
|
8
8
|
module Teapot
|
|
9
9
|
module Command
|
|
10
|
+
# A command to clean build artifacts.
|
|
10
11
|
class Clean < Samovar::Command
|
|
11
12
|
self.description = "Delete everything in the teapot directory."
|
|
12
13
|
|
|
14
|
+
# Delete build output directories for the specified targets or all targets.
|
|
13
15
|
def call
|
|
14
16
|
context = parent.context
|
|
15
17
|
logger = parent.logger
|
data/lib/teapot/command/clone.rb
CHANGED
|
@@ -13,11 +13,13 @@ require "build/uri"
|
|
|
13
13
|
|
|
14
14
|
module Teapot
|
|
15
15
|
module Command
|
|
16
|
+
# A command to clone a remote repository and fetch all dependencies.
|
|
16
17
|
class Clone < Samovar::Command
|
|
17
18
|
self.description = "Clone a remote repository and fetch all dependencies."
|
|
18
19
|
|
|
19
20
|
one :source, "The source repository to clone.", required: true
|
|
20
21
|
|
|
22
|
+
# Clone packages from their remote repositories using git, parallelizing the operations.
|
|
21
23
|
def call
|
|
22
24
|
logger = parent.logger
|
|
23
25
|
|
|
@@ -37,6 +39,11 @@ module Teapot
|
|
|
37
39
|
Fetch[parent: nested].call
|
|
38
40
|
end
|
|
39
41
|
|
|
42
|
+
# Provide credentials for repository authentication.
|
|
43
|
+
# @parameter url [String] The repository URL.
|
|
44
|
+
# @parameter username [String] The username.
|
|
45
|
+
# @parameter types [Array] The credential types allowed.
|
|
46
|
+
# @returns [Rugged::Credentials] The credentials object.
|
|
40
47
|
def credentials(url, username, types)
|
|
41
48
|
# We should prompt for username/password if required...
|
|
42
49
|
return Rugged::Credentials::SshKeyFromAgent.new(username: username)
|
|
@@ -11,6 +11,7 @@ require "rugged"
|
|
|
11
11
|
|
|
12
12
|
module Teapot
|
|
13
13
|
module Command
|
|
14
|
+
# A command to create a new teapot project.
|
|
14
15
|
class Create < Samovar::Command
|
|
15
16
|
self.description = "Create a new teapot package using the specified repository."
|
|
16
17
|
|
|
@@ -18,6 +19,7 @@ module Teapot
|
|
|
18
19
|
one :source, "The source repository to use for fetching packages, e.g. https://github.com/kurocha.", required: true
|
|
19
20
|
many :packages, "Any packages you'd like to include in the project.", default: ["generate-project"]
|
|
20
21
|
|
|
22
|
+
# Create a new project directory structure with default teapot.rb configuration.
|
|
21
23
|
def call
|
|
22
24
|
logger = parent.logger
|
|
23
25
|
|
|
@@ -64,6 +66,11 @@ module Teapot
|
|
|
64
66
|
)
|
|
65
67
|
end
|
|
66
68
|
|
|
69
|
+
# Generate the initial project files.
|
|
70
|
+
# @parameter root [Build::Files::Path] The project root path.
|
|
71
|
+
# @parameter name [String] The project name.
|
|
72
|
+
# @parameter source [String] The source repository URL.
|
|
73
|
+
# @parameter packages [Array(String)] The packages to include.
|
|
67
74
|
def generate_project(root, name, source, packages)
|
|
68
75
|
name = ::Build::Name.new(name)
|
|
69
76
|
|
data/lib/teapot/command/fetch.rb
CHANGED
|
@@ -8,7 +8,10 @@ require "rugged"
|
|
|
8
8
|
|
|
9
9
|
module Teapot
|
|
10
10
|
module Command
|
|
11
|
+
# Raised when a fetch operation fails.
|
|
11
12
|
class FetchError < StandardError
|
|
13
|
+
# @parameter package [Package] The package that caused the error.
|
|
14
|
+
# @parameter message [String] The error message.
|
|
12
15
|
def initialize(package, message)
|
|
13
16
|
super(message)
|
|
14
17
|
@package = package
|
|
@@ -17,6 +20,7 @@ module Teapot
|
|
|
17
20
|
attr :package
|
|
18
21
|
end
|
|
19
22
|
|
|
23
|
+
# A command to fetch remote packages and dependencies.
|
|
20
24
|
class Fetch < Samovar::Command
|
|
21
25
|
self.description = "Fetch remote packages according to the specified configuration."
|
|
22
26
|
|
|
@@ -32,10 +36,13 @@ module Teapot
|
|
|
32
36
|
|
|
33
37
|
many :packages, "Only update the specified packages, or all packages if none specified."
|
|
34
38
|
|
|
39
|
+
# Get the context for this command.
|
|
40
|
+
# @returns [Context] The current context.
|
|
35
41
|
def context
|
|
36
42
|
parent.context
|
|
37
43
|
end
|
|
38
44
|
|
|
45
|
+
# Update packages by pulling latest changes from their git remotes, subject to lock file constraints.
|
|
39
46
|
def call
|
|
40
47
|
selection = context.select
|
|
41
48
|
|
data/lib/teapot/command/list.rb
CHANGED
|
@@ -10,9 +10,13 @@ require_relative "selection"
|
|
|
10
10
|
|
|
11
11
|
module Teapot
|
|
12
12
|
module Command
|
|
13
|
+
# A command to list project definitions and dependencies.
|
|
13
14
|
class List < Selection
|
|
14
15
|
self.description = "List provisions and dependencies of the specified package."
|
|
15
16
|
|
|
17
|
+
# Create a terminal with custom styles for colorizing different definition types in output.
|
|
18
|
+
# @parameter output [IO] The output stream.
|
|
19
|
+
# @returns [Console::Terminal] The configured terminal.
|
|
16
20
|
def terminal(output = $stdout)
|
|
17
21
|
Console::Terminal.for(output).tap do |terminal|
|
|
18
22
|
terminal[:definition] = terminal.style(nil, nil, :bright)
|
|
@@ -24,6 +28,8 @@ module Teapot
|
|
|
24
28
|
end
|
|
25
29
|
end
|
|
26
30
|
|
|
31
|
+
# Process and display the selection.
|
|
32
|
+
# @parameter selection [Select] The selection to process.
|
|
27
33
|
def process(selection)
|
|
28
34
|
context = selection.context
|
|
29
35
|
terminal = self.terminal
|
|
@@ -7,17 +7,23 @@ require "samovar"
|
|
|
7
7
|
|
|
8
8
|
module Teapot
|
|
9
9
|
module Command
|
|
10
|
+
# Base class for commands that work with selections.
|
|
10
11
|
class Selection < Samovar::Command
|
|
11
12
|
options
|
|
12
13
|
|
|
13
14
|
many :targets, "Only consider the specified targets, if any."
|
|
14
15
|
|
|
16
|
+
# The set of target names to process, or nil if no targets were specified.
|
|
17
|
+
# @returns [Set | Nil] The set of target names.
|
|
15
18
|
def targets
|
|
16
19
|
if @targets and @targets.any?
|
|
17
20
|
Set.new(@targets)
|
|
18
21
|
end
|
|
19
22
|
end
|
|
20
23
|
|
|
24
|
+
# Get the selection for the given context.
|
|
25
|
+
# @parameter context [Context] The project context.
|
|
26
|
+
# @returns [Select] The selection.
|
|
21
27
|
def selection(context)
|
|
22
28
|
if targets = self.targets
|
|
23
29
|
context.select(targets)
|
|
@@ -26,6 +32,7 @@ module Teapot
|
|
|
26
32
|
end
|
|
27
33
|
end
|
|
28
34
|
|
|
35
|
+
# Execute the selection command.
|
|
29
36
|
def call
|
|
30
37
|
context = parent.context
|
|
31
38
|
|
|
@@ -9,9 +9,13 @@ require "console/terminal"
|
|
|
9
9
|
|
|
10
10
|
module Teapot
|
|
11
11
|
module Command
|
|
12
|
+
# A command to show git status of packages.
|
|
12
13
|
class Status < Selection
|
|
13
14
|
self.description = "List the git status of the specified package(s)."
|
|
14
15
|
|
|
16
|
+
# Create a terminal with custom styles for colorizing git status information.
|
|
17
|
+
# @parameter output [IO] The output stream.
|
|
18
|
+
# @returns [Console::Terminal] The configured terminal.
|
|
15
19
|
def terminal(output = $stdout)
|
|
16
20
|
Console::Terminal.for(output).tap do |terminal|
|
|
17
21
|
terminal[:worktree_new] = terminal.style(:green)
|
|
@@ -20,6 +24,9 @@ module Teapot
|
|
|
20
24
|
end
|
|
21
25
|
end
|
|
22
26
|
|
|
27
|
+
# Open the git repository for a package, or return nil if the package doesn't have a repository yet.
|
|
28
|
+
# @parameter package [Package] The package.
|
|
29
|
+
# @returns [Rugged::Repository | Nil] The repository or nil.
|
|
23
30
|
def repository_for(package)
|
|
24
31
|
Rugged::Repository.new(package.path.to_s)
|
|
25
32
|
rescue Rugged::RepositoryError
|
|
@@ -27,6 +34,8 @@ module Teapot
|
|
|
27
34
|
nil
|
|
28
35
|
end
|
|
29
36
|
|
|
37
|
+
# Process and display the selection.
|
|
38
|
+
# @parameter selection [Select] The selection to process.
|
|
30
39
|
def process(selection)
|
|
31
40
|
context = selection.context
|
|
32
41
|
terminal = self.terminal
|
|
@@ -3,48 +3,174 @@
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2017-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
|
+
require "samovar"
|
|
6
7
|
require_relative "selection"
|
|
7
|
-
require "
|
|
8
|
+
require "build/controller"
|
|
8
9
|
|
|
9
10
|
module Teapot
|
|
10
11
|
module Command
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
# A command to visualize dependency graphs.
|
|
13
|
+
class Visualize < Samovar::Command
|
|
14
|
+
self.description = "Generate visualizations of package and target dependencies."
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@
|
|
16
|
+
# Visualize package-level dependencies.
|
|
17
|
+
class Packages < Selection
|
|
18
|
+
self.description = "Visualize package-level dependencies from configuration.require."
|
|
19
|
+
|
|
20
|
+
options do
|
|
21
|
+
option "-o/--output-path <path>", "The output path for the visualization."
|
|
22
|
+
option "-d/--dependency-name <name>", "Show the partial chain for the given named dependency."
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Get the specific dependency name to visualize.
|
|
26
|
+
# @returns [String | Nil] The dependency name.
|
|
27
|
+
def dependency_name
|
|
28
|
+
@options[:dependency_name]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Process and generate the package dependency visualization.
|
|
32
|
+
# @parameter selection [Select] The selection to visualize.
|
|
33
|
+
# @returns [String] The generated Mermaid diagram.
|
|
34
|
+
def process(selection)
|
|
35
|
+
chain = selection.chain
|
|
36
|
+
|
|
37
|
+
if dependency_name
|
|
38
|
+
provider = selection.dependencies[dependency_name]
|
|
39
|
+
chain = chain.partial(provider)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
visualization = ::Build::Dependency::Visualization.new
|
|
43
|
+
diagram = visualization.generate(chain)
|
|
44
|
+
|
|
45
|
+
if output_path = @options[:output_path]
|
|
46
|
+
File.write(output_path, diagram)
|
|
47
|
+
else
|
|
48
|
+
$stdout.puts diagram
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
return diagram
|
|
52
|
+
end
|
|
25
53
|
end
|
|
26
54
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
55
|
+
# Visualize target-level dependencies.
|
|
56
|
+
class Targets < Selection
|
|
57
|
+
self.description = "Visualize target-level dependencies from target.depends."
|
|
30
58
|
|
|
31
|
-
|
|
32
|
-
|
|
59
|
+
options do
|
|
60
|
+
option "-o/--output-path <path>", "The output path for the visualization."
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Process and generate the target dependency visualization.
|
|
64
|
+
# @parameter selection [Select] The selection to visualize.
|
|
65
|
+
# @returns [String] The generated Mermaid diagram.
|
|
66
|
+
def process(selection)
|
|
67
|
+
lines = ["flowchart LR"]
|
|
68
|
+
lines << ""
|
|
69
|
+
|
|
70
|
+
# Build the graph from all targets in the selection
|
|
71
|
+
# The selection contains all targets loaded from packages
|
|
72
|
+
selection.targets.each do |name, target|
|
|
73
|
+
target.dependencies.each do |dependency|
|
|
74
|
+
dependency_name = dependency.name.to_s
|
|
75
|
+
|
|
76
|
+
# Create edge from target to its dependency
|
|
77
|
+
if dependency.private?
|
|
78
|
+
lines << " #{sanitize_id(name)}[#{name}] -.-> #{sanitize_id(dependency_name)}[#{dependency_name}]"
|
|
79
|
+
else
|
|
80
|
+
lines << " #{sanitize_id(name)}[#{name}] --> #{sanitize_id(dependency_name)}[#{dependency_name}]"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
diagram = lines.join("\n")
|
|
33
86
|
|
|
34
|
-
|
|
87
|
+
if output_path = @options[:output_path]
|
|
88
|
+
File.write(output_path, diagram)
|
|
89
|
+
else
|
|
90
|
+
$stdout.puts diagram
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
return diagram
|
|
35
94
|
end
|
|
36
95
|
|
|
37
|
-
|
|
96
|
+
private
|
|
38
97
|
|
|
39
|
-
|
|
98
|
+
# Convert a name to a valid Mermaid node ID.
|
|
99
|
+
# @parameter name [String] The name to sanitize.
|
|
100
|
+
# @returns [String] A sanitized identifier safe for use in Mermaid diagrams.
|
|
101
|
+
def sanitize_id(name)
|
|
102
|
+
name.to_s.gsub(/[^a-zA-Z0-9_]/, "_")
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Visualize file-level dependencies from the build graph.
|
|
107
|
+
class Files < Selection
|
|
108
|
+
self.description = "Visualize file-level dependencies by walking the build graph."
|
|
40
109
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
else
|
|
44
|
-
$stdout.puts graph.to_dot
|
|
110
|
+
options do
|
|
111
|
+
option "-o/--output-path <path>", "The output path for the visualization."
|
|
45
112
|
end
|
|
46
113
|
|
|
47
|
-
|
|
114
|
+
# Process and generate the file dependency visualization.
|
|
115
|
+
# @parameter selection [Select] The selection to visualize.
|
|
116
|
+
# @returns [String] The generated Mermaid diagram.
|
|
117
|
+
def process(selection)
|
|
118
|
+
require "build/graph/walker"
|
|
119
|
+
require "build/graph/visualization"
|
|
120
|
+
|
|
121
|
+
context = selection.context
|
|
122
|
+
chain = selection.chain
|
|
123
|
+
environment = context.configuration.environment
|
|
124
|
+
|
|
125
|
+
# Build the controller to get the root nodes
|
|
126
|
+
controller = ::Build::Controller.build(limit: 1) do |builder|
|
|
127
|
+
builder.add_chain(chain, [], environment)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Create a process group for task execution
|
|
131
|
+
group = ::Process::Group.new
|
|
132
|
+
|
|
133
|
+
# Create a walker that traverses without building
|
|
134
|
+
walker = ::Build::Graph::Walker.new do |walker, node, parent_task = nil|
|
|
135
|
+
task_class = node.task_class(parent_task) || ::Build::Graph::Task
|
|
136
|
+
task = task_class.new(walker, node, group)
|
|
137
|
+
|
|
138
|
+
# Use traverse instead of visit to skip building:
|
|
139
|
+
task.traverse
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Populate the walker by traversing from the root nodes
|
|
143
|
+
walker.update(controller.nodes)
|
|
144
|
+
|
|
145
|
+
# Generate the Mermaid diagram
|
|
146
|
+
visualization = ::Build::Graph::Visualization.new
|
|
147
|
+
diagram = visualization.generate(walker)
|
|
148
|
+
|
|
149
|
+
if output_path = @options[:output_path]
|
|
150
|
+
File.write(output_path, diagram)
|
|
151
|
+
else
|
|
152
|
+
$stdout.puts diagram
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
return diagram
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
nested :command, {
|
|
160
|
+
"packages" => Packages,
|
|
161
|
+
"targets" => Targets,
|
|
162
|
+
"files" => Files,
|
|
163
|
+
}, default: "packages"
|
|
164
|
+
|
|
165
|
+
# Delegate context to parent Top command.
|
|
166
|
+
# @returns [Context] The project context.
|
|
167
|
+
def context
|
|
168
|
+
parent.context
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Execute the visualize command.
|
|
172
|
+
def call
|
|
173
|
+
@command.call
|
|
48
174
|
end
|
|
49
175
|
end
|
|
50
176
|
end
|
data/lib/teapot/command.rb
CHANGED
|
@@ -23,7 +23,9 @@ require "fileutils"
|
|
|
23
23
|
require "console"
|
|
24
24
|
|
|
25
25
|
module Teapot
|
|
26
|
+
# @namespace
|
|
26
27
|
module Command
|
|
28
|
+
# Represents the top-level command for the teapot CLI.
|
|
27
29
|
class Top < Samovar::Command
|
|
28
30
|
self.description = "A decentralised package manager and build tool."
|
|
29
31
|
|
|
@@ -46,18 +48,26 @@ module Teapot
|
|
|
46
48
|
"clean" => Clean,
|
|
47
49
|
}, default: "build"
|
|
48
50
|
|
|
51
|
+
# The project root directory, either from --root option or current working directory.
|
|
52
|
+
# @returns [Build::Files::Path] The root directory path.
|
|
49
53
|
def root
|
|
50
54
|
::Build::Files::Path.expand(@options[:root] || Dir.getwd)
|
|
51
55
|
end
|
|
52
56
|
|
|
57
|
+
# Whether verbose logging is enabled via --verbose flag.
|
|
58
|
+
# @returns [Boolean] True if verbose mode is enabled.
|
|
53
59
|
def verbose?
|
|
54
60
|
@options[:logging] == :verbose
|
|
55
61
|
end
|
|
56
62
|
|
|
63
|
+
# Whether quiet logging is enabled via --quiet flag.
|
|
64
|
+
# @returns [Boolean] True if quiet mode is enabled.
|
|
57
65
|
def quiet?
|
|
58
66
|
@options[:logging] == :quiet
|
|
59
67
|
end
|
|
60
68
|
|
|
69
|
+
# Get the logger for the command.
|
|
70
|
+
# @returns [Console::Logger] The configured logger instance.
|
|
61
71
|
def logger
|
|
62
72
|
@logger ||= Console::Logger.new(Console.logger, verbose: self.verbose?).tap do |logger|
|
|
63
73
|
if verbose?
|
|
@@ -70,14 +80,20 @@ module Teapot
|
|
|
70
80
|
end
|
|
71
81
|
end
|
|
72
82
|
|
|
83
|
+
# The build configuration name from -c option or TEAPOT_CONFIGURATION environment variable.
|
|
84
|
+
# @returns [String | Nil] The configuration name if specified.
|
|
73
85
|
def configuration
|
|
74
86
|
@options[:configuration]
|
|
75
87
|
end
|
|
76
88
|
|
|
89
|
+
# Create a context for the project.
|
|
90
|
+
# @parameter root [Build::Files::Path] The root directory path.
|
|
91
|
+
# @returns [Context] A new context instance.
|
|
77
92
|
def context(root = self.root)
|
|
78
93
|
Context.new(root, configuration: configuration)
|
|
79
94
|
end
|
|
80
95
|
|
|
96
|
+
# Execute the command.
|
|
81
97
|
def call
|
|
82
98
|
if @options[:version]
|
|
83
99
|
puts "teapot v#{Teapot::VERSION}"
|