teapot 3.0.0 → 3.1.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
- data/.travis.yml +3 -3
- data/bin/teapot +32 -30
- data/lib/teapot/command.rb +10 -17
- data/lib/teapot/command/build.rb +3 -3
- data/lib/teapot/command/clean.rb +4 -4
- data/lib/teapot/command/clone.rb +4 -6
- data/lib/teapot/command/create.rb +12 -15
- data/lib/teapot/command/fetch.rb +21 -16
- data/lib/teapot/command/list.rb +32 -30
- data/lib/teapot/command/selection.rb +51 -0
- data/lib/teapot/command/status.rb +15 -25
- data/lib/teapot/command/visualize.rb +7 -9
- data/lib/teapot/context.rb +7 -4
- data/lib/teapot/loader.rb +7 -2
- data/lib/teapot/select.rb +7 -8
- data/lib/teapot/version.rb +1 -1
- data/spec/teapot/context_spec.rb +21 -3
- data/spec/teapot/context_spec/teapot.rb +9 -5
- data/teapot.gemspec +4 -5
- metadata +36 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: decb98e7874aae571e257044efad1fc480cdb9f0e7ee1f9fc780d9a8d5995b7f
|
4
|
+
data.tar.gz: 63ec173747e3992349864d3342b1a6cf91c4d9a95a98237f2f26100a4e85e64c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d0bf01d50bfe4bb0c87dae6ed592cda4507bb7fe59fc12020736ca0d3fb24b21d69d2e654029c7e5d6c1b273939fc0b1d9a92f2d22f03a115df388925080274
|
7
|
+
data.tar.gz: fe1e2de8b7b34b04d632058e5d8ad304696f7767772e50e3460280c97adfaaa7f5bec5854b6c74bb14c6b81eb84f39c8db072230d7d3e621e076c642086531d0
|
data/.travis.yml
CHANGED
@@ -16,7 +16,7 @@ matrix:
|
|
16
16
|
- rvm: 2.6
|
17
17
|
os: osx
|
18
18
|
before_install: brew install pkgconfig zlib curl openssl libssh2 libgit2
|
19
|
-
env: RUGGED_USE_SYSTEM_LIBRARIES=y
|
19
|
+
# env: RUGGED_USE_SYSTEM_LIBRARIES=y
|
20
20
|
- rvm: 2.6
|
21
21
|
env: COVERAGE=BriefSummary,Coveralls
|
22
22
|
|
@@ -29,5 +29,5 @@ addons:
|
|
29
29
|
- clang-4.0
|
30
30
|
- libc++-dev
|
31
31
|
- libc++abi-dev
|
32
|
-
env:
|
33
|
-
|
32
|
+
# env:
|
33
|
+
# - CC=clang-4.0 CXX=clang++-4.0
|
data/bin/teapot
CHANGED
@@ -20,40 +20,42 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
|
-
|
23
|
+
require_relative '../lib/teapot/command'
|
24
24
|
|
25
|
-
|
25
|
+
if command = Teapot::Command.parse(ARGV)
|
26
|
+
logger = command.logger
|
26
27
|
|
27
|
-
begin
|
28
|
-
|
29
|
-
rescue Teapot::IncompatibleTeapotError => error
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
28
|
+
begin
|
29
|
+
command.invoke
|
30
|
+
rescue Teapot::IncompatibleTeapotError => error
|
31
|
+
logger.error(command, error) do
|
32
|
+
"Supported minimum version #{Teapot::MINIMUM_LOADER_VERSION.dump} to #{Teapot::LOADER_VERSION.dump}."
|
33
|
+
end
|
34
|
+
|
35
|
+
exit 1
|
36
|
+
rescue Build::Dependency::UnresolvedDependencyError => error
|
37
|
+
logger.error(command, error) do |buffer|
|
38
|
+
buffer.puts "Unresolved dependencies:"
|
36
39
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
error.chain.unresolved.each do |name, parent|
|
41
|
+
buffer.puts "#{parent} depends on #{name.inspect}"
|
42
|
+
|
43
|
+
conflicts = error.chain.conflicts[name]
|
44
|
+
|
45
|
+
if conflicts
|
46
|
+
conflicts.each do |conflict|
|
47
|
+
buffer.puts " - provided by #{conflict.name}"
|
48
|
+
end
|
49
|
+
end
|
45
50
|
end
|
51
|
+
|
52
|
+
buffer.puts "Cannot continue due to unresolved dependencies!".color(:red)
|
46
53
|
end
|
54
|
+
|
55
|
+
exit 2
|
56
|
+
rescue StandardError => error
|
57
|
+
logger.error(command, error)
|
58
|
+
|
59
|
+
exit 3
|
47
60
|
end
|
48
|
-
|
49
|
-
$stderr.puts "Cannot continue due to unresolved dependencies!".color(:red)
|
50
|
-
|
51
|
-
exit 2
|
52
|
-
rescue StandardError => error
|
53
|
-
$stderr.puts error.message.color(:red)
|
54
|
-
|
55
|
-
# Could be nice to have some improved error reporting.
|
56
|
-
$stderr.puts error.backtrace
|
57
|
-
|
58
|
-
exit 3
|
59
61
|
end
|
data/lib/teapot/command.rb
CHANGED
@@ -33,12 +33,9 @@ require_relative 'context'
|
|
33
33
|
require_relative 'configuration'
|
34
34
|
require_relative 'version'
|
35
35
|
|
36
|
-
require 'uri'
|
37
|
-
require 'rainbow'
|
38
|
-
require 'rainbow/ext/string'
|
39
36
|
require 'fileutils'
|
40
37
|
|
41
|
-
require '
|
38
|
+
require 'console'
|
42
39
|
|
43
40
|
module Teapot
|
44
41
|
module Command
|
@@ -57,7 +54,7 @@ module Teapot
|
|
57
54
|
option '-v/--version', "Print out the application version."
|
58
55
|
end
|
59
56
|
|
60
|
-
nested
|
57
|
+
nested :command, {
|
61
58
|
"create" => Create,
|
62
59
|
"clone" => Clone,
|
63
60
|
"fetch" => Fetch,
|
@@ -81,15 +78,13 @@ module Teapot
|
|
81
78
|
end
|
82
79
|
|
83
80
|
def logger
|
84
|
-
@logger ||= Logger.new(
|
85
|
-
logger.formatter = ::Build::CompactFormatter.new(verbose: verbose?)
|
86
|
-
|
81
|
+
@logger ||= Console::Logger.new(Console.logger, verbose: self.verbose?).tap do |logger|
|
87
82
|
if verbose?
|
88
|
-
logger.
|
83
|
+
logger.debug!
|
89
84
|
elsif quiet?
|
90
|
-
logger.
|
85
|
+
logger.warn!
|
91
86
|
else
|
92
|
-
logger.
|
87
|
+
logger.info!
|
93
88
|
end
|
94
89
|
end
|
95
90
|
end
|
@@ -102,15 +97,13 @@ module Teapot
|
|
102
97
|
Context.new(root, configuration: configuration)
|
103
98
|
end
|
104
99
|
|
105
|
-
def invoke
|
100
|
+
def invoke
|
106
101
|
if @options[:version]
|
107
102
|
puts "teapot v#{Teapot::VERSION}"
|
108
|
-
elsif @options[:help]
|
109
|
-
print_usage(
|
103
|
+
elsif @options[:help]
|
104
|
+
print_usage(output: $stdout)
|
110
105
|
else
|
111
|
-
|
112
|
-
@command.invoke(self)
|
113
|
-
end
|
106
|
+
@command.invoke
|
114
107
|
end
|
115
108
|
end
|
116
109
|
end
|
data/lib/teapot/command/build.rb
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
|
21
|
+
require_relative 'selection'
|
22
22
|
|
23
23
|
require 'build/controller'
|
24
24
|
|
@@ -27,7 +27,7 @@ module Teapot
|
|
27
27
|
class BuildFailedError < StandardError
|
28
28
|
end
|
29
29
|
|
30
|
-
class Build <
|
30
|
+
class Build < Selection
|
31
31
|
self.description = "Build the specified target."
|
32
32
|
|
33
33
|
options do
|
@@ -38,7 +38,7 @@ module Teapot
|
|
38
38
|
many :targets, "Build these targets, or use them to help the dependency resolution process."
|
39
39
|
split :argv, "Arguments passed to child process(es) of build if any."
|
40
40
|
|
41
|
-
def invoke
|
41
|
+
def invoke
|
42
42
|
context = parent.context
|
43
43
|
|
44
44
|
# The targets to build:
|
data/lib/teapot/command/clean.rb
CHANGED
@@ -25,15 +25,15 @@ module Teapot
|
|
25
25
|
class Clean < Samovar::Command
|
26
26
|
self.description = "Delete everything in the teapot directory."
|
27
27
|
|
28
|
-
def invoke
|
28
|
+
def invoke
|
29
29
|
context = parent.context
|
30
30
|
logger = parent.logger
|
31
31
|
configuration = context.configuration
|
32
32
|
|
33
|
-
logger.info "Removing #{configuration.
|
34
|
-
FileUtils.rm_rf configuration.
|
33
|
+
logger.info "Removing #{configuration.build_path}..."
|
34
|
+
FileUtils.rm_rf configuration.build_path
|
35
35
|
|
36
|
-
logger.info "Removing #{configuration.packages_path}..."
|
36
|
+
logger.info "Removing #{configuration.packages_path}..."
|
37
37
|
FileUtils.rm_rf configuration.packages_path
|
38
38
|
end
|
39
39
|
end
|
data/lib/teapot/command/clone.rb
CHANGED
@@ -31,11 +31,9 @@ module Teapot
|
|
31
31
|
class Clone < Samovar::Command
|
32
32
|
self.description = "Clone a remote repository and fetch all dependencies."
|
33
33
|
|
34
|
-
one :source, "The source repository to clone."
|
34
|
+
one :source, "The source repository to clone.", required: true
|
35
35
|
|
36
|
-
def invoke
|
37
|
-
raise ArgumentError, "source is required" unless @source
|
38
|
-
|
36
|
+
def invoke
|
39
37
|
logger = parent.logger
|
40
38
|
|
41
39
|
name = File.basename(::Build::URI[@source].path, ".git")
|
@@ -47,11 +45,11 @@ module Teapot
|
|
47
45
|
raise ArgumentError.new("#{root} already exists!")
|
48
46
|
end
|
49
47
|
|
50
|
-
logger.info "Cloning #{@source} to #{root}..."
|
48
|
+
logger.info "Cloning #{@source} to #{root}..."
|
51
49
|
_repository = Rugged::Repository.clone_at(@source, root.to_s, credentials: self.method(:credentials))
|
52
50
|
|
53
51
|
# Fetch the initial packages:
|
54
|
-
Fetch[].invoke
|
52
|
+
Fetch[parent: nested].invoke
|
55
53
|
end
|
56
54
|
|
57
55
|
def credentials(url, username, types)
|
@@ -29,17 +29,14 @@ module Teapot
|
|
29
29
|
class Create < Samovar::Command
|
30
30
|
self.description = "Create a new teapot package using the specified repository."
|
31
31
|
|
32
|
-
one :
|
33
|
-
one :source, "The source repository to use for fetching packages, e.g. https://github.com/kurocha."
|
34
|
-
many :packages, "Any
|
32
|
+
one :name, "The name of the new project in title-case, e.g. 'My Project'.", required: true
|
33
|
+
one :source, "The source repository to use for fetching packages, e.g. https://github.com/kurocha.", required: true
|
34
|
+
many :packages, "Any packages you'd like to include in the project.", default: ["generate-project"]
|
35
35
|
|
36
|
-
def invoke
|
37
|
-
raise ArgumentError, "project_name is required" unless @project_name
|
38
|
-
raise ArgumentError, "source is required" unless @source
|
39
|
-
|
36
|
+
def invoke
|
40
37
|
logger = parent.logger
|
41
38
|
|
42
|
-
nested = parent['--root', parent.options[:root] ||
|
39
|
+
nested = parent['--root', parent.options[:root] || name.gsub(/\s+/, '-').downcase]
|
43
40
|
root = nested.root
|
44
41
|
|
45
42
|
if root.exist?
|
@@ -51,11 +48,11 @@ module Teapot
|
|
51
48
|
|
52
49
|
repository = Rugged::Repository.init_at(root.to_s)
|
53
50
|
|
54
|
-
logger.info "Creating project named #{
|
55
|
-
generate_project(root, @
|
51
|
+
logger.info "Creating project named #{name} at path #{root}..."
|
52
|
+
generate_project(root, @name, @source, @packages)
|
56
53
|
|
57
54
|
# Fetch the initial packages:
|
58
|
-
Fetch[].invoke
|
55
|
+
Fetch[parent: nested].invoke
|
59
56
|
|
60
57
|
context = nested.context
|
61
58
|
selection = context.select
|
@@ -63,10 +60,10 @@ module Teapot
|
|
63
60
|
|
64
61
|
if target_names.any?
|
65
62
|
# Generate the initial project files:
|
66
|
-
Build[*target_names].invoke
|
63
|
+
Build[*target_names, parent: nested].invoke
|
67
64
|
|
68
65
|
# Fetch any additional packages:
|
69
|
-
Fetch[].invoke
|
66
|
+
Fetch[parent: nested].invoke
|
70
67
|
end
|
71
68
|
|
72
69
|
# Stage all files:
|
@@ -82,8 +79,8 @@ module Teapot
|
|
82
79
|
)
|
83
80
|
end
|
84
81
|
|
85
|
-
def generate_project(root,
|
86
|
-
name = ::Build::Name.new(
|
82
|
+
def generate_project(root, name, source, packages)
|
83
|
+
name = ::Build::Name.new(name)
|
87
84
|
|
88
85
|
# Otherwise the initial commit will try to include teapot/
|
89
86
|
File.open(root + ".gitignore", "w") do |output|
|
data/lib/teapot/command/fetch.rb
CHANGED
@@ -18,8 +18,7 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
require_relative 'selection'
|
23
22
|
require 'rugged'
|
24
23
|
|
25
24
|
module Teapot
|
@@ -48,18 +47,21 @@ module Teapot
|
|
48
47
|
|
49
48
|
many :packages, "Only update the specified packages, or all packages if none specified."
|
50
49
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
50
|
+
def context
|
51
|
+
parent.context
|
52
|
+
end
|
53
|
+
|
54
|
+
def invoke
|
55
55
|
selection = context.select
|
56
56
|
|
57
57
|
packages = selection.configuration.packages
|
58
58
|
|
59
|
-
if
|
60
|
-
packages = packages.slice(
|
59
|
+
if specified_packages = self.packages
|
60
|
+
packages = packages.slice(specified_packages)
|
61
61
|
end
|
62
62
|
|
63
|
+
logger = parent.logger
|
64
|
+
|
63
65
|
# If no additional packages were resolved, we have reached a fixed point:
|
64
66
|
while packages.any?
|
65
67
|
packages.each do |package|
|
@@ -77,12 +79,15 @@ module Teapot
|
|
77
79
|
end
|
78
80
|
|
79
81
|
if selection.unresolved.count > 0
|
80
|
-
logger.error
|
81
|
-
|
82
|
-
|
82
|
+
logger.error(self) do |buffer|
|
83
|
+
buffer.puts "Could not fetch all packages!"
|
84
|
+
|
85
|
+
selection.unresolved.each do |package|
|
86
|
+
buffer.puts "\t#{package}"
|
87
|
+
end
|
83
88
|
end
|
84
89
|
else
|
85
|
-
logger.info "Completed fetch successfully."
|
90
|
+
logger.info "Completed fetch successfully."
|
86
91
|
end
|
87
92
|
end
|
88
93
|
|
@@ -98,7 +103,7 @@ module Teapot
|
|
98
103
|
end
|
99
104
|
|
100
105
|
def link_local_package(context, configuration, package, logger)
|
101
|
-
logger.info "Linking local #{package}..."
|
106
|
+
logger.info "Linking local #{package}..." #.color(:cyan)
|
102
107
|
|
103
108
|
local_path = context.root + package.options[:local]
|
104
109
|
|
@@ -119,7 +124,7 @@ module Teapot
|
|
119
124
|
end
|
120
125
|
|
121
126
|
def clone_or_pull_package(context, configuration, package, package_lock, logger)
|
122
|
-
logger.info "Processing #{package}..."
|
127
|
+
logger.info "Processing #{package}..." #.color(:cyan)
|
123
128
|
|
124
129
|
# Where we are going to put the package:
|
125
130
|
destination_path = package.path
|
@@ -140,7 +145,7 @@ module Teapot
|
|
140
145
|
end
|
141
146
|
|
142
147
|
if destination_path.exist?
|
143
|
-
logger.info "Updating package at path #{destination_path}..."
|
148
|
+
logger.info "Updating package at path #{destination_path}..." #.color(:cyan)
|
144
149
|
|
145
150
|
repository = Rugged::Repository.new(destination_path.to_s)
|
146
151
|
|
@@ -165,7 +170,7 @@ module Teapot
|
|
165
170
|
# Reset it to the requested commit if required:
|
166
171
|
repository.reset(commit_id, :hard)
|
167
172
|
else
|
168
|
-
logger.info "Cloning package at path #{destination_path}..."
|
173
|
+
logger.info "Cloning package at path #{destination_path}..." #.color(:cyan)
|
169
174
|
|
170
175
|
external_url = package.external_url(context.root)
|
171
176
|
|
data/lib/teapot/command/list.rb
CHANGED
@@ -19,75 +19,77 @@
|
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
21
|
require 'samovar'
|
22
|
+
require 'console/terminal'
|
23
|
+
|
24
|
+
require_relative 'selection'
|
22
25
|
|
23
26
|
module Teapot
|
24
27
|
module Command
|
25
|
-
class List <
|
28
|
+
class List < Selection
|
26
29
|
self.description = "List provisions and dependencies of the specified package."
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
def terminal(output = $stdout)
|
32
|
+
Console::Terminal.for(output).tap do |terminal|
|
33
|
+
terminal[:definition] = terminal.style(nil, nil, :bright)
|
34
|
+
terminal[:dependency] = terminal.style(:blue)
|
35
|
+
terminal[:provision] = terminal.style(:green)
|
36
|
+
terminal[:package] = terminal.style(:yellow)
|
37
|
+
terminal[:import] = terminal.style(:cyan)
|
38
|
+
terminal[:error] = terminal.style(:red)
|
33
39
|
end
|
34
40
|
end
|
35
41
|
|
36
|
-
def
|
37
|
-
context =
|
42
|
+
def process(selection)
|
43
|
+
context = selection.context
|
44
|
+
terminal = self.terminal
|
38
45
|
|
39
|
-
|
40
|
-
|
41
|
-
context.configuration.packages.each do |package|
|
42
|
-
# The root package is the local package for this context:
|
43
|
-
next unless only == nil or only.include?(package.name)
|
46
|
+
selection.resolved.each do |package|
|
47
|
+
terminal.puts "Package #{package.name} (from #{package.path}):"
|
44
48
|
|
45
|
-
logger.info "Package #{package.name} (from #{package.path}):".bright
|
46
|
-
|
47
49
|
begin
|
48
50
|
script = context.load(package)
|
49
51
|
definitions = script.defined
|
50
52
|
|
51
53
|
definitions.each do |definition|
|
52
|
-
|
54
|
+
terminal.puts "\t#{definition}", style: :definition
|
53
55
|
|
54
56
|
definition.description.each_line do |line|
|
55
|
-
|
57
|
+
terminal.puts "\t\t#{line.chomp}", style: :description
|
56
58
|
end if definition.description
|
57
59
|
|
58
60
|
case definition
|
59
61
|
when Project
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
62
|
+
terminal.puts "\t\t- Summary: #{definition.summary}" if definition.summary
|
63
|
+
terminal.puts "\t\t- License: #{definition.license}" if definition.license
|
64
|
+
terminal.puts "\t\t- Website: #{definition.website}" if definition.website
|
65
|
+
terminal.puts "\t\t- Version: #{definition.version}" if definition.version
|
64
66
|
|
65
67
|
definition.authors.each do |author|
|
66
|
-
contact_text = [author.email, author.website].compact.collect{|text|" <#{text}>"}.join
|
67
|
-
|
68
|
+
contact_text = [author.email, author.website].compact.collect{|text| " <#{text}>"}.join
|
69
|
+
terminal.puts "\t\t- Author: #{author.name}" + contact_text
|
68
70
|
end
|
69
71
|
when Target
|
70
72
|
definition.dependencies.each do |dependency|
|
71
|
-
|
73
|
+
terminal.puts "\t\t- #{dependency}", style: :dependency
|
72
74
|
end
|
73
75
|
|
74
76
|
definition.provisions.each do |name, provision|
|
75
|
-
|
77
|
+
terminal.puts "\t\t- #{provision}", style: :provision
|
76
78
|
end
|
77
79
|
when Configuration
|
78
80
|
definition.packages.each do |package|
|
79
|
-
|
81
|
+
terminal.puts "\t\t- #{package}", style: :package
|
80
82
|
end
|
81
83
|
|
82
84
|
definition.imports.select(&:explicit).each do |import|
|
83
|
-
|
85
|
+
terminal.puts "\t\t- import #{import.name}", style: :import
|
84
86
|
end
|
85
87
|
end
|
86
88
|
end
|
87
|
-
rescue
|
88
|
-
|
89
|
+
rescue MissingTeapotError => error
|
90
|
+
terminal.puts "\t#{error.message}", style: :error
|
89
91
|
rescue IncompatibleTeapotError => error
|
90
|
-
|
92
|
+
terminal.puts "\t#{error.message}", style: :error
|
91
93
|
end
|
92
94
|
end
|
93
95
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'samovar'
|
22
|
+
|
23
|
+
module Teapot
|
24
|
+
module Command
|
25
|
+
class Selection < Samovar::Command
|
26
|
+
options
|
27
|
+
|
28
|
+
many :targets, "Only consider the specified targets, if any."
|
29
|
+
|
30
|
+
def targets
|
31
|
+
if @targets and @targets.any?
|
32
|
+
Set.new(@targets)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def selection(context)
|
37
|
+
if targets = self.targets
|
38
|
+
context.select(targets)
|
39
|
+
else
|
40
|
+
context.select(context.configuration[:build])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def invoke
|
45
|
+
context = parent.context
|
46
|
+
|
47
|
+
self.process(selection(parent.context))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -18,30 +18,28 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
|
21
|
+
require_relative 'selection'
|
22
22
|
require 'rugged'
|
23
|
+
require 'console/terminal'
|
23
24
|
|
24
25
|
module Teapot
|
25
26
|
module Command
|
26
|
-
class Status <
|
27
|
+
class Status < Selection
|
27
28
|
self.description = "List the git status of the specified package(s)."
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
def terminal(output = $stdout)
|
31
|
+
Console::Terminal.for(output).tap do |terminal|
|
32
|
+
terminal[:worktree_new] = terminal.style(:green)
|
33
|
+
terminal[:worktree_modified] = terminal.style(:yellow)
|
34
|
+
terminal[:worktree_deleted] = terminal.style(:red)
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
37
|
-
def
|
38
|
-
context =
|
39
|
-
|
38
|
+
def process(selection)
|
39
|
+
context = selection.context
|
40
|
+
terminal = self.terminal
|
40
41
|
|
41
|
-
|
42
|
-
# The root package is the local package for this context:
|
43
|
-
next unless only == nil or only.include?(package.name)
|
44
|
-
|
42
|
+
selection.resolved.each do |package|
|
45
43
|
repository = Rugged::Repository.new(package.path.to_s)
|
46
44
|
|
47
45
|
changes = {}
|
@@ -53,18 +51,10 @@ module Teapot
|
|
53
51
|
|
54
52
|
next if changes.empty?
|
55
53
|
|
56
|
-
|
54
|
+
terminal.puts "Package #{package.name} (from #{package.path}):"
|
57
55
|
|
58
|
-
changes.each do |file,
|
59
|
-
|
60
|
-
logger.info "\t#{file}".color(:blue)
|
61
|
-
elsif status == [:worktree_modified]
|
62
|
-
logger.info "\t#{file}".color(:orange)
|
63
|
-
elsif status == [:worktree_deleted]
|
64
|
-
logger.info "\t#{file}".color(:red)
|
65
|
-
else
|
66
|
-
logger.info "\t#{file} #{status.inspect}"
|
67
|
-
end
|
56
|
+
changes.each do |file, statuses|
|
57
|
+
terminal.puts "\t#{file} (#{statuses})", style: statuses.last
|
68
58
|
end
|
69
59
|
end
|
70
60
|
end
|
@@ -18,12 +18,12 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
|
21
|
+
require_relative 'selection'
|
22
22
|
require 'graphviz'
|
23
23
|
|
24
24
|
module Teapot
|
25
25
|
module Command
|
26
|
-
class Visualize <
|
26
|
+
class Visualize < Selection
|
27
27
|
self.description = "Generate a picture of the dependency graph."
|
28
28
|
|
29
29
|
options do
|
@@ -31,8 +31,6 @@ module Teapot
|
|
31
31
|
option '-d/--dependency-name <name>', "Show the partial chain for the given named dependency."
|
32
32
|
end
|
33
33
|
|
34
|
-
many :targets, "Visualize these targets, or use them to help the dependency resolution process."
|
35
|
-
|
36
34
|
def dependency_names
|
37
35
|
@targets || []
|
38
36
|
end
|
@@ -41,15 +39,13 @@ module Teapot
|
|
41
39
|
@options[:dependency_name]
|
42
40
|
end
|
43
41
|
|
44
|
-
def
|
45
|
-
context =
|
46
|
-
selection = context.select(dependency_names)
|
42
|
+
def process(selection)
|
43
|
+
context = selection.context
|
47
44
|
chain = selection.chain
|
48
45
|
|
49
46
|
if dependency_name
|
50
47
|
provider = selection.dependencies[dependency_name]
|
51
48
|
|
52
|
-
# TODO The visualisation generated isn't quite right. It's introspecting too much from the packages and not reflecting #ordered and #provisions.
|
53
49
|
chain = chain.partial(provider)
|
54
50
|
end
|
55
51
|
|
@@ -58,7 +54,9 @@ module Teapot
|
|
58
54
|
graph = visualization.generate(chain)
|
59
55
|
|
60
56
|
if output_path = @options[:output_path]
|
61
|
-
Graphviz
|
57
|
+
Graphviz.output(graph, path: output_path, format: :svg)
|
58
|
+
else
|
59
|
+
$stdout.puts graph.to_dot
|
62
60
|
end
|
63
61
|
|
64
62
|
return graph
|
data/lib/teapot/context.rb
CHANGED
@@ -48,8 +48,8 @@ module Teapot
|
|
48
48
|
@repository ||= Rugged::Repository.new(@root.to_s)
|
49
49
|
end
|
50
50
|
|
51
|
-
def select(names =
|
52
|
-
Select.new(self, configuration, names)
|
51
|
+
def select(names = nil, configuration = @configuration)
|
52
|
+
Select.new(self, configuration, names || [])
|
53
53
|
end
|
54
54
|
|
55
55
|
def substitutions
|
@@ -69,6 +69,9 @@ module Teapot
|
|
69
69
|
# e.g. foo-bar, typically used for targets, executables
|
70
70
|
substitutions['PROJECT_TARGET_NAME'] = name.target
|
71
71
|
|
72
|
+
# e.g. foo_bar, typically used for variables.
|
73
|
+
substitutions['PROJECT_VARIABLE_NAME'] = name.key
|
74
|
+
|
72
75
|
substitutions['LICENSE'] = @project.license
|
73
76
|
end
|
74
77
|
|
@@ -105,10 +108,10 @@ module Teapot
|
|
105
108
|
def load_root_package(**options)
|
106
109
|
# Load the root package:
|
107
110
|
script = load(root_package)
|
108
|
-
|
111
|
+
|
109
112
|
# Find the default configuration, if it exists:
|
110
113
|
if configuration_name = options[:configuration]
|
111
|
-
@configuration =
|
114
|
+
@configuration = script.configurations[configuration_name]
|
112
115
|
else
|
113
116
|
@configuration = script.default_configuration
|
114
117
|
end
|
data/lib/teapot/loader.rb
CHANGED
@@ -47,7 +47,7 @@ module Teapot
|
|
47
47
|
attr :version
|
48
48
|
end
|
49
49
|
|
50
|
-
class
|
50
|
+
class MissingTeapotError < StandardError
|
51
51
|
def initialize(path)
|
52
52
|
super "Could not read file at #{path}!"
|
53
53
|
end
|
@@ -67,6 +67,8 @@ module Teapot
|
|
67
67
|
@defined = []
|
68
68
|
@version = nil
|
69
69
|
|
70
|
+
@configurations = Build::Dependency::Set.new
|
71
|
+
|
70
72
|
@default_project = nil
|
71
73
|
@default_configuration = nil
|
72
74
|
|
@@ -78,6 +80,8 @@ module Teapot
|
|
78
80
|
attr :defined
|
79
81
|
attr :version
|
80
82
|
|
83
|
+
attr :configurations
|
84
|
+
|
81
85
|
attr :default_project
|
82
86
|
attr :default_configuration
|
83
87
|
|
@@ -119,6 +123,7 @@ module Teapot
|
|
119
123
|
|
120
124
|
@default_configuration ||= configuration
|
121
125
|
@defined << configuration
|
126
|
+
@configurations << configuration
|
122
127
|
end
|
123
128
|
|
124
129
|
# Checks the host patterns and executes the block if they match.
|
@@ -165,7 +170,7 @@ module Teapot
|
|
165
170
|
|
166
171
|
# Load a teapot.rb file relative to the root of the @package.
|
167
172
|
def load!(path = teapot_path)
|
168
|
-
raise
|
173
|
+
raise MissingTeapotError.new(path) unless File.exist?(path)
|
169
174
|
|
170
175
|
script = Script.new(@context, @package)
|
171
176
|
|
data/lib/teapot/select.rb
CHANGED
@@ -47,11 +47,11 @@ module Teapot
|
|
47
47
|
@targets = {}
|
48
48
|
@configurations = {}
|
49
49
|
@projects = {}
|
50
|
-
@rules = Build::Rulebook.new
|
51
50
|
|
52
51
|
@dependencies = []
|
53
52
|
@selection = Set.new
|
54
|
-
@
|
53
|
+
@resolved = Build::Dependency::Set.new
|
54
|
+
@unresolved = Build::Dependency::Set.new
|
55
55
|
|
56
56
|
load!(configuration, names)
|
57
57
|
|
@@ -69,11 +69,11 @@ module Teapot
|
|
69
69
|
|
70
70
|
# All public configurations.
|
71
71
|
attr :configurations
|
72
|
-
|
73
|
-
attr :rules
|
74
72
|
|
75
73
|
attr :dependencies
|
76
74
|
attr :selection
|
75
|
+
|
76
|
+
attr :resolved
|
77
77
|
attr :unresolved
|
78
78
|
|
79
79
|
def chain
|
@@ -103,9 +103,6 @@ module Teapot
|
|
103
103
|
when Project
|
104
104
|
AlreadyDefinedError.check(definition, @projects)
|
105
105
|
@projects[definition.name] = definition
|
106
|
-
when Rule
|
107
|
-
AlreadyDefinedError.check(definition, @rules)
|
108
|
-
@rules << definition
|
109
106
|
end
|
110
107
|
end
|
111
108
|
|
@@ -117,7 +114,9 @@ module Teapot
|
|
117
114
|
script.defined.each do |definition|
|
118
115
|
append(definition)
|
119
116
|
end
|
120
|
-
|
117
|
+
|
118
|
+
@resolved << package
|
119
|
+
rescue MissingTeapotError, IncompatibleTeapotError
|
121
120
|
# If the package doesn't exist or the teapot version is too old, it failed:
|
122
121
|
@unresolved << package
|
123
122
|
end
|
data/lib/teapot/version.rb
CHANGED
data/spec/teapot/context_spec.rb
CHANGED
@@ -27,14 +27,32 @@ RSpec.describe Teapot::Context do
|
|
27
27
|
it "should specify correct number of packages" do
|
28
28
|
default_configuration = context.configuration
|
29
29
|
|
30
|
-
expect(default_configuration.packages.count).to be ==
|
30
|
+
expect(default_configuration.packages.count).to be == 0
|
31
31
|
end
|
32
32
|
|
33
|
-
it "should
|
33
|
+
it "should select configuration" do
|
34
|
+
expect(context.configuration.name).to be == 'development'
|
35
|
+
end
|
36
|
+
|
37
|
+
context "with specific configuration" do
|
38
|
+
let(:context) {Teapot::Context.new(root, configuration: 'context_spec')}
|
39
|
+
|
40
|
+
it "should select configuration" do
|
41
|
+
expect(context.configuration.name).to be == 'context_spec'
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should specify correct number of packages" do
|
45
|
+
default_configuration = context.configuration
|
46
|
+
|
47
|
+
expect(default_configuration.packages.count).to be == 13
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should load teapot script" do
|
34
52
|
selection = context.select
|
35
53
|
|
36
54
|
# There is one configuration:
|
37
|
-
expect(selection.configurations.count).to be ==
|
55
|
+
expect(selection.configurations.count).to be == 2
|
38
56
|
expect(selection.targets.count).to be == 1
|
39
57
|
|
40
58
|
# We didn't expect any of them to actually load...
|
@@ -3,9 +3,16 @@
|
|
3
3
|
# This file is part of the "Teapot" project, and is released under the MIT license.
|
4
4
|
#
|
5
5
|
|
6
|
-
teapot_version "
|
6
|
+
teapot_version "3.0.0"
|
7
7
|
|
8
|
-
|
8
|
+
define_target "context_spec" do |target|
|
9
|
+
end
|
10
|
+
|
11
|
+
define_configuration 'development' do |configuration|
|
12
|
+
configuration.import 'context_spec'
|
13
|
+
end
|
14
|
+
|
15
|
+
define_configuration 'context_spec' do |configuration|
|
9
16
|
configuration.public!
|
10
17
|
|
11
18
|
configuration[:source] = "../kurocha"
|
@@ -31,6 +38,3 @@ define_configuration 'test' do |configuration|
|
|
31
38
|
|
32
39
|
configuration.require "opencv"
|
33
40
|
end
|
34
|
-
|
35
|
-
define_target "context_spec" do |target|
|
36
|
-
end
|
data/teapot.gemspec
CHANGED
@@ -24,19 +24,18 @@ Gem::Specification.new do |spec|
|
|
24
24
|
|
25
25
|
spec.required_ruby_version = '>= 2.1.0'
|
26
26
|
|
27
|
-
spec.add_dependency "rainbow", "~> 2.0"
|
28
|
-
|
29
27
|
spec.add_dependency "graphviz", "~> 1.0"
|
30
|
-
|
31
28
|
spec.add_dependency "rugged"
|
32
29
|
|
33
|
-
spec.add_dependency "build", "~> 2.
|
30
|
+
spec.add_dependency "build", "~> 2.4"
|
31
|
+
spec.add_dependency "build-environment", "~> 1.10.0"
|
34
32
|
spec.add_dependency "build-files", "~> 1.4"
|
35
33
|
spec.add_dependency "build-dependency", "~> 1.4"
|
36
34
|
spec.add_dependency "build-uri", "~> 1.0"
|
37
35
|
spec.add_dependency "build-text", "~> 1.0"
|
38
36
|
|
39
|
-
spec.add_dependency "
|
37
|
+
spec.add_dependency "console", "~> 1.0"
|
38
|
+
spec.add_dependency "samovar", "~> 2.0"
|
40
39
|
|
41
40
|
spec.add_development_dependency "covered"
|
42
41
|
spec.add_development_dependency "bundler"
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: teapot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: rainbow
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '2.0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '2.0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: graphviz
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,14 +44,28 @@ dependencies:
|
|
58
44
|
requirements:
|
59
45
|
- - "~>"
|
60
46
|
- !ruby/object:Gem::Version
|
61
|
-
version: '2.
|
47
|
+
version: '2.4'
|
62
48
|
type: :runtime
|
63
49
|
prerelease: false
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
52
|
- - "~>"
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version: '2.
|
54
|
+
version: '2.4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: build-environment
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.10.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.10.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: build-files
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,20 +122,34 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '1.0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: console
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: samovar
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - "~>"
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
145
|
+
version: '2.0'
|
132
146
|
type: :runtime
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
150
|
- - "~>"
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
152
|
+
version: '2.0'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: covered
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -219,6 +233,7 @@ files:
|
|
219
233
|
- lib/teapot/command/create.rb
|
220
234
|
- lib/teapot/command/fetch.rb
|
221
235
|
- lib/teapot/command/list.rb
|
236
|
+
- lib/teapot/command/selection.rb
|
222
237
|
- lib/teapot/command/status.rb
|
223
238
|
- lib/teapot/command/visualize.rb
|
224
239
|
- lib/teapot/configuration.rb
|
@@ -267,7 +282,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
267
282
|
- !ruby/object:Gem::Version
|
268
283
|
version: '0'
|
269
284
|
requirements: []
|
270
|
-
rubygems_version: 3.0.
|
285
|
+
rubygems_version: 3.0.3
|
271
286
|
signing_key:
|
272
287
|
specification_version: 4
|
273
288
|
summary: Teapot is a tool for managing complex cross-platform builds.
|