teapot 1.0.0.pre.rc10 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a24978c48e16ae8ae1dcf5e330149396f08cf233
4
- data.tar.gz: b197ab21f377f556d084d06c2e2a88cfe275a2d0
3
+ metadata.gz: 1e1f73a2d005afa6215f58b96d42e2bf92775768
4
+ data.tar.gz: 4f45aabef2c5408870cb54534de67f17a9618bb4
5
5
  SHA512:
6
- metadata.gz: 9f460908b58d31f2683656d2f68087176f63698018f36ae3a29ae121a7c0d1a393929e31cf49e241b6e52e637b9ecc0d1178f4d9a86f557eb3cab0e3e5bfc28c
7
- data.tar.gz: 23a8accc88acb6436fdfb54f8e8db448c24a982918fe212a43fce96965098174605ff1784db255cdb1bae3058fb46a47f6c7b0f4c6b7b32ac3b18fc4976946fa
6
+ metadata.gz: 4c6edc444e2004f83e14684c6e7e3866350250c656493ff8c1b0560f9badd9b22e0acb1390fb41603a7b561cfbfd4a4395386c7a968ce2cec8a1aadc7d1fb4a2
7
+ data.tar.gz: d7014fa07c93aa84fafddb44eb032cc90f2950adfc619f8a2812d3dcb47769403a5e323546a591ecddeb4fa5b4229950fc24cf5622092f81633fccfcae7dabd0
data/.gitignore CHANGED
@@ -15,4 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
- dream-framework
18
+ kurocha
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.travis.yml CHANGED
@@ -1,8 +1,13 @@
1
1
  language: ruby
2
+ sudo: false
2
3
  before_install:
3
4
  # For testing purposes:
4
5
  - git config --local user.name "Samuel Williams"
5
6
  rvm:
6
- - "2.0"
7
- - "2.1"
7
+ - 2.0.0
8
+ - 2.1.8
9
+ - 2.2.4
10
+ - 2.3.0
11
+ - ruby-head
12
+ - rbx-2
8
13
  env: COVERAGE=true
data/Gemfile CHANGED
@@ -3,6 +3,11 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in teapot.gemspec
4
4
  gemspec
5
5
 
6
+ group :development do
7
+ gem 'pry'
8
+ gem 'pry-coolline'
9
+ end
10
+
6
11
  group :test do
7
12
  gem 'simplecov'
8
13
  gem 'coveralls', require: false
data/Gemfile.local ADDED
@@ -0,0 +1,23 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in teapot.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'pry'
8
+ gem 'pry-coolline'
9
+
10
+ gem 'build', path: '../build'
11
+ gem 'build-environment', path: '../build-environment'
12
+ gem 'build-files', path: '../build-files'
13
+ gem 'build-graph', path: '../build-graph'
14
+ gem 'build-makefile', path: '../build-makefile'
15
+
16
+ gem 'process-daemon', path: '../process-daemon'
17
+ gem 'process-group', path: '../process-group'
18
+ end
19
+
20
+ group :test do
21
+ gem 'simplecov'
22
+ gem 'coveralls', require: false
23
+ end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Teapot
1
+ # ![Teapot](materials/teapot.png?raw=true)
2
2
 
3
3
  Teapot is a decentralised build tool for managing complex cross-platform projects. It has many goals but it is primarily designed to improve the experience for developers trying to make cross-platform applications and libraries with a minimum of overhead.
4
4
 
@@ -23,7 +23,7 @@ Teapot doesn't have a centralised package management system. As such, this examp
23
23
 
24
24
  Firstly, create your project by running:
25
25
 
26
- $ teapot create "My Project" https://github.com/dream-framework project
26
+ $ teapot create "My Project" https://github.com/kurocha project
27
27
  $ cd my-project
28
28
 
29
29
  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.
@@ -47,13 +47,13 @@ The resulting libraries will be framework dependent, but are typically located i
47
47
 
48
48
  For Linux (requires `clang-3.2` and `libstdc++-4.8`):
49
49
 
50
- $ teapot create "Local Tagged Format" https://github.com/dream-framework platform-linux variants tagged-format
50
+ $ teapot create "Local Tagged Format" https://github.com/kurocha platform-linux variants tagged-format
51
51
  $ cd local-tagged-format
52
52
  $ teapot build Library/TaggedFormat variant-debug
53
53
 
54
54
  For Mac OS X (requires Xcode Command Line Tools):
55
55
 
56
- $ teapot create "Local Tagged Format" https://github.com/dream-framework platform-darwin-osx variants tagged-format
56
+ $ teapot create "Local Tagged Format" https://github.com/kurocha platform-darwin-osx variants tagged-format
57
57
  $ cd local-tagged-format
58
58
  $ teapot build Library/TaggedFormat variant-debug
59
59
 
data/bin/teapot CHANGED
@@ -47,7 +47,7 @@ OPTIONS = Trollop::options do
47
47
 
48
48
  opt :force, "Force the operation if it would otherwise be be stopped due to a warning."
49
49
 
50
- opt :verbose, "Verbose output and error backtraces."
50
+ opt :verbose, "Verbose output and error backtraces.", :type => :boolean
51
51
  opt :version, "Print version and exit", :short => :none
52
52
  end
53
53
 
@@ -88,8 +88,8 @@ module Application
88
88
  source = ARGV.shift
89
89
  packages = ARGV
90
90
 
91
- root = Pathname(Dir.getwd) + project_directory
92
-
91
+ root = Build::Files::Path.join(Dir.getwd, project_directory)
92
+
93
93
  if root.exist?
94
94
  abort "#{root} already exists!".color(:red)
95
95
  end
@@ -23,73 +23,18 @@ require 'set'
23
23
 
24
24
  require 'yaml/store'
25
25
 
26
- require 'teapot/context'
27
-
28
- require 'teapot/definition'
26
+ require_relative 'identity_set'
27
+ require_relative 'context'
28
+ require_relative 'definition'
29
29
 
30
30
  module Teapot
31
- # Very similar to a set but uses a specific callback for object identity.
32
- class IdentitySet
33
- include Enumerable
34
-
35
- def initialize(contents = [], &block)
36
- @table = {}
37
- @identity = block
38
-
39
- contents.each do |object|
40
- add(object)
41
- end
42
- end
43
-
44
- def initialize_dup(other)
45
- @table = other.table.dup
46
- end
47
-
48
- attr :table
49
-
50
- def add(object)
51
- @table[@identity[object]] = object
52
- end
53
-
54
- alias << add
55
-
56
- def remove(object)
57
- @table.delete(@identity[object])
58
- end
59
-
60
- def include?(object)
61
- @table.include?(@identity[object])
62
- end
63
-
64
- def each(&block)
65
- @table.each_value(&block)
66
- end
67
-
68
- def size
69
- @table.size
70
- end
71
-
72
- def clear
73
- @table.clear
74
- end
75
-
76
- alias count size
77
-
78
- def to_s
79
- @table.to_s
80
- end
81
-
82
- def self.by_name(contents = [])
83
- self.new(contents, &:name)
84
- end
85
- end
86
-
31
+ # A configuration represents a mapping between package/dependency names and actual source locations. Usually, there is only one configuration, but in some cases it is useful to have more than one, e.g. one for local development using local source code, one for continuous integration, and one for deployment.
87
32
  class Configuration < Definition
88
33
  Import = Struct.new(:name, :explicit, :options)
89
34
 
90
35
  DEFAULT_OPTIONS = {
91
36
  :import => true
92
- }
37
+ }.freeze
93
38
 
94
39
  def initialize(context, package, name, packages = [], options = nil)
95
40
  super context, package, name
@@ -100,12 +45,21 @@ module Teapot
100
45
  @options = DEFAULT_OPTIONS.dup
101
46
  end
102
47
 
103
- @packages = IdentitySet.by_name(packages)
104
- @imports = IdentitySet.by_name
48
+ @packages = IdentitySet.new(packages)
49
+ @imports = IdentitySet.new
105
50
 
106
51
  @visibility = :private
107
52
  end
108
53
 
54
+ def freeze
55
+ @options.freeze
56
+ @packages.freeze
57
+ @imports.freeze
58
+ @visibility.freeze
59
+
60
+ super
61
+ end
62
+
109
63
  # Controls how the configuration is exposed in the context.
110
64
  attr :visibility
111
65
 
