hull 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,6 +6,8 @@ require 'grit'
6
6
  require 'hull/command'
7
7
  require 'hull/hull'
8
8
  require 'hull/list'
9
+ require 'hull/help'
10
+ require 'hull/show'
9
11
 
10
12
  module Hull
11
13
  end
@@ -12,7 +12,7 @@ module Hull
12
12
  :white => "37",
13
13
  }
14
14
 
15
- def write(text, color)
15
+ def self.write(text, color)
16
16
  if BASH_COLORS.keys.include?(color)
17
17
  "\033[#{BASH_COLORS[color]}m#{text}\033[#{BASH_COLORS[:reset]}m"
18
18
  else
@@ -20,19 +20,19 @@ module Hull
20
20
  end
21
21
  end
22
22
 
23
- def error(text); puts "#{write('error', :red) }: #{text}"; end
24
- def warn(text); puts "#{write('warning', :purple)}: #{text}"; end
25
- def note(text); puts "#{write('note', :green) }: #{text}"; end
23
+ def self.error(text); puts "#{write('error', :red) }: #{text}"; end
24
+ def self.warn(text); puts "#{write('warning', :purple)}: #{text}"; end
25
+ def self.note(text); puts "#{write('note', :green) }: #{text}"; end
26
26
 
27
- def column_size
27
+ def self.column_size
28
28
  [ `stty size`.scan(/\d+/).last.to_i, 80 ].max
29
29
  end
30
30
 
31
- def pad_left(str, length)
31
+ def self.pad_left(str, length)
32
32
  "% #{length}s" % str[0, length]
33
33
  end
34
34
 
35
- def pad_right(str, length)
35
+ def self.pad_right(str, length)
36
36
  if str.length > length
37
37
  "#{str[0, length - 3]}..."
38
38
  elsif str.length < length
@@ -42,7 +42,7 @@ module Hull
42
42
  end
43
43
  end
44
44
 
45
- def validate_config
45
+ def self.validate_config
46
46
  if username == '' || api_token == ''
47
47
  error('github.user and github.token not found in git config')
48
48
  Help.new
@@ -52,35 +52,35 @@ module Hull
52
52
  end
53
53
  end
54
54
 
55
- def username
56
- @username ||= repo.config['github.user']
55
+ def self.username
56
+ @username ||= config['github.user']
57
57
  end
58
58
 
59
- def api_token
60
- @api_token ||= repo.config['github.token']
59
+ def self.api_token
60
+ @api_token ||= config['github.token']
61
61
  end
62
62
 
63
- def remote
64
- @remote ||= (repo.config['hull.remote'] || 'origin')
63
+ def self.remote
64
+ @remote ||= (config['hull.remote'] || 'origin')
65
65
  end
66
66
 
67
- def github_url
68
- @github_url ||=
69
- begin
70
- unless valid_repository?(repo)
71
- raise InvalidRepository.new("Must be a GitHub repository")
72
- end
73
- _, owner, project = repo.config["remote.#{remote}.url"].match(/^git@github.com:([^\/]*)\/(.*)/).to_a
74
- project.gsub!(/\.git$/, '')
75
- "https://github.com/api/v2/json/pulls/#{owner}/#{project}"
76
- end
67
+ def self.github_url(number=nil)
68
+ raise InvalidRepository unless has_valid_repository?
69
+ url = config["remote.#{remote}.url"]
70
+ _, owner, project = url.match(/^git@github.com:([^\/]*)\/(.*)/).to_a
71
+ project.gsub!(/\.git$/, '')
72
+ "https://github.com/api/v2/json/pulls/#{owner}/#{project}/#{number}"
77
73
  end
78
74
 
79
- def repo
75
+ def self.repo
80
76
  @repo = Grit::Repo.new(".")
81
77
  end
82
78
 
