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 +7 -7
- data/README +1 -0
- data/commands/commands.rb +57 -28
- data/commands/helpers.rb +36 -28
- data/lib/extensions.rb +28 -0
- data/lib/github.rb +41 -13
- data/lib/github/command.rb +1 -3
- data/spec/command_spec.rb +66 -0
- data/spec/extensions_spec.rb +34 -0
- data/spec/github_spec.rb +51 -0
- data/spec/helper_spec.rb +188 -0
- data/spec/spec_helper.rb +128 -4
- data/spec/ui_spec.rb +406 -0
- data/spec/windoze_spec.rb +36 -0
- metadata +21 -12
- data/spec/helpers/owner_spec.rb +0 -12
- data/spec/helpers/project_spec.rb +0 -24
- data/spec/helpers/public_url_for_spec.rb +0 -12
- data/spec/helpers/repo_for_spec.rb +0 -12
- data/spec/helpers/user_and_repo_from_spec.rb +0 -37
- data/spec/helpers/user_for_spec.rb +0 -12
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/
|
11
|
-
spec/
|
12
|
-
spec/
|
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
|
-
|
16
|
+
spec/ui_spec.rb
|
17
|
+
spec/windoze_spec.rb
|
data/README
CHANGED
data/commands/commands.rb
CHANGED
@@ -1,66 +1,95 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
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
|
-
|
7
|
-
|
8
|
+
desc "Open this repo in a web browser."
|
9
|
+
command :browse do |user, branch|
|
8
10
|
if helper.project
|
9
|
-
|
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
|
-
|
14
|
-
|
23
|
+
desc "Open the network page for this repo in a web browser."
|
24
|
+
command :network do |user|
|
15
25
|
if helper.project
|
16
|
-
|
26
|
+
user ||= helper.owner
|
27
|
+
helper.open helper.network_page_for(user)
|
17
28
|
end
|
18
29
|
end
|
19
30
|
|
20
|
-
|
21
|
-
|
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
|
-
|
31
|
-
|
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
|
-
|
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
|
-
|
39
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
57
|
-
|
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
|
-
|
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
|
-
|
8
|
+
helper :user_and_repo_for do |remote|
|
10
9
|
user_and_repo_from(url_for(remote))
|
11
10
|
end
|
12
11
|
|
13
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
33
|
+
helper :url_for do |remote|
|
35
34
|
`git config --get remote.#{remote}.url`.chomp
|
36
35
|
end
|
37
36
|
|
38
|
-
|
37
|
+
helper :remotes do
|
39
38
|
regexp = '^remote\.(.+)\.url$'
|
40
|
-
`git config --get-regexp '#{regexp}'`.split(/\n/).
|
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
|
42
|
+
memo[name.to_sym] = url
|
43
|
+
memo
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
|
48
|
-
remotes.
|
47
|
+
helper :tracking do
|
48
|
+
remotes.inject({}) do |memo, (name, url)|
|
49
49
|
if ur = user_and_repo_from(url)
|
50
|
-
[name
|
50
|
+
memo[name] = ur.first
|
51
51
|
else
|
52
|
-
[name
|
52
|
+
memo[name] = url
|
53
53
|
end
|
54
|
+
memo
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
57
|
-
|
58
|
-
tracking.include?(user)
|
58
|
+
helper :tracking? do |user|
|
59
|
+
tracking.values.include?(user)
|
59
60
|
end
|
60
61
|
|
61
|
-
|
62
|
+
helper :owner do
|
62
63
|
user_for(:origin)
|
63
64
|
end
|
64
65
|
|
65
|
-
|
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
|
-
|
76
|
+
helper :branch_user do
|
76
77
|
user_and_branch.first
|
77
78
|
end
|
78
79
|
|
79
|
-
|
80
|
+
helper :branch_name do
|
80
81
|
user_and_branch.last
|
81
82
|
end
|
82
83
|
|
83
|
-
|
84
|
+
helper :public_url_for do |user|
|
84
85
|
"git://github.com/#{user}/#{project}.git"
|
85
86
|
end
|
86
87
|
|
87
|
-
|
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
|
-
|
92
|
-
|
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
|
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
|
29
|
-
|
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
|
-
|
64
|
-
args.inject({}) do |memo, arg|
|
65
|
-
|
66
|
-
|
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
|
-
|
69
|
-
args.
|
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] == ?/ ?
|
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.
|
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
|
-
|
96
|
-
puts " #{
|
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
|
data/lib/github/command.rb
CHANGED
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
|