geet 0.2.1 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 810fe20ea861a01c88e0cad7fc14bfbb92ee7bf1
4
- data.tar.gz: 6aebe64e41a3fc69e6e6e8628d1d3d4bf74a2723
3
+ metadata.gz: 37b511c318e9f2cb1c18ecf1a1f247236c841040
4
+ data.tar.gz: 61aeabbdbd6e3616e49247acf47ffbbbf18d8085
5
5
  SHA512:
6
- metadata.gz: 37d3ef70153f9ff4fa010c3e28883e4e3f5d1ba896e737c6f6597cdfceb9d8e986ab5f1c5cdf2d5c4f1dd179bd1a871e0edf6cf89f98b655b3ab83ca890f5329
7
- data.tar.gz: c76276bb1bf6d9147e17fa92eb49baca3cd7f96a90a3c1786b4b6c60964ab24c6daca1df5e1a7164f69f3bebe09cb3683de26c1498b538b1c8f243a8575680d9
6
+ metadata.gz: 6692e7597431f0d0ef9d194030086112985f7f1f2e4e0b6b8caf3c6dbeea565fd3d22b7b0033cf3290bf156e6f331e4e70ea6b3cf3be962e45110aa32ffdf05c
7
+ data.tar.gz: e57f240a2c9a3b0ecb65a874efa7f3c4c61e0102cd365c7a53ac6b2579367c37c95dae072014f33ac5d6077ca75df649aff0dd4e7912a92502503e5a6a0e554e
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ source 'https://rubygems.org'
5
5
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
6
 
7
7
  gem 'simple_scripting', '~> 0.9.3'
8
+ gem 'temp-fork-tp-filter', '= 0.0.3'
8
9
 
9
10
  group :development, :test do
10
11
  gem 'byebug', '~> 9.1.0'
@@ -8,11 +8,17 @@ GEM
8
8
  crack (0.4.3)
9
9
  safe_yaml (~> 1.0.0)
10
10
  diff-lcs (1.3)
11
+ equatable (0.5.0)
11
12
  hashdiff (0.3.7)
13
+ hitimes (1.2.6)
14
+ necromancer (0.4.0)
12
15
  parallel (1.12.1)
13
16
  parseconfig (1.0.8)
14
17
  parser (2.4.0.2)
15
18
  ast (~> 2.3)
19
+ pastel (0.7.2)
20
+ equatable (~> 0.5.0)
21
+ tty-color (~> 0.4.0)
16
22
  powerpack (0.1.1)
17
23
  public_suffix (3.0.1)
18
24
  rainbow (3.0.0)
@@ -41,12 +47,28 @@ GEM
41
47
  safe_yaml (1.0.4)
42
48
  simple_scripting (0.9.3)
43
49
  parseconfig (~> 1.0)
50
+ temp-fork-tp-filter (0.0.3)
51
+ necromancer (~> 0.4.0)
52
+ pastel (~> 0.7.0)
53
+ timers (~> 4.1.2)
54
+ tty-cursor (~> 0.5.0)
55
+ tty-reader (~> 0.2.0)
56
+ timers (4.1.2)
57
+ hitimes
58
+ tty-color (0.4.2)
59
+ tty-cursor (0.5.0)
60
+ tty-reader (0.2.0)
61
+ tty-cursor (~> 0.5.0)
62
+ tty-screen (~> 0.6.4)
63
+ wisper (~> 2.0.0)
64
+ tty-screen (0.6.4)
44
65
  unicode-display_width (1.3.0)
45
66
  vcr (3.0.3)
46
67
  webmock (3.1.1)
47
68
  addressable (>= 2.3.6)
48
69
  crack (>= 0.3.2)
49
70
  hashdiff
71
+ wisper (2.0.0)
50
72
 
51
73
  PLATFORMS
52
74
  ruby
@@ -57,8 +79,9 @@ DEPENDENCIES
57
79
  rspec (~> 3.7.0)
