github 0.1.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/History.txt +37 -0
  2. data/Manifest +33 -12
  3. data/README.md +187 -0
  4. data/Rakefile +44 -0
  5. data/bin/gh +8 -0
  6. data/bin/github +4 -1
  7. data/github.gemspec +29 -34
  8. data/lib/commands/commands.rb +249 -0
  9. data/lib/commands/helpers.rb +486 -0
  10. data/lib/commands/issues.rb +17 -0
  11. data/lib/commands/network.rb +110 -0
  12. data/lib/github.rb +117 -29
  13. data/lib/github/command.rb +69 -14
  14. data/lib/github/extensions.rb +39 -0
  15. data/lib/github/ui.rb +19 -0
  16. data/setup.rb +1551 -0
  17. data/spec/command_spec.rb +82 -0
  18. data/spec/commands/command_browse_spec.rb +36 -0
  19. data/spec/commands/command_clone_spec.rb +87 -0
  20. data/spec/commands/command_create-from-local_spec.rb +7 -0
  21. data/spec/commands/command_fetch_spec.rb +56 -0
  22. data/spec/commands/command_fork_spec.rb +44 -0
  23. data/spec/commands/command_helper.rb +170 -0
  24. data/spec/commands/command_home_spec.rb +20 -0
  25. data/spec/commands/command_info_spec.rb +23 -0
  26. data/spec/commands/command_issues_spec.rb +97 -0
  27. data/spec/commands/command_network_spec.rb +30 -0
  28. data/spec/commands/command_pull-request_spec.rb +51 -0
  29. data/spec/commands/command_pull_spec.rb +82 -0
  30. data/spec/commands/command_search_spec.rb +34 -0
  31. data/spec/commands/command_track_spec.rb +82 -0
  32. data/spec/commands_spec.rb +49 -0
  33. data/spec/extensions_spec.rb +36 -0
  34. data/spec/github_spec.rb +85 -0
  35. data/spec/helper_spec.rb +368 -0
  36. data/spec/spec_helper.rb +160 -4
  37. data/spec/windoze_spec.rb +38 -0
  38. metadata +114 -47
  39. data/README +0 -49
  40. data/commands/commands.rb +0 -54
  41. data/commands/helpers.rb +0 -79
  42. data/spec/helpers/owner_spec.rb +0 -12
  43. data/spec/helpers/project_spec.rb +0 -12
  44. data/spec/helpers/public_url_for_spec.rb +0 -12
  45. data/spec/helpers/repo_for_spec.rb +0 -12
  46. data/spec/helpers/user_and_repo_from_spec.rb +0 -15
  47. data/spec/helpers/user_for_spec.rb +0 -12
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.dirname(__FILE__) + '/command_helper'
3
+
4
+ describe "github home" do
5
+ include CommandHelper
6
+
7
+ specify "home should open the project home page" do
8
+ running :home do
9
+ setup_url_for
10
+ @helper.should_receive(:open).once.with("https://github.com/user/project/tree/master")
11
+ end
12
+ end
13
+
14
+ specify "home defunkt should open the home page of defunkt's fork" do
15
+ running :home, "defunkt" do
16
+ setup_url_for
17
+ @helper.should_receive(:open).once.with("https://github.com/defunkt/project/tree/master")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.dirname(__FILE__) + '/command_helper'
3
+
4
+ describe "github info" do
5
+ include CommandHelper
6
+
7
+ specify "info should show info for this project" do
8
+ running :info do
9
+ setup_url_for
10
+ setup_remote(:origin, :user => "user", :ssh => true)
11
+ setup_remote(:defunkt)
12
+ setup_remote(:external, :url => "home:/path/to/project.git")
13
+ stdout.should == <<-EOF
14
+ == Info for project
15
+ You are user
16
+ Currently tracking:
17
+ - defunkt (as defunkt)
18
+ - home:/path/to/project.git (as external)
19
+ - user (as origin)
20
+ EOF
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,97 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.dirname(__FILE__) + '/command_helper'
3
+
4
+ describe "github issues" do
5
+ include CommandHelper
6
+
7
+ specify "issues without args should show help" do
8
+ running :issues do
9
+ setup_url_for
10
+ stdout.should == <<-EOS.gsub(/^ /, '')
11
+ You have to provide a command :
12
+
13
+ open - shows open tickets for this project
14
+ closed - shows closed tickets for this project
15
+
16
+ --user=<username> - show issues from <username>'s repository
17
+ --after=<date> - only show issues updated after <date>
18
+
19
+ EOS
20
+ end
21
+ end
22
+
23
+ specify "issues web opens the project's issues page" do
24
+ running :issues, "open" do
25
+ setup_url_for
26
+ mock_issues_for "open"
27
+ stdout.should == <<-EOS.gsub(/^ /, '')
28
+ -----
29
+ Issue #1 (0 votes): members.json 500 error
30
+ * Opened about 10 hours ago by bug_finder
31
+ * Last updated 5 minutes ago
32
+
33
+ I have a nasty bug.
34
+ -----
35
+ EOS
36
+ end
37
+ end
38
+
39
+ specify "issues web closed the project's issues page" do
40
+ running :issues, "closed" do
41
+ setup_url_for
42
+ mock_issues_for "closed"
43
+ stdout.should == <<-EOS.gsub(/^ /, '')
44
+ -----
45
+ Issue #1 (0 votes): members.json 500 error
46
+ * Opened about 10 hours ago by bug_finder
47
+ * Closed 5 minutes ago
48
+ * Last updated 5 minutes ago
49
+
50
+ I have a nasty bug.
51
+ -----
52
+ EOS
53
+ end
54
+ end
55
+
56
+ specify "issues web opens the project's issues page" do
57
+ running :issues, "web" do
58
+ setup_url_for
59
+ @helper.should_receive(:open).once.with("https://github.com/user/project/issues")
60
+ end
61
+ end
62
+
63
+ specify "issues web <user> opens the project's issues page for a user repo" do
64
+ running :issues, "web", "drnic" do
65
+ setup_url_for
66
+ @helper.should_receive(:open).once.with("https://github.com/drnic/project/issues")
67
+ end
68
+ end
69
+
70
+ class CommandHelper::Runner
71
+ def mock_issues_for(state = "open", options = {})
72
+ options[:updated_at] = 5.minutes.ago
73
+ options[:closed_at] = 5.minutes.ago
74
+ options[:created_at] = 10.hours.ago
75
+ options[:user] = "user"
76
+ options[:project] = "project"
77
+ yaml = <<-YAML.gsub(/^ /, '')
78
+ ---
79
+ issues:
80
+ - number: 1
81
+ votes: 0
82
+ created_at: #{options[:created_at].strftime("%Y-%m-%d %H:%M:%S %z")}
83
+ body: |-
84
+ I have a nasty bug.
85
+ title: members.json 500 error
86
+ updated_at: #{options[:updated_at].strftime("%Y-%m-%d %H:%M:%S %z")}
87
+ #{"closed_at: #{options[:closed_at].strftime("%Y-%m-%d %H:%M:%S %z")}" if state == "closed"}
88
+ user: bug_finder
89
+ labels: []
90
+
91
+ state: #{state}
92
+ YAML
93
+ api_url = "http://github.com/api/v2/yaml/issues/list/#{options[:user]}/#{options[:project]}/#{state}"
94
+ @command.should_receive(:open).with(api_url).and_return(yaml)
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.dirname(__FILE__) + '/command_helper'
3
+
4
+ describe "github network" do
5
+ include CommandHelper
6
+
7
+ specify "network list should show all users with a fork" do
8
+ running :network, 'list' do
9
+ setup_url_for 'origin', 'drnic'
10
+ users = %w[defunkt drnic _why]
11
+ @helper.should_receive(:network_members).with('drnic', {}).and_return(users)
12
+ stdout.should == "defunkt\ndrnic\n_why\n"
13
+ end
14
+ end
15
+
16
+ specify "network should open the network page for this repo" do
17
+ running :network, 'web' do
18
+ setup_url_for
19
+ @helper.should_receive(:open).once.with("https://github.com/user/project/network")
20
+ end
21
+ end
22
+
23
+ specify "network defunkt should open the network page for defunkt's fork" do
24
+ running :network, 'web', "defunkt" do
25
+ setup_url_for
26
+ @helper.should_receive(:open).once.with("https://github.com/defunkt/project/network")
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,51 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.dirname(__FILE__) + '/command_helper'
3
+
4
+ describe "github pull-request" do
5
+ include CommandHelper
6
+
7
+ specify "pull-request should die with no args" do
8
+ running :'pull-request' do
9
+ setup_url_for
10
+ @command.should_receive(:die).with("Specify a user for the pull request").and_return { raise "Died" }
11
+ self.should raise_error(RuntimeError)
12
+ end
13
+ end
14
+
15
+ specify "pull-request user should track user if untracked" do
16
+ running :'pull-request', "user" do
17
+ setup_url_for
18
+ setup_remote :origin, :user => "kballard"
19
+ setup_remote :defunkt
20
+ GitHub.should_receive(:invoke).with(:track, "user").and_return { raise "Tracked" }
21
+ self.should raise_error("Tracked")
22
+ end
23
+ end
24
+
25
+ specify "pull-request user/branch should generate a pull request" do
26
+ running :'pull-request', "user/branch" do
27
+ setup_url_for
28
+ setup_remote :origin, :user => "kballard"
29
+ setup_remote :user
30
+ @command.should_receive(:git_exec).with("request-pull user/branch origin")
31
+ end
32
+ end
33
+
34
+ specify "pull-request user should generate a pull request with branch master" do
35
+ running :'pull-request', "user" do
36
+ setup_url_for
37
+ setup_remote :origin, :user => "kballard"
38
+ setup_remote :user
39
+ @command.should_receive(:git_exec).with("request-pull user/master origin")
40
+ end
41
+ end
42
+
43
+ specify "pull-request user branch should generate a pull request" do
44
+ running:'pull-request', "user", "branch" do
45
+ setup_url_for
46
+ setup_remote :origin, :user => "kballard"
47
+ setup_remote :user
48
+ @command.should_receive(:git_exec).with("request-pull user/branch origin")
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.dirname(__FILE__) + '/command_helper'
3
+
4
+ describe "github pull" do
5
+ include CommandHelper
6
+
7
+ specify "pull defunkt should start tracking defunkt if they're not already tracked" do
8
+ running :pull, "defunkt" do
9
+ mock_members 'defunkt'
10
+ setup_remote(:origin, :user => "user", :ssh => true)
11
+ setup_remote(:external, :url => "home:/path/to/project.git")
12
+ GitHub.should_receive(:invoke).with(:track, "defunkt").and_return { raise "Tracked" }
13
+ self.should raise_error("Tracked")
14
+ end
15
+ end
16
+
17
+ specify "pull defunkt should create defunkt/master and pull from the defunkt remote" do
18
+ running :pull, "defunkt" do
19
+ mock_members 'defunkt'
20
+ setup_remote(:defunkt)
21
+ @helper.should_receive(:branch_dirty?).and_return false
22
+ @command.should_receive(:git).with("fetch defunkt").ordered
23
+ @command.should_receive(:git_exec).with("checkout -b defunkt/master defunkt/master").ordered
24
+ stdout.should == "Switching to defunkt-master\n"
25
+ end
26
+ end
27
+
28
+ specify "pull defunkt should switch to pre-existing defunkt/master and pull from the defunkt remote" do
29
+ running :pull, "defunkt" do
30
+ mock_members 'defunkt'
31
+ setup_remote(:defunkt)
32
+ @helper.should_receive(:branch_dirty?).and_return true
33
+ @command.should_receive(:die).with("Unable to switch branches, your current branch has uncommitted changes").and_return { raise "Died" }
34
+ self.should raise_error(RuntimeError)
35
+ end
36
+ end
37
+
38
+ specify "pull defunkt wip should create defunkt/wip and pull from wip branch on defunkt remote" do
39
+ running :pull, "defunkt", "wip" do
40
+ mock_members 'defunkt'
41
+ setup_remote(:defunkt)
42
+ @helper.should_receive(:branch_dirty?).and_return true
43
+ @command.should_receive(:die).with("Unable to switch branches, your current branch has uncommitted changes").and_return { raise "Died" }
44
+ self.should raise_error(RuntimeError)
45
+ end
46
+ end
47
+
48
+ specify "pull defunkt/wip should switch to pre-existing defunkt/wip and pull from wip branch on defunkt remote" do
49
+ running :pull, "defunkt/wip" do
50
+ mock_members 'defunkt'
51
+ setup_remote(:defunkt)
52
+ @helper.should_receive(:branch_dirty?).and_return false
53
+ @command.should_receive(:git).with("fetch defunkt").ordered
54
+ @command.should_receive(:git_exec).with("checkout -b defunkt/wip defunkt/wip").ordered
55
+ stdout.should == "Switching to defunkt-wip\n"
56
+ end
57
+ end
58
+
59
+ specify "pull --merge defunkt should pull from defunkt remote into current branch" do
60
+ running :pull, "--merge", "defunkt" do
61
+ mock_members 'defunkt'
62
+ setup_remote(:defunkt)
63
+ @helper.should_receive(:branch_dirty?).and_return false
64
+ @command.should_receive(:git_exec).with("pull defunkt master")
65
+ end
66
+ end
67
+
68
+ specify "pull falls through for non-recognized commands" do
69
+ running :pull, 'remote' do
70
+ mock_members 'defunkt'
71
+ setup_remote(:defunkt)
72
+ @command.should_receive(:git_exec).with("pull remote")
73
+ end
74
+ end
75
+
76
+ specify "pull passes along args when falling through" do
77
+ running :pull, 'remote', '--stat' do
78
+ mock_members 'defunkt'
79
+ @command.should_receive(:git_exec).with("pull remote --stat")
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.dirname(__FILE__) + '/command_helper'
3
+
4
+ describe "github search" do
5
+ include CommandHelper
6
+
7
+ specify "search finds multiple results" do
8
+ running :search, "github-gem" do
9
+ json = StringIO.new '{"repositories":[' +
10
+ '{"name":"github-gem","size":300,"followers":499,"username":"defunkt","language":"Ruby","fork":false,"id":"repo-1653","type":"repo","pushed":"2008-12-04T03:14:00Z","forks":59,"description":"The official `github` command line helper for simplifying your GitHub experience.","score":3.4152448,"created":"2008-02-28T09:35:34Z"},' +
11
+ '{"name":"github-gem-builder","size":76,"followers":26,"username":"pjhyett","language":"Ruby","fork":false,"id":"repo-67489","type":"repo","pushed":"2008-11-04T04:54:57Z","forks":3,"description":"The scripts used to build RubyGems on GitHub","score":3.4152448,"created":"2008-10-24T22:29:32Z"}' +
12
+ ']}'
13
+ json.rewind
14
+ @command.should_receive(:open).with("http://github.com/api/v1/json/search/github-gem").and_return(json)
15
+ stdout.should == "defunkt/github-gem\npjhyett/github-gem-builder\n"
16
+ end
17
+ end
18
+
19
+ specify "search finds no results" do
20
+ running :search, "xxxxxxxxxx" do
21
+ json = StringIO.new '{"repositories":[]}'
22
+ json.rewind
23
+ @command.should_receive(:open).with("http://github.com/api/v1/json/search/xxxxxxxxxx").and_return(json)
24
+ stdout.should == "No results found\n"
25
+ end
26
+ end
27
+
28
+ specify "search shows usage if no arguments given" do
29
+ running :search do
30
+ @command.should_receive(:die).with("Usage: github search [query]").and_return { raise "Died" }
31
+ self.should raise_error(RuntimeError)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.dirname(__FILE__) + '/command_helper'
3
+
4
+ describe "github track" do
5
+ include CommandHelper
6
+
7
+ specify "track defunkt should track a new remote for defunkt" do
8
+ running :track, "defunkt" do
9
+ setup_url_for
10
+ @helper.should_receive(:tracking?).with("defunkt").once.and_return(false)
11
+ @command.should_receive(:git).with("remote add defunkt git://github.com/defunkt/project.git").once
12
+ end
13
+ end
14
+
15
+ specify "track --private defunkt should track a new remote for defunkt using ssh" do
16
+ running :track, "--private", "defunkt" do
17
+ setup_url_for
18
+ @helper.should_receive(:tracking?).with("defunkt").and_return(false)
19
+ @command.should_receive(:git).with("remote add defunkt git@github.com:defunkt/project.git")
20
+ end
21
+ end
22
+
23
+ specify "track --ssh defunkt should be equivalent to track --private defunkt" do
24
+ running :track, "--ssh", "defunkt" do
25
+ setup_url_for
26
+ @helper.should_receive(:tracking?).with("defunkt").and_return(false)
27
+ @command.should_receive(:git).with("remote add defunkt git@github.com:defunkt/project.git")
28
+ end
29
+ end
30
+
31
+ specify "track defunkt should die if the defunkt remote exists" do
32
+ running :track, "defunkt" do
33
+ setup_url_for
34
+ @helper.should_receive(:tracking?).with("defunkt").once.and_return(true)
35
+ @command.should_receive(:die).with("Already tracking defunkt").and_return { raise "Died" }
36
+ self.should raise_error(RuntimeError)
37
+ end
38
+ end
39
+
40
+ specify "track should die with no args" do
41
+ running :track do
42
+ @command.should_receive(:die).with("Specify a user to track").and_return { raise "Died" }
43
+ self.should raise_error(RuntimeError)
44
+ end
45
+ end
46
+
47
+ specify "track should accept user/project syntax" do
48
+ running :track, "defunkt/github-gem.git" do
49
+ setup_url_for
50
+ @helper.should_receive(:tracking?).with("defunkt").and_return false
51
+ @command.should_receive(:git).with("remote add defunkt git://github.com/defunkt/github-gem.git")
52
+ end
53
+ end
54
+
55
+ specify "track defunkt/github-gem.git should function with no origin remote" do
56
+ running :track, "defunkt/github-gem.git" do
57
+ @helper.stub!(:url_for).with("origin").and_return ""
58
+ @helper.stub!(:tracking?).and_return false
59
+ @command.should_receive(:git).with("remote add defunkt git://github.com/defunkt/github-gem.git")
60
+ self.should_not raise_error(SystemExit)
61
+ stderr.should_not =~ /^Error/
62
+ end
63
+ end
64
+
65
+ specify "track origin defunkt/github-gem should track defunkt/github-gem as the origin remote" do
66
+ running :track, "origin", "defunkt/github-gem" do
67
+ @helper.stub!(:url_for).with("origin").and_return ""
68
+ @helper.stub!(:tracking?).and_return false
69
+ @command.should_receive(:git).with("remote add origin git://github.com/defunkt/github-gem.git")
70
+ stderr.should_not =~ /^Error/
71
+ end
72
+ end
73
+
74
+ specify "track --private origin defunkt/github-gem should track defunkt/github-gem as the origin remote using ssh" do
75
+ running :track, "--private", "origin", "defunkt/github-gem" do
76
+ @helper.stub!(:url_for).with("origin").and_return ""
77
+ @helper.stub!(:tracking?).and_return false
78
+ @command.should_receive(:git).with("remote add origin git@github.com:defunkt/github-gem.git")
79
+ stderr.should_not =~ /^Error/
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require File.dirname(__FILE__) + '/commands/command_helper'
3
+
4
+ describe "github" do
5
+ include CommandHelper
6
+
7
+ # -- fallthrough to git if unknown command --
8
+ specify "should fall through to actual git commands" do
9
+ running :commit do
10
+ @command.should_receive(:git_exec).with(["commit", []])
11
+ end
12
+ end
13
+
14
+ specify "should pass along arguments when falling through" do
15
+ running :commit, '-a', '-m', 'yo mama' do
16
+ @command.should_receive(:git_exec).with(["commit", ["-a", "-m", 'yo mama']])
17
+ end
18
+ end
19
+
20
+ # -- default --
21
+ specify "should print the default message" do
22
+ running :default do
23
+ GitHub.should_receive(:descriptions).any_number_of_times.and_return({
24
+ "home" => "Open the home page",
25
+ "browsing" => "Browse the github page for this branch",
26
+ "commands" => "description",
27
+ "tracking" => "Track a new repo"
28
+ })
29
+ GitHub.should_receive(:flag_descriptions).any_number_of_times.and_return({
30
+ "home" => {:flag => "Flag description"},
31
+ "browsing" => {},
32
+ "commands" => {},
33
+ "tracking" => {:flag1 => "Flag one", :flag2 => "Flag two"}
34
+ })
35
+ @command.should_receive(:puts).with(<<-EOS.gsub(/^ /, ''))
36
+ Usage: github command <space separated arguments>
37
+ Available commands:
38
+ browsing => Browse the github page for this branch
39
+ commands => description
40
+ home => Open the home page
41
+ --flag: Flag description
42
+ tracking => Track a new repo
43
+ --flag1: Flag one
44
+ --flag2: Flag two
45
+ EOS
46
+ end
47
+ end
48
+
49
+ end