@@ -199,7 +153,7 @@ module Teapot
199
153
  return false if @imports.count == 0
200
154
 
201
155
  # Avoid loops in the dependency chain:
202
- imported = IdentitySet.new(&:name)
156
+ imported = IdentitySet.new
203
157
 
204
158
  # Enumerate all imports and attempt to resolve the packages:
205
159
  begin
@@ -211,7 +165,7 @@ module Teapot
211
165
  end
212
166
 
213
167
  imports = @imports
214
- @imports = IdentitySet.new(&:name)
168
+ @imports = IdentitySet.new
215
169
 
216
170
  imports.each do |import|
217
171
  named_configuration = @context.configurations[import.name]
@@ -265,7 +219,7 @@ module Teapot
265
219
  end
266
220
 
267
221
  def to_s
268
- "<#{self.class.name} #{@name.dump} visibility=#{@visibility}>"
222
+ "#<#{self.class} #{@name.dump} visibility=#{@visibility}>"
269
223
  end
270
224
  end
271
225
  end
@@ -40,6 +40,8 @@ module Teapot
40
40
  end
41
41
  end
42
42
 
43
+ # A context represents a specific root package instance with a given configuration and all related definitions.
44
+ # A context is stateful in the sense that package selection is specialized based on #select and #dependency_chain. These parameters are usually set up initially as part of the context setup.
43
45
  class Context
44
46
  def initialize(root, options = {})
45
47
  @root = Path[root]
@@ -37,9 +37,11 @@ module Teapot
37
37
  ordered = context.direct_targets(ordered)
38
38
  end
39
39
 
40
- controller = Build::Controller.new do |controller|
41
- ordered.each do |(target, dependency)|
42
- environment = target.environment_for_configuration(context.configuration)
40
+ controller = Build::Controller.new(logger: self.logger) do |controller|
41
+ ordered.each do |resolution|
42
+ target = resolution.provider
43
+
44
+ environment = target.environment(context.configuration)
43
45
 
44
46
  if target.build
45
47
  controller.add_target(target, environment.flatten)
@@ -26,6 +26,8 @@ require 'rainbow'
26
26
  require 'rainbow/ext/string'
27
27
  require 'fileutils'
28
28
 
29
+ require 'build/logger'
30
+
29
31
  module Teapot
30
32
  class Controller
31
33
  MAXIMUM_FETCH_DEPTH = 20
@@ -34,13 +36,25 @@ module Teapot
34
36
  @root = Pathname(root)
35
37
  @options = options
36
38
 
37
- @log_output = @options.fetch(:log, $stdout)
39
+ log_output = @options.fetch(:log, $stdout)
40
+
41
+ @logger = Logger.new(log_output)
42
+
43
+ @logger.formatter = Build::CompactFormatter.new(verbose: options[:verbose])
44
+
45
+ if options[:verbose]
46
+ @logger.level = Logger::DEBUG
47
+ else
48
+ @logger.level = Logger::INFO
49
+ end
38
50
 
39
51
  @options[:maximum_fetch_depth] ||= MAXIMUM_FETCH_DEPTH
40
52
  end
41
53
 
54
+ attr :logger
55
+
42
56
  def log(*args)
43
- @log_output.puts *args
57
+ @logger.info(*args)
44
58
  end
45
59
 
46
60
  def context
@@ -28,7 +28,18 @@ module Teapot
28
28
 
29
29
  @description = nil
30
30
  end
31
-
31
+
32
+ def freeze
33
+ @name.freeze
34
+ @description.freeze
35
+
36
+ super
37
+ end
38
+
39
+ def pretty_print(pp)
40
+ pp.text self.inspect
41
+ end
42
+
32
43
  # The context in which the definition was loaded:
33
44
  attr :context
34
45
 
@@ -55,7 +66,7 @@ module Teapot
55
66
  end
56
67
 
57
68
  def to_s
58
- "<#{self.class.name} #{@name.dump}>"
69
+ "#<#{self.class} #{@name.dump}>"
59
70
  end
60
71
  end
61
72
  end
@@ -34,6 +34,7 @@ module Teapot
34
34
 
35
35
  Provision = Struct.new(:value)
36
36
  Alias = Struct.new(:dependencies)
37
+ Resolution = Struct.new(:provider, :name)
37
38
 
