teapot 0.8.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4f0ac3f8f5a835ed05d72ed5789a28617dc89672
4
- data.tar.gz: 9cdbc779f23d8f16787091936845897a8ebfcaca
5
- SHA512:
6
- metadata.gz: 763f58203bf5632541edf4cb1db726b955e7971adda43d7af17c0a816ac5dcbd8a0b5d52464c0564824c2e2550ebef04c785ac641f38bb4eb09156f3efb528d1
7
- data.tar.gz: 2aa81a03e51e0d1cd0a4e028cfc610590941d4522de5b6ae549c80146719d141f3508e3afc3067c82e234f0dd95831b5292295fef42e1bcf89281566e26307d4
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OTIzOGRjMDQzOGJmOTZmZmE0ODQ0NWU4MzA2YTNiMTJhYWU0YWI4Yg==
5
+ data.tar.gz: !binary |-
6
+ NTc4YWMzMjdjNjE4M2I0MWUxMmQxYjBhN2NlMmZiMTgwY2NkYThkNQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NTMxYzQ2Mzg3ODAzOTNiYjBhMDkzOTllOGM1NGE3YjUyNDczMzhkNGNlZWIz
10
+ MDJhMzUyMDlmNWFhOGM1YzQ3YzBjMDNmNDlhYzVkYjdlNjliOWQ4MzFlZTM5
11
+ MDY0M2UwMmQzNDI5MmNkOWE0MWZiMjhlNTJiZTE3MTE3ZTkyMjE=
12
+ data.tar.gz: !binary |-
13
+ OTIxOTIzNWVmZWVhZjMxZDU3OWZlYjk3NzZmOTgwNWE4YzkyYzUyOGNjMGNi
14
+ ZDIxNWFkYTAwYzQ1ZWZlYzdmY2I2MzU2M2RlMGU4ZDM2OGRhNmNkMWNjM2Rm
15
+ ODlkYzFiOWJhYjE4ZTEwOTliYTQwOTRhNjE3NDRlMzY0NjI5Mzg=
@@ -25,6 +25,16 @@ require 'facter'
25
25
 
26
26
  module Teapot
27
27
  module Commands
28
+ module Helpers
29
+ def run_executable(path, environment)
30
+ environment = environment.flatten
31
+
32
+ executable = environment[:install_prefix] + path
33
+
34
+ Commands.run(executable)
35
+ end
36
+ end
37
+
28
38
  def self.processor_count
29
39
  # Get the number of virtual/physical processors
30
40
  count = Facter.processorcount.to_i rescue 1
@@ -43,6 +53,9 @@ module Teapot
43
53
  def self.run(*args)
44
54
  args = args.flatten.collect &:to_s
45
55
 
56
+ # Ensure we aren't invoking the shell
57
+ args[0] = [args[0], args[0]]
58
+
46
59
  puts args.join(' ').color(:blue)
47
60
 
48
61
  if system(*args)
@@ -45,6 +45,7 @@ module Teapot
45
45
  @targets = {}
46
46
  @generators = {}
47
47
  @configurations = {}
48
+ @projects = {}
48
49
 
49
50
  @dependencies = []
50
51
  @selection = Set.new
@@ -72,6 +73,7 @@ module Teapot
72
73
 
73
74
  attr :targets
74
75
  attr :generators
76
+ attr :projects
75
77
 
76
78
  # All public configurations.
77
79
  attr :configurations
@@ -79,6 +81,9 @@ module Teapot
79
81
  # The context's primary configuration.
80
82
  attr :configuration
81
83
 
84
+ # The context's primary project.
85
+ attr :project
86
+
82
87
  attr :dependencies
83
88
  attr :selection
84
89
 
@@ -128,6 +133,12 @@ module Teapot
128
133
 
129
134
  @configurations[definition.name] = definition
130
135
  end
136
+ when Project
137
+ AlreadyDefinedError.check(definition, @projects)
138
+
139
+ @project ||= definition
140
+
141
+ @projects[definition.name] = definition
131
142
  end
132
143
  end
133
144
 
@@ -38,6 +38,16 @@ module Teapot
38
38
  end if definition.description
39
39
 
40
40
  case definition
41
+ when Project
42
+ log "\t\t- Summary: #{definition.summary}" if definition.summary
43
+ log "\t\t- License: #{definition.license}" if definition.license
44
+ log "\t\t- Website: #{definition.website}" if definition.website
45
+ log "\t\t- Version: #{definition.version}" if definition.version
46
+
47
+ definition.authors.each do |author|
48
+ contact_text = [author.email, author.website].compact.collect{|text|" <#{text}>"}.join
49
+ log "\t\t- Author: #{author.name}" + contact_text
50
+ end
41
51
  when Target
