hustle_and_flow 0.0.3 → 0.0.4

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: 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