nex3-github 0.1.2 → 0.1.3

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.
data/Manifest CHANGED
@@ -1,17 +1,17 @@
1
1
  bin/github
2
2
  commands/commands.rb
3
3
  commands/helpers.rb
4
+ lib/extensions.rb
4
5
  lib/github/command.rb
5
6
  lib/github/helper.rb
6
7
  lib/github.rb
7
8
  LICENSE
9
+ Manifest
8
10
  README
9
11
  spec/command_spec.rb
10
- spec/helpers/owner_spec.rb
11
- spec/helpers/project_spec.rb
12
- spec/helpers/public_url_for_spec.rb
13
- spec/helpers/repo_for_spec.rb
14
- spec/helpers/user_and_repo_from_spec.rb
15
- spec/helpers/user_for_spec.rb
12
+ spec/extensions_spec.rb
13
+ spec/github_spec.rb
14
+ spec/helper_spec.rb
16
15
  spec/spec_helper.rb
17
- Manifest
16
+ spec/ui_spec.rb
17
+ spec/windoze_spec.rb
data/README CHANGED
@@ -51,3 +51,4 @@ Contributors
51
51
  - defunkt
52
52
  - maddox
53
53
  - halorgium
54
+ - kballard
data/commands/commands.rb CHANGED
@@ -1,66 +1,95 @@
1
- GitHub.register :helper do |name, comma_args|
2
- comma_args ||= ''
3
- puts helper.send(name, comma_args.split(/,/))
1
+ desc "Open this repo's master branch in a web browser."
2
+ command :home do |user|
3
+ if helper.project
4
+ helper.open helper.homepage_for(user || helper.owner, 'master')
5
+ end
4
6
  end
5
7
 
6
- GitHub.describe :home => "Open this repo's master branch in a web browser."
7
- GitHub.register :home do
8
+ desc "Open this repo in a web browser."
9
+ command :browse do |user, branch|
8
10
  if helper.project
9
- exec "#{helper.open} #{helper.homepage_for(helper.owner, 'master')}"
11
+ # if one arg given, treat it as a branch name
12
+ # unless it maches user/branch, then split it
13
+ # if two args given, treat as user branch
14
+ # if no args given, use defaults
15
+ user, branch = user.split("/", 2) if branch.nil? unless user.nil?
16
+ branch = user and user = nil if branch.nil?
17
+ user ||= helper.branch_user
18
+ branch ||= helper.branch_name
19
+ helper.open helper.homepage_for(user, branch)
10
20
  end
11
21
  end
12
22
 
13
- GitHub.describe :browse => "Open this repo in a web browser."
14
- GitHub.register :browse do
23
+ desc "Open the network page for this repo in a web browser."
24
+ command :network do |user|
15
25
  if helper.project
16
- exec "#{helper.open} #{helper.homepage_for(helper.branch_user, helper.branch_name)}"
26
+ user ||= helper.owner
27
+ helper.open helper.network_page_for(user)
17
28
  end
18
29
  end
19
30
 
20
- GitHub.describe :info => "Info about this project."
21
- GitHub.register :info do
31
+ desc "Info about this project."
32
+ command :info do
22
33
  puts "== Info for #{helper.project}"
23
34
  puts "You are #{helper.owner}"
24
- puts "Currently tracking: "
35
+ puts "Currently tracking:"
25
36
  helper.tracking.each do |(name,user_or_url)|
26
37
  puts " - #{user_or_url} (as #{name})"
27
38
  end
28
39
  end
29
40
 
30
- GitHub.describe :track => "Track another user's repository."
31
- GitHub.register :track do |user|
41
+ desc "Track another user's repository."
42
+ flags :private => "Use git@github.com: instead of git://github.com/."
43
+ command :track do |user|
32
44
  die "Specify a user to track" if user.nil?
33
45
  die "Already tracking #{user}" if helper.tracking?(user)
34
46
 
35
- git "remote add #{user} #{helper.public_url_for(user)}"
47
+ if options[:private]
48
+ git "remote add #{user} #{helper.private_url_for(user)}"
49
+ else
50
+ git "remote add #{user} #{helper.public_url_for(user)}"
51
+ end
36
52
  end
37
53
 
38
- GitHub.describe :pull => "Pull from a remote. Pass --merge to automatically merge remote's changes into your master."
39
- GitHub.register :pull do |user, branch|
54
+ desc "Pull from a remote."
55
+ flags :merge => "Automatically merge remote's changes into your master."
56
+ command :pull do |user, branch|
40
57
  die "Specify a user to pull from" if user.nil?
41
- GitHub.invoke(:track, user) unless helper.tracking?(user)
58
+ user, branch = user.split("/", 2) if branch.nil?
42
59
  branch ||= 'master'
