versionian 0.1.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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +8 -0
  4. data/CODE_OF_CONDUCT.md +132 -0
  5. data/README.adoc +874 -0
  6. data/Rakefile +12 -0
  7. data/docs/Gemfile +8 -0
  8. data/docs/_guides/custom-schemes.adoc +110 -0
  9. data/docs/_guides/index.adoc +12 -0
  10. data/docs/_pages/component-types.adoc +151 -0
  11. data/docs/_pages/declarative-schemes.adoc +260 -0
  12. data/docs/_pages/index.adoc +15 -0
  13. data/docs/_pages/range-matching.adoc +102 -0
  14. data/docs/_pages/schemes.adoc +68 -0
  15. data/docs/_references/api.adoc +251 -0
  16. data/docs/_references/index.adoc +13 -0
  17. data/docs/_references/schemes.adoc +410 -0
  18. data/docs/_tutorials/getting-started.adoc +119 -0
  19. data/docs/_tutorials/index.adoc +11 -0
  20. data/docs/index.adoc +287 -0
  21. data/lib/versionian/component_definition.rb +71 -0
  22. data/lib/versionian/component_types/base.rb +19 -0
  23. data/lib/versionian/component_types/date_part.rb +41 -0
  24. data/lib/versionian/component_types/enum.rb +32 -0
  25. data/lib/versionian/component_types/float.rb +23 -0
  26. data/lib/versionian/component_types/hash.rb +21 -0
  27. data/lib/versionian/component_types/integer.rb +23 -0
  28. data/lib/versionian/component_types/postfix.rb +51 -0
  29. data/lib/versionian/component_types/prerelease.rb +70 -0
  30. data/lib/versionian/component_types/registry.rb +35 -0
  31. data/lib/versionian/component_types/string.rb +21 -0
  32. data/lib/versionian/errors/invalid_scheme_error.rb +7 -0
  33. data/lib/versionian/errors/invalid_version_error.rb +7 -0
  34. data/lib/versionian/errors/parse_error.rb +7 -0
  35. data/lib/versionian/parsers/declarative.rb +214 -0
  36. data/lib/versionian/scheme_loader.rb +102 -0
  37. data/lib/versionian/scheme_registry.rb +34 -0
  38. data/lib/versionian/schemes/calver.rb +94 -0
  39. data/lib/versionian/schemes/composite.rb +82 -0
  40. data/lib/versionian/schemes/declarative.rb +138 -0
  41. data/lib/versionian/schemes/pattern.rb +236 -0
  42. data/lib/versionian/schemes/semantic.rb +136 -0
  43. data/lib/versionian/schemes/solover.rb +121 -0
  44. data/lib/versionian/schemes/wendtver.rb +141 -0
  45. data/lib/versionian/version.rb +6 -0
  46. data/lib/versionian/version_component.rb +28 -0
  47. data/lib/versionian/version_identifier.rb +121 -0
  48. data/lib/versionian/version_range.rb +61 -0
  49. data/lib/versionian/version_scheme.rb +68 -0
  50. data/lib/versionian.rb +64 -0
  51. data/lib/versius.rb +5 -0
  52. data/sig/versius.rbs +4 -0
  53. metadata +157 -0
