teapot 0.6.0 → 0.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.
@@ -0,0 +1,40 @@
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 'teapot/controller'
22
+
23
+ module Teapot
24
+ class Controller
25
+ def generate(name, arguments)
26
+ context, configuration = load_teapot
27
+
28
+ configuration.load_all
29
+
30
+ generator = context.generators[name]
31
+
32
+ unless generator
33
+ abort "Could not find generator with name #{name.inspect}".color(:red)
34
+ end
35
+
36
+ log "Generating #{name.inspect} with arguments #{arguments.inspect}".color(:cyan)
37
+ generator.generate!(*arguments)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,79 @@
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 'teapot/controller'
22
+
23
+ module Teapot
24
+ class Controller
25
+ def list
26
+ context, configuration = load_teapot
27
+
28
+ # Should this somehow consider context.root_package?
29
+ configuration.packages.each do |package|
30
+ log "Package #{package.name} (from #{package.path}):".bright
31
+
32
+ begin
33
+ definitions = context.load(package)
34
+
35
+ definitions.each do |definition|
36
+ log "\t#{definition}"
37
+
38
+ definition.description.each_line do |line|
39
+ log "\t\t#{line.chomp}".color(:cyan)
40
+ end if definition.description
41
+
42
+ case definition
43
+ when Target
44
+ definition.dependencies.each do |name|
45
+ log "\t\t- depends on #{name.inspect}".color(:red)
46
+ end
47
+
48
+ definition.provisions.each do |(name, provision)|
49
+ if Dependency::Alias === provision
50
+ log "\t\t- provides #{name.inspect} => #{provision.dependencies.inspect}".color(:green)
51
+ else
52
+ log "\t\t- provides #{name.inspect}".color(:green)
53
+ end
54
+ end
55
+ when Configuration
56
+ definition = definition.materialize
57
+
58
+ definition.packages.each do |package|
59
+ if package.local?
60
+ log "\t\t- links #{package.name} from #{package.options[:local]}".color(:green)
61
+ elsif package.external?
62
+ log "\t\t- clones #{package.name} from #{package.external_url(context.root)}".color(:green)
63
+ else
64
+ log "\t\t- references #{package.name} from #{package.path}".color(:green)
65
+ end
66
+ end
67
+
68
+ definition.imports.each do |import|
69
+ log "\t\t- unmaterialised import #{import.name}".color(:red)
70
+ end
71
+ end
72
+ end
73
+ rescue NonexistantTeapotError => error
74
+ log "\t#{error.message}".color(:red)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,61 @@
1
+ # Copyright, 2013, 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
+ module Teapot
22
+ class Definition
23
+ def initialize(context, package, name)
24
+ @context = context
25
+ @package = package
26
+
27
+ @name = name
28
+
29
+ @description = nil
30
+ end
31
+
32
+ # The context in which the definition was loaded:
33
+ attr :context
34
+
35
+ # The package in which the definition was specified:
36
+ attr :package
37
+
38
+ # The name of the definition:
39
+ attr :name
40
+
41
+ # A textual description of the definition, possibly in markdown format:
42
+ attr :description, true
43
+
44
+ def description=(text)
45
+ if text =~ /^(\t+)/
46
+ text = text.gsub(/#{$1}/, '')
47
+ end
48
+
49
+ @description = text
50
+ end
51
+
52
+ # The path that the definition is relative to:
53
+ def path
54
+ @package.path
55
+ end
56
+
57
+ def to_s
58
+ "<#{self.class.name} #{@name.dump}>"
59
+ end
60
+ end
61
+ end
@@ -43,7 +43,7 @@ module Teapot
43
43
  else
44
44
  aliases = name_or_aliases
45
45
 
46
- aliases.each do |(name, dependencies)|
46
+ aliases.each do |name, dependencies|
47
47
  provisions[name] = Alias.new(Array dependencies)
48
48
  end
49
49
  end
@@ -0,0 +1,109 @@
1
+ # Copyright, 2013, 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 'teapot/definition'
22
+ require 'tempfile'
23
+
24
+ module Teapot
25
+ class Generator < Definition
26
+ def initialize(context, package, name)
27
+ super context, package, name
28
+
29
+ @generate = nil
30
+ end
31
+
32
+ def generate(&block)
33
+ @generate = Proc.new(&block)
34
+ end
35
+
36
+ def generate!(*args)
37
+ @generate[*args]
38
+ end
39
+
40
+ def substitute(text, substitutions)
41
+ return text unless substitutions
42
+
43
+ # Use positive look behind so that the pattern is just the substitution key:
44
+ pattern = Regexp.new(substitutions.keys.map{|x| Regexp.escape(x)}.join('|'))
45
+
46
+ text.gsub(pattern) {|key| substitutions[key]}
47
+ end
48
+
49
+ def write(source, destination, substitutions = nil, mode = "a")
50
+ source_path = Pathname(path) + source
51
+ destination_path = Pathname(context.root) + destination
52
+
53
+ destination_path.dirname.mkpath
54
+
55
+ File.open(destination_path, mode) do |file|
56
+ text = File.read(source_path)
57
+
58
+ file.write substitute(text, substitutions)
59
+ end
60
+ end
61
+
62
+ def append(source, destination, substitutions = nil)
63
+ write(source, destination, substitutions, "a")
64
+ end
65
+
66
+ def merge(source, destination, substitutions = nil)
67
+ source_path = Pathname(path) + source
68
+ destination_path = Pathname(context.root) + destination
69
+
70
+ if destination_path.exist?
71
+ temporary_file = Tempfile.new(destination_path.basename.to_s)
72
+
73
+ # This functionality works, but needs improvements.
74
+ begin
75
+ # Need to ask user what to do?
76
+ write(source_path, temporary_file.path, substitutions, "w")
77
+
78
+ if temporary_file.read != destination_path.read
79
+ if `which opendiff`.chomp != ''
80
+ system("opendiff", "-merge", destination_path.to_s, destination_path.to_s, temporary_file.path)
81
+ elsif `which sdiff`.chomp != ''
82
+ system("sdiff", "-o", destination_path.to_s, destination_path.to_s, temporary_file.path)
83
+ else
84
+ abort "Can't find diff/merge tools. Please install sdiff!"
85
+ end
86
+ end
87
+ ensure
88
+ temporary_file.unlink
89
+ end
90
+ else
91
+ write(source_path, destination_path, substitutions, "w")
92
+ end
93
+ end
94
+
95
+ def copy(source, destination, substitutions = nil)
96
+ source_path = Pathname(path) + source
97
+
98
+ if source_path.directory?
99
+ destination_path = Pathname(context.root) + destination
100
+
101
+ source_path.children(false).each do |child_path|
102
+ copy(source_path + child_path, destination_path + substitute(child_path.to_s, substitutions), substitutions)
103
+ end
104
+ else
105
+ merge(source_path, destination, substitutions)
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,135 @@
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 'teapot/target'
22
+ require 'teapot/generator'
23
+ require 'teapot/configuration'
24
+
25
+ require 'teapot/name'
26
+ require 'teapot/build'
27
+
28
+ module Teapot
29
+ LOADER_VERSION = "0.7"
30
+ MINIMUM_LOADER_VERSION = "0.7"
31
+
32
+ class IncompatibleTeapotError < StandardError
33
+ def initialize(version)
34
+ super "Version #{version} isn't compatible with current loader! Minimum supported version: #{MINIMUM_LOADER_VERSION}; Current version: #{LOADER_VERSION}."
35
+ end
36
+
37
+ attr :version
38
+ end
39
+
40
+ class NonexistantTeapotError < StandardError
41
+ def initialize(path)
42
+ super "Could not load #{path}!"
43
+ end
44
+
45
+ attr :path
46
+ end
47
+
48
+ class Loader
49
+ class Definitions < Array
50
+ def default_configuration
51
+ find{|definition| Configuration === definition}
52
+ end
53
+ end
54
+
55
+ # Provides build_directory and build_external methods
56
+ include Build::Helpers
57
+
58
+ def initialize(context, package)
59
+ @context = context
60
+ @package = package
61
+
62
+ @defined = Definitions.new
63
+ @version = nil
64
+ end
65
+
66
+ attr :context
67
+ attr :package
68
+ attr :defined
69
+ attr :version
70
+
71
+ def teapot_version(version)
72
+ version = version[0..2]
73
+
74
+ if version >= MINIMUM_LOADER_VERSION && version <= LOADER_VERSION
75
+ @version = version
76
+ else
77
+ raise IncompatibleTeapotError.new(version)
78
+ end
79
+ end
80
+
81
+ alias required_version teapot_version
82
+
83
+ def define_target(*args)
84
+ target = Target.new(@context, @package, *args)
85
+
86
+ yield target
87
+
88
+ @defined << target
89
+ end
90
+
91
+ def define_generator(*args)
92
+ generator = Generator.new(@context, @package, *args)
93
+
94
+ yield generator
95
+
96
+ @defined << generator
97
+ end
98
+
99
+ def define_configuration(*args)
100
+ configuration = Configuration.new(@context, @package, *args)
101
+
102
+ yield configuration
103
+
104
+ configuration.top!
105
+
106
+ @defined << configuration
107
+ end
108
+
109
+ # Checks the host patterns and executes the block if they match.
110
+ def host(*args, &block)
111
+ name = @context.options[:host_platform] || RUBY_PLATFORM
112
+
113
+ if block_given?
114
+ if args.find{|arg| arg === name}
115
+ yield
116
+ end
117
+ else
118
+ name
119
+ end
120
+ end
121
+
122
+ # Load a teapot.rb file relative to the root of the @package.
123
+ def load(path)
124
+ absolute_path = @package.path + path
125
+
126
+ raise NonexistantTeapotError.new(absolute_path) unless File.exist?(absolute_path)
127
+
128
+ self.instance_eval(absolute_path.read, absolute_path.to_s)
129
+
130
+ if @version == nil
131
+ raise IncompatibleTeapotError.new("<unspecified>")
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright, 2013, 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
+ module Teapot
22
+ class Name
23
+ def initialize(text)
24
+ @text = text
25
+ end
26
+
27
+ attr :text
28
+
29
+ def identifier
30
+ @identifier ||= @text.gsub(/\s+/, '')
31
+ end
32
+
33
+ def target
34
+ @target ||= @text.gsub(/\s+/, '-').downcase
35
+ end
36
+ end
37
+ end