asrake 0.8.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,55 @@
1
+ require 'rake/tasklib'
2
+ require 'zip/zip'
3
+
4
+ module ASRake
5
+ class PackageTask < Rake::TaskLib
6
+
7
+ attr_accessor :output
8
+ attr_accessor :files
9
+
10
+ attr_reader :output_file
11
+ attr_reader :output_dir
12
+
13
+ def initialize(name = :package)
14
+
15
+ yield self if block_given?
16
+
17
+ fail "You must define 'output' for #{self}" if output == nil
18
+ fail "You must define 'files' to include for #{self}" if files == nil
19
+
20
+ #define named task first so if desc was called it will be attached to it instead of the file task
21
+ Rake::Task.define_task name do
22
+ puts "#{c output} (#{File.size(output)} bytes)"
23
+ end
24
+
25
+ #if the task name is a hash (ie, has dependencies defined) make sure we pull out the task name from it
26
+ name, _ = name.first if name.is_a? Hash
27
+
28
+ @output_dir = File.dirname(output)
29
+ @output_file = File.basename(output)
30
+
31
+ directory output_dir
32
+
33
+ # setup file dependencies
34
+ file output => output_dir
35
+ files.each do |to, from|
36
+ file output => [cf(from)]
37
+ end
38
+
39
+ #add output file task as a dependency to the named task created
40
+ task name => output
41
+
42
+ #create the zip task
43
+ file output do
44
+ rm_r output rescue nil
45
+ Zip::ZipFile.open(output, Zip::ZipFile::CREATE) do |zipfile|
46
+ files.each do |to, from|
47
+ zipfile.add(cf(to), cf(from))
48
+ end
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,90 @@
1
+ # (The MIT License)
2
+ #
3
+ # Copyright (c) 2010-2010 Stephen Touset
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ class Version::Component
25
+ attr_accessor :digits
26
+ attr_accessor :letter
27
+
28
+ #
29
+ # Creates a single Component of a version, consisting of digits and
30
+ # possibly a letter. For example, +1+, +3a+, +12+, or +0+.
31
+ #
32
+ def initialize(component)
33
+ parts = component.split /(?=\D)/
34
+
35
+ self.digits = parts[0].to_i
36
+ self.letter = parts[1].to_s.strip
37
+ end
38
+
39
+ def initialize_copy(other)
40
+ self.digits = other.digits
41
+ self.letter = other.letter.dup
42
+ end
43
+
44
+ def prerelease?
45
+ not self.letter.empty?
46
+ end
47
+
48
+ def unprerelease!
49
+ self.next! if self.prerelease?
50
+ end
51
+
52
+ def next(pre = false)
53
+ self.dup.next!(pre)
54
+ end
55
+
56
+ def next!(pre = false)
57
+ case
58
+ when ( pre and self.prerelease?) then self.letter.next!
59
+ when ( pre and not self.prerelease?) then self.letter = 'a'
60
+ when (not pre and self.prerelease?) then self.letter = ''
61
+ when (not pre and not self.prerelease?) then self.digits = self.digits.next
62
+ end
63
+
64
+ self
65
+ end
66
+
67
+ def <=>(other)
68
+ self.to_sortable_a <=> other.to_sortable_a
69
+ end
70
+
71
+ def to_sortable_a
72
+ [ self.digits, self.prerelease? ? 0 : 1, self.letter ]
73
+ end
74
+
75
+ def to_a
76
+ [ self.digits, self.letter ]
77
+ end
78
+
79
+ def to_i
80
+ self.digits
81
+ end
82
+
83
+ def to_s
84
+ self.to_a.join
85
+ end
86
+
87
+ def inspect
88
+ self.to_s.inspect
89
+ end
90
+ end
@@ -0,0 +1,250 @@
1
+ # (The MIT License)
2
+ #
3
+ # Copyright (c) 2010-2010 Stephen Touset
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ require 'pathname'
25
+
26
+ #
27
+ # Encodes version-numbering logic into a convenient class.
28
+ #
29
+ class Version
30
+ include Comparable
31
+ autoload :Component, 'asrake/version/component'
32
+ #
33
+ # Searches through the parent directories of the calling method and looks
34
+ # for a VERSION or VERSION.yml file to parse out the current version. Pass
35
+ #
36
+ # Pass a filename to +path+ to override autodetection, or pass a directory
37
+ # name as +path+ to autodetect within a given directory
38
+ #
39
+ def self.current(path = nil)
40
+ # if path is nil, detect automatically; if path is a directory, detect
41
+ # automatically in the directory; if path is a filename, use it directly
42
+ path = path ? Pathname.new(path) : self.version_file(caller.first)
43
+ path = self.version_file(path) unless path.nil? or path.file?
44
+
45
+ return nil unless path
46
+
47
+ case path.extname
48
+ when '' then Version.to_version(path.read.strip)
49
+ when '.yml' then Version.to_version(YAML::load(path.read))
50
+ end
51
+ end
52
+
53
+ #
54
+ # Attempts to detect the version file for the passed +filename+. Looks up
55
+ # the directory hierarchy for a file named VERSION or VERSION.yml. Returns
56
+ # a Pathname for the file if found, otherwise nil.
57
+ #
58
+ def self.version_file(filename)
59
+ Pathname(filename).dirname.expand_path.ascend do |d|
60
+ break d.join('VERSION') if d.join('VERSION').file?
61
+ break d.join('VERSION.yml') if d.join('VERSION.yml').file?
62
+ end
63
+ end
64
+
65
+ #
66
+ # Converts a String, Hash, or Array into a Version instance
67
+ #
68
+ def self.to_version(obj)
69
+ if obj.kind_of? String
70
+ Version.new *obj.split(%r{\.})
71
+ elsif obj.kind_of? Hash
72
+ Version.new *obj.values_at(:major, :minor, :revision, :rest)
73
+ elsif obj.kind_of? Array
74
+ Version.new *obj
75
+ end
76
+ end
77
+
78
+ #
79
+ # Creates a new version number, with a +major+ version number, +minor+
80
+ # revision number, +revision+ number, and optionally more (unnamed)
81
+ # version components.
82
+ #
83
+ def initialize(major, minor = 0, revision = nil, *rest)
84
+ self.components = [ major, minor, revision, *rest ]
85
+ end
86
+
87
+ #
88
+ # For +major+, +minor+, and +revision+, make a helper method that gets and
89
+ # sets each based on accessing indexes.
90
+ #--
91
+ # TODO: make these rdoc-capable
92
+ #++
93
+ #
94
+ [ :major, :minor, :revision ].to_enum.each.with_index do |component, i|
95
+ define_method(:"#{component}") { self.components[i] ? self.components[i].to_s : nil }
96
+ define_method(:"#{component}=") {|v| self[i] = v }
97
+ end
98
+
99
+ #
100
+ # Set the component of the Version at +index+ to +value+. Zeroes out any
101
+ # trailing components.
102
+ #
103
+ # If +index+ is greater than the length of the version number, pads the
104
+ # version number with zeroes until +index+.
105
+ #
106
+ def []=(index, value)
107
+ return self.resize!(index) if value.nil? || value.to_s.empty?
108
+ return self[self.length + index] = value if index < 0
109
+
110
+ length = self.length - index
111
+ zeroes = Array.new length.abs, Version::Component.new('0')
112
+ value = Version::Component.new(value.to_s)
113
+
114
+ if length >= 0
115
+ self.components[index, length] = zeroes
116
+ self.components[index] = value
117
+ else
118
+ self.components += zeroes
119
+ self.components << value
120
+ end
121
+ end
122
+
123
+ def prerelease?
124
+ self.components.any? {|c| c.prerelease? }
125
+ end
126
+
127
+ #
128
+ # Resizes the Version to +length+, removing any trailing components. Is a
129
+ # no-op if +length+ is greater than its current length.
130
+ #
131
+ def resize!(length)
132
+ self.components = self.components.take(length)
133
+ self
134
+ end
135
+
136
+ #
137
+ # Bumps the version number. Pass +component+ to bump a component other than
138
+ # the least-significant part. Set +pre+ to true if you want to bump the
139
+ # component to a prerelease version. Set +trim+ to true if you want the
140
+ # version to be resized to only large enough to contain the component set.
141
+ #
142
+ # "1.0.4a".bump! # => '1.0.4'
143
+ # "1.0.4a".bump!(:pre) # => '1.0.4b'
144
+ # "1.0.4a".bump!(:minor, false, true) # => '1.1'
145
+ # "1.0.4a".bump!(:minor, true, true) # => '1.1a
146
+ # "1.0.4a".bump!(:minor, true, false) # => '1.1.0a'
147
+ #
148
+ def bump!(component = -1, pre = false, trim = false)
149
+ case component
150
+ when :major then self.bump!(0, pre, trim)
151
+ when :minor then self.bump!(1, pre, trim)
152
+ when :revision then self.bump!(2, pre, trim)
153
+ when :pre then self.bump!(-1, true, trim)
154
+ else
155
+ # resize to match the new length, if applicable
156
+ self.resize!(component + 1) if (trim or component >= self.length)
157
+
158
+ # mark all but the changed bit as non-prerelease
159
+ self[0...component].each(&:unprerelease!)
160
+
161
+ # I don't even understand this part any more; god help you
162
+ self[component] = self[component].next if pre and self.prerelease? and component == self.length - 1
163
+ self[component] = self[component].next unless pre and self.prerelease? and component == -1
164
+ self[-1] = self[-1].next(true) if pre
165
+ self
166
+ end
167
+ end
168
+
169
+ def bump(component = -1, pre = false, trim = false)
170
+ return (Version.to_version(self.to_hash)).bump!(component, pre, trim)
171
+ end
172
+
173
+ #
174
+ # Returns the current length of the version number.
175
+ #
176
+ def length
177
+ self.components.length
178
+ end
179
+
180
+ #
181
+ # Compares a Version against any +other+ object that responds to
182
+ # +to_version+.
183
+ #
184
+ def <=>(other)
185
+ self.components <=> other.to_version.components
186
+ end
187
+
188
+ #
189
+ # Converts the version number into an array of its components.
190
+ #
191
+ def to_a
192
+ self.components.map {|c| c.to_s }
193
+ end
194
+
195
+ #
196
+ # Converts the version number into a hash of its components.
197
+ #
198
+ def to_hash
199
+ { :major => self.major,
200
+ :minor => self.minor,
201
+ :revision => self.revision,
202
+ :rest => self.length > 3 ? self.to_a.drop(3) : nil }.
203
+ delete_if {|k,v| v.nil? }
204
+ end
205
+
206
+ #
207
+ # The canonical representation of a version number.
208
+ #
209
+ def to_s
210
+ self.to_a.join('.')
211
+ end
212
+
213
+ #
214
+ # Returns +self+.
215
+ #
216
+ def to_version
217
+ self
218
+ end
219
+
220
+ #
221
+ # Returns a YAML representation of the version number.
222
+ #
223
+ def to_yaml
224
+ YAML::dump(self.to_hash)
225
+ end
226
+
227
+ #
228
+ # Returns a human-friendly version format.
229
+ #
230
+ def inspect
231
+ self.to_s.inspect
232
+ end
233
+
234
+ protected
235
+
236
+ #
237
+ # Retrieves the component of the Version at +index+.
238
+ #
239
+ def [](index)
240
+ self.components[index] || Component.new('0')
241
+ end
242
+
243
+ def components
244
+ @components ||= []
245
+ end
246
+
247
+ def components=(components)
248
+ components.each_with_index {|c, i| self[i] = c }
249
+ end
250
+ end
@@ -0,0 +1,90 @@
1
+ require 'rake/tasklib'
2
+
3
+ require 'asrake/version/version'
4
+
5
+ module ASRake
6
+ class VersionTask < Rake::TaskLib
7
+
8
+ attr_accessor :filename
9
+ attr_accessor :filetype
10
+ attr_reader :version
11
+
12
+ def initialize(name = :version, filename = "VERSION")
13
+ self.filename = filename
14
+
15
+ yield self if block_given?
16
+
17
+ # fail if no filename was provided
18
+ fail "You must define 'filename' for #{self}" if filename == nil
19
+
20
+ @path = Pathname.new(self.filename)
21
+ # set filetype from the filename if it hasn't been set already
22
+ self.filetype ||= @path.extname[1..-1]
23
+
24
+ # read in the current version
25
+ contents = @path.read rescue '0.0.0'
26
+ @version = case filetype.to_s
27
+ when '' then Version.to_version(contents.chomp)
28
+ when 'yml' then Version.to_version(YAML::load(contents))
29
+ end
30
+
31
+ # create the primary version task
32
+ desc "Increment version from #{@version}"
33
+ @version_task = Rake::Task.define_task name
34
+
35
+ # if the task name is a hash (ie, has dependencies defined) make sure we pull out the task name from it
36
+ name, _ = name.first if name.is_a? Hash
37
+
38
+ Rake::Task.define_task name, [:part] => filename do |t, args|
39
+ case (args[:part] || "").chomp.downcase
40
+ when 'major'
41
+ puts "Incremented version from #{@version} to #{save(@version.bump!(:major))}"
42
+ when 'minor'
43
+ puts "Incremented version from #{@version} to #{save(@version.bump!(:minor))}"
44
+ when 'revision', 'rev', 'patch'
45
+ puts "Incremented version from #{@version} to #{save(@version.bump!(:revision))}"
46
+ when ''
47
+ puts "Current version is #{@version}"
48
+ else
49
+ fail "Invalid version argument '#{args[:part]}', run 'rake #{@help_task}' for help."
50
+ end
51
+ @sync_task.execute()
52
+ end
53
+
54
+ file filename do
55
+ puts "Created version #{save(Version.to_version(ENV['VERSION'] || '0.0.0'))} at #{filename}"
56
+ end
57
+
58
+ # create a namespace with the same name as the task to provide further options
59
+ namespace name do
60
+
61
+ #add to this task to perform some operation post-bump
62
+ @sync_task = task :sync
63
+
64
+ desc "Display help for version task"
65
+ @help_task = task :help do
66
+ puts "Version number format is Major.Minor.Revision (aka Major.Minor.Patch)"
67
+ puts "To display the current version, run without arguments"
68
+ puts "rake #{@version_task} => #{@version}"
69
+ puts "To increment the version, provide the respective part as an argument."
70
+ puts "rake #{@version_task}[major] => #{@version.bump(:major)}"
71
+ puts "rake #{@version_task}[minor] => #{@version.bump(:minor)}"
72
+ puts "rake #{@version_task}[revision] => #{@version.bump(:revision)}"
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ private
79
+
80
+ def save(version)
81
+ @path.open('w') do |file|
82
+ file << case filetype.to_s
83
+ when '' then version.to_s + "\n"
84
+ when 'yml' then version.to_yaml
85
+ end
86
+ end
87
+ return version
88
+ end
89
+ end
90
+ end