versionomy 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # Versionomy schema namespace
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
6
  # Copyright 2008-2009 Daniel Azuma
7
- #
7
+ #
8
8
  # All rights reserved.
9
- #
9
+ #
10
10
  # Redistribution and use in source and binary forms, with or without
11
11
  # modification, are permitted provided that the following conditions are met:
12
- #
12
+ #
13
13
  # * Redistributions of source code must retain the above copyright notice,
14
14
  # this list of conditions and the following disclaimer.
15
15
  # * Redistributions in binary form must reproduce the above copyright notice,
@@ -18,7 +18,7 @@
18
18
  # * Neither the name of the copyright holder, nor the names of any other
19
19
  # contributors to this software, may be used to endorse or promote products
20
20
  # derived from this software without specific prior written permission.
21
- #
21
+ #
22
22
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
23
  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
24
  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -35,10 +35,10 @@
35
35
 
36
36
 
37
37
  module Versionomy
38
-
39
-
38
+
39
+
40
40
  # === Version number schema.
41
- #
41
+ #
42
42
  # A schema defines the structure and semantics of a version number.
43
43
  # The schema controls what fields are present in the version, how
44
44
  # version numbers are compared, what the default values are, and how
@@ -46,50 +46,50 @@ module Versionomy
46
46
  # compared with one another, and version numbers can be converted
47
47
  # trivially to formats that share the same schema, without requiring a
48
48
  # Conversion implementation.
49
- #
49
+ #
50
50
  # At its simplest, a version number is defined as a sequence of fields,
51
51
  # each with a name and data type. These fields may be integer-valued,
52
52
  # string-valued, or symbolic, though most will probably be integers.
53
53
  # Symbolic fields are enumerated types that are useful, for example, if
54
54
  # you want a field to specify the type of prerelease (e.g. "alpha",
55
55
  # "beta", or "release candidate").
56
- #
56
+ #
57
57
  # As a simple conceptual example, you could construct a schema for
58
58
  # version numbers of the form "major.minor.tiny" like this. (This is a
59
59
  # conceptual diagram, not actual syntax.)
60
- #
60
+ #
61
61
  # ("major": integer), ("minor": integer), ("tiny": integer)
62
- #
62
+ #
63
63
  # More generally, fields are actually organized into a DAG (directed
64
64
  # acyclic graph) in which the "most significant" field is the root, the
65
65
  # next most significant is a child of that root, and so forth down the
66
66
  # line. The simple schema above, then, is actually represented as a
67
67
  # linked list (a graph with one path), like this:
68
- #
68
+ #
69
69
  # ("major": integer) ->
70
70
  # ("minor": integer) ->
71
71
  # ("tiny": integer) ->
72
72
  # nil
73
- #
73
+ #
74
74
  # It is, however, possible for the form of a field to depend on the value
75
75
  # of the previous field. For example, suppose we wanted a schema in which
76
76
  # if the value of the "minor" field is 0, then the "tiny" field doesn't
77
77
  # exist. e.g.
78
- #
78
+ #
79
79
  # ("major": integer) ->
80
80
  # ("minor": integer) ->
81
81
  # [value == 0] : nil
82
82
  # [otherwise] : ("tiny": integer) ->
83
83
  # nil
84
- #
84
+ #
85
85
  # The Versionomy::Schema::Field class represents a field in this graph.
86
86
  # The Versionomy::Schema::Wrapper class represents a full schema object.
87
- #
87
+ #
88
88
  # Generally, you should create schemas using Versionomy::Schema#create.
89
89
  # That method provides a DSL that lets you quickly create the fields.
90
-
90
+
91
91
  module Schema
92
92
  end
93
-
94
-
93
+
94
+
95
95
  end
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # Versionomy schema field class
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
6
  # Copyright 2008-2009 Daniel Azuma
7
- #
7
+ #
8
8
  # All rights reserved.
9
- #
9
+ #
10
10
  # Redistribution and use in source and binary forms, with or without
11
11
  # modification, are permitted provided that the following conditions are met:
12
- #
12
+ #
13
13
  # * Redistributions of source code must retain the above copyright notice,
14
14
  # this list of conditions and the following disclaimer.
15
15
  # * Redistributions in binary form must reproduce the above copyright notice,
@@ -18,7 +18,7 @@
18
18
  # * Neither the name of the copyright holder, nor the names of any other
19
19
  # contributors to this software, may be used to endorse or promote products
20
20
  # derived from this software without specific prior written permission.
21
- #
21
+ #
22
22
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
23
  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