58
80
  rubocop (~> 0.52.0)
59
81
  simple_scripting (~> 0.9.3)
82
+ temp-fork-tp-filter (= 0.0.3)
60
83
  vcr (~> 3.0.3)
61
84
  webmock (~> 3.1.1)
62
85
 
63
86
  BUNDLED WITH
64
- 1.16.0.pre.3
87
+ 1.16.1
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.required_ruby_version = '>= 2.3.0'
12
12
  s.authors = ['Saverio Miroddi']
13
- s.date = '2018-01-14'
13
+ s.date = '2018-01-19'
14
14
  s.email = ['saverio.pub2@gmail.com']
15
15
  s.homepage = 'https://github.com/saveriomiroddi/geet'
16
16
  s.summary = 'Commandline interface for performing SCM (eg. GitHub) operations (eg. PR creation).'
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.license = 'GPL-3.0'
19
19
 
20
20
  s.add_runtime_dependency 'simple_scripting', '~> 0.9.3'
21
+ s.add_runtime_dependency 'temp-fork-tp-filter', '= 0.0.3'
21
22
 
22
23
  s.files = `git ls-files`.split("\n")
23
24
  s.executables << 'geet'
@@ -23,7 +23,7 @@ module Geet
23
23
  ISSUE_CREATE_OPTIONS = [
24
24
  ['-n', '--no-open-issue', "Don't open the issue link in the browser after creation"],
25
25
  ['-l', '--label-patterns "bug,help wanted"', 'Label patterns'],
26
- ['-m', '--milestone number_or_pattern', 'Milestone number or description pattern'],
26
+ ['-m', '--milestone 1.5.0', 'Milestone title pattern'],
27
27
  ['-a', '--assignee-patterns john,tom,adrian,kevin', 'Assignee login patterns. Defaults to authenticated user'],
28
28
  ['-u', '--upstream', 'Create on the upstream repository'],
29
29
  long_help: 'The default editor will be opened for editing title and description.'
@@ -46,7 +46,7 @@ module Geet
46
46
  PR_CREATE_OPTIONS = [
47
47
  ['-n', '--no-open-pr', "Don't open the PR link in the browser after creation"],
48
48
  ['-l', '--label-patterns "legacy,code review"', 'Label patterns'],
49
- ['-m', '--milestone number_or_pattern', 'Milestone number or description pattern'],
49
+ ['-m', '--milestone 1.5.0', 'Milestone title pattern'],
50
50
  ['-r', '--reviewer-patterns john,tom,adrian,kevin', 'Reviewer login patterns'],
51
51
  ['-u', '--upstream', 'Create on the upstream repository'],
52
52
  long_help: 'The default editor will be opened for editing title and description; if the PR adds one commit only, '\
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../helpers/os_helper.rb'
4
+ require_relative '../utils/manual_list_selection.rb'
5
+ require_relative '../utils/pattern_matching_selection.rb'
4
6
 
5
7
  module Geet
6
8
  module Services
7
9
  class CreateIssue
8
10
  include Geet::Helpers::OsHelper
9
11
 
12
+ MANUAL_LIST_SELECTION_FLAG = '-'.freeze
13
+
10
14
  # options:
11
15
  # :label_patterns
12
16
  # :milestone_pattern: number or description pattern.
@@ -18,30 +22,17 @@ module Geet
18
22
  label_patterns: nil, milestone_pattern: nil, assignee_patterns: nil, no_open_issue: nil,
19
23
  output: $stdout, **
20
24
  )
21
- labels_thread = select_labels(repository, label_patterns, output) if label_patterns
22
- milestone_thread = find_milestone(repository, milestone_pattern, output) if milestone_pattern
23
- assignees_thread = select_assignees(repository, assignee_patterns, output) if assignee_patterns
25
+ all_labels, all_milestones, all_collaborators = find_all_attribute_entries(
26
+ repository, label_patterns, milestone_pattern, assignee_patterns, output
27
+ )
24
28
 
25
- selected_labels = labels_thread&.join&.value
26
- assignees = assignees_thread&.join&.value
27
- milestone = milestone_thread&.join&.value
29
+ labels = select_entries('label', all_labels, label_patterns, :multiple, :name) if label_patterns
30
+ milestone, _ = select_entries('milestone', all_milestones, milestone_pattern, :single, :title) if milestone_pattern
31
+ assignees = select_entries('collaborator', all_collaborators, assignee_patterns, :multiple, nil) if assignee_patterns
28
32
 
29
- output.puts 'Creating the issue...'
33
+ issue = create_issue(repository, title, description, output)
30
34
 
31
- issue = repository.create_issue(title, description)
32
-
33
- add_labels_thread = add_labels(issue, selected_labels, output) if selected_labels
34
- set_milestone_thread = set_milestone(issue, milestone, output) if milestone
35
-
36
- if assignees
37
- assign_users_thread = assign_users(issue, assignees, output)
38
- else
39
- assign_users_thread = assign_authenticated_user(repository, issue, output)
40
- end
41
-
42
- add_labels_thread&.join
43
- set_milestone_thread&.join
44
- assign_users_thread.join
35
+ edit_issue(repository, issue, labels, milestone, assignees, output)
45
36
 
46
37
  if no_open_issue
47
38
  output.puts "Issue address: #{issue.link}"
@@ -56,38 +47,48 @@ module Geet
56
47
 
57
48
  # Internal actions
58
49
 
59
- def select_labels(repository, label_patterns, output)
60
- output.puts 'Finding labels...'
61
-
62
- Thread.new do
63
- all_labels = repository.labels
50
+ def find_all_attribute_entries(repository, label_patterns, milestone_pattern, assignee_patterns, output)
51
+ if label_patterns
52
+ output.puts 'Finding labels...'
53
+ labels_thread = Thread.new { repository.labels }
54
+ end
64
55
 
65
- select_entries(all_labels, label_patterns, type: 'labels', instance_method: :name)
56
+ if milestone_pattern
57
+ output.puts 'Finding milestone...'
58
+ milestone_thread = Thread.new { repository.milestones }
66
59
  end
67
- end
68
60
 
69
- def find_milestone(repository, milestone_pattern, output)
70
- output.puts 'Finding milestone...'
61
+ if assignee_patterns
62
+ output.puts 'Finding collaborators...'
63
+ reviewers_thread = Thread.new { repository.collaborators }
64
+ end
71
65
 
72
- Thread.new do
73
- if milestone_pattern =~ /\A\d+\Z/
74
- repository.milestone(milestone_pattern)
75
- else
76
- all_milestones = repository.milestones
66
+ labels = labels_thread&.value
67
+ milestones = milestone_thread&.value
68
+ reviewers = reviewers_thread&.value
77
69
 
78
- select_entries(all_milestones, milestone_pattern, type: 'milestones', instance_method: :title).first
79
- end
80
- end
70
+ [labels, milestones, reviewers]
81
71
  end
82
72
 
83
- def select_assignees(repository, assignee_patterns, output)
84
- output.puts 'Finding collaborators...'
73
+ def create_issue(repository, title, description, output)
74
+ output.puts 'Creating the issue...'
85
75
 
86
- Thread.new do
87
- all_collaborators = repository.collaborators
76
+ issue = repository.create_issue(title, description)
77
+ end
78
+
79
+ def edit_issue(repository, issue, labels, milestone, assignees, output)
80
+ add_labels_thread = add_labels(issue, labels, output) if labels
81
+ set_milestone_thread = set_milestone(issue, milestone, output) if milestone
88
82
 
89
- select_entries(all_collaborators, assignee_patterns, type: 'collaborators')
83
+ if assignees
84
+ assign_users_thread = assign_users(issue, assignees, output)
85
+ else
86
+ assign_users_thread = assign_authenticated_user(repository, issue, output)
90
87
  end
88
+
89
+ add_labels_thread&.join
90
+ set_milestone_thread&.join
91
+ assign_users_thread.join
91
92
  end
92
93
 
93
94
  def add_labels(issue, selected_labels, output)
@@ -126,23 +127,11 @@ module Geet
126
127
 
127
128
  # Generic helpers
128
129
 
129
- def select_entries(entries, raw_patterns, type: 'entries', instance_method: nil)
130
- patterns = raw_patterns.split(',')
131
-
132
- patterns.map do |pattern|
133
- entries_found = entries.select do |entry|
134
- entry = entry.send(instance_method) if instance_method
135
- entry =~ /#{pattern}/i
136
- end
137
-
138
- case entries_found.size
139
- when 1
140
- entries_found.first
141
- when 0
142
- raise "No #{type} found for pattern: #{pattern.inspect}"
143
- else
144
- raise "Multiple #{type} found for pattern #{pattern.inspect}: #{entries_found}"
145
- end
130
+ def select_entries(entry_type, entries, raw_patterns, selection_type, instance_method)
131
+ if raw_patterns == MANUAL_LIST_SELECTION_FLAG
132
+ Geet::Utils::ManualListSelection.new.select(entry_type, entries, selection_type, instance_method: instance_method)
133
+ else
134
+ Geet::Utils::PatternMatchingSelection.new.select(entry_type, entries, raw_patterns, instance_method: instance_method)
146
135
  end
147
136
  end
148
137
  end
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../helpers/os_helper.rb'
4
+ require_relative '../utils/manual_list_selection.rb'
5
+ require_relative '../utils/pattern_matching_selection.rb'
4
6
 
5
7
  module Geet
6
8
  module Services
7
9
  class CreatePr
8
10
  include Geet::Helpers::OsHelper
9
11
 
12
+ MANUAL_LIST_SELECTION_FLAG = '-'.freeze
13
+
10
14
  # options:
11
15
  # :label_patterns
12
16
  # :reviewer_patterns
@@ -16,25 +20,17 @@ module Geet
16
20
  repository, title, description, label_patterns: nil, milestone_pattern: nil, reviewer_patterns: nil,
17
21
  no_open_pr: nil, output: $stdout, **
18
22
  )