38
39
  def priority= value
39
40
  @priority = value
@@ -151,7 +152,6 @@ module Teapot
151
152
  explicit_providers = filter_by_priority(explicit_providers)
152
153
  end
153
154
 
154
-
155
155
  if explicit_providers.size == 0
156
156
  # No provider was explicitly specified, thus we require explicit conflict resolution:
157
157
  @conflicts[dependency] = viable_providers
@@ -212,7 +212,7 @@ module Teapot
212
212
  # puts "** Appending #{dependency} -> ordered".color(:magenta)
213
213
 
214
214
  # Add the provider to the ordered list.
215
- @ordered << [provider, dependency]
215
+ @ordered << Resolution.new(provider, dependency)
216
216
  end
217
217
 
218
218
  # This goes here because we want to ensure 1/ that if
@@ -66,7 +66,7 @@ module Teapot
66
66
  source_path = Pathname(path) + source
67
67
  destination_path = Pathname(context.root) + destination
68
68
 
69
- destination_path.dirname.create
69
+ destination_path.dirname.mkpath
70
70
 
71
71
  File.open(destination_path, mode) do |file|
72
72
  text = File.read(source_path)
@@ -0,0 +1,74 @@
1
+ # Copyright, 2015, 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 'forwardable'
22
+
23
+ module Teapot
24
+ # Very similar to a set but uses a specific callback (defaults to &:name) for object identity.
25
+ class IdentitySet
26
+ include Enumerable
27
+
28
+ def initialize(contents = [])
29
+ @table = {}
30
+
31
+ contents.each do |object|
32
+ add(object)
33
+ end
34
+ end
35
+
36
+ def freeze
37
+ @table.freeze
38
+
39
+ super
40
+ end
41
+
42
+ def initialize_dup(other)
43
+ @table = other.table.dup
44
+ end
45
+
46
+ def identity(object)
47
+ object.name
48
+ end
49
+
50
+ attr :table
51
+
52
+ def add(object)
53
+ @table[identity(object)] = object
54
+ end
55
+
56
+ alias << add
57
+
58
+ def delete(object)
59
+ @table.delete(identity(object))
60
+ end
61
+
62
+ def include?(object)
63
+ @table.include?(identity(object))
64
+ end
65
+
66
+ def each(&block)
67
+ @table.each_value(&block)
68
+ end
69
+
70
+ extend Forwardable
71
+
72
+ def_delegators :@table, :size, :empty?, :clear, :count, :[], :to_s, :inspect
73
+ end
74
+ end
data/lib/teapot/loader.rb CHANGED
@@ -27,6 +27,9 @@ require 'build/rule'
27
27
  require 'build/name'
28
28
  require 'build/files'
29
29
 
30
+ # Required for CPU count, etc.
31
+ require 'system'
32
+
30
33
  module Teapot
31
34
  LOADER_VERSION = "1.0.0"
32
35
  MINIMUM_LOADER_VERSION = "1.0"
@@ -49,6 +49,15 @@ module Teapot
49
49
  # Copy the options provided:
50
50
  @options = options
51
51
  end
52
+
53
+ def freeze
54
+ @path.freeze
55
+ @name.freeze
56
+ @uri.freeze
57
+ @options.freeze
58
+
59
+ super
60
+ end
52
61
 
53
62
  attr :name
54
63
  attr :path
@@ -79,7 +88,7 @@ module Teapot
79
88
  end
80
89
 
81
90
  def to_s
82
- "<#{self.class.name} #{@name.dump} path=#{path}>"
91
+ "#<#{self.class} #{@name.dump} path=#{path}>"
83
92
  end
84
93
 
85
94
  # Package may be used as hash key / in a set:
@@ -31,6 +31,17 @@ module Teapot
31
31
  @authors = []
32
32
  end
33
33
 
34
+ def freeze
35
+ @summary.freeze
36
+ @license.freeze
37
+ @website.freeze
38
+ @version.freeze
39
+
40
+ @authors.freeze
41
+
42
+ super
43
+ end
44
+
34
45
  attr :summary, true
35
46
  attr :license, true
36
47
  attr :website, true
@@ -20,12 +20,24 @@
20
20
 
21
21
  module Teapot
22
22
  class Indentation