24
  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -38,19 +38,19 @@ require 'set'
38
38
 
39
39
 
40
40
  module Versionomy
41
-
41
+
42
42
  module Schema
43
-
44
-
43
+
44
+
45
45
  # Objects of this class represent fields in a schema.
46
-
46
+
47
47
  class Field
48
-
49
-
48
+
49
+
50
50
  # Create a field with the given name.
51
- #
51
+ #
52
52
  # Recognized options include:
53
- #
53
+ #
54
54
  # <tt>:type</tt>::
55
55
  # Type of field. This should be <tt>:integer</tt>, <tt>:string</tt>,
56
56
  # or <tt>:symbol</tt>. Default is <tt>:integer</tt>.
@@ -58,14 +58,14 @@ module Versionomy
58
58
  # Default value for the field if no value is explicitly set. Default
59
59
  # is 0 for an integer field, the empty string for a string field, or
60
60
  # the first symbol added for a symbol field.
61
- #
61
+ #
62
62
  # You may provide an optional block. Within the block, you may call
63
63
  # methods of Versionomy::Schema::FieldBuilder to further customize the
64
64
  # field, or add child fields.
65
- #
65
+ #
66
66
  # Raises Versionomy::Errors::IllegalValueError if the given default
67
67
  # value is not legal.
68
-
68
+
69
69
  def initialize(name_, opts_={}, &block_)
70
70
  @name = name_.to_sym
71
71
  @type = opts_[:type] || :integer
@@ -93,12 +93,12 @@ module Versionomy
93
93
  ::Blockenspiel.invoke(block_, Schema::FieldBuilder.new(self, master_builder_)) if block_
94
94
  @default_value = canonicalize_value(@default_value)
95
95
  end
96
-
97
-
96
+
97
+
98
98
  def _set_default_value(value_) # :nodoc:
99
99
  @default_value = value_
100
100
  end
101
-
101
+
102
102
  def _add_symbol(symbol_, opts_={}) # :nodoc:
103
103
  if @type != :symbol
104
104
  raise Errors::TypeMismatchError
@@ -112,64 +112,64 @@ module Versionomy
112
112
  @default_value = symbol_
113
113
  end
114
114
  end
115
-
115
+
116
116
  def _set_bump_proc(block_) # :nodoc:
117
117
  @bump_proc = block_
118
118
  end
119
-
119
+
120
120
  def _set_canonicalize_proc(block_) # :nodoc:
121
121
  @canonicalize_proc = block_
122
122
  end
123
-
123
+
124
124
  def _set_compare_proc(block_) # :nodoc:
125
125
  @compare_proc = block_
126
126
  end
127
-
128
-
127
+
128
+
129
129
  def inspect # :nodoc:
130
130
  "#<#{self.class}:0x#{object_id.to_s(16)} name=#{@name}>"
131
131
  end
132
-
132
+
133
133
  def to_s # :nodoc:
134
134
  inspect
135
135
  end
136
-
137
-
136
+
137
+
138
138
  # The name of the field.
139
-
139
+
140
140
  def name
141
141
  @name
142
142
  end
143
-
144
-
143
+
144
+
145
145
  # The type of the field.
146
146
  # Possible values are <tt>:integer</tt>, <tt>:string</tt>, or
147
147
  # <tt>:symbol</tt>.
148
-
148
+
149
149
  def type
150
150
  @type
151
151
  end
152
-
153
-
152
+
153
+
154
154
  # The default value of the field
155
-
155
+
156
156
  def default_value
157
157
  @default_value
158
158
  end
159
-
160
-
159
+
160
+
161
161
  # Returns a list of possible values for this field, if the type is
162
162
  # <tt>:symbol</tt>. Returns nil for any other type
163
-
163
+
164
164
  def possible_values
165
165
  @symbol_order ? @symbol_order.dup : nil
166
166
  end
167
-
168
-
167
+
168
+
169
169
  # Given a value, bump it to the "next" value.
170
170
  # Utilizes a bump procedure if given;
171
171
  # otherwise uses default behavior depending on the type.
172
-
172
+
173
173
  def bump_value(value_)
174
174
  if @bump_proc
175
175
  nvalue_ = @bump_proc.call(value_)
@@ -181,13 +181,13 @@ module Versionomy
181
181
  info_ ? info_[1] || value_ : nil
182
182
  end
183
183
  end
184
-
185
-
184
+
185
+
186
186
  # Perform a standard comparison on two values.
187
187
  # Returns an integer that may be positive, negative, or 0.