42
52
  definition.dependencies.each do |name|
43
53
  log "\t\t- depends on #{name.inspect}".color(:red)
@@ -1,15 +1,15 @@
1
1
  # Copyright, 2013, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the "Software"), to deal
5
5
  # in the Software without restriction, including without limitation the rights
6
6
  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
7
  # copies of the Software, and to permit persons to whom the Software is
8
8
  # furnished to do so, subject to the following conditions:
9
- #
9
+ #
10
10
  # The above copyright notice and this permission notice shall be included in
11
11
  # all copies or substantial portions of the Software.
12
- #
12
+ #
13
13
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
14
  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
15
  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -20,14 +20,18 @@
20
20
 
21
21
  require 'teapot/definition'
22
22
  require 'teapot/substitutions'
23
+ require 'teapot/merge'
23
24
 
24
25
  require 'tempfile'
25
26
 
26
27
  module Teapot
28
+ class GeneratorError < StandardError
29
+ end
30
+
27
31
  class Generator < Definition
28
32
  def initialize(context, package, name)
29
33
  super context, package, name
30
-
34
+
31
35
  @generate = nil
32
36
  end
33
37
 
@@ -38,56 +42,52 @@ module Teapot
38
42
  def generate!(*args)
39
43
  @generate[*args]
40
44
  end
41
-
45
+
42
46
  def substitute(text, substitutions)
43
47
  return text unless substitutions
44
-
48
+
45
49
  if Hash === substitutions
46
50
  pattern = Regexp.new(substitutions.keys.map{|x| Regexp.escape(x)}.join('|'))
47
-
51
+
48
52
  text.gsub(pattern) {|key| substitutions[key]}
49
53
  else
50
54
  substitutions.call(text)
51
55
  end
52
56
  end
53
-
57
+
54
58
  def write(source, destination, substitutions = nil, mode = "a")
55
59
  source_path = Pathname(path) + source
56
60
  destination_path = Pathname(context.root) + destination
57
-
61
+
58
62
  destination_path.dirname.mkpath
59
-
63
+
60
64
  File.open(destination_path, mode) do |file|
61
65
  text = File.read(source_path)
62
-
66
+
63
67
  file.write substitute(text, substitutions)
64
68
  end
65
69
  end
66
-
70
+
67
71
  def append(source, destination, substitutions = nil)
68
72
  write(source, destination, substitutions, "a")
69
73
  end
70
-
74
+
71
75
  def merge(source, destination, substitutions = nil)
72
76
  source_path = Pathname(path) + source
73
77
  destination_path = Pathname(context.root) + destination
74
-
78
+
75
79
  if destination_path.exist?
76
80
  temporary_file = Tempfile.new(destination_path.basename.to_s)
77
-
81
+
78
82
  # This functionality works, but needs improvements.
79
83
  begin
80
84
  # Need to ask user what to do?
81
85
  write(source_path, temporary_file.path, substitutions, "w")
82
-
83
- if temporary_file.read != destination_path.read
84
- if `which opendiff`.chomp != ''
85
- system("opendiff", "-merge", destination_path.to_s, destination_path.to_s, temporary_file.path)
86
- elsif `which sdiff`.chomp != ''
87
- system("sdiff", "-o", destination_path.to_s, destination_path.to_s, temporary_file.path)
88
- else
89
- abort "Can't find diff/merge tools. Please install sdiff!"
90
- end
86
+
87
+ result = Merge::combine(destination.readlines, temporary_file.readlines)
88
+
89
+ destination.open("w") do |file|
90
+ file.write result.join
91
91
  end
92
92
  ensure
93
93
  temporary_file.unlink
@@ -96,13 +96,13 @@ module Teapot
96
96
  write(source_path, destination_path, substitutions, "w")
97
97
  end
98
98
  end
99
-
99
+
100
100
  def copy(source, destination, substitutions = nil)
101
101
  source_path = Pathname(path) + source
102
-
102
+
103
103
  if source_path.directory?
104
104
  destination_path = Pathname(context.root) + destination
105
-
105
+
106
106
  source_path.children(false).each do |child_path|
107
107
  copy(source_path + child_path, destination_path + substitute(child_path.to_s, substitutions), substitutions)
108
108
  end
data/lib/teapot/loader.rb CHANGED
@@ -18,6 +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
+ require 'teapot/project'
21
22
  require 'teapot/target'
22
23
  require 'teapot/generator'