19
- labels_thread = select_labels(repository, label_patterns, output) if label_patterns
20
- milestone_thread = find_milestone(repository, milestone_pattern, output) if milestone_pattern
21
- reviewers_thread = select_reviewers(repository, reviewer_patterns, output) if reviewer_patterns
23
+ all_labels, all_milestones, all_collaborators = find_all_attribute_entries(
24
+ repository, label_patterns, milestone_pattern, reviewer_patterns, output
25
+ )
22
26
 
23
- selected_labels = labels_thread&.join&.value
24
- reviewers = reviewers_thread&.join&.value
25
- milestone = milestone_thread&.join&.value
27
+ labels = select_entries('label', all_labels, label_patterns, :multiple, :name) if label_patterns
28
+ milestone, _ = select_entries('milestone', all_milestones, milestone_pattern, :single, :title) if milestone_pattern
29
+ reviewers = select_entries('collaborator', all_collaborators, reviewer_patterns, :multiple, nil) if reviewer_patterns
26
30
 
27
31
  pr = create_pr(repository, title, description, output)
28
32
 
29
- assign_user_thread = assign_authenticated_user(pr, repository, output)
30
- add_labels_thread = add_labels(pr, selected_labels, output) if selected_labels
31
- set_milestone_thread = set_milestone(pr, milestone, output) if milestone
32
- request_review_thread = request_review(pr, reviewers, output) if reviewers
33
-
34
- assign_user_thread.join
35
- add_labels_thread&.join
36
- set_milestone_thread&.join
37
- request_review_thread&.join
33
+ edit_pr(repository, pr, labels, milestone, reviewers, output)
38
34
 