188
188
  # Utilizes a comparison procedure if given;
189
189
  # otherwise uses default behavior depending on the type.
190
-
190
+
191
191
  def compare_values(val1_, val2_)
192
192
  if @compare_proc
193
193
  @compare_proc.call(val1_, val2_)
@@ -199,15 +199,15 @@ module Versionomy
199
199
  info1_ && info2_ ? info1_[0] <=> info2_[0] : nil
200
200
  end
201
201
  end
202
-
203
-
202
+
203
+
204
204
  # Given a value, return a "canonical" value for this field.
205
205
  # Utilizes a canonicalization procedure if given;
206
206
  # otherwise uses default behavior depending on the type.
207
- #
207
+ #
208
208
  # Raises Versionomy::Errors::IllegalValueError if the given value is
209
209
  # not legal.
210
-
210
+
211
211
  def canonicalize_value(value_)
212
212
  orig_value_ = value_
213
213
  if @canonicalize_proc
@@ -227,11 +227,11 @@ module Versionomy
227
227
  end
228
228
  value_
229
229
  end
230
-
231
-
230
+
231
+
232
232
  # Returns the child field associated with the given value.
233
233
  # Returns nil if this field has no child for the given value.
234
-
234
+
235
235
  def child(value_) # :nodoc:
236
236
  if @ranges
237
237
  @ranges.each do |r_|
@@ -248,30 +248,30 @@ module Versionomy
248
248
  end
249
249
  @default_child
250
250
  end
251
-
252
-
251
+
252
+
253
253
  # Adds the given child field for the given range.
254
- #
254
+ #
255
255
  # If you provide a range of nil, adds the given child field as the
256
256
  # default child for values that do not fall into any other
257
257
  # explicitly specified range.
258
- #
258
+ #
259
259
  # Otherwise, the ranges parameter must be an array of "range" objects.
260
260
  # Each of these range objects must be either a single String, Symbol,
261
261
  # or Integer to specify a single value; or a two-element array or a
262
262
  # Range object (only inclusive ends are supported) to specify a range
263
263
  # of values.
264
- #
264
+ #
265
265
  # Raises Versionomy::Errors::RangeOverlapError if the specified
266
266
  # range overlaps another previously specified range, or if more than
267
267
  # one default child has been set.
268
- #
268
+ #
269
269
  # Raises Versionomy::Errors::RangeSpecificationError if the range
270
270
  # is incorrectly specified.
271
- #
271
+ #
272
272
  # Raises Versionomy::Errors::CircularDescendantError if adding this
273
273
  # child will result in a circular reference.
274
-
274
+
275
275
  def add_child(child_, ranges_=nil)
276
276
  if child_._descendant_fields.include?(self)
277
277
  raise Errors::CircularDescendantError
@@ -348,101 +348,101 @@ module Versionomy
348
348
  @ranges.insert(insert_index_, normalized_range_)
349
349
  end
350
350
  end
351
-
352
-
351
+
352
+
353
353
  # Compute descendants as a hash of names to fields, including this field.
354
-
354
+
355
355
  def _descendants_by_name # :nodoc:
356
356
  hash_ = {@name => self}
357
357
  @children.each{ |child_| hash_.merge!(child_._descendants_by_name) }
358
358
  hash_
359
359
  end
360
-
361
-
360
+
361
+
362
362
  # Return a set of all descendant fields, including this field.
363
-
363
+
364
364
  def _descendant_fields(set_=nil) # :nodoc:
365
365
  set_ ||= Set.new
366
366
  set_ << self
367
367
  @children.each{ |child_| child_._descendant_fields(set_) }
368
368
  set_
369
369
  end
370
-
371
-
370
+
371
+
372
372
  end
373
-
374
-
373
+
374
+
375
375
  # These methods are available in a schema field definition block.
376
-
376
+
377
377
  class FieldBuilder
378
-
378
+
379
379
  include ::Blockenspiel::DSL
380
-
380
+
381
381
  def initialize(field_, master_builder_) # :nodoc:
382
382
  @field = field_
383
383
  @master_builder = master_builder_
384
384
  end
385
-
386
-
385
+
386
+
387
387
  # Define the given symbol.
388
- #
388
+ #
389
389
  # Recognized options include:
390
- #
390
+ #
391
391
  # <tt>:bump</tt>::
392
392
  # The symbol to transition to when "bump" is called.
393
393
  # Default is to remain on the same value.
394
- #
394
+ #
395
395
  # Raises Versionomy::Errors::TypeMismatchError if called when the current field