23
+ TAB = "\t".freeze
24
+
23
25
  def initialize(prefix, level, indent)
24
26
  @prefix = prefix
25
27
  @level = level
26
28
  @indent = indent
27
29
  end
28
30
 
31
+ def freeze
32
+ indentation
33
+
34
+ @prefix.freeze
35
+ @level.freeze
36
+ @indent.freeze
37
+
38
+ super
39
+ end
40
+
29
41
  def indentation
30
42
  @indentation ||= @prefix + (@indent * @level)
31
43
  end
@@ -47,7 +59,7 @@ module Teapot
47
59
  end
48
60
 
49
61
  def self.none
50
- self.new('', 0, "\t")
62
+ self.new('', 0, TAB)
51
63
  end
52
64
  end
53
65
 
@@ -56,6 +68,12 @@ module Teapot
56
68
  @ordered = ordered
57
69
  end
58
70
 
71
+ def freeze
72
+ @ordered.freeze
73
+
74
+ super
75
+ end
76
+
59
77
  def []= keyword, value
60
78
  if Array === value
61
79
  open, close = *value.each_slice(value.length / 2)
@@ -107,6 +125,13 @@ module Teapot
107
125
 
108
126
  attr :keyword
109
127
  attr :value
128
+
129
+ def freeze
130
+ @keyword.freeze
131
+ @value.freeze
132
+
133
+ super
134
+ end
110
135
 
111
136
  def apply(text)
112
137
  text.gsub(@keyword, @value)
@@ -131,6 +156,15 @@ module Teapot
131
156
  @indent = indent
132
157
  end
133
158
 
159
+ def freeze
160
+ @keyword.freeze
161
+ @open.freeze
162
+ @close.freeze
163
+ @indent.freeze
164
+
165
+ super
166
+ end
167
+
134
168
  def line_pattern(prefix = '')
135
169
  tag_pattern = Regexp.escape('<' + prefix + @keyword + '>')
136
170
 
@@ -208,7 +242,8 @@ module Teapot
208
242
  substitutions = self.new
209
243
 
210
244
  # The user's current name:
211
- substitutions['AUTHOR_NAME'] = `git config --global user.name`.chomp
245
+ substitutions['AUTHOR_NAME'] = context.metadata.user.name
246
+ substitutions['AUTHOR_EMAIL'] = context.metadata.user.email
212
247
 
213
248
  substitutions['PROJECT_NAME'] = context.project.name
214
249
  substitutions['LICENSE'] = context.project.license
data/lib/teapot/target.rb CHANGED
@@ -42,14 +42,23 @@ module Teapot
42
42
 
43
43
  attr :rulebook
44
44
 
45
+ def freeze
46
+ @build.freeze
47
+ @rulebook.freeze
48
+
49
+ super
50
+ end
51
+
52
+ # Given a configuration, compute the dependency chain for this target.
45
53
  def provision_chain(configuration)
46
54
  # Reduce the number of keystrokes for good health:
47
55
  context = configuration.context
48
56
 
49
- chain = Dependency::chain(context.selection, dependencies, context.targets.values)
57
+ chain = Dependency::chain(context.selection, self.dependencies, context.targets.values)
50
58
  end
51
59
 
52
- def environment_for_configuration(configuration)
60
+ # Given a specific configuration, generate the build environment based on this target and it's provision chain.
61
+ def environment(configuration)
53
62
  chain = provision_chain(configuration)
54
63
 
55
64
  environments = []
@@ -64,14 +73,15 @@ module Teapot
64
73
 
65
74
  # Merge all the environments together:
66
75
  environment = Build::Environment.combine(*environments)
67
-
76
+
68
77
  environment.merge do
69
78
  default platforms_path configuration.platforms_path
70
- default build_prefix {platforms_path + "cache/#{platform_name}-#{variant}"}
71
- default install_prefix {platforms_path + "#{platform_name}-#{variant}"}
72
79
  end
73
80
  end
74
81
 
82
+ # Legacy method name.
83
+ alias environment_for_configuration environment
84
+
75
85
  def build(&block)
76
86
  if block_given?
77
87
  @build = block
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Teapot
22
- VERSION = "1.0.0-rc10"
22
+ VERSION = "1.0.0"
23
23
  end
Binary file