hustle_and_flow 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4e0388db2dcb3bd47c54a5e03da9956cf4b7a85f
4
- data.tar.gz: 4a59058b00ec6581f3cd0fc33bb8b6c0bb0fec09
3
+ metadata.gz: b208fd589872053209e23ac77b8dc192e2fff811
4
+ data.tar.gz: 2898d3598469cad68cd50403a514349991d5b90f
5
5
  SHA512:
6
- metadata.gz: 48892f977a6e1a681caf40921f84c0761f9b8ec4de97b1715eefd95fe571c1aeb9b699334d408f48c33073bcd58b4ccb8fe73bfd4ab8b621e9f085d9fa8293cc
7
- data.tar.gz: 0ea72b1ccb1cd67a9935b842eab8187cc5a61fa6caca0006b7801a9ac8badd65100a9d50922acafdf7e922f8d38dd4fd1ba09e469be43159679e516f82d6d7a3
6
+ metadata.gz: 090d2b0c0ae614290be17b94ab0981c20c2d9a5601f24ad6fc2beca83c917ddb5a198ad73cb07383506a335b4de0f4a62a8a82a5457b69f8c46fa4f3d41d3ada
7
+ data.tar.gz: 4a859cb4f997ee5a999b68d94b8217b1e0e7e33f7c5298363736891b337f3704cc85565d6381af141b5f996d64bb1810cfcbc5f2010969c8a0f82f1fe138dea7
data/bin/hustle CHANGED
@@ -6,4 +6,9 @@ trap 'SIGINT' do
6
6
  exit 130
7
7
  end
8
8
 
9
- HustleAndFlow::Binary::Runner.start
9
+ begin
10
+ HustleAndFlow::Binary::Runner.start
11
+ rescue Git::GitExecuteError => e
12
+ io.say 'There was a problem running a git command.'
13
+ io.say e.message
14
+ end
@@ -1,5 +1,6 @@
1
1
  require 'thor'
2
2
  require 'hustle_and_flow/commands/start'
3
+ require 'hustle_and_flow/commands/ready'
3
4
 
4
5
  module HustleAndFlow
5
6
  module Binary
@@ -34,6 +35,22 @@ class Runner < Thor
34
35
 
35
36
  Commands::Start.new(io: HustleAndFlow::Io::Shell.new, **symbolized_options).call
36
37
  end
38
+
39
+ desc 'ready', 'For when development on an issue is complete and ready to be merged'
40
+ method_option :number,
41
+ type: :string,
42
+ aliases: '-n',
43
+ desc: 'The number of the issue which should be marked as ready. If ' \
44
+ 'no number is specified, it will try to parse it from your ' \
45
+ 'current branch.'
46
+
47
+ def ready
48
+ symbolized_options = options.each_with_object({}) do |value, memo|
49
+ memo[value[0].to_sym] = value[1]
50
+ end
51
+
52
+ Commands::Ready.new(io: HustleAndFlow::Io::Shell.new, **symbolized_options).call
53
+ end
37
54
  end
38
55
  end
39
56
  end
@@ -0,0 +1,30 @@
1
+ require 'hustle_and_flow/issue_trackers/commands/ready'
2
+ require 'hustle_and_flow/version_controls/commands/ready'
3
+
4
+ module HustleAndFlow
5
+ module Commands
6
+ class Ready
7
+ attr_accessor :io,
8
+ :options
9
+
10
+ def initialize(io:, **args)
11
+ self.io = io
12
+ self.options = args
13
+ end
14
+
15
+ def call
16
+ repo = VersionControl.new(path: Dir.pwd)
17
+ VersionControls::Commands::Ready.call \
18
+ io: io,
19
+ repo: repo
20
+ IssueTrackers::Commands::Ready.call \
21
+ io: io,
22
+ repo: repo,
23
+ me: repo.user,
24
+ branch_name: repo.current_branch.name,
25
+ overwritten: [],
26
+ options: options
27
+ end
28
+ end
29
+ end
30
+ end
@@ -26,9 +26,6 @@ class Start
26
26
  number: issue.number,
