riquedafreak-github 0.2.1 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +6 -4
- data/README +8 -8
- data/bin/gh +5 -0
- data/commands/commands.rb +75 -35
- data/commands/helpers.rb +103 -18
- data/github-gem.gemspec +6 -5
- data/lib/github/command.rb +12 -41
- data/lib/github.rb +18 -2
- data/spec/ui_spec.rb +69 -20
- metadata +15 -4
data/Manifest
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
+
LICENSE
|
2
|
+
Manifest
|
3
|
+
README
|
4
|
+
bin/gh
|
1
5
|
bin/github
|
2
6
|
commands/commands.rb
|
3
7
|
commands/helpers.rb
|
4
|
-
|
8
|
+
github-gem.gemspec
|
5
9
|
lib/github/command.rb
|
10
|
+
lib/github/extensions.rb
|
6
11
|
lib/github/helper.rb
|
7
12
|
lib/github.rb
|
8
|
-
LICENSE
|
9
|
-
Manifest
|
10
|
-
README
|
11
13
|
spec/command_spec.rb
|
12
14
|
spec/extensions_spec.rb
|
13
15
|
spec/github_spec.rb
|
data/README
CHANGED
@@ -22,7 +22,7 @@ Pulling Upstream Changes
|
|
22
22
|
|
23
23
|
Let's say you just forked `github-gem` on GitHub from defunkt.
|
24
24
|
|
25
|
-
$
|
25
|
+
$ github clone git://github.com/YOU/github-gem.git
|
26
26
|
$ cd github-gem
|
27
27
|
$ github pull defunkt
|
28
28
|
|
@@ -36,8 +36,8 @@ checkout master` and then `git merge defunkt/master` to merge defunkt's changes
|
|
36
36
|
into your own master branch. In summary:
|
37
37
|
|
38
38
|
$ github pull defunkt
|
39
|
-
$
|
40
|
-
$
|
39
|
+
$ github checkout master
|
40
|
+
$ github merge defunkt/master
|
41
41
|
|
42
42
|
If you've already reviewed defunkt's changes and just want to merge them into your
|
43
43
|
master branch, use the `merge` flag:
|
@@ -67,12 +67,12 @@ Your local 'mojombo/master' branch is now at the exact same place as mojombo's
|
|
67
67
|
If mojombo's changes are good, you'll want to merge your 'master' (or another
|
68
68
|
branch) into those changes so you can retest post-integration:
|
69
69
|
|
70
|
-
$
|
70
|
+
$ github merge master
|
71
71
|
|
72
72
|
Test/analyze again and if everything is ok:
|
73
73
|
|
74
|
-
$
|
75
|
-
$
|
74
|
+
$ github checkout master
|
75
|
+
$ github merge mojombo/master
|
76
76
|
|
77
77
|
The latter command will be a fast-forward merge since you already did the
|
78
78
|
real merge previously.
|
@@ -111,12 +111,12 @@ which will show you something like this:
|
|
111
111
|
These are all the commits that you don't have in your current branch that have been
|
112
112
|
pushed to other forks of your project. If you want to incorporate them, you can use:
|
113
113
|
|
114
|
-
$
|
114
|
+
$ github cherry-pick ee013a
|
115
115
|
|
116
116
|
for example to apply that single patch to your branch. You can also merge a branch,
|
117
117
|
if you want all the changes introduced in another branch:
|
118
118
|
|
119
|
-
$
|
119
|
+
$ github merge jchris/gist
|
120
120
|
|
121
121
|
The next time you run the 'github network commits' command, you won't see any of the
|
122
122
|
patches you have cherry-picked or merged (or rebased). If you want to ignore a
|
data/bin/gh
ADDED
data/commands/commands.rb
CHANGED
@@ -27,10 +27,13 @@ flags :shas => "Only show shas"
|
|
27
27
|
flags :project => "Filter commits on a certain project"
|
28
28
|
flags :author => "Filter commits on a email address of author"
|
29
29
|
flags :applies => "Filter commits to patches that apply cleanly"
|
30
|
+
flags :noapply => "Filter commits to patches that do not apply cleanly"
|
30
31
|
flags :nocache => "Do not use the cached network data"
|
31
32
|
flags :cache => "Use the network data even if it's expired"
|
32
33
|
flags :sort => "How to sort : date(*), branch, author"
|
33
34
|
flags :common => "Show common branch point"
|
35
|
+
flags :thisbranch => "Look at branches that match the current one"
|
36
|
+
flags :limit => "Only look through the first X heads - useful for really large projects"
|
34
37
|
command :network do |command, user|
|
35
38
|
return if !helper.project
|
36
39
|
user ||= helper.owner
|
@@ -39,13 +42,13 @@ command :network do |command, user|
|
|
39
42
|
when 'web'
|
40
43
|
helper.open helper.network_page_for(user)
|
41
44
|
when 'list'
|
42
|
-
data = get_network_data(user, options)
|
45
|
+
data = helper.get_network_data(user, options)
|
43
46
|
data['users'].each do |hsh|
|
44
47
|
puts [ hsh['name'].ljust(20), hsh['heads'].map {|a| a['name']}.uniq.join(', ') ].join(' ')
|
45
48
|
end
|
46
49
|
when 'fetch'
|
47
50
|
# fetch each remote we don't have
|
48
|
-
data = get_network_data(user, options)
|
51
|
+
data = helper.get_network_data(user, options)
|
49
52
|
data['users'].each do |hsh|
|
50
53
|
u = hsh['name']
|
51
54
|
GitHub.invoke(:track, u) unless helper.tracking?(u)
|
@@ -54,36 +57,69 @@ command :network do |command, user|
|
|
54
57
|
end
|
55
58
|
when 'commits'
|
56
59
|
# show commits we don't have yet
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
60
|
+
|
61
|
+
$stderr.puts 'gathering heads'
|
62
|
+
cherry = []
|
63
|
+
|
64
|
+
if helper.cache_commits_data(options)
|
65
|
+
ids = []
|
66
|
+
data = helper.get_network_data(user, options)
|
67
|
+
data['users'].each do |hsh|
|
68
|
+
u = hsh['name']
|
69
|
+
if options[:thisbranch]
|
70
|
+
user_ids = hsh['heads'].map { |a| a['id'] if a['name'] == helper.current_branch }.compact
|
71
|
+
else
|
72
|
+
user_ids = hsh['heads'].map { |a| a['id'] }
|
73
|
+
end
|
74
|
+
user_ids.each do |id|
|
75
|
+
if !helper.has_commit?(id) && helper.cache_expired?
|
76
|
+
GitHub.invoke(:track, u) unless helper.tracking?(u)
|
77
|
+
puts "fetching #{u}"
|
78
|
+
GitHub.invoke(:fetch_all, u)
|
79
|
+
end
|
67
80
|
end
|
81
|
+
ids += user_ids
|
68
82
|
end
|
69
|
-
ids
|
70
|
-
end
|
71
|
-
ids.uniq!
|
83
|
+
ids.uniq!
|
72
84
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
85
|
+
$stderr.puts 'has heads'
|
86
|
+
|
87
|
+
# check that we have all these shas locally
|
88
|
+
local_heads = helper.local_heads
|
89
|
+
local_heads_not = local_heads.map { |a| "^#{a}"}
|
90
|
+
looking_for = (ids - local_heads) + local_heads_not
|
91
|
+
commits = helper.get_commits(looking_for)
|
92
|
+
|
93
|
+
$stderr.puts 'ID SIZE:' + ids.size.to_s
|
94
|
+
|
95
|
+
ignores = helper.ignore_sha_array
|
96
|
+
|
97
|
+
ids.each do |id|
|
98
|
+
next if ignores[id] || !commits.assoc(id)
|
99
|
+
cherries = helper.get_cherry(id)
|
100
|
+
cherries = helper.remove_ignored(cherries, ignores)
|
101
|
+
cherry += cherries
|
102
|
+
helper.ignore_shas([id]) if cherries.size == 0
|
103
|
+
$stderr.puts "checking head #{id} : #{cherry.size.to_s}"
|
104
|
+
break if options[:limit] && cherry.size > options[:limit].to_i
|
105
|
+
end
|
83
106
|
end
|
84
|
-
|
107
|
+
|
108
|
+
if cherry.size > 0 || !helper.cache_commits_data(options)
|
85
109
|
helper.print_network_cherry_help if !options[:shas]
|
86
|
-
|
110
|
+
|
111
|
+
if helper.cache_commits_data(options)
|
112
|
+
$stderr.puts "caching..."
|
113
|
+
$stderr.puts "commits: " + cherry.size.to_s
|
114
|
+
our_commits = cherry.map { |item| c = commits.assoc(item[1]); [item, c] if c }
|
115
|
+
our_commits.delete_if { |item| item == nil }
|
116
|
+
helper.cache_commits(our_commits)
|
117
|
+
else
|
118
|
+
$stderr.puts "using cached..."
|
119
|
+
our_commits = helper.commits_cache
|
120
|
+
end
|
121
|
+
|
122
|
+
helper.print_commits(our_commits, options)
|
87
123
|
else
|
88
124
|
puts "no unapplied commits"
|
89
125
|
end
|
@@ -158,34 +194,38 @@ flags :merge => "Automatically merge remote's changes into your master."
|
|
158
194
|
command :pull do |user, branch|
|
159
195
|
die "Specify a user to pull from" if user.nil?
|
160
196
|
user, branch = user.split("/", 2) if branch.nil?
|
197
|
+
|
198
|
+
if !helper.network_members.include?(user)
|
199
|
+
git_exec "#{helper.argv.join(' ')}".strip
|
200
|
+
end
|
201
|
+
|
161
202
|
branch ||= 'master'
|
162
203
|
GitHub.invoke(:track, user) unless helper.tracking?(user)
|
163
204
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
unless options[:merge]
|
205
|
+
if options[:merge]
|
206
|
+
git_exec "pull #{user} #{branch}"
|
207
|
+
else
|
168
208
|
puts "Switching to #{user}/#{branch}"
|
169
209
|
git "update-ref refs/heads/#{user}/#{branch} HEAD"
|
170
210
|
git "checkout #{user}/#{branch}"
|
171
211
|
end
|
172
|
-
git_exec "pull #{user} #{branch}"
|
173
212
|
end
|
174
213
|
|
175
214
|
desc "Clone a repo."
|
176
215
|
flags :ssh => "Clone using the git@github.com style url."
|
177
216
|
command :clone do |user, repo, dir|
|
178
217
|
die "Specify a user to pull from" if user.nil?
|
179
|
-
if user.include?
|
218
|
+
if user.include?('/') && !user.include?('@') && !user.include?(':')
|
180
219
|
die "Expected user/repo dir, given extra argument" if dir
|
181
220
|
(user, repo), dir = [user.split('/', 2), repo]
|
182
221
|
end
|
183
|
-
die "Specify a repo to pull from" if repo.nil?
|
184
222
|
|
185
223
|
if options[:ssh]
|
186
224
|
git_exec "clone git@github.com:#{user}/#{repo}.git" + (dir ? " #{dir}" : "")
|
187
|
-
|
225
|
+
elsif repo
|
188
226
|
git_exec "clone git://github.com/#{user}/#{repo}.git" + (dir ? " #{dir}" : "")
|
227
|
+
else
|
228
|
+
git_exec "#{helper.argv.join(' ')}".strip
|
189
229
|
end
|
190
230
|
end
|
191
231
|
|
data/commands/helpers.rb
CHANGED
@@ -53,7 +53,7 @@ helper :resolve_commits do |treeish|
|
|
53
53
|
else
|
54
54
|
# standard in
|
55
55
|
puts 'reading from stdin...'
|
56
|
-
commits = $stdin.read.split("\n")
|
56
|
+
commits = $stdin.read.split("\n")
|
57
57
|
end
|
58
58
|
commits.select { |a| a.size == 40 } # only the shas, not the ^SHAs
|
59
59
|
end
|
@@ -67,6 +67,10 @@ helper :ignore_sha_array do
|
|
67
67
|
File.open( ignore_file_path ) { |yf| YAML::load( yf ) } rescue {}
|
68
68
|
end
|
69
69
|
|
70
|
+
helper :remove_ignored do |array, ignore_array|
|
71
|
+
array.reject { |id| ignore_array[id] }
|
72
|
+
end
|
73
|
+
|
70
74
|
helper :ignore_shas do |shas|
|
71
75
|
ignores = ignore_sha_array
|
72
76
|
shas.each do |sha|
|
@@ -91,19 +95,18 @@ helper :get_common do |branch|
|
|
91
95
|
`git rev-list ..#{branch} --boundary | tail -1 | git name-rev --stdin`.split(' ')[1] rescue 'unknown'
|
92
96
|
end
|
93
97
|
|
94
|
-
helper :print_commits do |
|
98
|
+
helper :print_commits do |our_commits, options|
|
95
99
|
ignores = ignore_sha_array
|
96
|
-
|
97
|
-
|
100
|
+
|
98
101
|
case options[:sort]
|
99
102
|
when 'branch'
|
100
103
|
our_commits.sort! { |a, b| a[0][2] <=> b[0][2] }
|
101
104
|
when 'author'
|
102
105
|
our_commits.sort! { |a, b| a[1][1] <=> b[1][1] }
|
103
106
|
else
|
104
|
-
our_commits.sort! { |a, b| Date.parse(a[1][4]) <=> Date.parse(b[1][4]) }
|
107
|
+
our_commits.sort! { |a, b| Date.parse(a[1][4]) <=> Date.parse(b[1][4]) } rescue 'cant parse dates'
|
105
108
|
end
|
106
|
-
|
109
|
+
|
107
110
|
shown_commits = {}
|
108
111
|
before = Date.parse(options[:before]) if options[:before] rescue puts 'cant parse before date'
|
109
112
|
after = Date.parse(options[:after]) if options[:after] rescue puts 'cant parse after date'
|
@@ -114,15 +117,17 @@ helper :print_commits do |cherries, commits, options|
|
|
114
117
|
ref_name = ref_name.gsub('remotes/', '')
|
115
118
|
if status == '+' && commit
|
116
119
|
next if options[:author] && !commit[1].match(Regexp.new(options[:author]))
|
117
|
-
next if options[:before] && before && (before < Date.parse(commit[4]))
|
118
|
-
next if options[:after] && after && (after > Date.parse(commit[4]))
|
119
|
-
|
120
|
+
next if options[:before] && before && (before < Date.parse(commit[4])) rescue false
|
121
|
+
next if options[:after] && after && (after > Date.parse(commit[4])) rescue false
|
122
|
+
applies = applies_cleanly(sha)
|
123
|
+
next if options[:applies] && !applies
|
124
|
+
next if options[:noapply] && applies
|
120
125
|
if options[:shas]
|
121
126
|
puts sha
|
122
127
|
else
|
123
128
|
common = options[:common] ? get_common(sha) : ''
|
124
|
-
puts [sha[0,6], ref_name.ljust(25), commit[1][0,20].ljust(21),
|
125
|
-
commit[2][0, 36].ljust(38), commit[3], common].join(" ")
|
129
|
+
puts [sha[0,6], ref_name.ljust(25), commit[1][0,20].ljust(21),
|
130
|
+
commit[2][0, 36].ljust(38), commit[3][0,15], common].join(" ")
|
126
131
|
end
|
127
132
|
end
|
128
133
|
shown_commits[sha] = true
|
@@ -184,8 +189,12 @@ helper :owner do
|
|
184
189
|
user_for(:origin)
|
185
190
|
end
|
186
191
|
|
192
|
+
helper :current_branch do
|
193
|
+
`git rev-parse --symbolic-full-name HEAD`.chomp.sub(/^refs\/heads\//, '')
|
194
|
+
end
|
195
|
+
|
187
196
|
helper :user_and_branch do
|
188
|
-
raw_branch =
|
197
|
+
raw_branch = current_branch
|
189
198
|
user, branch = raw_branch.split(/\//, 2)
|
190
199
|
if branch
|
191
200
|
[user, branch]
|
@@ -253,17 +262,17 @@ You have to provide a command :
|
|
253
262
|
|
254
263
|
web [user] - opens your web browser to the network graph page for this
|
255
264
|
project, or for the graph page for [user] if provided
|
256
|
-
|
265
|
+
|
257
266
|
list - shows the projects in your network that have commits
|
258
|
-
that you have not pulled in yet, and branch names
|
259
|
-
|
267
|
+
that you have not pulled in yet, and branch names
|
268
|
+
|
260
269
|
fetch - adds all projects in your network as remotes and fetches
|
261
270
|
any objects from them that you don't have yet
|
262
|
-
|
271
|
+
|
263
272
|
commits - will show you a list of all commits in your network that
|
264
273
|
you have not ignored or have not merged or cherry-picked.
|
265
274
|
This will automatically fetch objects you don't have yet.
|
266
|
-
|
275
|
+
|
267
276
|
--project (user/branch) - only show projects that match string
|
268
277
|
--author (email) - only show projects that match string
|
269
278
|
--after (date) - only show commits after date
|
@@ -275,7 +284,7 @@ You have to provide a command :
|
|
275
284
|
end
|
276
285
|
|
277
286
|
helper :print_network_cherry_help do
|
278
|
-
puts "
|
287
|
+
$stderr.puts "
|
279
288
|
=========================================================================================
|
280
289
|
These are all the commits that other people have pushed that you have not
|
281
290
|
applied or ignored yet (see 'github ignore'). Some things you might want to do:
|
@@ -289,3 +298,79 @@ applied or ignored yet (see 'github ignore'). Some things you might want to do:
|
|
289
298
|
"
|
290
299
|
end
|
291
300
|
|
301
|
+
helper :argv do
|
302
|
+
GitHub.original_args
|
303
|
+
end
|
304
|
+
|
305
|
+
helper :network_members do
|
306
|
+
get_network_data(owner, {})['users'].map do |hash|
|
307
|
+
hash['name']
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
|
312
|
+
helper :get_network_data do |user, options|
|
313
|
+
if options[:cache] && has_cache?
|
314
|
+
return get_cache
|
315
|
+
end
|
316
|
+
if cache_network_data(options)
|
317
|
+
return cache_data(user)
|
318
|
+
else
|
319
|
+
return get_cache
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
helper :cache_commits do |commits|
|
324
|
+
File.open( commits_cache_path, 'w' ) do |out|
|
325
|
+
out.write(commits.to_yaml)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
helper :commits_cache do
|
330
|
+
YAML.load(File.open(commits_cache_path))
|
331
|
+
end
|
332
|
+
|
333
|
+
helper :cache_commits_data do |options|
|
334
|
+
cache_expired? || options[:nocache] || !has_commits_cache?
|
335
|
+
end
|
336
|
+
|
337
|
+
helper :cache_network_data do |options|
|
338
|
+
cache_expired? || options[:nocache] || !has_cache?
|
339
|
+
end
|
340
|
+
|
341
|
+
helper :network_cache_path do
|
342
|
+
dir = `git rev-parse --git-dir`.chomp
|
343
|
+
File.join(dir, 'network-cache')
|
344
|
+
end
|
345
|
+
|
346
|
+
helper :commits_cache_path do
|
347
|
+
dir = `git rev-parse --git-dir`.chomp
|
348
|
+
File.join(dir, 'commits-cache')
|
349
|
+
end
|
350
|
+
|
351
|
+
helper :cache_data do |user|
|
352
|
+
raw_data = Kernel.open(network_meta_for(user)).read
|
353
|
+
File.open( network_cache_path, 'w' ) do |out|
|
354
|
+
out.write(raw_data)
|
355
|
+
end
|
356
|
+
data = JSON.parse(raw_data)
|
357
|
+
end
|
358
|
+
|
359
|
+
helper :cache_expired? do
|
360
|
+
return true if !has_cache?
|
361
|
+
age = Time.now - File.stat(network_cache_path).mtime
|
362
|
+
return true if age > (60 * 60) # 1 hour
|
363
|
+
false
|
364
|
+
end
|
365
|
+
|
366
|
+
helper :has_cache? do
|
367
|
+
File.file?(network_cache_path)
|
368
|
+
end
|
369
|
+
|
370
|
+
helper :has_commits_cache? do
|
371
|
+
File.file?(commits_cache_path)
|
372
|
+
end
|
373
|
+
|
374
|
+
helper :get_cache do
|
375
|
+
JSON.parse(File.read(network_cache_path))
|
376
|
+
end
|
data/github-gem.gemspec
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
|
-
s.name =
|
3
|
-
s.version = "0.
|
2
|
+
s.name = "github"
|
3
|
+
s.version = "0.3.1"
|
4
4
|
|
5
5
|
s.specification_version = 2 if s.respond_to? :specification_version=
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Chris Wanstrath, Kevin Ballard, Scott Chacon"]
|
9
9
|
s.date = %q{2008-05-18}
|
10
|
-
s.default_executable = %q{
|
10
|
+
s.default_executable = %q{gh}
|
11
11
|
s.description = %q{The official `github` command line helper for simplifying your GitHub experience.}
|
12
12
|
s.email = %q{chris@ozmm.org}
|
13
|
-
s.executables = ["github"]
|
14
|
-
s.extra_rdoc_files = ["bin/github", "lib/github/extensions.rb", "lib/github/command.rb", "lib/github/helper.rb", "lib/github.rb", "LICENSE", "README"]
|
13
|
+
s.executables = ["github", "gh"]
|
14
|
+
s.extra_rdoc_files = ["bin/github", "bin/gh", "lib/github/extensions.rb", "lib/github/command.rb", "lib/github/helper.rb", "lib/github.rb", "LICENSE", "README"]
|
15
15
|
s.files = ["bin/github", "commands/commands.rb", "commands/helpers.rb", "lib/github/extensions.rb", "lib/github/command.rb", "lib/github/helper.rb", "lib/github.rb", "LICENSE", "Manifest", "README", "spec/command_spec.rb", "spec/extensions_spec.rb", "spec/github_spec.rb", "spec/helper_spec.rb", "spec/spec_helper.rb", "spec/ui_spec.rb", "spec/windoze_spec.rb", "github-gem.gemspec"]
|
16
16
|
s.has_rdoc = true
|
17
17
|
s.homepage = %q{http://github.com/}
|
@@ -22,4 +22,5 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.summary = %q{The official `github` command line helper for simplifying your GitHub experience.}
|
23
23
|
|
24
24
|
# s.add_dependency(%q<launchy>, [">= 0"])
|
25
|
+
s.add_dependency('json', [">= 0"])
|
25
26
|
end
|
data/lib/github/command.rb
CHANGED
@@ -20,7 +20,7 @@ module GitHub
|
|
20
20
|
args << nil while args.size < arity
|
21
21
|
send :command, *args
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def helper
|
25
25
|
@helper ||= Helper.new
|
26
26
|
end
|
@@ -46,45 +46,6 @@ module GitHub
|
|
46
46
|
def sh(*command)
|
47
47
|
Shell.new(*command).run
|
48
48
|
end
|
49
|
-
|
50
|
-
def get_network_data(user, options)
|
51
|
-
if options[:cache] && has_cache?
|
52
|
-
return get_cache
|
53
|
-
end
|
54
|
-
if cache_expired? || options[:nocache] || !has_cache?
|
55
|
-
return cache_data(user)
|
56
|
-
else
|
57
|
-
return get_cache
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def network_cache_path
|
62
|
-
dir = `git rev-parse --git-dir`.chomp
|
63
|
-
File.join(dir, 'network-cache')
|
64
|
-
end
|
65
|
-
|
66
|
-
def cache_data(user)
|
67
|
-
raw_data = open(helper.network_meta_for(user)).read
|
68
|
-
File.open( network_cache_path, 'w' ) do |out|
|
69
|
-
out.write(raw_data)
|
70
|
-
end
|
71
|
-
data = JSON.parse(raw_data)
|
72
|
-
end
|
73
|
-
|
74
|
-
def cache_expired?
|
75
|
-
return true if !has_cache?
|
76
|
-
age = Time.now - File.stat(network_cache_path).mtime
|
77
|
-
return true if age > (60 * 60) # 1 hour
|
78
|
-
false
|
79
|
-
end
|
80
|
-
|
81
|
-
def has_cache?
|
82
|
-
File.file?(network_cache_path)
|
83
|
-
end
|
84
|
-
|
85
|
-
def get_cache
|
86
|
-
JSON.parse(File.read(network_cache_path))
|
87
|
-
end
|
88
49
|
|
89
50
|
def die(message)
|
90
51
|
puts "=> #{message}"
|
@@ -102,7 +63,7 @@ module GitHub
|
|
102
63
|
def run
|
103
64
|
GitHub.debug "sh: #{command}"
|
104
65
|
_, out, err = Open3.popen3(*@command)
|
105
|
-
|
66
|
+
|
106
67
|
out = out.read.strip
|
107
68
|
err = err.read.strip
|
108
69
|
|
@@ -125,4 +86,14 @@ module GitHub
|
|
125
86
|
end
|
126
87
|
end
|
127
88
|
end
|
89
|
+
|
90
|
+
class GitCommand < Command
|
91
|
+
def initialize(name)
|
92
|
+
@name = name
|
93
|
+
end
|
94
|
+
|
95
|
+
def command(*args)
|
96
|
+
git_exec *[ @name, args ]
|
97
|
+
end
|
98
|
+
end
|
128
99
|
end
|
data/lib/github.rb
CHANGED
@@ -13,7 +13,7 @@ require 'yaml'
|
|
13
13
|
# $ github <command> <args>
|
14
14
|
#
|
15
15
|
# GitHub.command <command> do |*args|
|
16
|
-
# whatever
|
16
|
+
# whatever
|
17
17
|
# end
|
18
18
|
#
|
19
19
|
# We'll probably want to use the `choice` gem for concise, tasty DSL
|
@@ -49,6 +49,7 @@ module GitHub
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def activate(args)
|
52
|
+
@@original_args = args.clone
|
52
53
|
@options = parse_options(args)
|
53
54
|
@debug = @options[:debug]
|
54
55
|
load 'helpers.rb'
|
@@ -57,11 +58,16 @@ module GitHub
|
|
57
58
|
end
|
58
59
|
|
59
60
|
def invoke(command, *args)
|
60
|
-
block =
|
61
|
+
block = find_command(command)
|
61
62
|
debug "Invoking `#{command}`"
|
62
63
|
block.call(*args)
|
63
64
|
end
|
64
65
|
|
66
|
+
def find_command(name)
|
67
|
+
name = name.to_s
|
68
|
+
commands[name] || GitCommand.new(name) || commands['default']
|
69
|
+
end
|
70
|
+
|
65
71
|
def commands
|
66
72
|
@commands ||= {}
|
67
73
|
end
|
@@ -78,6 +84,10 @@ module GitHub
|
|
78
84
|
@options
|
79
85
|
end
|
80
86
|
|
87
|
+
def original_args
|
88
|
+
@@original_args ||= []
|
89
|
+
end
|
90
|
+
|
81
91
|
def parse_options(args)
|
82
92
|
idx = 0
|
83
93
|
args.clone.inject({}) do |memo, arg|
|
@@ -128,3 +138,9 @@ GitHub.command :default do
|
|
128
138
|
end
|
129
139
|
puts
|
130
140
|
end
|
141
|
+
|
142
|
+
GitHub.commands[''] = GitHub.commands['default']
|
143
|
+
GitHub.commands['-h'] = GitHub.commands['default']
|
144
|
+
GitHub.commands['--help'] = GitHub.commands['default']
|
145
|
+
GitHub.commands['-help'] = GitHub.commands['default']
|
146
|
+
GitHub.commands['help'] = GitHub.commands['default']
|
data/spec/ui_spec.rb
CHANGED
@@ -165,8 +165,9 @@ EOF
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
-
specify "
|
169
|
-
running :
|
168
|
+
specify "pull defunkt should start tracking defunkt if they're not already tracked" do
|
169
|
+
running :pull, "defunkt" do
|
170
|
+
mock_members 'defunkt'
|
170
171
|
setup_remote(:origin, :user => "user", :ssh => true)
|
171
172
|
setup_remote(:external, :url => "home:/path/to/project.git")
|
172
173
|
GitHub.should_receive(:invoke).with(:track, "defunkt").and_return { raise "Tracked" }
|
@@ -174,8 +175,9 @@ EOF
|
|
174
175
|
end
|
175
176
|
end
|
176
177
|
|
177
|
-
specify "
|
178
|
-
running :
|
178
|
+
specify "pull defunkt should create defunkt/master and pull from the defunkt remote" do
|
179
|
+
running :pull, "defunkt" do
|
180
|
+
mock_members 'defunkt'
|
179
181
|
setup_remote(:defunkt)
|
180
182
|
@helper.should_receive(:branch_dirty?).and_return false
|
181
183
|
@command.should_receive(:git).with("update-ref refs/heads/defunkt/master HEAD").ordered
|
@@ -185,8 +187,9 @@ EOF
|
|
185
187
|
end
|
186
188
|
end
|
187
189
|
|
188
|
-
specify "
|
189
|
-
running :
|
190
|
+
specify "pull defunkt should switch to pre-existing defunkt/master and pull from the defunkt remote" do
|
191
|
+
running :pull, "defunkt" do
|
192
|
+
mock_members 'defunkt'
|
190
193
|
setup_remote(:defunkt)
|
191
194
|
@helper.should_receive(:branch_dirty?).and_return true
|
192
195
|
@command.should_receive(:die).with("Unable to switch branches, your current branch has uncommitted changes").and_return { raise "Died" }
|
@@ -241,8 +244,9 @@ EOF
|
|
241
244
|
end
|
242
245
|
end
|
243
246
|
|
244
|
-
specify "
|
245
|
-
running :
|
247
|
+
specify "pull defunkt wip should create defunkt/wip and pull from wip branch on defunkt remote" do
|
248
|
+
running :pull, "defunkt", "wip" do
|
249
|
+
mock_members 'defunkt'
|
246
250
|
setup_remote(:defunkt)
|
247
251
|
@helper.should_receive(:branch_dirty?).and_return true
|
248
252
|
@command.should_receive(:die).with("Unable to switch branches, your current branch has uncommitted changes").and_return { raise "Died" }
|
@@ -250,25 +254,42 @@ EOF
|
|
250
254
|
end
|
251
255
|
end
|
252
256
|
|
253
|
-
specify "
|
254
|
-
running :
|
255
|
-
|
256
|
-
|
257
|
-
@command.should_receive(:git).with("
|
257
|
+
specify "pull defunkt/wip should switch to pre-existing defunkt/wip and pull from wip branch on defunkt remote" do
|
258
|
+
running :pull, "defunkt/wip" do
|
259
|
+
mock_members 'defunkt'
|
260
|
+
setup_remote(:defunkt)
|
261
|
+
@command.should_receive(:git).with("checkout -b defunkt/wip").ordered.and_return do
|
262
|
+
mock("checkout -b defunkt/wip").tap { |m| m.should_receive(:error?) { true } }
|
263
|
+
end
|
258
264
|
@command.should_receive(:git).with("checkout defunkt/wip").ordered
|
259
265
|
@command.should_receive(:git_exec).with("fetch defunkt wip").ordered
|
260
266
|
stdout.should == "Switching to defunkt/wip\n"
|
261
267
|
end
|
262
268
|
end
|
263
269
|
|
264
|
-
specify "
|
265
|
-
running :
|
270
|
+
specify "pull --merge defunkt should pull from defunkt remote into current branch" do
|
271
|
+
running :pull, "--merge", "defunkt" do
|
272
|
+
mock_members 'defunkt'
|
266
273
|
setup_remote(:defunkt)
|
267
274
|
@helper.should_receive(:branch_dirty?).and_return false
|
268
275
|
@command.should_receive(:git_exec).with("fetch defunkt master")
|
269
276
|
end
|
270
277
|
end
|
271
278
|
|
279
|
+
specify "pull falls through for non-recognized commands" do
|
280
|
+
running :pull, 'remote' do
|
281
|
+
mock_members 'defunkt'
|
282
|
+
@command.should_receive(:git_exec).with("pull remote")
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
specify "pull passes along args when falling through" do
|
287
|
+
running :pull, 'remote', '--stat' do
|
288
|
+
mock_members 'defunkt'
|
289
|
+
@command.should_receive(:git_exec).with("pull remote --stat")
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
272
293
|
# -- clone --
|
273
294
|
specify "clone should die with no args" do
|
274
295
|
running :clone do
|
@@ -277,10 +298,9 @@ EOF
|
|
277
298
|
end
|
278
299
|
end
|
279
300
|
|
280
|
-
specify "clone should
|
281
|
-
running :clone, "
|
282
|
-
@command.should_receive(:
|
283
|
-
self.should raise_error("Died")
|
301
|
+
specify "clone should fall through with just one arg" do
|
302
|
+
running :clone, "git://git.kernel.org/linux.git" do
|
303
|
+
@command.should_receive(:git_exec).with("clone git://git.kernel.org/linux.git")
|
284
304
|
end
|
285
305
|
end
|
286
306
|
|
@@ -290,6 +310,12 @@ EOF
|
|
290
310
|
end
|
291
311
|
end
|
292
312
|
|
313
|
+
specify "clone defunkt/github-gem should clone the repo" do
|
314
|
+
running :clone, "defunkt/github-gem" do
|
315
|
+
@command.should_receive(:git_exec).with("clone git://github.com/defunkt/github-gem.git")
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
293
319
|
specify "clone --ssh defunkt github-gem should clone the repo using the private URL" do
|
294
320
|
running :clone, "--ssh", "defunkt", "github-gem" do
|
295
321
|
@command.should_receive(:git_exec).with("clone git@github.com:defunkt/github-gem.git")
|
@@ -302,6 +328,12 @@ EOF
|
|
302
328
|
end
|
303
329
|
end
|
304
330
|
|
331
|
+
specify "clone defunkt/github-gem repo should clone the repo into the dir 'repo'" do
|
332
|
+
running :clone, "defunkt/github-gem", "repo" do
|
333
|
+
@command.should_receive(:git_exec).with("clone git://github.com/defunkt/github-gem.git repo")
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
305
337
|
specify "clone --ssh defunkt github-gem repo should clone the repo using the private URL into the dir 'repo'" do
|
306
338
|
running :clone, "--ssh", "defunkt", "github-gem", "repo" do
|
307
339
|
@command.should_receive(:git_exec).with("clone git@github.com:defunkt/github-gem.git repo")
|
@@ -360,6 +392,19 @@ EOF
|
|
360
392
|
end
|
361
393
|
end
|
362
394
|
|
395
|
+
# -- fallthrough --
|
396
|
+
specify "should fall through to actual git commands" do
|
397
|
+
running :commit do
|
398
|
+
@command.should_receive(:git_exec).with("commit")
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
specify "should pass along arguments when falling through" do
|
403
|
+
running :commit, '-a', '-m', 'yo mama' do
|
404
|
+
@command.should_receive(:git_exec).with("commit -a -m 'yo mama'")
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
363
408
|
# -- default --
|
364
409
|
specify "should print the default message" do
|
365
410
|
running :default do
|
@@ -399,7 +444,7 @@ EOF
|
|
399
444
|
|
400
445
|
def initialize(parent, cmd, *args, &block)
|
401
446
|
@cmd_name = cmd.to_s
|
402
|
-
@command = GitHub.
|
447
|
+
@command = GitHub.find_command(cmd)
|
403
448
|
@helper = @command.helper
|
404
449
|
@args = args
|
405
450
|
@block = block
|
@@ -458,6 +503,10 @@ EOF
|
|
458
503
|
@helper.should_receive(:remotes).any_number_of_times.and_return(@remotes)
|
459
504
|
end
|
460
505
|
|
506
|
+
def mock_members(members)
|
507
|
+
@helper.should_receive(:network_members).any_number_of_times.and_return(members)
|
508
|
+
end
|
509
|
+
|
461
510
|
def should(result)
|
462
511
|
@expected_result = [:should, result]
|
463
512
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: riquedafreak-github
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Wanstrath, Kevin Ballard, Scott Chacon
|
@@ -10,17 +10,27 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
|
12
12
|
date: 2008-05-18 00:00:00 -07:00
|
13
|
-
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
13
|
+
default_executable: gh
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
16
24
|
description: The official `github` command line helper for simplifying your GitHub experience.
|
17
25
|
email: chris@ozmm.org
|
18
26
|
executables:
|
19
27
|
- github
|
28
|
+
- gh
|
20
29
|
extensions: []
|
21
30
|
|
22
31
|
extra_rdoc_files:
|
23
32
|
- bin/github
|
33
|
+
- bin/gh
|
24
34
|
- lib/github/extensions.rb
|
25
35
|
- lib/github/command.rb
|
26
36
|
- lib/github/helper.rb
|
@@ -46,6 +56,7 @@ files:
|
|
46
56
|
- spec/ui_spec.rb
|
47
57
|
- spec/windoze_spec.rb
|
48
58
|
- github-gem.gemspec
|
59
|
+
- bin/gh
|
49
60
|
has_rdoc: true
|
50
61
|
homepage: http://github.com/
|
51
62
|
post_install_message:
|