git_toolbox 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/get/commons/git.rb +11 -1
- data/lib/get/subcommand/complete/bash_completion.rb +5 -0
- data/lib/get/subcommand/complete/complete.rb +22 -6
- data/lib/get/subcommand/describe/change.rb +23 -4
- data/lib/get/subcommand/describe/describe.rb +3 -47
- data/lib/get/subcommand/describe/prerelease.rb +28 -9
- data/lib/get/subcommand/init/init.rb +1 -1
- data/lib/get/subcommand/tree/tree.rb +13 -6
- data/lib/get/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d18e02ebf90eb2595af4735f88043d1fdea653a03d8500dec75a7cf9a510bc51
|
4
|
+
data.tar.gz: c0344b2969623ab61aa94c6960fa88bdad522057541ece00052bfdf9f4cbf636
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9cbe2abd8b068d78436841419dddd776f72e97b57a5575f8447ae31e7744d8a7e54de9eaa55a242ff0c177b52a1f81b74309b044970c12ccaf98f4dc7d431d4
|
7
|
+
data.tar.gz: 9248e4bcce0371b73542e336591bc6844ac8a66f6d93334702fa0e7fbb2b13556c6d914682d9e8f62e964f5eb8aee6462bd4ebe739c4881effe69241c141ca1a
|
data/lib/get/commons/git.rb
CHANGED
@@ -23,6 +23,15 @@ require_relative './command_issuer'
|
|
23
23
|
module Git
|
24
24
|
# Groups: 1 = type, 2 = scope with (), 3 = scope, 4 = breaking change, 5 = summary
|
25
25
|
CONVENTIONAL_COMMIT_REGEX = %r{^(\w+)(\(([\w/-]+)\))?(!)?:(.*)}
|
26
|
+
DEFAULT_RELEASE_VERSION = '0.1.0'
|
27
|
+
# Groups:
|
28
|
+
# 1 = full stable version ; 2,3,4 = major,minor,patch
|
29
|
+
# 5 = prerelease ; 6 = metadata
|
30
|
+
FULL_SEMANTIC_VERSION_REGEX = /
|
31
|
+
^((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)) # Stable version, major, minor, patch
|
32
|
+
(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))? # prerelease
|
33
|
+
(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ # metadata
|
34
|
+
/x
|
26
35
|
|
27
36
|
# Check if the command is called while in a git repository.
|
28
37
|
# If the command fails, it is assumed to not be in a git repository.
|
@@ -61,11 +70,12 @@ module Git
|
|
61
70
|
# Returns the last release and caches it for the next calls.
|
62
71
|
def self.last_release
|
63
72
|
@last_release ||=
|
64
|
-
CommandIssuer.run('git', '--no-pager', 'tag', '--list')
|
73
|
+
CommandIssuer.run('git', '--no-pager', 'tag', '--list', '--merged')
|
65
74
|
.then do |value|
|
66
75
|
unless value.output.empty?
|
67
76
|
value.output
|
68
77
|
.split("\n")
|
78
|
+
.select { |str| str.match(FULL_SEMANTIC_VERSION_REGEX)[5].nil? }
|
69
79
|
.map { |str| str.sub('+', '_') }
|
70
80
|
.sort
|
71
81
|
.map { |str| str.sub('_', '+') }
|
@@ -28,6 +28,10 @@ module BashCompletion
|
|
28
28
|
private
|
29
29
|
|
30
30
|
INITIAL_LEVEL = 1
|
31
|
+
NOT_NEGABLE_OPTIONS = [
|
32
|
+
'help',
|
33
|
+
'version',
|
34
|
+
].freeze
|
31
35
|
|
32
36
|
HEADER = <<~HEADER
|
33
37
|
#!/usr/bin/env bash
|
@@ -77,6 +81,7 @@ module BashCompletion
|
|
77
81
|
|
78
82
|
command_class.instance.option_parser.specs.each_value do |option|
|
79
83
|
long_options.push("--#{option.long}")
|
84
|
+
long_options.push("--no-#{option.long}") if option.flag? && !NOT_NEGABLE_OPTIONS.include?(option.long)
|
80
85
|
short_options.push("-#{option.short.nil? ? option.long[0] : option.short}") if option.short != :none
|
81
86
|
end
|
82
87
|
|
@@ -33,8 +33,18 @@ class Complete < Command
|
|
33
33
|
def initialize
|
34
34
|
super() do
|
35
35
|
@usage = 'complete -h|(<subcommand> [<subcommand-options])'
|
36
|
-
@description = 'Print the shell completion script.'
|
36
|
+
@description = 'Print the shell completion script. ' \
|
37
|
+
'Run \'get complete --info\' to learn how to install the completion.'
|
37
38
|
@subcommands = {}
|
39
|
+
@completions = {
|
40
|
+
bash: {
|
41
|
+
generator: proc { bash_completion(Get, 'get') },
|
42
|
+
info: <<~INFO
|
43
|
+
Add the following line to your .bashrc (or a sourced script):
|
44
|
+
eval "$(get complete)" && complete -F _get_completion get
|
45
|
+
INFO
|
46
|
+
}
|
47
|
+
}
|
38
48
|
end
|
39
49
|
end
|
40
50
|
|
@@ -51,6 +61,9 @@ class Complete < Command
|
|
51
61
|
opt :shell,
|
52
62
|
'Select the type of shell of which the completion will be generated.',
|
53
63
|
{ type: :string, default: 'bash' }
|
64
|
+
opt :info,
|
65
|
+
'Print the instructions to install the completion for the selected shell.',
|
66
|
+
{ short: :none }
|
54
67
|
educate_on_error
|
55
68
|
stop_on stop_condition
|
56
69
|
end
|
@@ -62,16 +75,19 @@ class Complete < Command
|
|
62
75
|
@option_parser.parse
|
63
76
|
end
|
64
77
|
|
65
|
-
@completions = {
|
66
|
-
bash: proc { bash_completion(Get, 'get') }
|
67
|
-
}
|
68
|
-
|
69
78
|
selected_shell = @options[:shell].to_sym
|
70
79
|
|
80
|
+
print_info_and_exit(selected_shell) if @options[:info]
|
81
|
+
|
71
82
|
Common.error "Completion for shell '#{selected_shell}' not available." unless @completions.key?(selected_shell)
|
72
83
|
|
73
|
-
puts @completions[selected_shell].call
|
84
|
+
puts @completions[selected_shell][:generator].call
|
74
85
|
end
|
75
86
|
end
|
87
|
+
|
88
|
+
def print_info_and_exit(selected_shell)
|
89
|
+
puts @completions[selected_shell][:info]
|
90
|
+
exit 0
|
91
|
+
end
|
76
92
|
end
|
77
93
|
# rubocop:enable Metrics/ClassLength
|
@@ -30,6 +30,27 @@ module ChangeHandler
|
|
30
30
|
Common.module_instance_attr(self, 'minor_trigger', :DEFAULT_MINOR_TRIGGER)
|
31
31
|
Common.module_instance_attr(self, 'patch_trigger', :DEFAULT_PATCH_TRIGGER)
|
32
32
|
|
33
|
+
def updated_stable_version(stable_version)
|
34
|
+
return Git::DEFAULT_RELEASE_VERSION if stable_version.nil?
|
35
|
+
|
36
|
+
greatest_change_from_stable_version = Git.with_commit_list_from(stable_version) do |commits_from_version|
|
37
|
+
greatest_change_in(commits_from_version)
|
38
|
+
end
|
39
|
+
split_version = stable_version.split('.')
|
40
|
+
case greatest_change_from_stable_version
|
41
|
+
when :MAJOR
|
42
|
+
"#{split_version[0].to_i + 1}.0.0"
|
43
|
+
when :MINOR
|
44
|
+
"#{split_version[0].to_i}.#{split_version[1].to_i + 1}.0"
|
45
|
+
when :PATCH
|
46
|
+
"#{split_version[0].to_i}.#{split_version[1].to_i}.#{split_version[2].to_i + 1}"
|
47
|
+
else
|
48
|
+
"#{split_version[0].to_i}.#{split_version[1].to_i}.#{split_version[2].to_i}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
33
54
|
def greatest_change_in(commit_list)
|
34
55
|
commit_list
|
35
56
|
.grep(Git::CONVENTIONAL_COMMIT_REGEX)
|
@@ -37,8 +58,6 @@ module ChangeHandler
|
|
37
58
|
.max { |a, b| CHANGE_TYPE.index(a) <=> CHANGE_TYPE.index(b) }
|
38
59
|
end
|
39
60
|
|
40
|
-
private
|
41
|
-
|
42
61
|
# In this block method arguments can be used by user.
|
43
62
|
# Also `eval` is needed to allow users to define their custom triggers.
|
44
63
|
# rubocop:disable Lint/UnusedMethodArgument
|
@@ -61,8 +80,8 @@ module ChangeHandler
|
|
61
80
|
def to_change(commit_message)
|
62
81
|
groups = Git::CONVENTIONAL_COMMIT_REGEX.match(commit_message)
|
63
82
|
return :MAJOR if triggers_major?(groups[1], groups[3], !groups[4].nil?)
|
64
|
-
return :MINOR if triggers_minor?(groups[1], groups[
|
65
|
-
return :PATCH if triggers_patch?(groups[1], groups[
|
83
|
+
return :MINOR if triggers_minor?(groups[1], groups[3])
|
84
|
+
return :PATCH if triggers_patch?(groups[1], groups[3])
|
66
85
|
|
67
86
|
:NONE
|
68
87
|
end
|
@@ -38,13 +38,6 @@ class Describe < Command
|
|
38
38
|
include PrereleaseHandler
|
39
39
|
include MetadataHandler
|
40
40
|
|
41
|
-
DEFAULT_RELEASE_VERSION = '0.1.0'
|
42
|
-
FULL_SEMANTIC_VERSION_REGEX = /
|
43
|
-
^((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)) # Stable version, major, minor, patch
|
44
|
-
(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))? # prerelease
|
45
|
-
(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ # metadata
|
46
|
-
/x
|
47
|
-
|
48
41
|
def initialize
|
49
42
|
super() do
|
50
43
|
@usage = 'describe -h|(<subcommand> [<subcommand-options])'
|
@@ -84,50 +77,13 @@ class Describe < Command
|
|
84
77
|
|
85
78
|
def next_release
|
86
79
|
if @options[:prerelease]
|
87
|
-
|
80
|
+
updated_stable_version(Git.last_release)
|
81
|
+
.then { |stable| "#{stable}-#{updated_prerelease(Git.last_version, stable)}" }
|
88
82
|
else
|
89
|
-
|
83
|
+
updated_stable_version(Git.last_release).to_s
|
90
84
|
end + metadata
|
91
85
|
end
|
92
86
|
|
93
|
-
def prepare_release_tag(last_release)
|
94
|
-
updated_stable_version(last_release).to_s
|
95
|
-
end
|
96
|
-
|
97
|
-
def prepare_prerelease_tag(last_release, last_version)
|
98
|
-
new_stable_version = updated_stable_version(last_release)
|
99
|
-
base_version_match_data = FULL_SEMANTIC_VERSION_REGEX.match(last_version)
|
100
|
-
no_changes_from_last_release = base_version_match_data[1] == new_stable_version && base_version_match_data[5].nil?
|
101
|
-
Common.error 'No changes from last release' if no_changes_from_last_release
|
102
|
-
new_stable_version +
|
103
|
-
"-#{updated_prerelease(base_version_match_data[5], need_reset: base_version_match_data[1] != new_stable_version)}"
|
104
|
-
end
|
105
|
-
|
106
|
-
def updated_stable_version(stable_version)
|
107
|
-
return DEFAULT_RELEASE_VERSION if stable_version.nil?
|
108
|
-
|
109
|
-
greatest_change_from_stable_version = Git.with_commit_list_from(stable_version) do |commits_from_version|
|
110
|
-
greatest_change_in(commits_from_version)
|
111
|
-
end
|
112
|
-
split_version = stable_version.split('.')
|
113
|
-
case greatest_change_from_stable_version
|
114
|
-
when :MAJOR
|
115
|
-
"#{split_version[0].to_i + 1}.0.0"
|
116
|
-
when :MINOR
|
117
|
-
"#{split_version[0].to_i}.#{split_version[1].to_i + 1}.0"
|
118
|
-
when :PATCH
|
119
|
-
"#{split_version[0].to_i}.#{split_version[1].to_i}.#{split_version[2].to_i + 1}"
|
120
|
-
else
|
121
|
-
"#{split_version[0].to_i}.#{split_version[1].to_i}.#{split_version[2].to_i}"
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
# Return the updated prerelease number
|
126
|
-
def updated_prerelease(prerelease = nil, need_reset: false)
|
127
|
-
compute_prerelease(prerelease, need_reset: prerelease.nil? || need_reset)
|
128
|
-
end
|
129
|
-
|
130
|
-
# Compute the metadata string
|
131
87
|
def metadata
|
132
88
|
return '' if @options[:exclude_metadata] || @options[:metadata].empty?
|
133
89
|
|
@@ -27,20 +27,31 @@ module PrereleaseHandler
|
|
27
27
|
Common.module_instance_attr(self, 'prerelease_pattern', :DEFAULT_PRERELEASE_PATTERN)
|
28
28
|
Common.module_instance_attr(self, 'old_prerelease_pattern', 'proc { prerelease_pattern }')
|
29
29
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
30
|
+
def updated_prerelease(last_version, new_stable_version)
|
31
|
+
if last_version.nil?
|
32
|
+
compute_prerelease(nil, need_reset: true)
|
33
|
+
else
|
34
|
+
base_version_match_data = Git::FULL_SEMANTIC_VERSION_REGEX.match(last_version)
|
35
|
+
no_changes_from_last_release = base_version_match_data[1] == new_stable_version &&
|
36
|
+
base_version_match_data[5].nil?
|
37
|
+
Common.error 'No changes from last release' if no_changes_from_last_release
|
38
|
+
compute_prerelease(base_version_match_data[5], need_reset: base_version_match_data[1] != new_stable_version)
|
39
|
+
end
|
33
40
|
end
|
34
41
|
|
35
42
|
private
|
36
43
|
|
44
|
+
def compute_prerelease(current_prerelease, need_reset: false)
|
45
|
+
pattern_changed = PrereleaseHandler.prerelease_pattern != actual_old_prerelease_pattern
|
46
|
+
new_prerelease = if need_reset || pattern_changed
|
47
|
+
FIRST_PRERELEASE
|
48
|
+
else
|
49
|
+
extract_prerelease_number(current_prerelease) + 1
|
50
|
+
end.to_s
|
51
|
+
PrereleaseHandler.prerelease_pattern.sub(PRERELEASE_PLACEHOLDER, new_prerelease)
|
52
|
+
end
|
53
|
+
|
37
54
|
def extract_prerelease_number(current_prerelease)
|
38
|
-
actual_old_prerelease_pattern =
|
39
|
-
if PrereleaseHandler.old_prerelease_pattern.respond_to?('call')
|
40
|
-
PrereleaseHandler.old_prerelease_pattern.call
|
41
|
-
else
|
42
|
-
PrereleaseHandler.old_prerelease_pattern
|
43
|
-
end
|
44
55
|
Common.error "The given old pattern does not contains the placeholder '(p)'" unless
|
45
56
|
actual_old_prerelease_pattern.include?(PRERELEASE_PLACEHOLDER)
|
46
57
|
old_prerelease_regex = actual_old_prerelease_pattern.sub(PRERELEASE_PLACEHOLDER, '(\\d+)')
|
@@ -51,4 +62,12 @@ module PrereleaseHandler
|
|
51
62
|
"does not match the analyzed prerelease: '#{current_prerelease}'."
|
52
63
|
end
|
53
64
|
end
|
65
|
+
|
66
|
+
def actual_old_prerelease_pattern
|
67
|
+
if PrereleaseHandler.old_prerelease_pattern.respond_to?('call')
|
68
|
+
PrereleaseHandler.old_prerelease_pattern.call
|
69
|
+
else
|
70
|
+
PrereleaseHandler.old_prerelease_pattern
|
71
|
+
end
|
72
|
+
end
|
54
73
|
end
|
@@ -47,7 +47,7 @@ class Init < Command
|
|
47
47
|
|
48
48
|
def create_first_commit
|
49
49
|
command_result = CommandIssuer.run('git', 'commit', '--allow-empty', '-m', '"chore: initialize repository"')
|
50
|
-
Common.error
|
50
|
+
Common.error "Failed to create first commit: #{command_result.error}" if command_result.exit_status.positive?
|
51
51
|
end
|
52
52
|
|
53
53
|
protected
|
@@ -70,21 +70,18 @@ class Tree < Command
|
|
70
70
|
# calc color escape codes length
|
71
71
|
time_color_length = first_line_time.length - first_line_time.match(TIME_REGEX)[1].length
|
72
72
|
|
73
|
-
|
74
|
-
time_padding = 0
|
75
|
-
split_lines.each { |element| time_padding = [time_padding, element[1].length - time_color_length].max }
|
73
|
+
time_padding = global_fitting_time_padding(split_lines, time_color_length)
|
76
74
|
|
77
|
-
# format strings
|
78
75
|
split_lines
|
79
76
|
.map do |element|
|
80
77
|
# Only lines with the date reference have the color escape codes,
|
81
78
|
# the other lines do not need the additional padding
|
82
79
|
left_padding = TIME_MINIMUM_PADDING + time_padding +
|
83
|
-
|
80
|
+
(!element[1].nil? && element[1].match?(TIME_REGEX) ? time_color_length : 0)
|
84
81
|
format(
|
85
82
|
'%<date>s %<tree_mark>s %<pointers>s %<commit_text>s',
|
86
83
|
{
|
87
|
-
date: element[1].rjust(left_padding),
|
84
|
+
date: (element[1].nil? ? '' : element[1]).rjust(left_padding),
|
88
85
|
tree_mark: element[0],
|
89
86
|
pointers: element[2],
|
90
87
|
commit_text: element[3]
|
@@ -95,6 +92,16 @@ class Tree < Command
|
|
95
92
|
end
|
96
93
|
# rubocop:enable Metrics/MethodLength
|
97
94
|
|
95
|
+
def global_fitting_time_padding(lines, time_color_length)
|
96
|
+
time_padding = 0
|
97
|
+
lines
|
98
|
+
# If element[1].nil? then the line refers to a intersection between branch lines
|
99
|
+
# they do not have a time reference
|
100
|
+
.reject { |element| element[1].nil? }
|
101
|
+
.each { |element| time_padding = [time_padding, element[1].length - time_color_length].max }
|
102
|
+
time_padding
|
103
|
+
end
|
104
|
+
|
98
105
|
protected
|
99
106
|
|
100
107
|
def setup_option_parser
|
data/lib/get/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git_toolbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Speranza
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -96,7 +96,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
96
|
requirements:
|
97
97
|
- - ">="
|
98
98
|
- !ruby/object:Gem::Version
|
99
|
-
version: 3.
|
99
|
+
version: 3.0.0
|
100
100
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
102
|
- - ">="
|