27
27
  title: issue.title,
28
28
  branch_template: issue.to_branch_name(version: '*****')
29
- rescue Git::GitExecuteError => e
30
- io.say 'There was a problem running a git command.'
31
- io.say e.message
32
29
  end
33
30
  end
34
31
  end
@@ -15,6 +15,12 @@ class Shell < Thor::Shell::Color
15
15
  end
16
16
  end
17
17
 
18
+ def reopen_issue?(issue)
19
+ if issue.closed?
20
+ yes?("This #{issue.class.name} is currenly closed. Would you like to reopen it?")
21
+ end
22
+ end
23
+
18
24
  def reassign_issue?(from:)
19
25
  yes?("Do you want to reassign this issue from #{from} to yourself?")
20
26
  end
@@ -0,0 +1,17 @@
1
+ require 'hustle_and_flow/issue_tracker'
2
+ require 'hustle_and_flow/issue_trackers/github/commands/ready'
3
+
4
+ module HustleAndFlow
5
+ module IssueTrackers
6
+ module Commands
7
+ class Ready
8
+ def self.call(**args)
9
+ issue_tracker_type = IssueTracker.detect.name.gsub('::Tracker', '')
10
+ command_class = const_get("::#{issue_tracker_type}::Commands::Ready")
11
+
12
+ command_class.call(**args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,78 @@
1
+ require 'hustle_and_flow/issue_trackers/github/tracker'
2
+ require 'hustle_and_flow/issue_trackers/github/pull_requests'
3
+ require 'hustle_and_flow/issue_trackers/github/issues'
4
+
5
+ module HustleAndFlow
6
+ module IssueTrackers
7
+ module Github
8
+ module Commands
9
+ class Ready
10
+ attr_accessor :branch_name,
11
+ :me,
12
+ :pull_requests,
13
+ :issues,
14
+ :tracker,
15
+ :io
16
+
17
+ def initialize(**args)
18
+ self.branch_name = args[:branch_name]
19
+ self.me = args[:me]
20
+ self.io = args[:io]
21
+ self.tracker = Github::Tracker.new(repo: args[:repo])
22
+ self.pull_requests = Github::PullRequests.new tracker: tracker,
23
+ io: io
24
+ self.issues = Github::Issues.new tracker: tracker,
25
+ io: io
26
+ end
27
+
28
+ def call
29
+ pull_request = pull_requests.find(branch: branch_name)
30
+ issue = issues.filter_by_branch(branch: branch_name).first
31
+
32
+ if !issue && !pull_request
33
+ io.say "Couldn't find either an issue or a pull request for #{branch_name}"
34
+
35
+ exit
36
+ elsif issue && !pull_request
37
+ pull_request = issue.convert_to_pull_request(branch: branch_name)
38
+ elsif !issue && pull_request
39
+ issue = pull_request
40
+ end
41
+
42
+ if pull_request.merged?
43
+ io.say "This pull request has already been merged and cannot be modified. " \
44
+ "If you would like to make any code changes, please begin with " \
45
+ "'hustle start' and create a new issue."
46
+
47
+ exit
48
+ end
49
+
50
+ if io.reopen_issue?(pull_request)
51
+ pull_request.reopen
52
+ end
53
+
54
+ if pull_request.in_development?
55
+ pull_request.ready_for_review
56
+ elsif pull_request.ready_for_review?
57
+ io.say "Just a note. It looks like this pull request is already marked as ready " \
58
+ "for review so I'm not going to touch it."
59
+ elsif pull_request.being_reviewed?
60
+ io.say <<-HEREDOC
61
+ Just a note. It looks like the issue is currently being reviewed by <person>.
62
+ Because of this, we're going to stop here and not do any notifications or
63
+ modifications to the Pull Request.
64
+
65
+ If you'd like to do something else, you can open the PR by pressing 'o',
66
+ otherwise, press any other key to exit.
67
+ HEREDOC
68
+ end
69
+ end
70
+
71
+ def self.call(**args)
72
+ new(**args).call
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -26,9 +26,9 @@ class Start
26
26
  self.me = args[:me]
27
27
  self.io = args[:io]
28
28
  self.tracker = Github::Tracker.new(repo: args[:repo])
29
- self.issues = Issues.new(tracker: tracker,
30
- io: io,
31
- statuses: statuses)
29
+ self.issues = Github::Issues.new(tracker: tracker,
30
+ io: io,
31
+ statuses: statuses)
32
32
  end
33
33
 
34
34
  def call
@@ -1,5 +1,6 @@
1
1
  require 'hustle_and_flow/utils/url_slug'
2
2
  require 'hustle_and_flow/errors/unknown_issue_action_error'
3
+ require 'hustle_and_flow/issue_trackers/github/pull_request'
3
4
  require 'hustle_and_flow/io/shell'
4
5
 
5
6
  module HustleAndFlow
@@ -88,6 +89,12 @@ class Issue
88
89
  result = true
89
90
  conditions = args
90
91
 
92
+ args.delete(:version)
93
+
94
+ if title = args.delete(:title)
95
+ sanitize(title) == sanitize(self.title)
96
+ end
97
+
91
98
  conditions.each do |key, value|
92
99
  result &&= public_send(key) == value
93
100
  end
@@ -135,6 +142,31 @@ class Issue
135
142
  branch_name.join('/')
136
143
  end
137
144
 
145
+ def convert_to_pull_request(branch: branch)
146
+ pr_data = client.create_pull_request_for_issue(tracker.repo_name, 'master', branch, number)
147
+
148
+ PullRequest.new(tracker: tracker, data: pr_data)
149
+ end
150
+
151
+ def self.from_branch_name(branch_name)
152
+ branch_name = branch_name.dup
153
+ branch_data = {}
154
+
155
+ version_pattern = /\-v(\d+)\z/
156
+ number_pattern = /\-(\d+)\z/
157
+ action_pattern = /\-(closes|references|fixes)\z/
158
+ type_pattern = %r{\A(\w+)/}
159
+ title_pattern = /([\w\-]+)\z/
160
+
161
+ branch_data[:version] = branch_name[version_pattern, 1] and branch_name.sub!(version_pattern, '')
162
+ branch_data[:number] = branch_name[number_pattern, 1] and branch_name.sub!(number_pattern, '')
163
+ branch_data[:action] = branch_name[action_pattern, 1] and branch_name.sub!(action_pattern, '')
164
+ branch_data[:type] = branch_name[type_pattern, 1] and branch_name.sub!(type_pattern, '')
165
+ branch_data[:title] = branch_name[title_pattern, 1] and branch_name.sub!(title_pattern, '')
166
+
167
+ branch_data
168
+ end
169
+
138
170
  private
139
171
 
140
172
  def reopen
@@ -186,6 +218,12 @@ class Issue
186
218
 
187
219
  base.join('-').downcase
188
220
  end
221
+
222
+ def sanitize(other)
223
+ other.
224
+ gsub(/[\W\-\s_]/, '').
225
+ downcase
226
+ end
189
227
  end
190
228
  end
191
229
  end
@@ -36,6 +36,20 @@ class Issues
36
36
  end)