83
- def get_json(url)
79
+ def self.config
80
+ repo.config
81
+ end
82
+
83
+ def self.get_json(url)
84
84
  options = {
85
85
  :http_basic_authentication => [
86
86
  "#{username}/token",
@@ -90,10 +90,11 @@ module Hull
90
90
  JSON.load(open(url, options))
91
91
  end
92
92
 
93
- def valid_repository?(repository)
94
- repository.remote_list.include?(remote) &&
95
- repository.config["remote.#{remote}.url"].match(/^git@github.com:/)
93
+ def self.has_valid_repository?
94
+ repo.remote_list.include?(remote) &&
95
+ config["remote.#{remote}.url"].match(/^git@github.com:/)
96
96
  end
97
+
97
98
  end
98
99
 
99
100
  class InvalidRepository < RuntimeError; end
@@ -0,0 +1,65 @@
1
+ module Hull
2
+ class Help < Command
3
+ def self.title(title)
4
+ write(title, :cyan)
5
+ end
6
+
7
+ def self.hull
8
+ write('hull', :yellow)
9
+ end
10
+
11
+ def self.command(command)
12
+ write(command, :pink)
13
+ end
14
+
15
+ def self.number(number)
16
+ write(number, :purple)
17
+ end
18
+
19
+ def self.red(red)
20
+ write(red, :red)
21
+ end
22
+
23
+ def self.help
24
+ <<HELP
25
+ #{title('### Setup')}
26
+
27
+ Config Github user name:
28
+
29
+ $ git config github.username <github_username>
30
+
31
+ Config GitHub API key (https://github.com/account/admin):
32
+
33
+ $ git config github.token <api_token>
34
+
35
+ #{title('### Usage')}
36
+
37
+ This help doc:
38
+
39
+ $ #{hull} #{command('help')}
40
+
41
+ List all pull requests for this project:
42
+
43
+ $ #{hull} #{command('list')}
44
+
45
+ Show details about pull request number <number>:
46
+
47
+ $ #{hull} #{command('show')} <#{number('number')}>
48
+
49
+ #{title('### Unimplemented Features')}
50
+
51
+ Check out the contents of pull request number <number> and switch to that branch:
52
+
53
+ $ #{hull} <#{command('checkout')}|#{command('co')}|#{command('pull')}> <#{number('number')}>
54
+
55
+ Remove contents of pull request <number> that has been checked out:
56
+
57
+ $ #{hull} <#{command('rm')}|#{command('remove')}|#{command('delete')}> <#{number('number')}>
58
+
59
+ #{title('### Why Hull?')}
60
+
61
+ Originally it was called puller, but @natekross pushed a gem with the same name to rubygems.org, literally the day I started working on Hull. #{red("\x28\xe2\x95\xaf\xc2\xb0\xe2\x96\xa1\xc2\xb0\xef\xbc\x89\xe2\x95\xaf")}\xef\xb8\xb5\x20\xe2\x94\xbb\xe2\x94\x81\xe2\x94\xbb
62
+ HELP
63
+ end
64
+ end
65
+ end
@@ -9,14 +9,15 @@ module Hull
9
9
  def run
10
10
  case command
11
11
  when 'list'
12
- List.new
12
+ puts List.run
13
13
  when 'show'
14
- Show.new(number)
14
+ puts Show.run(number)
15
15
  when 'pull', 'checkout', 'co'
16
16
  Pull.new(number)
17
17
  when 'rm', 'remove', 'delete'
18
18
  Remove.new(number)
19
- else # help
19
+ else
20
+ puts Help.help
20
21
  end
21
22
  end
22
23
 
@@ -1,26 +1,27 @@
1
1
  module Hull
2
2
  class List < Command
3
- def initialize
3
+ def self.run
4
4
  validate_config
5
5
  json = get_json(github_url)
6
6
  if json['error'].to_s != ''
7
- return error("Pull request ##{request_number} might not exist.")
7
+ return error(json['error'])
8
8
  end
9
9
 
10
10
  pulls = json['pulls']
11
- puts "Number of pull requests: #{pulls.length}"
12
11
  return if pulls.length == 0
13
12
 
14
13
  branch_names = pulls.map { |pull| pull['head']['label'].split(/:/) }
15
14
  @repo_len = [ branch_names.map(&:first).map(&:length).max, 15 ].min
16
15
  @branch_len = [ branch_names.map(&:last).map(&:length).max, 30 ].min
17
16
 
17
+ lines = [ "Number of pull requests: #{pulls.length}" ]
18
18
  pulls.each do |pull|
19
- puts pull_info(pull)
19
+ lines << pull_info(pull)
20
20
  end
21
+ lines.join("\n")
21
22
  end
22
23
 
23
- def pull_info(pull)
24
+ def self.pull_info(pull)
24
25
  number = pull['number'].to_s
25
26
  mergeable = pull['mergeable']
26
27
  title = pull['title']
@@ -0,0 +1,72 @@
1
+ module Hull
2
+ class Show < Command
3
+ def self.run(number)
4
+ validate_config
5
+
6
+ url = github_url(number)
7
+ begin
8
+ body = get_json(url)
9
+ rescue OpenURI::HTTPError
10
+ return error("Pull request ##{number} might not exist. Try running 'hull list'.")
11
+ end
12
+
13
+ if body['error'].to_s != ''
14
+ return error(body['error'])
15
+ end
16
+
17
+ pull = body["pull"]
18
+ title = pull["title"]
19
+ description = pull["body"]
20
+ discussions = pull["discussion"]
21
+ comments = discussions.select do |msg|
22
+ msg["type"] =~ /Comment/
23
+ end.map do |msg|
24
+ message = {}
25
+ message[:user] = msg["user"]["login"]
26
+ message[:message] = msg["body"]
27
+ message[:path] = msg["path"]
28
+ message
29
+ end
30
+
31
+ if pull['merged_at']
32
+ merge_status = write('MERGED', :green)
33
+ elsif pull['mergeable']
34
+ merge_status = write('NOT MERGED', :yellow)
35
+ elsif pull["state"] == "closed"
36
+ merge_status = write('CLOSED', :red)
37
+ else
38
+ merge_status = write('CONFLICT', :red)
39
+ end
40
+
41
+ lines = []
42
+ lines << "Number: #{write(number, :yellow)}"
43
+ lines << "Title: #{write(title, :purple)}"
44
+ lines << "Description: #{pad_right(description.gsub(/[\r\n]+/, ' '), column_size - 13)}"
45
+ lines << "Status: #{merge_status}"
46
+
47
+ if comments.length > 0
48
+ lines.push('', 'Comments:')
49
+ comments.each do |comment|
50
+ lines << write_comment(comment)
51
+ end
52
+ end
53
+ lines.join("\n")
54
+ end
55
+
56
+ def self.write_comment(comment)
57
+ arr = []
58
+ remaining_cols = column_size
59
+ if comment[:path]
60
+ path = comment[:path].split(/\//).last
61
+ arr.push('@', write(path, :pink), ' ')
62
+ remaining_cols -= path.length + 2
63
+ end
64
+ arr.push('<', write(comment[:user], :yellow), '>')
65
+ remaining_cols -= comment[:user].length + 4
66
+ remaining_cols = [ remaining_cols, 30 ].max
67
+ message = pad_right(comment[:message].gsub(/[\r\n]+/, ' '), remaining_cols)
68
+ arr.push(': ', write(message, :white))
69
+ arr.join('')
70
+ end
71
+ end
72
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hull
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-01-20 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &70150332753920 !ruby/object:Gem::Requirement
16
+ requirement: &70337977483900 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70150332753920
24
+ version_requirements: *70337977483900
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: grit
27
- requirement: &70150332753480 !ruby/object:Gem::Requirement
27
+ requirement: &70337977483460 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70150332753480
35
+ version_requirements: *70337977483460
36
36
  description: Code Review helper using GitHub's Pull Requests
37
37
  email: hc5duke@gmail.com
38
38
  executables: