geet 0.3.6 → 0.3.7
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 +4 -4
- data/README.md +2 -5
- data/geet.gemspec +1 -1
- data/lib/geet/git/repository.rb +6 -10
- data/lib/geet/github/abstract_issue.rb +4 -8
- data/lib/geet/github/issue.rb +4 -4
- data/lib/geet/github/milestone.rb +9 -11
- data/lib/geet/github/pr.rb +27 -11
- data/lib/geet/gitlab/PR.rb +37 -0
- data/lib/geet/gitlab/issue.rb +10 -6
- data/lib/geet/gitlab/milestone.rb +43 -0
- data/lib/geet/gitlab/user.rb +30 -0
- data/lib/geet/helpers/json_helper.rb +17 -0
- data/lib/geet/services/list_issues.rb +1 -3
- data/lib/geet/services/list_milestones.rb +33 -17
- data/lib/geet/version.rb +1 -1
- data/spec/integration/list_issues_spec.rb +26 -2
- data/spec/integration/list_milestones_spec.rb +83 -47
- data/spec/integration/list_prs_spec.rb +9 -9
- data/spec/vcr_cassettes/github_com/list_milestones.yml +621 -0
- data/spec/vcr_cassettes/gitlab_com/list_issues.yml +3 -3
- data/spec/vcr_cassettes/gitlab_com/list_issues_with_assignee.yml +162 -0
- data/spec/vcr_cassettes/gitlab_com/list_milestones.yml +397 -0
- data/spec/vcr_cassettes/list_milestones_upstream.yml +271 -22
- data/spec/vcr_cassettes/list_prs.yml +25 -20
- data/spec/vcr_cassettes/list_prs_upstream.yml +25 -16
- metadata +9 -3
- data/spec/vcr_cassettes/list_milestones.yml +0 -468
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd623b15d744959be72ee1fd7438cbae8e8a8de8086f60c71ad6b269f457f975
|
4
|
+
data.tar.gz: fd84684c150029c3e0028703aa36d6834d9b0909f1872007abf82e6c75753ebf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f7ede545d5ba98c5ab018fe81644bf9e78c64eeecaae39c619c6407fce4ae4080e6c6be152425d4eb33d073b2514c4e6322d7be2a22403465d39c243839a016
|
7
|
+
data.tar.gz: 12543389e4ccbbbdd185c771acbc90669347b568f0a6d6a39bba8da4263cddd1da738d0397ef0d9991e9536052f10459ff5258752f5c03ad9ada3c36c3ed241b
|
data/README.md
CHANGED
@@ -10,11 +10,7 @@ Please see the [development status](#development-status) section for information
|
|
10
10
|
|
11
11
|
## Development status
|
12
12
|
|
13
|
-
Geet is
|
14
|
-
|
15
|
-
Although I keep using it daily, and I have many ideas for making it very smooth and efficient (beside the fact that it's very easy to extend), it has no userbase, while [Hub](https://github.com/github/hub) has a very large one.
|
16
|
-
|
17
|
-
Therefore, it's probably better to put effort in contributing Hub, rather than improving Geet.
|
13
|
+
Geet is (again) under active development. The current focus is implementing Gitlab functionalities.
|
18
14
|
|
19
15
|
## Operation/providers support
|
20
16
|
|
@@ -33,6 +29,7 @@ The functionalities currently supported are:
|
|
33
29
|
- Gitlab:
|
34
30
|
- list issues
|
35
31
|
- list labels
|
32
|
+
- list milestones
|
36
33
|
|
37
34
|
## Samples
|
38
35
|
|
data/geet.gemspec
CHANGED
@@ -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-
|
13
|
+
s.date = '2018-07-01'
|
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).'
|
data/lib/geet/git/repository.rb
CHANGED
@@ -54,12 +54,8 @@ module Geet
|
|
54
54
|
attempt_provider_call(:Branch, :delete, name, api_interface)
|
55
55
|
end
|
56
56
|
|
57
|
-
def
|
58
|
-
attempt_provider_call(:
|
59
|
-
end
|
60
|
-
|
61
|
-
def issues(assignee: nil)
|
62
|
-
attempt_provider_call(:Issue, :list, api_interface, assignee: assignee)
|
57
|
+
def issues(assignee: nil, milestone: nil)
|
58
|
+
attempt_provider_call(:Issue, :list, api_interface, assignee: assignee, milestone: milestone)
|
63
59
|
end
|
64
60
|
|
65
61
|
def milestone(number)
|
@@ -77,8 +73,8 @@ module Geet
|
|
77
73
|
attempt_provider_call(:PR, :create, title, description, head, api_interface, base: base)
|
78
74
|
end
|
79
75
|
|
80
|
-
def prs(head: nil)
|
81
|
-
attempt_provider_call(:PR, :list, api_interface, head: head)
|
76
|
+
def prs(head: nil, milestone: nil)
|
77
|
+
attempt_provider_call(:PR, :list, api_interface, head: head, milestone: milestone)
|
82
78
|
end
|
83
79
|
|
84
80
|
# REMOTE FUNCTIONALITIES (ACCOUNT)
|
@@ -116,12 +112,12 @@ module Geet
|
|
116
112
|
klass = Kernel.const_get(full_class_name)
|
117
113
|
|
118
114
|
if !klass.respond_to?(meth)
|
119
|
-
raise "The functionality invoked (#{class_name}
|
115
|
+
raise "The functionality invoked (#{class_name}.#{meth}) is not currently supported!"
|
120
116
|
end
|
121
117
|
|
122
118
|
klass.send(meth, *args)
|
123
119
|
else
|
124
|
-
raise "The
|
120
|
+
raise "The class referenced (#{full_class_name}) is not currently supported!"
|
125
121
|
end
|
126
122
|
end
|
127
123
|
|
@@ -22,12 +22,12 @@ module Geet
|
|
22
22
|
|
23
23
|
# See https://developer.github.com/v3/issues/#list-issues-for-a-repository
|
24
24
|
#
|
25
|
-
def self.list(api_interface,
|
25
|
+
def self.list(api_interface, milestone: nil, assignee: nil, &type_filter)
|
26
26
|
api_path = 'issues'
|
27
27
|
|
28
28
|
request_params = {}
|
29
|
-
request_params[:milestone] = milestone if milestone
|
30
|
-
request_params[:assignee] = assignee if assignee
|
29
|
+
request_params[:milestone] = milestone.number if milestone
|
30
|
+
request_params[:assignee] = assignee.username if assignee
|
31
31
|
|
32
32
|
response = api_interface.send_request(api_path, params: request_params, multipage: true)
|
33
33
|
|
@@ -36,11 +36,7 @@ module Geet
|
|
36
36
|
title = issue_data.fetch('title')
|
37
37
|
link = issue_data.fetch('html_url')
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
if !only_issues || klazz == Issue
|
42
|
-
klazz.new(number, api_interface, title, link)
|
43
|
-
end
|
39
|
+
new(number, api_interface, title, link) if type_filter.nil? || type_filter.call(issue_data)
|
44
40
|
end
|
45
41
|
|
46
42
|
abstract_issues_list.compact
|
data/lib/geet/github/issue.rb
CHANGED
@@ -17,10 +17,10 @@ module Geet
|
|
17
17
|
new(issue_number, api_interface, title, link)
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
def self.list(api_interface, assignee: nil, milestone: nil)
|
21
|
+
super do |issue_data|
|
22
|
+
!issue_data.key?('pull_request')
|
23
|
+
end
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -1,12 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative '../helpers/json_helper'
|
4
4
|
|
5
5
|
module Geet
|
6
6
|
module Github
|
7
7
|
class Milestone
|
8
8
|
attr_reader :number, :title, :due_on
|
9
9
|
|
10
|
+
class << self
|
11
|
+
private
|
12
|
+
|
13
|
+
include Helpers::JsonHelper
|
14
|
+
end
|
15
|
+
|
10
16
|
def initialize(number, title, due_on, api_interface)
|
11
17
|
@number = number
|
12
18
|
@title = title
|
@@ -24,7 +30,7 @@ module Geet
|
|
24
30
|
|
25
31
|
number = response.fetch('number')
|
26
32
|
title = response.fetch('title')
|
27
|
-
due_on =
|
33
|
+
due_on = parse_iso_8601_timestamp(raw_due_on)
|
28
34
|
|
29
35
|
new(number, title, due_on, api_interface)
|
30
36
|
end
|
@@ -39,19 +45,11 @@ module Geet
|
|
39
45
|
response.map do |milestone_data|
|
40
46
|
number = milestone_data.fetch('number')
|
41
47
|
title = milestone_data.fetch('title')
|
42
|
-
due_on =
|
48
|
+
due_on = parse_iso_8601_timestamp(milestone_data.fetch('due_on'))
|
43
49
|
|
44
50
|
new(number, title, due_on, api_interface)
|
45
51
|
end
|
46
52
|
end
|
47
|
-
|
48
|
-
class << self
|
49
|
-
private
|
50
|
-
|
51
|
-
def parse_due_on(raw_due_on)
|
52
|
-
Date.strptime(raw_due_on, '%FT%TZ') if raw_due_on
|
53
|
-
end
|
54
|
-
end
|
55
53
|
end
|
56
54
|
end
|
57
55
|
end
|
data/lib/geet/github/pr.rb
CHANGED
@@ -26,20 +26,26 @@ module Geet
|
|
26
26
|
new(number, api_interface, title, link)
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
def self.list(api_interface, head: nil)
|
32
|
-
api_path = 'pulls'
|
33
|
-
request_params = { head: head } if head
|
29
|
+
def self.list(api_interface, milestone: nil, assignee: nil, head: nil)
|
30
|
+
check_list_params!(milestone, assignee, head)
|
34
31
|
|
35
|
-
|
32
|
+
if head
|
33
|
+
api_path = 'pulls'
|
34
|
+
request_params = { head: head }
|
36
35
|
|
37
|
-
|
38
|
-
number = issue_data.fetch('number')
|
39
|
-
title = issue_data.fetch('title')
|
40
|
-
link = issue_data.fetch('html_url')
|
36
|
+
response = api_interface.send_request(api_path, params: request_params, multipage: true)
|
41
37
|
|
42
|
-
|
38
|
+
response.map do |issue_data|
|
39
|
+
number = issue_data.fetch('number')
|
40
|
+
title = issue_data.fetch('title')
|
41
|
+
link = issue_data.fetch('html_url')
|
42
|
+
|
43
|
+
new(number, api_interface, title, link)
|
44
|
+
end
|
45
|
+
else
|
46
|
+
super(api_interface, milestone: milestone, assignee: assignee) do |issue_data|
|
47
|
+
issue_data.key?('pull_request')
|
48
|
+
end
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
@@ -57,6 +63,16 @@ module Geet
|
|
57
63
|
|
58
64
|
@api_interface.send_request(api_path, data: request_data)
|
59
65
|
end
|
66
|
+
|
67
|
+
class << self
|
68
|
+
private
|
69
|
+
|
70
|
+
def check_list_params!(milestone, assignee, head)
|
71
|
+
if (milestone || assignee) && head
|
72
|
+
raise "Head can't be specified with milestone or assignee!"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
60
76
|
end
|
61
77
|
end
|
62
78
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Geet
|
4
|
+
module Gitlab
|
5
|
+
class PR
|
6
|
+
attr_reader :number, :title, :link
|
7
|
+
|
8
|
+
def initialize(number, title, link)
|
9
|
+
@number = number
|
10
|
+
@title = title
|
11
|
+
@link = link
|
12
|
+
end
|
13
|
+
|
14
|
+
# See https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests
|
15
|
+
#
|
16
|
+
def self.list(api_interface, milestone: nil, assignee: nil, head: nil)
|
17
|
+
raise ":head parameter currently unsupported!" if head
|
18
|
+
|
19
|
+
api_path = "projects/#{api_interface.path_with_namespace(encoded: true)}/merge_requests"
|
20
|
+
|
21
|
+
request_params = {}
|
22
|
+
request_params[:assignee_id] = assignee.id if assignee
|
23
|
+
request_params[:milestone] = milestone.title if milestone
|
24
|
+
|
25
|
+
response = api_interface.send_request(api_path, params: request_params, multipage: true)
|
26
|
+
|
27
|
+
response.map do |issue_data, result|
|
28
|
+
number = issue_data.fetch('iid')
|
29
|
+
title = issue_data.fetch('title')
|
30
|
+
link = issue_data.fetch('web_url')
|
31
|
+
|
32
|
+
new(number, title, link)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end # PR
|
36
|
+
end # Gitlab
|
37
|
+
end # Geet
|
data/lib/geet/gitlab/issue.rb
CHANGED
@@ -11,19 +11,23 @@ module Geet
|
|
11
11
|
@link = link
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
# See https://docs.gitlab.com/ee/api/issues.html#list-issues
|
15
|
+
#
|
16
|
+
def self.list(api_interface, assignee: nil, milestone: nil)
|
17
17
|
api_path = "projects/#{api_interface.path_with_namespace(encoded: true)}/issues"
|
18
18
|
|
19
|
-
|
19
|
+
request_params = {}
|
20
|
+
request_params[:assignee_id] = assignee.id if assignee
|
21
|
+
request_params[:milestone] = milestone.title if milestone
|
22
|
+
|
23
|
+
response = api_interface.send_request(api_path, params: request_params, multipage: true)
|
20
24
|
|
21
|
-
response.
|
25
|
+
response.map do |issue_data, result|
|
22
26
|
number = issue_data.fetch('iid')
|
23
27
|
title = issue_data.fetch('title')
|
24
28
|
link = issue_data.fetch('web_url')
|
25
29
|
|
26
|
-
|
30
|
+
new(number, title, link)
|
27
31
|
end
|
28
32
|
end
|
29
33
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module Geet
|
6
|
+
module Gitlab
|
7
|
+
class Milestone
|
8
|
+
attr_reader :number, :title, :due_on
|
9
|
+
|
10
|
+
def initialize(number, title, due_on, api_interface)
|
11
|
+
@number = number
|
12
|
+
@title = title
|
13
|
+
@due_on = due_on
|
14
|
+
|
15
|
+
@api_interface = api_interface
|
16
|
+
end
|
17
|
+
|
18
|
+
# See https://docs.gitlab.com/ee/api/milestones.html#list-project-milestones
|
19
|
+
#
|
20
|
+
def self.list(api_interface)
|
21
|
+
api_path = "projects/#{api_interface.path_with_namespace(encoded: true)}/milestones"
|
22
|
+
|
23
|
+
response = api_interface.send_request(api_path, multipage: true)
|
24
|
+
|
25
|
+
response.map do |milestone_data|
|
26
|
+
number = milestone_data.fetch('iid')
|
27
|
+
title = milestone_data.fetch('title')
|
28
|
+
due_on = parse_due_date(milestone_data.fetch('due_date'))
|
29
|
+
|
30
|
+
new(number, title, due_on, api_interface)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
private
|
36
|
+
|
37
|
+
def parse_due_date(raw_due_date)
|
38
|
+
Date.parse(raw_due_date) if raw_due_date
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end # Milestone
|
42
|
+
end # Gitlab
|
43
|
+
end # Geet
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Geet
|
4
|
+
module Gitlab
|
5
|
+
class User
|
6
|
+
attr_reader :id, :username
|
7
|
+
|
8
|
+
def initialize(id, username, api_interface)
|
9
|
+
@id = id
|
10
|
+
@username = username
|
11
|
+
@api_interface = api_interface
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns an array of User instances
|
15
|
+
#
|
16
|
+
def self.list_collaborators(api_interface)
|
17
|
+
api_path = "projects/#{api_interface.path_with_namespace(encoded: true)}/members"
|
18
|
+
|
19
|
+
response = api_interface.send_request(api_path, multipage: true)
|
20
|
+
|
21
|
+
response.map do |user_entry|
|
22
|
+
id = user_entry.fetch('id')
|
23
|
+
username = user_entry.fetch('username')
|
24
|
+
|
25
|
+
new(id, username, api_interface)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end # User
|
29
|
+
end # Gitlab
|
30
|
+
end # Geet
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module Geet
|
6
|
+
module Helpers
|
7
|
+
module JsonHelper
|
8
|
+
# Most common Json time format.
|
9
|
+
#
|
10
|
+
# Returns nil if nil is passed.
|
11
|
+
#
|
12
|
+
def parse_iso_8601_timestamp(timestamp)
|
13
|
+
Time.iso8601(timestamp).to_date if timestamp
|
14
|
+
end
|
15
|
+
end # JsonHelper
|
16
|
+
end # Helpers
|
17
|
+
end # Geet
|
@@ -27,9 +27,7 @@ module Geet
|
|
27
27
|
|
28
28
|
selection_manager.add_attribute(:collaborators, 'assignee', assignee, :single, name_method: :username)
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
selected_assignee&.username
|
30
|
+
selection_manager.select_attributes[0]
|
33
31
|
end
|
34
32
|
end
|
35
33
|
end
|
@@ -10,19 +10,23 @@ module Geet
|
|
10
10
|
|
11
11
|
def execute
|
12
12
|
milestones = find_milestones
|
13
|
-
|
13
|
+
all_milestone_entries = find_all_milestone_entries(milestones)
|
14
14
|
|
15
15
|
@out.puts
|
16
16
|
|
17
|
-
|
17
|
+
all_milestone_entries.each do |milestone, milestone_entries|
|
18
18
|
@out.puts milestone_description(milestone)
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
milestone_issues.each do |issue|
|
20
|
+
milestone_entries.fetch(:issues).each do |issue|
|
23
21
|
@out.puts " #{issue.number}. #{issue.title} (#{issue.link})"
|
24
22
|
end
|
23
|
+
|
24
|
+
milestone_entries.fetch(:prs).each do |pr|
|
25
|
+
@out.puts " #{pr.number}. #{pr.title} (#{pr.link})"
|
26
|
+
end
|
25
27
|
end
|
28
|
+
|
29
|
+
all_milestone_entries.keys
|
26
30
|
end
|
27
31
|
|
28
32
|
private
|
@@ -41,27 +45,39 @@ module Geet
|
|
41
45
|
@repository.milestones
|
42
46
|
end
|
43
47
|
|
44
|
-
|
45
|
-
|
48
|
+
# Returns the structure:
|
49
|
+
#
|
50
|
+
# { milestone => {issues: [...], prs: [...]}}
|
51
|
+
#
|
52
|
+
def find_all_milestone_entries(milestones)
|
53
|
+
@out.puts 'Finding issues and PRs...'
|
54
|
+
|
55
|
+
all_milestone_entries = {}
|
56
|
+
all_threads = []
|
46
57
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
58
|
+
milestones.each_with_object(Mutex.new) do |milestone, mutex|
|
59
|
+
all_milestone_entries[milestone] = {}
|
60
|
+
|
61
|
+
all_threads << Thread.new do
|
62
|
+
issues = @repository.issues(milestone: milestone)
|
63
|
+
|
64
|
+
mutex.synchronize do
|
65
|
+
all_milestone_entries[milestone][:issues] = issues
|
66
|
+
end
|
67
|
+
end
|
51
68
|
|
52
|
-
|
53
|
-
|
54
|
-
issues = @repository.abstract_issues(milestone: milestone.number)
|
69
|
+
all_threads << Thread.new do
|
70
|
+
prs = @repository.prs(milestone: milestone)
|
55
71
|
|
56
72
|
mutex.synchronize do
|
57
|
-
|
73
|
+
all_milestone_entries[milestone][:prs] = prs
|
58
74
|
end
|
59
75
|
end
|
60
76
|
end
|
61
77
|
|
62
|
-
|
78
|
+
all_threads.map(&:join)
|
63
79
|
|
64
|
-
|
80
|
+
all_milestone_entries
|
65
81
|
end
|
66
82
|
end
|
67
83
|
end
|