37
37
  end
38
38
 
39
+ def filter_by_branch(branch:)
40
+ data_from_branch = Issue.
41
+ from_branch_name(branch).
42
+ each_with_object({}) do |item, memo|
43
+ memo[item[0]] = item[1] unless item[1].nil?
44
+ end
45
+
46
+ self.class.new(io: io,
47
+ tracker: tracker,
48
+ issues: issues.select do |issue|
49
+ issue if issue.match?(**data_from_branch)
50
+ end)
51
+ end
52
+
39
53
  private
40
54
 
41
55
  def find(labels: nil, title: nil, number: nil)
@@ -0,0 +1,108 @@
1
+ require 'hustle_and_flow/issue_trackers/github/issue'
2
+
3
+ module HustleAndFlow
4
+ module IssueTrackers
5
+ module Github
6
+ class PullRequest
7
+ attr_accessor :tracker,
8
+ :data,
9
+ :issue
10
+
11
+ def initialize(tracker:, data:)
12
+ self.tracker = tracker
13
+ self.data = data
14
+ self.issue = Issue.new(tracker: tracker, data: client.issue(tracker.repo_name, number))
15
+ end
16
+
17
+ def reopen
18
+ reopened_issue_data = client.update_pull_request(tracker.repo_name, number, state: 'open')
19
+
20
+ closed? ? PullRequest.new(tracker: tracker, data: reopened_issue_data) : self
21
+ end
22
+
23
+ def merged?
24
+ client.pull_request_merged?(tracker.repo_name, number)
25
+ end
26
+
27
+ def in_development?
28
+ !has_label?(%w{needs-review in-review})
29
+ end
30
+
31
+ def ready_for_review?
32
+ has_label?(%w{needs-review})
33
+ end
34
+
35
+ def being_reviewed?
36
+ has_label?(%w{in-review})
37
+ end
38
+
39
+ def ready_for_review
40
+ reviewed_labels = labels.dup.push('needs-review')
41
+
42
+ client.update_issue(tracker.repo_name, number, title, body, labels: reviewed_labels)
43
+ end
44
+
45
+ def closed?
46
+ status == 'closed'
47
+ end
48
+
49
+ def status
50
+ data[:state]
51
+ end
52
+
53
+ def body
54
+ data[:body]
55
+ end
56
+
57
+ def find(me: tracker.me, **filters)
58
+ client.
59
+ pull_requests(
60
+ repo.base_name,
61
+ pull_request_data,
62
+ )
63
+ end
64
+
65
+ def self.find(tracker:, **args)
66
+ new(tracker: tracker).find(**args)
67
+ end
68
+
69
+ def match?(labels: nil, **args)
70
+ result = true
71
+ conditions = args
72
+
73
+ conditions.each do |key, value|
74
+ result &&= public_send(key) == value
75
+ end
76
+
77
+ result &&= labels ? has_label?(labels) : true
78
+ end
79
+
80
+ def title
81
+ data[:title]
82
+ end
83
+
84
+ def number
85
+ data[:number]
86
+ end
87
+
88
+ def labels
89
+ issue.send(:labels)
90
+ end
91
+
92
+ def branch
93
+ data[:head][:label]
94
+ end
95
+
96
+ def has_label?(other = [])
97
+ issue.has_label?(other)
98
+ end
99
+
100
+ private
101
+
102
+ def client
103
+ tracker.client
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,77 @@
1
+ require 'hustle_and_flow/issue_trackers/github/pull_request'
2
+
3
+ module HustleAndFlow
4
+ module IssueTrackers
5
+ module Github
6
+ class PullRequests
7
+ include Enumerable
8
+
9
+ attr_accessor :tracker,
10
+ :pull_requests,
11
+ :io
12
+
13
+ def initialize(tracker:, io:, pull_requests: nil)
14
+ self.io = io
15
+ self.tracker = tracker
16
+ self.pull_requests = pull_requests
17
+ end
18
+
19
+ # def find_or_create(**args)
20
+ # find(**args) || Issue.create(tracker: tracker, io: io, **args)
21
+ # end
22
+
23
+ def each
24
+ pull_requests.each do |pull_request|
25
+ yield pull_request
26
+ end
27
+ end
28
+
29
+ # def filter_by(**args)
30
+ # self.class.new(io: io,
31
+ # tracker: tracker,
32
+ # issues: issues.select do |issue|
33
+ # issue if issue.match?(**args)
34
+ # end)
35
+ # end
36
+ #
37
+ # private
38
+
39
+ def find(labels: nil,
40
+ title: nil,
41
+ number: nil,
42
+ branch: nil,
43
+ me: tracker.me,
44
+ organization_name: tracker.organization_name)
45
+
46
+ pull_requests.find do |pull_request|
47
+ pull_request.match?(labels: labels, title: title) ||
48
+ pull_request.match?(number: number.to_i) ||
49
+ pull_request.match?(branch: "#{me}:#{branch}") ||
50
+ pull_request.match?(branch: "#{organization_name}:#{branch}")
51
+ end
52
+ end
53
+
54
+ def pull_requests
55
+ @pull_requests ||= client.
56
+ pull_requests(tracker.repo_name, query: { state: statuses.first }).
57
+ map do |pull_request_data|
58
+ PullRequest.new(tracker: tracker,
59
+ data: pull_request_data)
60
+ end
61
+ end
62
+
63
+ def client
64
+ tracker.client
65
+ end
66
+
67
+ def statuses
68
+ @statuses ||= [:all]
69
+ end
70
+
71
+ def statuses=(other)
72
+ @statuses ||= other.nil? ? [:all] : other
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -18,45 +18,13 @@ class Tracker
18
18
  repo.base_name