43
-
44
- puts "Switching to #{user}/#{branch}"
45
- git "checkout #{user}/#{branch}" if git("checkout -b #{user}/#{branch}").error?
60
+ GitHub.invoke(:track, user) unless helper.tracking?(user)
46
61
 
47
62
  if options[:merge]
48
- git "pull #{user} #{branch}"
49
- git "checkout master"
50
- git_exec "merge #{user}/#{branch}"
63
+ git_exec "pull #{user} #{branch}"
51
64
  else
65
+ puts "Switching to #{user}/#{branch}"
66
+ git "checkout #{user}/#{branch}" if git("checkout -b #{user}/#{branch}").error?
52
67
  git_exec "pull #{user} #{branch}"
53
68
  end
54
69
  end
55
70
 
56
- GitHub.describe :clone => "Clone a repo. Pass --ssh to clone from your own git@github.com schema."
57
- GitHub.register :clone do |user, repo|
71
+ desc "Clone a repo."
72
+ flags :ssh => "Clone using the git@github.com style url."
73
+ command :clone do |user, repo, dir|
74
+ die "Specify a user to pull from" if user.nil?
58
75
  user, repo = user.split('/') unless repo
59
76
  die "Specify a repo to pull from" if repo.nil?
60
77
 
61
78
  if options[:ssh]
62
- git_exec "clone git@github.com:#{user}/#{repo}.git"
79
+ git_exec "clone git@github.com:#{user}/#{repo}.git" + (dir ? " #{dir}" : "")
63
80
  else
64
- git_exec "clone git://github.com/#{user}/#{repo}.git"
81
+ git_exec "clone git://github.com/#{user}/#{repo}.git" + (dir ? " #{dir}" : "")
82
+ end
83
+ end
84
+
85
+ desc "Generate the text for a pull request."
86
+ command :'pull-request' do |user, branch|
87
+ if helper.project
88
+ die "Specify a user for the pull request" if user.nil?
89
+ user, branch = user.split('/', 2) if branch.nil?
90
+ branch ||= 'master'
91
+ GitHub.invoke(:track, user) unless helper.tracking?(user)
92
+
93
+ git_exec "request-pull #{user}/#{branch} origin"
65
94
  end
66
95
  end
data/commands/helpers.rb CHANGED
@@ -1,26 +1,25 @@
1
- GitHub.helper :user_and_repo_from do |url|
1
+ helper :user_and_repo_from do |url|
2
2
  case url
3
3
  when %r|^git://github\.com/([^/]+/[^/]+)$|: $1.split('/')