39
35
  if no_open_pr
40
36
  output.puts "PR address: #{pr.link}"
@@ -49,38 +45,27 @@ module Geet
49
45
 
50
46
  # Internal actions
51
47
 
52
- def select_labels(repository, label_patterns, output)
53
- output.puts 'Finding labels...'
54
-
55
- Thread.new do
56
- all_labels = repository.labels
57
-
58
- select_entries(all_labels, label_patterns, type: 'labels', instance_method: :name)
48
+ def find_all_attribute_entries(repository,label_patterns, milestone_pattern, reviewer_patterns, output)
49
+ if label_patterns
50
+ output.puts 'Finding labels...'
51
+ labels_thread = Thread.new { repository.labels }
59
52
  end
60
- end
61
-
62
- def find_milestone(repository, milestone_pattern, output)
63
- output.puts 'Finding milestone...'
64
-
65
- Thread.new do
66
- if milestone_pattern =~ /\A\d+\Z/
67
- repository.milestone(milestone_pattern)
68
- else
69
- all_milestones = repository.milestones
70
53
 
71
- select_entries(all_milestones, milestone_pattern, type: 'milestones', instance_method: :title).first
72
- end
54
+ if milestone_pattern
55
+ output.puts 'Finding milestone...'
56
+ milestone_thread = Thread.new { repository.milestones }
73
57
  end