19
19
  end
20
20
 
21
- # def ready_for_review(branch)
22
- #
23
- # No issue number
24
- # Find by title
25
- # Has issue number
26
- # Find by number
27
- #
28
- # Issue found
29
- # Issue closed
30
- # Ask to reopen issue
31
- # Issue open
32
- # Issue being reviewed
33
- # Issue not being reviewed
34
- # Issue not found
35
- # Ask to create issue
36
- #
37
- # Lookup Pull Request from Issue and Version Number
38
- #
39
- # Pull Request Found
40
- # How are PR's found?
41
- #
42
- # PR Title Format: #15 v1 - My Issue Title
43
- #
44
- # Pull Request Closed
45
- # Reopen PR
46
- # Pull Request Open
47
- # Use found PR
48
- # Pull Request Not Found
49
- # Create New PR
50
- #
51
- # pull_request = PullRequest.find_or_create_from_branch_name(branch.name)
52
- # issue = Issue.find_or_create_from_branch_name(branch.name)
53
- #
54
- # issue.ready_for_review(reviewer_names: branch.overwritten_authors)
55
- # end
56
- #
57
- # def update_pull_request(branch)
58
- # client.create_pull_request()
59
- # end
21
+ def organization_name
22
+ repo.organization
23
+ end
24
+
25
+ def me
26
+ client.login
27
+ end
60
28
  end