23
24
  require 'teapot/configuration'
@@ -26,7 +27,7 @@ require 'teapot/name'
26
27
  require 'teapot/build'
27
28
 
28
29
  module Teapot
29
- LOADER_VERSION = "0.8"
30
+ LOADER_VERSION = "0.9"
30
31
  MINIMUM_LOADER_VERSION = "0.8"
31
32
 
32
33
  class IncompatibleTeapotError < StandardError
@@ -55,6 +56,9 @@ module Teapot
55
56
  # Provides build_directory and build_external methods
56
57
  include Build::Helpers
57
58
 
59
+ # Provides run_executable and other related methods.
60
+ include Commands::Helpers
61
+
58
62
  def initialize(context, package)
59
63
  @context = context
60
64
  @package = package
@@ -80,6 +84,14 @@ module Teapot
80
84
 
81
85
  alias required_version teapot_version
82
86
 
87
+ def define_project(*args)
88
+ project = Project.new(@context, @package, *args)
89
+
90
+ yield project
91
+
92
+ @defined << project
93
+ end
94
+
83
95
  def define_target(*args)
84
96
  target = Target.new(@context, @package, *args)
85
97
 
@@ -99,10 +111,10 @@ module Teapot
99
111
  def define_configuration(*args)
100
112
  configuration = Configuration.new(@context, @package, *args)
101
113
 
102
- yield configuration
103
-
104
114
  configuration.top!
105
115
 
116
+ yield configuration
117
+
106
118
  @defined << configuration
107
119
  end
108
120
 
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright, 2013, by Samuel G. D. Williams. <http://www.codeotaku.com>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+
22
+ module Teapot
23
+ module Merge
24
+ Difference = Struct.new(:type, :value)
25
+
26
+ def self.combine(old_text, new_text)
27
+ lcs = lcs(old_text, new_text)
28
+ changes = []
29
+
30
+ n = 0; o = 0; l = 0
31
+ while o < old_text.size and n < new_text.size and l < lcs.size
32
+ if !similar(old_text[o], lcs[l])
33
+ changes << Difference.new(:old, old_text[o])
34
+ o+=1
35
+ elsif !similar(new_text[n], lcs[l])
36
+ changes << Difference.new(:new, new_text[n])
37
+ n+=1
38
+ else
39
+ changes << Difference.new(:both, lcs[l])
40
+ o+=1; n+=1; l+=1
41
+ end
42
+ end
43
+
44
+ changes.map do |change|
45
+ change.value
46
+ end
47
+ end
48
+
49
+ # This code is based directly on the Text gem implementation
50
+ # Returns a value representing the "cost" of transforming str1 into str2
51
+ def self.levenshtein_distance(s, t)
52
+ n = s.length
53
+ m = t.length
54
+
55
+ return m if n == 0
56
+ return n if m == 0
57
+
58
+ d = (0..m).to_a
59
+ x = nil
60
+
61
+ n.times do |i|
62
+ e = i+1
63
+
64
+ m.times do |j|
65
+ cost = (s[i] == t[j]) ? 0 : 1
66
+ x = [
67
+ d[j+1] + 1, # insertion
68
+ e + 1, # deletion
69
+ d[j] + cost # substitution
70
+ ].min
71
+ d[j] = e
72
+ e = x
73
+ end
74
+
75
+ d[m] = x
76
+ end
77
+
78
+ return x
79
+ end
80
+
81
+ # Calculate the similarity of two sequences, return true if they are with factor% similarity.
82
+ def self.similar(s, t, factor = 0.15)
83
+ return true if s == t
84
+
85
+ distance = levenshtein_distance(s, t)
86
+ average_length = (s.length + t.length) / 2.0
87
+
88
+ proximity = (distance.to_f / average_length)
89
+
90
+ return proximity <= factor
91
+ end
92
+
93
+ LCSNode = Struct.new(:value, :previous)
94
+
95
+ # Find the Longest Common Subsequence in the given sequences x, y.
96
+ def self.lcs(x, y)
97
+ # Create the lcs matrix:
98
+ m = Array.new(x.length + 1) do
99
+ Array.new(y.length + 1) do
100
+ LCSNode.new(nil, nil)
101
+ end
102
+ end
103
+
104
+ # LCS(i, 0) and LCS(0, j) are always 0:
105
+ for i in 0..x.length do m[i][0].value = 0 end
106
+ for j in 0..y.length do m[0][j].value = 0 end
107
+
108
+ # Main algorithm, solve row by row:
109
+ for i in 1..x.length do
110
+ for j in 1..y.length do
111
+ if similar(x[i-1], y[j-1])
112
+ # Value is based on maximizing the length of the matched strings:
113
+ m[i][j].value = m[i-1][j-1].value + (x[i-1].chomp.length + y[j-1].chomp.length) / 2.0
114
+ m[i][j].previous = [-1, -1]
115
+ else
116
+ if m[i-1][j].value >= m[i][j-1].value
117
+ m[i][j].value = m[i-1][j].value
118
+ m[i][j].previous = [-1, 0]
119
+ else
120
+ m[i][j].value = m[i][j-1].value
121
+ m[i][j].previous = [0, -1]
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ # Get the solution by following the path backwards from m[x.length][y.length]
128
+ lcs = []
129
+
130
+ i = x.length; j = y.length
131
+ until m[i][j].previous == nil do
132
+ if m[i][j].previous == [-1, -1]
133
+ lcs << x[i-1]
134
+ end
135
+
136
+ i, j = i + m[i][j].previous[0], j + m[i][j].previous[1]
137
+ end
138
+
139
+ return lcs.reverse!
140
+ end
141
+ end
142
+ end
data/lib/teapot/name.rb CHANGED
@@ -34,8 +34,8 @@ module Teapot
34
34
  @target ||= @text.gsub(/\s+/, '-').downcase