@@ -0,0 +1,410 @@
1
+ ---
2
+ layout: default
3
+ title: Scheme Reference
4
+ nav_order: 1
5
+ parent: Reference
6
+ ---
7
+
8
+ = Versioning Schemes Reference
9
+
10
+ This reference documents all versioning schemes supported by Versionian, including their
11
+ formats, rules, and implementation details.
12
+
13
+ == SemVer: Semantic Versioning
14
+
15
+ [horizontal]
16
+ Format:: `MAJOR.MINOR.PATCH[-PRERELEASE][+BUILD]`
17
+ Status:: Built-in
18
+ Reference:: https://semver.org[semver.org]
19
+
20
+ === Description
21
+
22
+ Semantic Versioning (SemVer) is the most widely used versioning scheme in open source software.
23
+ It follows a simple format where:
24
+
25
+ * **MAJOR** version increments indicate incompatible API changes
26
+ * **MINOR** version increments add functionality in a backward-compatible manner
27
+ * **PATCH** version increments make backward-compatible bug fixes
28
+
29
+ Originally proposed by Tom Preston-Werner in 2010, SemVer has become the de facto standard
30
+ for versioning in the open source community, used by npm, RubyGems, and Cargo.
31
+
32
+ === Usage
33
+
34
+ [source,ruby]
35
+ ----
36
+ scheme = Versionian.get_scheme(:semantic)
37
+ version = scheme.parse("1.2.3-alpha.1+build.123")
38
+
39
+ # Component access
40
+ version.component(:major).value # => 1
41
+ version.component(:minor).value # => 2
42
+ version.component(:patch).value # => 3
43
+
44
+ # Comparison
45
+ scheme.compare("1.2.3", "2.0.0") # => -1
46
+ ----
47
+
48
+ == CalVer: Calendar Versioning
49
+
50
+ [horizontal]
51
+ Format:: `YYYY.MM.DD`, `YYYY.MM`, `YY.MM.DD`, etc.
52
+ Status:: Built-in
53
+ Reference:: https://calver.org[calver.org]
54
+
55
+ === Description
56
+
57
+ Calendar Versioning (CalVer) uses a date-based version number. The format provides a clear
58
+ indication of when a release was made. Multiple calendar-based formats are supported:
59
+
60
+ * `YYYY.MM.DD` - Full date (e.g., 2024.03.22)
61
+ * `YYYY.MM` - Year and month (e.g., 2024.03)
62
+ * `YY.0M.DD` - Short year, zero-padded month and day (e.g., 24.03.22)
63
+ * `YYYY.WW` - Year and week number (e.g., 2024.12)
64
+
65
+ Proposed by Mahmoud Hashemi in March 2016.
66
+
67
+ === Usage
68
+
69
+ [source,ruby]
70
+ ----
71
+ scheme = Versionian.get_scheme(:calver)
72
+
73
+ # Default format: YYYY.MM.DD
74
+ version = scheme.parse("2024.03.22")
75
+
76
+ # Compare by date
77
+ scheme.compare("2024.01.01", "2024.12.31") # => -1
78
+ ----
79
+
80
+ == SoloVer: Single Number Versioning
81
+
82
+ [horizontal]
83
+ Format:: `N[+-postfix]`
84
+ Status:: Built-in
85
+ Proposed:: March 2024 by beza1e1
86
+
87
+ === Description
88
+
89
+ SoloVer is a simple versioning scheme using a single integer with optional postfixes:
90
+
91
+ * **Version number**: A single integer starting at 0
92
+ * **Postfix**: Optional, matching regex `[+-][A-Za-z0-9_]+`
93
+
94
+ === Precedence Rules
95
+
96
+ . Higher numbers follow lower numbers
97
+ . `+` postfixes come after no postfix (for hotfixes)
98
+ . `-` postfixes come before no postfix (for pre-releases)
99
+ . Postfixes are sorted alphanumerically
100
+
101
+ === Usage
102
+
103
+ [source,ruby]
104
+ ----
105
+ scheme = Versionian.get_scheme(:solover)
106
+
107
+ # Simple version
108
+ v1 = scheme.parse("5")
109
+ v2 = scheme.parse("10")
110
+
111
+ # With postfix
112
+ v3 = scheme.parse("5+hotfix")
113
+ v4 = scheme.parse("5-beta")
114
+
115
+ # Comparison follows SoloVer rules
116
+ scheme.compare("5-beta", "5") # => -1
117
+ scheme.compare("5", "5+hotfix") # => -1
118
+ ----
119
+
120
+ == WendtVer: Auto-Incrementing Versioning
121
+
122
+ [horizontal]
123
+ Format:: `MAJOR.MINOR.PATCH`
124
+ Status:: Built-in
125
+ Proposed:: August 2018 by Brian Wendt
126
+
127
+ === Description
128
+
129
+ WendtVer minimizes thought required for version increments. Starting at 0.0.0:
130
+
131
+ * **PATCH** increments on every commit
132
+ * **MINOR** increments when PATCH would reach 10, rolling PATCH to 0
133
+ * **MAJOR** increments when MINOR would reach 10, rolling MINOR to 0
134
+
135
+ === Usage
136
+
137
+ [source,ruby]
138
+ ----
139
+ scheme = Versionian.get_scheme(:wendtver)
140
+
141
+ version = scheme.parse("1.2.3")
142
+ next_version = scheme.increment("1.2.3", :patch) # => "1.2.4"
143
+ ----
144
+
145
+ == ZeroVer
146
+
147
+ [horizontal]
148
+ Format:: `0.MAJOR.MINOR`
149
+ Status:: Reference Implementation
150
+ Proposed:: April 2018 by Mahmoud Hashemi
151
+
152
+ === Description
153
+
154
+ ZeroVer is a satirical versioning scheme where versions always start with 0,
155
+ suggesting perpetual early development. While meant as a joke, many projects
156
+ fall into ZeroVer simply because they've never made the jump to 1.0.0.
157
+
158
+ == EffVer: Intended Effort Versioning
159
+
160
+ [horizontal]
161
+ Format:: `MAJOR.MINOR.PATCH`
162
+ Status:: Reference Implementation
163
+ Proposed:: January 2024 by Jacob Tomlinson
164
+
165
+ === Description
166
+
167
+ EffVer quantifies the intended work required to adopt a change, rather than
168
+ the orthogonality of changes. It focuses on user adoption effort rather than
169
+ categorizing changes as bug fixes, enhancements, or features.
170
+
171
+ == RomVer: Romantic Versioning
172
+
173
+ [horizontal]
174
+ Format:: `HUMAN.MAJOR.MINOR`
175
+ Status:: Reference Implementation
176
+ Proposed:: 2015 by Daniel V (Legacy Blog crew)
177
+
178
+ === Description
179
+
180
+ Romantic Versioning follows the format `HUMAN.MAJOR.MINOR` where:
181
+
182
+ * **HUMAN** is a memorable, human-readable name or word
183
+ * **MAJOR** indicates significant, potentially backward-incompatible changes
184
+ * **MINOR** denotes smaller, backward-compatible updates
185
+
186
+ == HashVer: Hash Versioning
187
+
188
+ [horizontal]
189
+ Format:: `YYYY.MM[.DD].HASH`
190
+ Status:: Reference Implementation
191
+ Proposed:: 2020 by miniscruff
192
+
193
+ === Description
194
+
195
+ HashVer is perfect for frequent publishing. The format consists of:
196
+
197
+ . Full year (YYYY)
198
+ . Zero-padded month (MM)
199
+ . [Optional] Zero-padded day (DD)
200
+ . 10+ characters of the current commit hash
201
+
202
+ Examples: `2024.01.67092445a1abc`, `2024.03.21.3731a8be0f1a8`
203
+
204
+ == GitDate
205
+
206
+ [horizontal]
207
+ Format:: `YYYY.MM.DD.gCOMMIT_HASH`
208
+ Status:: Reference Implementation
209
+ Proposed:: June 2022 by Taylor Brazelton
210
+
211
+ === Description
212
+
213
+ GitDate uses the commit date from a Git repository for clear tracking:
214
+
215
+ Examples: `2024.03.22.d31d336`, `2024.03.31.44cf59b1`
216
+
217
+ == PragVer: Pragmatic Versioning
218
+
219
+ [horizontal]
220
+ Format:: `BIGRELEASE.ANNOUNCE.INCREMENT`
221
+ Status:: Reference Implementation
222
+ Proposed:: December 2023 by Severin Ibarluzea
223
+
224
+ === Description
225
+
226
+ PragVer optimizes for communicating changes to package consumers:
227
+
228
+ * **BIGRELEASE** - Major updates or significant milestones
229
+ * **ANNOUNCE** - Notable announcements or changes
230
+ * **INCREMENT** - Smaller updates for every contribution
231
+
232
+ == BreakVer: Break Versioning
233
+
234
+ [horizontal]
235
+ Format:: `MAJOR.MINOR.NON-BREAKING[-QUALIFIER]`
236
+ Status:: Reference Implementation
237
+ Proposed:: August 2015 by Peter Taoussanis
238
+
239
+ === Description
240
+
241
+ BreakVer addresses SemVer complexity with a simpler format:
242
+
243
+ * **MAJOR** - Major breaking changes
244
+ * **MINOR** - Minor breaking changes
245
+ * **NON-BREAKING** - Strictly no breaking changes
246
+
247
+ == Explicit Versioning
248
+
249
+ [horizontal]
250
+ Format:: `DISRUPTIVE.INCOMPATIBLE.COMPATIBLE.FIX[-OPTIONAL]`
251
+ Status:: Reference Implementation
252
+ Proposed:: February 2017 by Paulo Renato
253
+
254
+ === Description
255
+
256
+ Explicit Versioning uses four identifiers to isolate intentional incompatible
257
+ releases from other types of releases, reducing ambiguity in interpretation.
258
+
259
+ == ZenVer: Zen Versioning
260
+
261
+ [horizontal]
262
+ Format:: `VERSION`
263
+ Status:: Reference Implementation
264
+ Proposed:: May 2024 by NotAShelf
265
+
266
+ === Description
267
+
268
+ ZenVer is revolutionary in its simplicity: number go up, software go new.
269
+ Increment VERSION when making any change.
270
+
271
+ == PVP: Package Versioning Policy
272
+
273
+ [horizontal]
274
+ Format:: `A.B.C`
275
+ Status:: Reference Implementation
276
+ Proposed:: 2006 for Haskell (Bulat Ziganshin)
277
+
278
+ === Description
279
+
280
+ PVP is designed for the Haskell ecosystem:
281
+
282
+ * `A.B` - Major version
283
+ * `C` - Minor version
284
+
285
+ Rules for incrementing are tied to API changes in the package.
286
+
287
+ == FloatVer: Floating Point Versioning
288
+
289
+ [horizontal]
290
+ Format:: `BREAKING.NONBREAKING`
291
+ Status:: Reference Implementation
292
+ Proposed:: July 2024 by Alex Shroyer
293
+
294
+ === Description
295
+
296
+ FloatVer uses IEEE754 32-bit floating point numbers:
297
+
298
+ * **BREAKING** - Incremented for backward-incompatible changes
299
+ * **NONBREAKING** - Incremented for backward-compatible changes
300
+
301
+ Examples: `0.7`, `290.10008`
302
+
303
+ == AsymptoVer
304
+
305
+ [horizontal]
306
+ Format:: `DECIMAL`
307
+ Status:: Reference Implementation
308
+ Popularized:: Donald Knuth (TeX, Metafont)
309
+
310
+ === Description
311
+
312
+ AsymptoVer uses decimal numbers that asymptotically approach an irrational number:
313
+
314
+ * TeX approaches π: 3, 3.1, 3.14, 3.141, 3.1415...
315
+ * Metafont approaches e: 2, 2.7, 2.71, 2.718...
316
+
317
+ == TrunkVer
318
+
319
+ [horizontal]
320
+ Format:: `YYYYMMDDHHMMSS.0.0-gCOMMIT_HASH-BUILD_REF`
321
+ Status:: Reference Implementation
322
+ Proposed:: May 2024 by Chris Klyk & Raimo Radczewski
323
+
324
+ === Description
325
+
326
+ TrunkVer is designed for trunk-based development:
327
+
328
+ * Timestamp: `YYYYMMDDHHMMSS` in UTC
329
+ * Commit Hash: `gCOMMIT_HASH`
330
+ * Build Ref: CI/CD reference
331
+
332
+ Ensures each build is uniquely identifiable and supports traceability.
333
+
334
+ == Declarative: Custom Schemes
335
+
336
+ [horizontal]
337
+ Format:: User-defined via YAML
338
+ Status:: Built-in
339
+
340
+ === Description
341
+
342
+ Versionian's Declarative scheme allows you to define custom versioning schemes using
343
+ YAML configuration with segment-based definitions. This approach provides:
344
+
345
+ * **No ReDoS vulnerabilities** - State machine parsing is immune to catastrophic backtracking
346
+ * **O(n) performance** - Single pass through the string
347
+ * **Declarative syntax** - Clear, readable component definitions
348
+ * **Type-aware parsing** - Each component type handles its own validation
349
+
350
+ [source,yaml]
351
+ ----
352
+ # my_scheme.yaml
353
+ name: my_app
354
+ type: declarative
355
+ description: MyApp versioning
356
+ components:
357
+ - name: major
358
+ type: integer
359
+ separator: "."
360
+ - name: minor
361
+ type: integer
362
+ separator: "."
363
+ - name: patch
364
+ type: integer
365
+ ----
366
+
367
+ [source,ruby]
368
+ ----
369
+ # Load and use the scheme
370
+ scheme = Versionian::SchemeLoader.from_yaml_file('my_scheme.yaml')
371
+ Versionian.register_scheme(:my_app, scheme)
372
+
373
+ version = scheme.parse("1.2.3")
374
+ puts version.major # => 1
375
+ ----
376
+
377
+ For more details, see link:../core-topics/declarative-schemes.html[Declarative Schemes].
378
+
379
+ == Composite: Multiple Format Support
380
+
381
+ [horizontal]
382
+ Format:: Multiple formats tried in order
383
+ Status:: Built-in
384
+
385
+ === Description
386
+
387
+ Composite schemes try multiple declarative schemes until one matches, supporting projects
388
+ that use different version formats in different contexts.
389
+
390
+ [source,yaml]
391
+ ----
392
+ name: multi_format
393
+ type: composite
394
+ fallback_scheme: semantic
395
+ schemes:
396
+ - name: with_patch
397
+ type: declarative
398
+ components:
399
+ - { name: major, type: integer, separator: "." }
400
+ - { name: minor, type: integer, separator: "." }
401
+ - { name: patch, type: integer, separator: "." }
402
+ - { name: patchlevel, type: integer }
403
+ - name: git_hash
404
+ type: declarative
405
+ components:
406
+ - { name: major, type: integer, separator: "." }
407
+ - { name: minor, type: integer, separator: "." }
408
+ - { name: patch, type: integer }
409
+ - { name: git_hash, type: hash, prefix: "-git", include_prefix_in_value: true }
410
+ ----
@@ -0,0 +1,119 @@
1
+ ---
2
+ layout: default
3
+ title: Getting Started
4
+ nav_order: 1
5
+ parent: Tutorials
6
+ ---
7
+
8
+ = Getting Started with Versionian
9
+
10
+ == Installation
11
+
12
+ Add Versionian to your Gemfile:
13
+
14
+ [source,ruby]
15
+ ----
16
+ gem 'versionian'
17
+ ----
18
+
19
+ Or install directly:
20
+
21
+ [source,shell]
22
+ ----
23
+ gem install versionian
24
+ ----
25
+
26
+ == Basic Usage
27
+
28
+ === Parsing Versions
29
+
30
+ [source,ruby]
31
+ ----
32
+ require 'versionian'
33
+
34
+ # Use built-in Semantic Versioning
35
+ scheme = Versionian.get_scheme(:semantic)
36
+ version = scheme.parse("1.12.0")
37
+
38
+ puts version.raw_string # => "1.12.0"
39
+ puts version.component(:major).value # => 1
40
+ puts version.component(:minor).value # => 12
41
+ puts version.component(:patch).value # => 0
42
+ ----
43
+
44
+ === Comparing Versions
45
+
46
+ [source,ruby]
47
+ ----
48
+ scheme = Versionian.get_scheme(:semantic)
49
+
50
+ v1 = scheme.parse("1.12.0")
51
+ v2 = scheme.parse("2.0.0")
52
+
53
+ result = v1 <=> v2
54
+ # => -1 (v1 is less than v2)
55
+
56
+ # Or use scheme comparison
57
+ result = scheme.compare("1.12.0", "2.0.0")
58
+ # => -1
59
+ ----
60
+
61
+ === Building Versions Programmatically
62
+
63
+ [source,ruby]
64
+ ----
65
+ scheme = Versionian.get_scheme(:semantic)
66
+
67
+ version = scheme.build(major: 1, minor: 12, patch: 0)
68
+ puts version.to_s # => "1.12.0"
69
+ ----
70
+
71
+ == Using different schemes
72
+
73
+ === Calendar Versioning
74
+
75
+ [source,ruby]
76
+ ----
77
+ scheme = Versionian.get_scheme(:calver)
78
+ version = scheme.parse("2024.03.22")
79
+
80
+ puts version.to_s # => "2024.03.22"
81
+ ----
82
+
83
+ === Custom declarative scheme
84
+
85
+ Create a custom scheme using YAML:
86
+
87
+ [source,yaml]
88
+ ----
89
+ # schemes/my_app.yaml
90
+ name: my_app
91
+ type: declarative
92
+ description: MyApp versioning
93
+ components:
94
+ - name: major
95
+ type: integer
96
+ separator: "."
97
+ - name: minor
98
+ type: integer
99
+ separator: "."
100
+ - name: patch
101
+ type: integer
102
+ ----
103
+
104
+ [source,ruby]
105
+ ----
106
+ # Load and use the scheme
107
+ scheme = Versionian::SchemeLoader.from_yaml_file('schemes/my_app.yaml')
108
+ Versionian.register_scheme(:my_app, scheme)
109
+
110
+ version = scheme.parse("1.2.3")
111
+ puts version.major # => 1
112
+ ----
113
+
114
+ == Next Steps
115
+
116
+ * link:../core-topics/schemes.html[Learn about version schemes]
117
+ * link:../core-topics/declarative-schemes.html[Create custom declarative schemes]
118
+ * link:../core-topics/range-matching.html[Use version range matching]
119
+ * link:../guides/custom-schemes.html[Build custom scheme classes]
@@ -0,0 +1,11 @@
1
+ ---
2
+ layout: default
3
+ title: Overview
4
+ nav_order: 1
5
+ ---
6
+
7
+ = Tutorials
8
+
9
+ Step-by-step guides for learning Versionian.
10
+
11
+ * link:getting-started.html[Getting Started] - Quick introduction to Versionian