4
4
  when %r|^(?:ssh://)?(?:git@)?github\.com:([^/]+/[^/]+)$|: $1.split('/')
5
- else ['', '']
6
5
  end
7
6
  end
8
7
 
9
- GitHub.helper :user_and_repo_for do |remote|
8
+ helper :user_and_repo_for do |remote|
10
9
  user_and_repo_from(url_for(remote))
11
10
  end
12
11
 
13
- GitHub.helper :user_for do |remote|
14
- user_and_repo_for(remote).first
12
+ helper :user_for do |remote|
13
+ user_and_repo_for(remote).try.first
15
14
  end
16
15
 
17
- GitHub.helper :repo_for do |remote|
18
- user_and_repo_for(remote).last
16
+ helper :repo_for do |remote|
17
+ user_and_repo_for(remote).try.last
19
18
  end
20
19
 
21
- GitHub.helper :project do
20
+ helper :project do
22
21
  repo = repo_for(:origin)
23
- if repo == ""
22
+ if repo.nil?
24
23
  if url_for(:origin) == ""
25
24
  STDERR.puts "Error: missing remote 'origin'"
26
25
  else
@@ -31,38 +30,40 @@ GitHub.helper :project do
31
30
  repo.chomp('.git')
32
31
  end
33
32
 
34
- GitHub.helper :url_for do |remote|
33
+ helper :url_for do |remote|
35
34
  `git config --get remote.#{remote}.url`.chomp
36
35
  end
37
36
 
38
- GitHub.helper :remotes do
37
+ helper :remotes do
39
38
  regexp = '^remote\.(.+)\.url$'
40
- `git config --get-regexp '#{regexp}'`.split(/\n/).map do |line|
39
+ `git config --get-regexp '#{regexp}'`.split(/\n/).inject({}) do |memo, line|
41
40
  name_string, url = line.split(/ /, 2)
42
41
  m, name = *name_string.match(/#{regexp}/)
43
- [name, url]
42
+ memo[name.to_sym] = url
43
+ memo
44
44
  end
45
45
  end
46
46
 
47
- GitHub.helper :tracking do
48
- remotes.map do |(name, url)|
47
+ helper :tracking do
48
+ remotes.inject({}) do |memo, (name, url)|
49
49
  if ur = user_and_repo_from(url)
50
- [name, ur.first]
50
+ memo[name] = ur.first
51
51
  else
52
- [name, url]
52
+ memo[name] = url
53
53
  end
54
+ memo
54
55
  end
55
56
  end
56
57
 
57
- GitHub.helper :tracking? do |user|
58
- tracking.include?(user)
58
+ helper :tracking? do |user|
59
+ tracking.values.include?(user)
59
60
  end
60
61
 
61
- GitHub.helper :owner do
62
+ helper :owner do
62
63
  user_for(:origin)
63
64
  end
64
65
 
65
- GitHub.helper :user_and_branch do
66
+ helper :user_and_branch do
66
67
  raw_branch = `git rev-parse --symbolic-full-name HEAD`.chomp.sub(/^refs\/heads\//, '')
67
68
  user, branch = raw_branch.split(/\//, 2)
68
69
  if branch
@@ -72,23 +73,30 @@ GitHub.helper :user_and_branch do
72
73
  end
73
74
  end
74
75
 
75
- GitHub.helper :branch_user do
76
+ helper :branch_user do
76
77
  user_and_branch.first
77
78
  end
78
79
 
79
- GitHub.helper :branch_name do
80
+ helper :branch_name do
80
81
  user_and_branch.last
81
82
  end
82
83
 
83
- GitHub.helper :public_url_for do |user|
84
+ helper :public_url_for do |user|
84
85
  "git://github.com/#{user}/#{project}.git"
85
86
  end
86
87
 
87
- GitHub.helper :homepage_for do |user, branch|
88
+ helper :private_url_for do |user|
89
+ "git@github.com:#{user}/#{project}.git"
90
+ end
91
+
92
+ helper :homepage_for do |user, branch|
88
93
  "https://github.com/#{user}/#{project}/tree/#{branch}"
89
94
  end
90
95
 
91
- GitHub.helper :open do
92
- Windoze ? 'start' : 'open'
96
+ helper :network_page_for do |user|
97
+ "https://github.com/#{user}/#{project}/network"
98
+ end
99
+
100
+ helper :open do |url|
101
+ Launchy::Browser.new.visit url
93
102
  end
94
-
data/lib/extensions.rb ADDED
@@ -0,0 +1,28 @@
1
+ # define #try
2
+ class Object
3
+ def try
4
+ self
5
+ end
6
+ end
7
+
8
+ class NilClass
9
+ klass = Class.new
10
+ klass.class_eval do
11
+ instance_methods.each { |meth| undef_method meth.to_sym unless meth =~ /^__(id|send)__$/ }
12
+ def method_missing(*args)
13
+ nil
14
+ end
15
+ end
16
+ NilProxy = klass.new
17
+ def try
18
+ NilProxy
19
+ end
20
+ end
21
+
22
+ # define #tap
23
+ class Object
24
+ def tap(&block)
25
+ block.call(self)
26
+ self
27
+ end
28
+ end
data/lib/github.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
+ require 'extensions'
2
3
  require 'github/command'
3
4
  require 'github/helper'
5
+ require 'rubygems'
6
+ require 'launchy'
4
7
 
5
8
  ##
6
9
  # Starting simple.
@@ -20,13 +23,22 @@ module GitHub
20
23
 
21
24
  BasePath = File.expand_path(File.dirname(__FILE__) + '/..')
22
25
 
23
- def register(command, &block)
26
+ def command(command, &block)
24
27
  debug "Registered `#{command}`"
28
+ descriptions[command] = @next_description if @next_description
29
+ @next_description = nil
30
+ flag_descriptions[command].update @next_flags if @next_flags
31
+ @next_flags = nil
25
32
  commands[command.to_s] = Command.new(block)
26
33
  end
27
34
 
28
- def describe(hash)
29
- descriptions.update hash
35
+ def desc(str)
36
+ @next_description = str
37
+ end
38
+
39
+ def flags(hash)
40
+ @next_flags ||= {}
41
+ @next_flags.update hash
30
42
  end
31
43
 
32
44
  def helper(command, &block)
@@ -55,27 +67,38 @@ module GitHub
55
67
  @descriptions ||= {}
56
68
  end
57
69
 
70
+ def flag_descriptions
71
+ @flagdescs ||= Hash.new { |h, k| h[k] = {} }
72
+ end
73
+
58
74
  def options
59
75
  @options
60
76
  end
61
77
 
62
78
  def parse_options(args)
63
- @debug = args.delete('--debug')
64
- args.inject({}) do |memo, arg|
65
- if arg =~ /^--([^=]+)=(.+)/
66
- args.delete(arg)
79
+ idx = 0
80
+ args.clone.inject({}) do |memo, arg|
81
+ case arg
82
+ when /^--(.+?)=(.*)/
83
+ args.delete_at(idx)
67
84
  memo.merge($1.to_sym => $2)
68
- elsif arg =~ /^--(.+)/
69
- args.delete(arg)
85
+ when /^--(.+)/
86
+ args.delete_at(idx)
70
87
  memo.merge($1.to_sym => true)
88
+ when "--"
89
+ args.delete_at(idx)
90
+ return memo
71
91
  else
92
+ idx += 1
72
93
  memo
73
94
  end
74
95
  end
75
96
  end
76
97
 
77
98
  def load(file)
78
- file[0] == ?/ ? super : super(BasePath + "/commands/#{file}")
99
+ file[0] == ?/ ? path = file : path = BasePath + "/commands/#{file}"
100
+ data = File.read(path)
101
+ GitHub.module_eval data, path
79
102
  end
80
103
 
81
104
  def debug(*messages)
@@ -87,13 +110,18 @@ module GitHub
87
110
  end
88
111
  end
89
112
 
90
- GitHub.register :default do
113
+ GitHub.command :default do
91
114
  puts "Usage: github command <space separated arguments>", ''
92
115
  puts "Available commands:", ''
93
116
  longest = GitHub.descriptions.map { |d,| d.to_s.size }.max
94
117
  GitHub.descriptions.each do |command, desc|
95
- command = "%-#{longest}s" % command
96
- puts " #{command} => #{desc}"
118
+ cmdstr = "%-#{longest}s" % command
119
+ puts " #{cmdstr} => #{desc}"
120
+ flongest = GitHub.flag_descriptions[command].map { |d,| "--#{d}".size }.max
121
+ GitHub.flag_descriptions[command].each do |flag, fdesc|
122
+ flagstr = "#{" " * longest} %-#{flongest}s" % "--#{flag}"
123
+ puts " #{flagstr}: #{fdesc}"
124
+ end
97
125
  end
98
126
  puts
99
127
  end
@@ -1,6 +1,4 @@
1
- Windoze = RUBY_PLATFORM =~ /mswin|mingw/
2
-
3
- if Windoze
1
+ if RUBY_PLATFORM =~ /mswin|mingw/
4
2
  begin
5
3
  require 'win32/open3'
6
4
  rescue LoadError
data/spec/command_spec.rb CHANGED
@@ -0,0 +1,66 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe GitHub::Command do
4
+ before(:each) do
5
+ @command = GitHub::Command.new(proc { |x| puts x })
6
+ end
7
+
8
+ it "should return a GitHub::Helper" do
9
+ @command.helper.should be_instance_of(GitHub::Helper)
10
+ end
11
+
12
+ it "should call successfully" do
13
+ @command.should_receive(:puts).with("test").once
14
+ @command.call("test")
15
+ end
16
+
17
+ it "should return options" do
18
+ GitHub.should_receive(:options).with().once.and_return({:ssh => true})
19
+ @command.options.should == {:ssh => true}
20
+ end
21
+
22
+ it "should successfully call out to the shell" do
23
+ unguard(Kernel, :fork)
24
+ unguard(Kernel, :exec)
25
+ hi = @command.sh("echo hi")
26
+ hi.should == "hi"
27
+ hi.out?.should be(true)
28
+ hi.error?.should be(false)
29
+ hi.command.should == "echo hi"
30
+ bye = @command.sh("echo bye >&2")
31
+ bye.should == "bye"
32
+ bye.out?.should be(false)
33
+ bye.error?.should be(true)
34
+ bye.command.should == "echo bye >&2"
35
+ end
36
+
37
+ it "should return the results of a git operation" do
38
+ GitHub::Command::Shell.should_receive(:new).with("git rev-parse master").once.and_return do |*cmds|
39
+ s = mock("GitHub::Commands::Shell")
40
+ s.should_receive(:run).once.and_return("sha1")
41
+ s
42
+ end
43
+ @command.git("rev-parse master").should == "sha1"
44
+ end
45
+
46
+ it "should print the results of a git operation" do
47
+ @command.should_receive(:puts).with("sha1").once
48
+ GitHub::Command::Shell.should_receive(:new).with("git rev-parse master").once.and_return do |*cmds|
49
+ s = mock("GitHub::Commands::Shell")
50
+ s.should_receive(:run).once.and_return("sha1")
51
+ s
52
+ end
53
+ @command.pgit("rev-parse master")
54
+ end
55
+
56
+ it "should exec a git command" do
57
+ @command.should_receive(:exec).with("git rev-parse master").once
58
+ @command.git_exec "rev-parse master"
59
+ end
60
+
61
+ it "should die" do
62
+ @command.should_receive(:puts).once.with("=> message")
63
+ @command.should_receive(:exit!).once
64
+ @command.die "message"
65
+ end
66
+ end