74
- end
75
58
 
76
- def select_reviewers(repository, reviewer_patterns, output)
77
- output.puts 'Finding collaborators...'
59
+ if reviewer_patterns
60
+ output.puts 'Finding collaborators...'
61
+ reviewers_thread = Thread.new { repository.collaborators }
62
+ end
78
63
 
79
- Thread.new do
80
- all_collaborators = repository.collaborators
64
+ labels = labels_thread&.value
65
+ milestones = milestone_thread&.value
66
+ reviewers = reviewers_thread&.value
81
67
 
82
- select_entries(all_collaborators, reviewer_patterns, type: 'collaborators')
83
- end
68
+ [labels, milestones, reviewers]
84
69
  end
85
70
 
86
71
  def create_pr(repository, title, description, output)
@@ -89,6 +74,19 @@ module Geet
89
74
  repository.create_pr(title, description, repository.current_branch)
90
75
  end
91
76
 
77
+ def edit_pr(repository, pr, labels, milestone, reviewers, output)
78
+ assign_user_thread = assign_authenticated_user(pr, repository, output)
79
+
80
+ add_labels_thread = add_labels(pr, labels, output) if labels
81
+ set_milestone_thread = set_milestone(pr, milestone, output) if milestone
82
+ request_review_thread = request_review(pr, reviewers, output) if reviewers
83
+
84
+ assign_user_thread.join
85
+ add_labels_thread&.join
86
+ set_milestone_thread&.join
87
+ request_review_thread&.join
88
+ end
89
+
92
90
  def assign_authenticated_user(pr, repository, output)
93
91
  output.puts 'Assigning authenticated user...'
94
92
 
@@ -125,23 +123,11 @@ module Geet
125
123
 
126
124
  # Generic helpers
127
125
 
128
- def select_entries(entries, raw_patterns, type: 'entries', instance_method: nil)
129
- patterns = raw_patterns.split(',')
130
-
131
- patterns.map do |pattern|
132
- entries_found = entries.select do |entry|
133
- entry = entry.send(instance_method) if instance_method
134
- entry =~ /#{pattern}/i
135
- end
136
-
137
- case entries_found.size
138
- when 1
139
- entries_found.first
140
- when 0
141
- raise "No #{type} found for pattern: #{pattern.inspect}"
142
- else
143
- raise "Multiple #{type} found for pattern #{pattern.inspect}: #{entries_found}"
144
- end
126
+ def select_entries(entry_type, entries, raw_patterns, selection_type, instance_method)
127
+ if raw_patterns == MANUAL_LIST_SELECTION_FLAG
128
+ Geet::Utils::ManualListSelection.new.select(entry_type, entries, selection_type, instance_method: instance_method)
129
+ else
130
+ Geet::Utils::PatternMatchingSelection.new.select(entry_type, entries, raw_patterns, instance_method: instance_method)
145
131
  end