61
29
  end
62
30
  end
@@ -1,3 +1,3 @@
1
1
  module HustleAndFlow
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end
@@ -0,0 +1,17 @@
1
+ require 'hustle_and_flow/version_control'
2
+ require 'hustle_and_flow/version_controls/git/commands/ready'
3
+
4
+ module HustleAndFlow
5
+ module VersionControls
6
+ module Commands
7
+ class Ready
8
+ def self.call(**args)
9
+ version_controls_class = VersionControl.detect.name.gsub('::Repository', '')
10
+ command_class = const_get("::#{version_controls_class}::Commands::Ready")
11
+
12
+ command_class.call(**args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ module HustleAndFlow
2
+ module VersionControls
3
+ module Git
4
+ module Commands
5
+ class Ready
6
+ attr_accessor :repo,
7
+ :io
8
+
9
+ def initialize(**args)
10
+ self.repo = args[:repo]
11
+ self.io = args[:io]
12
+ end
13
+
14
+ def call
15
+ system('git update --quiet') &&
16
+ (
17
+ system('git ccrtb') ||
18
+ system('git poc')
19
+ ) &&
20
+ system('bundle exec rspec')
21
+ end
22
+
23
+ def self.call(**args)
24
+ new(**args).call
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -14,8 +14,12 @@ class Repository
14
14
  repo.config('github.user')
15
15
  end
16
16
 
17
+ def organization
18
+ repo_name_parts[0]
19
+ end
20
+
17
21
  def base_name
18
- origin_url[%r{github\.com.([\w\-]+/[\w\-]+)}, 1]
22
+ repo_name_parts.join('/')
19
23
  end
20
24
 
21
25
  def upstream_remote_for_branch(branch_name, value = nil)
@@ -47,6 +51,13 @@ class Repository
47
51
  branches: repo.branches)