35
35
  end
36
36
 
37
- def macro
38
- @guard ||= @text.upcase.gsub(/\s+/, '_')
37
+ def macro(prefix = [])
38
+ (Array(prefix) + [@text]).collect{|name| name.upcase.gsub(/\s+/, '_')}.join('_')
39
39
  end
40
40
  end
41
41
  end
@@ -0,0 +1,45 @@
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
+
23
+ module Teapot
24
+ class Project < Definition
25
+ Author = Struct.new(:name, :email, :website)
26
+
27
+ def initialize(context, package, name)
28
+ super context, package, name
29
+
30
+ @version = "0.0.0"
31
+ @authors = []
32
+ end
33
+
34
+ attr :summary, true
35
+ attr :license, true
36
+ attr :website, true
37
+ attr :version, true
38
+
39
+ attr :authors
40
+
41
+ def add_author name, options
42
+ @authors << Author.new(name, options[:email], options[:website])
43
+ end
44
+ end
45
+ end
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Teapot
22
- VERSION = "0.8.3"
22
+ VERSION = "0.9.0"
23
23
  end
metadata CHANGED
@@ -1,74 +1,74 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teapot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.3
4
+ version: 0.9.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: 2013-06-12 00:00:00.000000000 Z
11
+ date: 2013-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rainbow
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ! '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rexec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ! '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ! '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: trollop
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ! '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ! '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: facter
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ! '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description: "\tTeapot is a tool for managing complex cross-platform builds. It provides\n\tadvanced
70
- dependency management via the Teapot file and is supported by\n\tthe infusions ecosystem
71
- of packages and platform tooling.\n"
69
+ description: ! "\tTeapot is a tool for managing complex cross-platform builds. It
70
+ provides\n\tadvanced dependency management via the Teapot file and is supported
71
+ by\n\tthe infusions ecosystem of packages and platform tooling.\n"
72
72
  email:
73
73
  - samuel.williams@oriontransfer.co.nz
74
74
  executables:
@@ -120,8 +120,10 @@ files:
120
120
  - lib/teapot/generator.rb
121
121
  - lib/teapot/graph.rb
122
122
  - lib/teapot/loader.rb
123
+ - lib/teapot/merge.rb
123
124
  - lib/teapot/name.rb
124
125
  - lib/teapot/package.rb
126
+ - lib/teapot/project.rb
125
127
  - lib/teapot/substitutions.rb
126
128
  - lib/teapot/target.rb
127
129
  - lib/teapot/version.rb
@@ -140,17 +142,17 @@ require_paths:
140
142
  - lib
141
143
  required_ruby_version: !ruby/object:Gem::Requirement
142
144
  requirements:
143
- - - '>='
145
+ - - ! '>='
144
146
  - !ruby/object:Gem::Version
145
147
  version: 1.9.3
146
148
  required_rubygems_version: !ruby/object:Gem::Requirement
147
149
  requirements:
148
- - - '>='
150
+ - - ! '>='
149
151
  - !ruby/object:Gem::Version
150
152
  version: '0'
151
153
  requirements: []
152
154
  rubyforge_project:
153
- rubygems_version: 2.0.3
155
+ rubygems_version: 2.0.2
154
156
  signing_key:
155
157
  specification_version: 4
156
158
  summary: Teapot is a tool for managing complex cross-platform builds.