146
132
  end
147
133
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'temp-fork-tp-filter'
4
+
5
+ module Geet
6
+ module Utils
7
+ class ManualListSelection
8
+ PAGER_SIZE = 16
9
+
10
+ PROMPT_METHODS = {
11
+ single: :select,
12
+ multiple: :multi_select,
13
+ }
14
+
15
+ # selection_type: :single or :multiple
16
+ def select(entry_type, entries, selection_type, instance_method: nil)
17
+ raise "No #{entry_type} provided!" if entries.empty?
18
+
19
+ prompt_method = find_prompt_method(selection_type)
20
+ prompt_title = "Please select the #{entry_type}(s):"
21
+
22
+ if instance_method
23
+ entries = entries.each_with_object({}) do |entry, current_map|
24
+ current_map[entry.send(instance_method)] = entry
25
+ end
26
+ end
27
+
28
+ selected_entries = TTY::Prompt.new.send(prompt_method, prompt_title, entries, filter: true, per_page: PAGER_SIZE)
29
+
30
+ if selected_entries.is_a?(Array)
31
+ raise "No #{entry_type} selected!" if selected_entries.empty?
32
+ else
33
+ raise "No #{entry_type} selected!" if selected_entries.nil?
34
+ end
35
+
36
+ selected_entries
37
+ end
38
+
39
+ private
40
+
41
+ def find_prompt_method(selection_type)
42
+ PROMPT_METHODS[selection_type] || raise("Unrecognized selection_type: #{selection_type}")
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Geet
4
+ module Utils
5
+ class PatternMatchingSelection
6
+ def select(entry_type, entries, raw_patterns, instance_method: nil)
7
+ patterns = raw_patterns.split(',')
8
+
9
+ patterns.map do |pattern|
10
+ entries_found = entries.select do |entry|
11
+ entry = entry.send(instance_method) if instance_method
12
+ entry =~ /#{pattern}/i
13
+ end
14
+
15
+ case entries_found.size
16
+ when 1
17
+ entries_found.first
18
+ when 0
19
+ raise "No entry found for #{entry_type} pattern: #{pattern.inspect}"
20
+ else
21
+ raise "Multiple entries found for #{entry_type} pattern #{pattern.inspect}: #{entries_found}"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Geet
4
- VERSION = '0.2.1'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Saverio Miroddi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-14 00:00:00.000000000 Z
11
+ date: 2018-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simple_scripting
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.9.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: temp-fork-tp-filter
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.3
27
41
  description: Commandline interface for performing SCM (eg. GitHub) operations (eg.
28
42
  PR creation).
29
43
  email:
@@ -76,6 +90,8 @@ files:
76
90
  - lib/geet/services/list_prs.rb
77
91
  - lib/geet/services/merge_pr.rb
78
92
  - lib/geet/utils/git.rb
93
+ - lib/geet/utils/manual_list_selection.rb
94
+ - lib/geet/utils/pattern_matching_selection.rb
79
95
  - lib/geet/version.rb
80
96
  - spec/integration/create_gist_spec.rb
81
97
  - spec/integration/create_issue_spec.rb
@@ -126,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
142
  version: '0'
127
143
  requirements: []
128
144
  rubyforge_project:
129
- rubygems_version: 2.6.13
145
+ rubygems_version: 2.6.14
130
146
  signing_key:
131
147
  specification_version: 4
132
148
  summary: Commandline interface for performing SCM (eg. GitHub) operations (eg. PR