sycersion 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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.sycersion/environment.yml +3 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +121 -0
- data/LICENSE.txt +21 -0
- data/README.md +133 -0
- data/Rakefile +13 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/sycersion +9 -0
- data/lib/sycersion/options.rb +96 -0
- data/lib/sycersion/semver.rb +40 -0
- data/lib/sycersion/version.rb +5 -0
- data/lib/sycersion/version_compare.rb +90 -0
- data/lib/sycersion/version_environment.rb +169 -0
- data/lib/sycersion/version_incrementer.rb +40 -0
- data/lib/sycersion/version_info.rb +20 -0
- data/lib/sycersion/version_setter.rb +38 -0
- data/lib/sycersion.rb +57 -0
- data/man/sycersion.1 +184 -0
- data/man/sycersion.1.html +211 -0
- data/man/sycersion.1.ronn +114 -0
- data/notes/design.md +2 -0
- data/notes/setup.md +106 -0
- data/notes/versioning.md +167 -0
- data/sycersion.gemspec +45 -0
- metadata +129 -0
@@ -0,0 +1,169 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module Sycersion
|
7
|
+
SYCERSION_DIR = '.sycersion'
|
8
|
+
SYCERSION_ENV = '.sycersion/environment.yml'
|
9
|
+
SYCERSION_VER = '.sycersion/version'
|
10
|
+
|
11
|
+
# Creates a version and a version file where the version is stored to.
|
12
|
+
class VersionEnvironment
|
13
|
+
attr_accessor :version
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
return if load_environment
|
17
|
+
|
18
|
+
determine_version_and_version_file
|
19
|
+
end
|
20
|
+
|
21
|
+
def setup
|
22
|
+
puts "\nSetup the version environment"
|
23
|
+
puts "=============================\n"
|
24
|
+
prompt_version_and_version_file
|
25
|
+
create_environment
|
26
|
+
summary
|
27
|
+
end
|
28
|
+
|
29
|
+
def summary
|
30
|
+
summary_of_configuration
|
31
|
+
summary_of_environment
|
32
|
+
end
|
33
|
+
|
34
|
+
def summary_of_configuration
|
35
|
+
puts "\nYour configuration"
|
36
|
+
puts "------------------\n"
|
37
|
+
puts "\nVersion #{@version}"
|
38
|
+
puts "Version-file #{@version_file}\n"
|
39
|
+
puts create_code_snippet(@version_file)
|
40
|
+
end
|
41
|
+
|
42
|
+
def summary_of_environment
|
43
|
+
puts "\nWhere to find the configuration files"
|
44
|
+
puts "-------------------------------------\n"
|
45
|
+
puts "\nDirectory: #{SYCERSION_DIR}"
|
46
|
+
puts "Configuration file: #{SYCERSION_ENV}\n"
|
47
|
+
puts "\nChange the configuration file only if you know what you are doing."
|
48
|
+
puts 'Otherwise run `sycersion --init` again.'
|
49
|
+
end
|
50
|
+
|
51
|
+
def determine_version_and_version_file
|
52
|
+
files = Dir.glob('**/*version*')
|
53
|
+
files.each do |file|
|
54
|
+
File.readlines(file, chomp: true).each do |line|
|
55
|
+
scan_result = line.scan(Sycersion::SEMVER_LAX_REGEX)
|
56
|
+
if scan_result[0]
|
57
|
+
@version_files[file] = [scan_result[0], line]
|
58
|
+
break
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def prompt_version_and_version_file
|
65
|
+
if File.exist?(SYCERSION_VER)
|
66
|
+
resume_version_and_version_file
|
67
|
+
elsif @version_files.empty?
|
68
|
+
define_version_and_version_file
|
69
|
+
else
|
70
|
+
select_version_and_version_file
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def resume_version_and_version_file
|
75
|
+
print "Current version-file #{@version_file}. To keep hit RETURN otherwise specify new: "
|
76
|
+
selection = gets.chomp
|
77
|
+
@version_file = selection.empty? ? @version_file : selection
|
78
|
+
print "Current version #{@version}. To keep hit RETURN otherwise enter new: "
|
79
|
+
selection = gets.chomp
|
80
|
+
@version = selection.empty? ? @version : selection
|
81
|
+
end
|
82
|
+
|
83
|
+
def define_version_and_version_file
|
84
|
+
puts 'No version and version-file found'
|
85
|
+
print "To use #{SYCERSION_VER} hit RETURN or specify own file: "
|
86
|
+
selection = gets.chomp
|
87
|
+
@version_file = selection.empty? ? SYCERSION_VER : selection
|
88
|
+
print 'To use `0.0.1` as initial version hit RETURN or specify own version: '
|
89
|
+
selection = gets.chomp.scan(Sycersion::SEMVER_REGEX)
|
90
|
+
@version = selection.empty? ? @version : selection
|
91
|
+
@version_string = @version
|
92
|
+
end
|
93
|
+
|
94
|
+
def select_version_and_version_file
|
95
|
+
puts "\nFound version-files\n"
|
96
|
+
puts "-------------------\n"
|
97
|
+
list_versions_and_version_files
|
98
|
+
print "\nChoose version-file and version with number or hit return for [0]: "
|
99
|
+
selection = gets.chomp.to_i
|
100
|
+
app_version_file = @version_files.keys[selection]
|
101
|
+
@version = Sycersion::Semver.version(@version_files[app_version_file][0])
|
102
|
+
@version_string = @version_files[@version_file[1]]
|
103
|
+
end
|
104
|
+
|
105
|
+
def list_versions_and_version_files
|
106
|
+
digits = digit_counter(@version_files)
|
107
|
+
filler = filler_string(' ', digits + 2)
|
108
|
+
@version_files.each_with_index do |entry, index|
|
109
|
+
choice = "[#{index.to_s.rjust(digits, ' ')}]"
|
110
|
+
print_line(choice, 'file: ', entry[0])
|
111
|
+
print_line(filler, 'version:', Sycersion::Semver.version(entry[1][0]))
|
112
|
+
print_line(filler, 'line: ', (entry[1][1]).strip)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def digit_counter(object)
|
117
|
+
object.size.to_s.length
|
118
|
+
end
|
119
|
+
|
120
|
+
def filler_string(fill_char, size)
|
121
|
+
fill_char * size
|
122
|
+
end
|
123
|
+
|
124
|
+
def print_line(prescriptor, descriptor, value)
|
125
|
+
puts "#{prescriptor} #{descriptor} #{value}"
|
126
|
+
end
|
127
|
+
|
128
|
+
def create_code_snippet(version_file)
|
129
|
+
<<-CODE_SNIP
|
130
|
+
|
131
|
+
In your application you can now access the version with
|
132
|
+
|
133
|
+
> File.read(#{version_file})
|
134
|
+
|
135
|
+
If you application framework has a defined place to assign
|
136
|
+
the version you could do like so
|
137
|
+
|
138
|
+
> version = File.read(#{version_file})
|
139
|
+
CODE_SNIP
|
140
|
+
end
|
141
|
+
|
142
|
+
def save
|
143
|
+
create_environment
|
144
|
+
end
|
145
|
+
|
146
|
+
def create_environment
|
147
|
+
FileUtils.mkdir(SYCERSION_DIR) unless Dir.exist?(SYCERSION_DIR)
|
148
|
+
File.open(@version_file, 'w') { |f| f.write(@version) }
|
149
|
+
File.open(SYCERSION_ENV, 'w') do |f|
|
150
|
+
YAML.dump([@version_file, @version], f)
|
151
|
+
end
|
152
|
+
rescue IOError => e
|
153
|
+
puts e.message
|
154
|
+
end
|
155
|
+
|
156
|
+
def load_environment
|
157
|
+
if File.exist?(SYCERSION_ENV)
|
158
|
+
@version_file, @version = YAML.load_file(SYCERSION_ENV)
|
159
|
+
true
|
160
|
+
else
|
161
|
+
@version_file = SYCERSION_VER
|
162
|
+
@version = '0.1.0'
|
163
|
+
@version_files = {}
|
164
|
+
@version_string = ''
|
165
|
+
false
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sycersion
|
4
|
+
NORMAL_REGEX = /^(\d+)\.(\d+)\.(\d+)/.freeze
|
5
|
+
|
6
|
+
# Increments the elements of a semantic version number major, minor, patch
|
7
|
+
class VersionIncrementer
|
8
|
+
def initialize
|
9
|
+
@environment = Sycersion::VersionEnvironment.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def increment(position)
|
13
|
+
@environment.version = case position
|
14
|
+
when :major
|
15
|
+
increment_major
|
16
|
+
when :minor
|
17
|
+
increment_minor
|
18
|
+
when :patch
|
19
|
+
increment_patch
|
20
|
+
end
|
21
|
+
@environment.save
|
22
|
+
end
|
23
|
+
|
24
|
+
def increment_major
|
25
|
+
"#{current_version[0].to_i + 1}.0.0"
|
26
|
+
end
|
27
|
+
|
28
|
+
def increment_minor
|
29
|
+
"#{current_version[0]}.#{current_version[1].to_i + 1}.0"
|
30
|
+
end
|
31
|
+
|
32
|
+
def increment_patch
|
33
|
+
"#{current_version[0]}.#{current_version[1]}.#{current_version[2].to_i + 1}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def current_version
|
37
|
+
@environment.version.scan(NORMAL_REGEX).flatten
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Managing the application's version according semver
|
4
|
+
module Sycersion
|
5
|
+
# Provides information about the `sycersion` settings and the current version
|
6
|
+
class VersionInfo
|
7
|
+
def initialize
|
8
|
+
@environment = Sycersion::VersionEnvironment.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def process(options)
|
12
|
+
case options[:info]
|
13
|
+
when :version
|
14
|
+
print @environment.version
|
15
|
+
when :summary
|
16
|
+
@environment.summary
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sycersion
|
4
|
+
# Sets the version
|
5
|
+
class VersionSetter
|
6
|
+
def initialize
|
7
|
+
@environment = Sycersion::VersionEnvironment.new
|
8
|
+
end
|
9
|
+
|
10
|
+
# Sets the version provided by the version array. The version array is in
|
11
|
+
# the form ["version", "major", "minor", "patch", "pre-release", "build"]
|
12
|
+
def version=(version)
|
13
|
+
@environment.version = version[0]
|
14
|
+
@environment.save
|
15
|
+
end
|
16
|
+
|
17
|
+
# Sets the pre-release part only. The pre-release parameter is of the form
|
18
|
+
# ["pre-release", "pre-release"]
|
19
|
+
def pre_release=(pre_release)
|
20
|
+
create_version(3, pre_release[0])
|
21
|
+
end
|
22
|
+
|
23
|
+
# Sets the build part only. The build parameter is of the form
|
24
|
+
# ["build", "build"]
|
25
|
+
def build=(build)
|
26
|
+
create_version(4, build[0])
|
27
|
+
end
|
28
|
+
|
29
|
+
# Helper method for build= and pre_release=
|
30
|
+
def create_version(position, value)
|
31
|
+
version = @environment.version
|
32
|
+
semver_array = version.scan(Sycersion::SEMVER_REGEX).flatten
|
33
|
+
semver_array[position] = value
|
34
|
+
@environment.version = Sycersion::Semver.version(semver_array)
|
35
|
+
@environment.save
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/sycersion.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'sycersion/version'
|
4
|
+
require_relative 'sycersion/options'
|
5
|
+
require_relative 'sycersion/version_environment'
|
6
|
+
require_relative 'sycersion/version_setter'
|
7
|
+
require_relative 'sycersion/version_incrementer'
|
8
|
+
require_relative 'sycersion/version_info'
|
9
|
+
require_relative 'sycersion/version_compare'
|
10
|
+
require_relative 'sycersion/semver'
|
11
|
+
|
12
|
+
module Sycersion
|
13
|
+
class Error < StandardError; end
|
14
|
+
|
15
|
+
# Runs the program based on the arguments provided at the commandline
|
16
|
+
class Runner
|
17
|
+
def initialize(argv)
|
18
|
+
@options = Options.new(argv).options
|
19
|
+
pp @options if ENV['SYC_DEBUG']
|
20
|
+
end
|
21
|
+
|
22
|
+
def run
|
23
|
+
environment_settings
|
24
|
+
version_manipulation
|
25
|
+
version_compare
|
26
|
+
configuration_information
|
27
|
+
end
|
28
|
+
|
29
|
+
def environment_settings
|
30
|
+
Sycersion::VersionEnvironment.new.setup if @options[:init]
|
31
|
+
end
|
32
|
+
|
33
|
+
def version_manipulation
|
34
|
+
case @options.keys
|
35
|
+
when [:set]
|
36
|
+
Sycersion::VersionSetter.new.version = (@options[:set])
|
37
|
+
when [:pre_release]
|
38
|
+
Sycersion::VersionSetter.new.pre_release = (@options[:pre_release])
|
39
|
+
when [:build]
|
40
|
+
Sycersion::VersionSetter.new.build = (@options[:build])
|
41
|
+
when [:inc]
|
42
|
+
Sycersion::VersionIncrementer.new.increment(@options[:inc])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def version_compare
|
47
|
+
return unless @options[:compare]
|
48
|
+
|
49
|
+
@options[:compare].shift
|
50
|
+
puts Sycersion::VersionCompare.new.compare(@options[:compare])
|
51
|
+
end
|
52
|
+
|
53
|
+
def configuration_information
|
54
|
+
puts Sycersion::VersionInfo.new.process(@options) if @options[:info]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/man/sycersion.1
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
.\" generated with Ronn/v0.7.3
|
2
|
+
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
3
|
+
.
|
4
|
+
.TH "SYCERSION" "1" "January 2025" "" ""
|
5
|
+
.
|
6
|
+
.SH "NAME"
|
7
|
+
\fBsycersion\fR \- manage application versions according to semantic versioning
|
8
|
+
.
|
9
|
+
.SH "SYNOPSIS"
|
10
|
+
.
|
11
|
+
.nf
|
12
|
+
|
13
|
+
`sycersion` `\-\-init`
|
14
|
+
`sycersion` `\-i`|`\-\-info`
|
15
|
+
`sycersion` `\-\-inc major|minor|patch`
|
16
|
+
`sycersion` `\-\-set major\.minor\.patch[+build|\-pre\-release+build]`
|
17
|
+
`sycersion` `\-p`|`\-\-pre` `pre\-release`
|
18
|
+
`sycersion` `\-b`|`\-\-build` `build`
|
19
|
+
`sycersion` `\-c`|`\-\-compare` `version`
|
20
|
+
`sycersion` `\-h`|`\-\-help`
|
21
|
+
.
|
22
|
+
.fi
|
23
|
+
.
|
24
|
+
.SH "Description"
|
25
|
+
\fBsycersion\fR is a command\-line tool to manage application versions following the guiding principles of \fIsemantic versioning\fR found at semver\.org \fIhttps://semver\.org\fR\.
|
26
|
+
.
|
27
|
+
.P
|
28
|
+
\fBsycersion\fR has a default start version of 0\.1\.0\. This can be activitated with the initalization running \fBsycersion \-\-init\fR\. During this intialization another version can be chosen\. The version is saved to the \fIversion\-file\fR and also the \fIconfiguration\-directory\fR is created\. While initialization \fBsycersion\fR additionally searches for files that contain a version according to semantic versioning and the user can select out of the list of files which version out of that files to intially start with\.
|
29
|
+
.
|
30
|
+
.P
|
31
|
+
The \fIversion\-file\fR and \fIconfiguration\-directory\fR are also created it the user is setting an initial version with \fBsycersion \-\-set 0\.1\.1\fR\.
|
32
|
+
.
|
33
|
+
.P
|
34
|
+
If the version is updated the version is written into the \fIversion\-file\fR\. Within the application the version can be read from the file and displayed somewhere in the application\'s UI\.
|
35
|
+
.
|
36
|
+
.P
|
37
|
+
\fBsycersion\fR evaluates version numbers provided that they comply to semantic versioning\.
|
38
|
+
.
|
39
|
+
.P
|
40
|
+
If \fBsycersion\fR is used within a \fIRuby\fR application, it can be added to the development section within the Gemfile\.
|
41
|
+
.
|
42
|
+
.SH "FILES"
|
43
|
+
.
|
44
|
+
.nf
|
45
|
+
|
46
|
+
`\.sycersion` is the configuration directory
|
47
|
+
`\.sycersion/environment\.yml` holds the version file and the version
|
48
|
+
`\.sycersion/version` contains the version
|
49
|
+
.
|
50
|
+
.fi
|
51
|
+
.
|
52
|
+
.SH "OPTIONS"
|
53
|
+
.
|
54
|
+
.IP "\(bu" 4
|
55
|
+
\fB\-\-init\fR Initializes the \fBsycersion\fR environment with \fIversion\fR and \fIversion\-file\fR
|
56
|
+
.
|
57
|
+
.IP "\(bu" 4
|
58
|
+
\fB\-i\fR, \fB\-\-info VERSION|SUMMARY\fR Shows the current \fIversion\fR (default) or additionally information about the \fIversion\-file\fR, the \fIconfiguration\-directory\fR and \fIcode\fR how to read the version within an application\.
|
59
|
+
.
|
60
|
+
.IP "\(bu" 4
|
61
|
+
\fB\-\-inc MAJOR|MINOR|PATCH\fR increments the major, minor, patch part of the version\.
|
62
|
+
.
|
63
|
+
.IP "\(bu" 4
|
64
|
+
\fB\-\-set MAJOR\.MINOR\.PATCH[+BUILD|\-PRE_RELEASE[+BUILD]]\fR sets the version where all three version parts need to be provided, major\.minor\.patch with optionally adding a pre\-release part and/or a build part\.
|
65
|
+
.
|
66
|
+
.IP "\(bu" 4
|
67
|
+
\fB\-\-pre PRE\-RELEASE\fR Set the pre\-release part in the version
|
68
|
+
.
|
69
|
+
.IP "\(bu" 4
|
70
|
+
\fB\-\-build BUILD\fR Set the build part in the version
|
71
|
+
.
|
72
|
+
.IP "\(bu" 4
|
73
|
+
\fB\-c\fR, \fB\-\-compare VERSION\fR Compares the current version with the version provided following the semver precedence guidline
|
74
|
+
.
|
75
|
+
.IP "\(bu" 4
|
76
|
+
\fB\-\-help\fR Prints the command line help
|
77
|
+
.
|
78
|
+
.IP "" 0
|
79
|
+
.
|
80
|
+
.SH "EXAMPLES"
|
81
|
+
Initialize \fBsycersion\fR
|
82
|
+
.
|
83
|
+
.IP "" 4
|
84
|
+
.
|
85
|
+
.nf
|
86
|
+
|
87
|
+
$ sycersion \-\-init
|
88
|
+
.
|
89
|
+
.fi
|
90
|
+
.
|
91
|
+
.IP "" 0
|
92
|
+
.
|
93
|
+
.P
|
94
|
+
Set the version with pre\-release
|
95
|
+
.
|
96
|
+
.IP "" 4
|
97
|
+
.
|
98
|
+
.nf
|
99
|
+
|
100
|
+
$ sycersion \-\-set 0\.1\.1\-beta\.1\.0
|
101
|
+
.
|
102
|
+
.fi
|
103
|
+
.
|
104
|
+
.IP "" 0
|
105
|
+
.
|
106
|
+
.P
|
107
|
+
Set the version with a build
|
108
|
+
.
|
109
|
+
.IP "" 4
|
110
|
+
.
|
111
|
+
.nf
|
112
|
+
|
113
|
+
$ sycersion \-\-set 0\.1\.1+build\-a\.1
|
114
|
+
.
|
115
|
+
.fi
|
116
|
+
.
|
117
|
+
.IP "" 0
|
118
|
+
.
|
119
|
+
.P
|
120
|
+
Set the version with a pre\-release and a build
|
121
|
+
.
|
122
|
+
.IP "" 4
|
123
|
+
.
|
124
|
+
.nf
|
125
|
+
|
126
|
+
$ sycersion \-\-set 0\.1\.1\-beta\.1\.0+build\-a\.1
|
127
|
+
.
|
128
|
+
.fi
|
129
|
+
.
|
130
|
+
.IP "" 0
|
131
|
+
.
|
132
|
+
.P
|
133
|
+
Show the current version
|
134
|
+
.
|
135
|
+
.IP "" 4
|
136
|
+
.
|
137
|
+
.nf
|
138
|
+
|
139
|
+
$ sycersion \-i
|
140
|
+
0\.1\.1\-beta\.1\.0+build\-a\.1
|
141
|
+
.
|
142
|
+
.fi
|
143
|
+
.
|
144
|
+
.IP "" 0
|
145
|
+
.
|
146
|
+
.P
|
147
|
+
Increment minor part of the version 0\.1\.1, which will lead to 0\.2\.0
|
148
|
+
.
|
149
|
+
.IP "" 4
|
150
|
+
.
|
151
|
+
.nf
|
152
|
+
|
153
|
+
$ sycersion \-\-inc minor
|
154
|
+
$ sycersion \-i
|
155
|
+
0\.2\.0
|
156
|
+
.
|
157
|
+
.fi
|
158
|
+
.
|
159
|
+
.IP "" 0
|
160
|
+
.
|
161
|
+
.P
|
162
|
+
When increasing one of major, minor or patch, the subsequent numbers are eather reset to 0 or pre\-release and build are removed\.
|
163
|
+
.
|
164
|
+
.P
|
165
|
+
Compare the assumed current version 0\.1\.1 to the provided version
|
166
|
+
.
|
167
|
+
.IP "" 4
|
168
|
+
.
|
169
|
+
.nf
|
170
|
+
|
171
|
+
$ sycersion \-c 0\.1\.1\-alpha
|
172
|
+
0\.1\.1 > 0\.1\.1\-alpha
|
173
|
+
.
|
174
|
+
.fi
|
175
|
+
.
|
176
|
+
.IP "" 0
|
177
|
+
.
|
178
|
+
.SH "ENVIRONMENT"
|
179
|
+
.
|
180
|
+
.IP "\(bu" 4
|
181
|
+
SYC_DEBUG=true Will display erros and show contents of the parsed options\. To be called as \fBSYC_DEBUG=true sycersion [options]\fR
|
182
|
+
.
|
183
|
+
.IP "" 0
|
184
|
+
|