48
52
  end
49
53
 
54
+ def current_branch
55
+ current = repo.branch(repo.current_branch)
56
+
57
+ Branch.new(repo: self,
58
+ branch: current)
59
+ end
60
+
50
61
  private
51
62
 
52
63
  def origin_url
@@ -64,6 +75,12 @@ class Repository
64
75
  def upstream_merge_config_key(branch_name)
65
76
  "branch.#{branch_name}.merge"
66
77
  end
78
+
79
+ def repo_name_parts
80
+ @repo_name_parts ||= origin_url[%r{github\.com.([\w\-]+/[\w\-]+)}, 1].
81
+ to_s.
82
+ split('/')
83
+ end
67
84
  end
68
85
  end
69
86
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hustle_and_flow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - thekompanee
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-13 00:00:00.000000000 Z
12
+ date: 2014-08-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: octokit
@@ -166,6 +166,7 @@ files:
166
166
  - bin/hustle
167
167
  - lib/hustle_and_flow.rb
168
168
  - lib/hustle_and_flow/binary/runner.rb
169
+ - lib/hustle_and_flow/commands/ready.rb
169
170
  - lib/hustle_and_flow/commands/start.rb
170
171
  - lib/hustle_and_flow/errors/unknown_issue_action_error.rb
171
172
  - lib/hustle_and_flow/formatters/branch_table_formatter.rb
@@ -173,18 +174,24 @@ files:
173
174
  - lib/hustle_and_flow/formatters/issue_table_formatter.rb
174
175
  - lib/hustle_and_flow/io/shell.rb
175
176
  - lib/hustle_and_flow/issue_tracker.rb
177
+ - lib/hustle_and_flow/issue_trackers/commands/ready.rb
176
178
  - lib/hustle_and_flow/issue_trackers/commands/start.rb
179
+ - lib/hustle_and_flow/issue_trackers/github/commands/ready.rb
177
180
  - lib/hustle_and_flow/issue_trackers/github/commands/start.rb
178
181
  - lib/hustle_and_flow/issue_trackers/github/issue.rb
179
182
  - lib/hustle_and_flow/issue_trackers/github/issues.rb
183
+ - lib/hustle_and_flow/issue_trackers/github/pull_request.rb
184
+ - lib/hustle_and_flow/issue_trackers/github/pull_requests.rb
180
185
  - lib/hustle_and_flow/issue_trackers/github/tracker.rb
181
186
  - lib/hustle_and_flow/utils/string.rb
182
187
  - lib/hustle_and_flow/utils/url_slug.rb
183
188
  - lib/hustle_and_flow/version.rb
184
189
  - lib/hustle_and_flow/version_control.rb
190
+ - lib/hustle_and_flow/version_controls/commands/ready.rb
185
191
  - lib/hustle_and_flow/version_controls/commands/start.rb
186
192
  - lib/hustle_and_flow/version_controls/git/branch.rb
187
193
  - lib/hustle_and_flow/version_controls/git/branches.rb
194
+ - lib/hustle_and_flow/version_controls/git/commands/ready.rb
188
195
  - lib/hustle_and_flow/version_controls/git/commands/start.rb
189
196
  - lib/hustle_and_flow/version_controls/git/repository.rb
190
197
  - spec/lib/hustle_and_flow/formatters/branch_table_formatter_spec.rb