396
396
  # is not of type <tt>:symbol</tt>.
397
- #
397
+ #
398
398
  # Raises Versionomy::Errors::SymbolRedefinedError if the given symbol name is
399
399
  # already defined.
400
-
400
+
401
401
  def symbol(symbol_, opts_={})
402
402
  @field._add_symbol(symbol_, opts_)
403
403
  end
404
-
405
-
404
+
405
+
406
406
  # Provide a default value.
407
-
407
+
408
408
  def default_value(value_)
409
409
  @field._set_default_value(value_)
410
410
  end
411
-
412
-
411
+
412
+
413
413
  # Provide a "bump" procedure.
414
414
  # The given block should take a value, and return the value to transition to.
415
415
  # If you return nil, the value will remain the same.
416
-
416
+
417
417
  def to_bump(&block_)
418
418
  @field._set_bump_proc(block_)
419
419
  end
420
-
421
-
420
+
421
+
422
422
  # Provide a "compare" procedure.
423
423
  # The given block should take two values and compare them.
424
424
  # It should return a negative integer if the first is less than the second,
425
425
  # a positive integer if the first is greater than the second, or 0 if the
426
426
  # two values are equal. If the values cannot be compared, return nil.
427
-
427
+
428
428
  def to_compare(&block_)
429
429
  @field._set_compare_proc(block_)
430
430
  end
431
-
432
-
431
+
432
+
433
433
  # Provide a "canonicalize" procedure.
434
434
  # The given block should take a value and return a canonicalized value.
435
435
  # Return nil if the given value is illegal.
436
-
436
+
437
437
  def to_canonicalize(&block_)
438
438
  @field._set_canonicalize_proc(block_)
439
439
  end
440
-
441
-
440
+
441
+
442
442
  # Add a child field.
443
- #
443
+ #
444
444
  # Recognized options include:
445
- #
445
+ #
446
446
  # <tt>:only</tt>::
447
447
  # The child should be available only for the given values of this
448
448
  # field. See below for ways to specify this constraint.
@@ -453,16 +453,16 @@ module Versionomy
453
453
  # Default value for the field if no value is explicitly set. Default
454
454
  # is 0 for an integer field, the empty string for a string field, or
455
455
  # the first symbol added for a symbol field.
456
- #
456
+ #
457
457
  # You may provide an optional block. Within the block, you may call
458
458
  # methods of this class again to customize the child.
459
- #
459
+ #
460
460
  # Raises Versionomy::Errors::IllegalValueError if the given default
461
461
  # value is not legal.
462
- #
462
+ #
463
463
  # The <tt>:only</tt> constraint may be specified in one of the
464
464
  # following ways:
465
- #
465
+ #
466
466
  # * A single value (integer, string, or symbol)
467
467
  # * The result of calling range() to define an inclusive range of
468
468
  # integers, strings, or symbols. In this case, either element may be
@@ -472,38 +472,38 @@ module Versionomy
472
472
  # * A Range object defining a range of integers or strings.
473
473
  # Only inclusive, not exclusive, ranges are supported.
474
474
  # * An array of the above.
475
- #
475
+ #
476
476
  # Raises Versionomy::Errors::RangeSpecificationError if the given
477
477
  # ranges are not legal.
478
- #
478
+ #
479
479
  # Raises Versionomy::Errors::RangeOverlapError if the given ranges
480
480
  # overlap previously specified ranges, or more than one default schema
481
481
  # is specified.
482
-
482
+
483
483
  def field(name_, opts_={}, &block_)
484
484
  only_ = opts_.delete(:only)
485
485
  opts_.merge!(:master_builder => @master_builder)
486
486
  @field.add_child(Schema::Field.new(name_, opts_, &block_), only_)
487
487
  end
488
-
489
-
488
+
489
+
490
490
  # Define a range for the <tt>:only</tt> parameter to +child+.
491
- #
491
+ #
492
492
  # This creates an object that +child+ interprets like a standard ruby Range. However, it
493
493
  # is customized for the use of +child+ in the following ways:
494
- #
494
+ #
495
495
  # * It supports only inclusive, not exclusive ranges.
496
496
  # * It supports open-ended ranges by setting either endpoint to nil.
497
497
  # * It supports symbol ranges under Ruby 1.8.
498
-
498
+
499
499
  def range(first_, last_)
500
500
  [first_, last_]
501
501
  end
502
-
503
-
502
+
503
+
504
504
  end
505
-
506
-
505
+
506
+
507
507
  end
508
-
508
+
509
509
  end