git-forks 0.0.3 → 0.0.4
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/lib/git-forks.rb +189 -55
- metadata +1 -1
data/lib/git-forks.rb
CHANGED
@@ -11,7 +11,8 @@ require 'time'
|
|
11
11
|
|
12
12
|
class GitForks
|
13
13
|
|
14
|
-
CACHE_FILE
|
14
|
+
CACHE_FILE = '.git/forks_cache.json'
|
15
|
+
NO_UPDATE_ACTIONS = ['help', 'usage', 'update', 'config']
|
15
16
|
|
16
17
|
def initialize(args)
|
17
18
|
@command = args.shift
|
@@ -30,7 +31,7 @@ class GitForks
|
|
30
31
|
# If the cache file doesn't exist, make sure we run update
|
31
32
|
# before any other command. git-forks will otherwise crash
|
32
33
|
# with an exception.
|
33
|
-
update unless File.exists?(CACHE_FILE) || @command
|
34
|
+
update unless File.exists?(CACHE_FILE) || NO_UPDATE_ACTIONS.include?(@command)
|
34
35
|
|
35
36
|
self.send @command
|
36
37
|
elsif %w(-h --help).include?(@command)
|
@@ -62,6 +63,58 @@ class GitForks
|
|
62
63
|
# Commands
|
63
64
|
#-----------------------------------------------------------------------------
|
64
65
|
|
66
|
+
# list
|
67
|
+
# get
|
68
|
+
# add
|
69
|
+
# remove
|
70
|
+
#
|
71
|
+
def config
|
72
|
+
action = @args.shift
|
73
|
+
owner = @args.shift
|
74
|
+
|
75
|
+
if action
|
76
|
+
if owner || action == "list"
|
77
|
+
case action
|
78
|
+
when "list"
|
79
|
+
if (f = config_get_forks).size > 0
|
80
|
+
puts f
|
81
|
+
end
|
82
|
+
when "get"
|
83
|
+
if (v = config_get_fork(owner)).size > 0
|
84
|
+
puts v
|
85
|
+
end
|
86
|
+
when "add"
|
87
|
+
if config_get_fork(owner).size > 0
|
88
|
+
puts "#{owner} already exists."
|
89
|
+
else
|
90
|
+
config_add_fork(owner)
|
91
|
+
puts "Added #{owner}."
|
92
|
+
end
|
93
|
+
when "remove"
|
94
|
+
if config_get_fork(owner).empty?
|
95
|
+
puts "#{owner} not found."
|
96
|
+
else
|
97
|
+
# (Forces cache update.)
|
98
|
+
config_remove_fork(owner)
|
99
|
+
puts "Removed #{owner}."
|
100
|
+
end
|
101
|
+
else
|
102
|
+
puts "<action> '#{action}' unknown"
|
103
|
+
puts
|
104
|
+
usage
|
105
|
+
end
|
106
|
+
else
|
107
|
+
puts "<owner> argument missing"
|
108
|
+
puts
|
109
|
+
usage
|
110
|
+
end
|
111
|
+
else
|
112
|
+
puts "<action> argument missing"
|
113
|
+
puts
|
114
|
+
usage
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
65
118
|
# Get the latest GitHub data.
|
66
119
|
def update
|
67
120
|
puts 'Retrieving the latest GitHub data...'
|
@@ -92,66 +145,82 @@ class GitForks
|
|
92
145
|
def fetch
|
93
146
|
target_owners = @args
|
94
147
|
|
95
|
-
update if not @updated
|
148
|
+
update if not @updated # force cache update
|
149
|
+
|
150
|
+
cached_owners = []
|
96
151
|
get_cached_data('forks').each do |fork|
|
97
|
-
|
98
|
-
|
152
|
+
cached_owners << fork['owner']['login']
|
153
|
+
end
|
154
|
+
|
155
|
+
# fetch all configured forks by default
|
156
|
+
target_owners = cached_owners if target_owners.empty?
|
157
|
+
|
158
|
+
target_owners.each do |owner|
|
159
|
+
if cached_owners.include?(owner)
|
99
160
|
puts '-' * 80
|
100
161
|
puts "Fething Git data from fork '#{owner}/#{@repo}'"
|
101
|
-
|
102
|
-
|
162
|
+
git_fetch_fork(owner)
|
163
|
+
else
|
164
|
+
# TODO: add --force => add owner to config automatically
|
165
|
+
puts '-' * 80
|
166
|
+
puts "'#{owner}/#{@repo}' is not in your forks whitelist."
|
167
|
+
puts
|
168
|
+
puts "Run: $ git forks config add #{owner}"
|
169
|
+
puts "and then try again, if you really want to pull from this fork."
|
170
|
+
puts
|
171
|
+
print "This is your current forks whitelist: "
|
172
|
+
if (f = config_get_forks).size > 0
|
173
|
+
puts f.gsub("\n", ', ')
|
174
|
+
else
|
175
|
+
puts "<empty>"
|
176
|
+
end
|
177
|
+
exit 1
|
103
178
|
end
|
104
179
|
end
|
105
180
|
end
|
106
181
|
|
107
182
|
# List all forks.
|
108
183
|
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
# --------------------------------------------------------------------------------
|
112
|
-
# Forks of 'doubleotoo/foo/master'
|
113
|
-
#
|
114
|
-
# Owner Branches Updated
|
115
|
-
# ------ -------- -------
|
116
|
-
# justintoo 2 01-May-12
|
117
|
-
# rose-compiler 3 27-Apr-12
|
184
|
+
# TODO: add sorting by column
|
118
185
|
#
|
119
186
|
def list
|
120
187
|
forks = get_cached_data('forks')
|
121
188
|
forks.reverse! if @args.shift == '--reverse'
|
122
189
|
|
190
|
+
whitelist = config_get_forks.split("\n")
|
191
|
+
|
123
192
|
output = forks.collect do |f|
|
193
|
+
owner = f['owner']['login']
|
194
|
+
whitelist.delete(owner)
|
195
|
+
|
124
196
|
line = ""
|
125
|
-
line << l(
|
197
|
+
line << l(owner, 25)
|
126
198
|
line << l(f['branches'].size, 12)
|
127
199
|
line << strftime(clean(f['updated_at']))
|
128
200
|
end
|
129
201
|
|
130
202
|
if output.compact.empty?
|
131
|
-
puts "No forks of '#{@user}/#{@repo}'"
|
203
|
+
puts "No forks of '#{@user}/#{@repo}'."
|
132
204
|
else
|
133
205
|
puts '-' * 80
|
134
|
-
puts "Forks of '#{@user}/#{@repo}'"
|
206
|
+
puts "Forks of '#{@user}/#{@repo}':"
|
135
207
|
puts
|
136
208
|
puts l('Owner', 25) + l('Branches', 12) + 'Updated'
|
137
209
|
puts l('------', 25) + l('--------', 12) + '-------'
|
138
210
|
puts output.compact
|
211
|
+
if whitelist.size > 0
|
212
|
+
whitelist.each do |f|
|
213
|
+
puts l(f, 25) + l('*', 12) + '*'
|
214
|
+
end
|
215
|
+
|
216
|
+
puts
|
217
|
+
puts '* no cache data available; may require `update`'
|
218
|
+
end
|
139
219
|
puts '-' * 80
|
140
220
|
end
|
141
221
|
end
|
142
222
|
|
143
223
|
# Show details of one fork.
|
144
|
-
#
|
145
|
-
# Example::
|
146
|
-
#
|
147
|
-
# -------------------------------------------------------------------------------
|
148
|
-
# Owner : justintoo
|
149
|
-
# Created : 01-May-12
|
150
|
-
# Updated : 01-May-12
|
151
|
-
# Branches : 2
|
152
|
-
# 444a867d338cafc0c82d058b458b4fe268fa14d6 master
|
153
|
-
# 14178fe5b204c38650de8ddaf5d9fb80aa834e74 foo
|
154
|
-
#
|
155
224
|
def show
|
156
225
|
owner = @args.shift
|
157
226
|
option = @args.shift
|
@@ -210,25 +279,43 @@ class GitForks
|
|
210
279
|
end
|
211
280
|
|
212
281
|
def help
|
213
|
-
puts "No command: #{@command}"
|
214
|
-
puts "Try: browse, fetch, list, show, update"
|
215
|
-
puts "or call with '-h' for usage information"
|
282
|
+
puts "No command: #{@command}" if not @command == 'help'
|
283
|
+
puts "Try: browse, config, fetch, list, show, update;"
|
284
|
+
puts " or call with '-h' for usage information"
|
216
285
|
end
|
217
286
|
|
218
287
|
# Show a quick reference of available commands.
|
219
288
|
def usage
|
220
|
-
puts 'Usage: git forks <command>'
|
221
|
-
puts
|
289
|
+
puts 'Usage: git forks [-h] <command>'
|
290
|
+
puts
|
291
|
+
puts 'Manage your GitHub project\'s forks.'
|
222
292
|
puts
|
223
293
|
puts 'Available commands:'
|
224
294
|
puts ' browse <owner>[:<ref>] Show fork in web browser.'
|
225
295
|
puts ' <ref> denotes a Git Tree or a Git Commit.'
|
226
|
-
puts '
|
296
|
+
puts ' config <action> [owner] Configure which forks you are interested in (all by default).'
|
297
|
+
puts
|
298
|
+
puts ' Available actions: '
|
299
|
+
puts ' list List all forks.'
|
300
|
+
puts ' get <owner> Check for <owner>.'
|
301
|
+
puts ' add <owner> Add <owner>.'
|
302
|
+
puts ' remove <owner> Remove <owner>. (Forces cache update.)'
|
303
|
+
puts
|
304
|
+
puts ' The associated git-ref data is also removed.'
|
305
|
+
puts
|
306
|
+
puts ' You may want to run `git gc --prune=now` to'
|
307
|
+
puts ' remove stale objects that you fetched from'
|
308
|
+
puts ' your forks. (Also, see git-reflog.)'
|
309
|
+
puts
|
310
|
+
puts ' You can run `git fsck` to list dangling objects.'
|
311
|
+
puts
|
312
|
+
puts ' (git-gc does have various default expiry times.)'
|
313
|
+
puts ' fetch [<owners>] git-fetch fork data from GitHub. (Forces cache update.)'
|
227
314
|
puts ' <owners> is a space separate list.'
|
228
|
-
puts ' (Forces cache update.)'
|
229
315
|
puts ' list [--reverse] List all forks.'
|
230
316
|
puts ' show <owner> Show details for a single fork.'
|
231
317
|
puts ' update Retrieve fork info from GitHub API v3.'
|
318
|
+
puts ' usage Show this usage information.'
|
232
319
|
end
|
233
320
|
|
234
321
|
#-----------------------------------------------------------------------------
|
@@ -266,30 +353,16 @@ class GitForks
|
|
266
353
|
#-----------------------------------------------------------------------------
|
267
354
|
|
268
355
|
def fetch_fork_info
|
269
|
-
|
356
|
+
targets = config_get_forks # optional fork targets
|
357
|
+
forks = Octokit.forks("#{@user}/#{@repo}").select {|f|
|
358
|
+
targets.empty? or targets.include?(f.owner.login)
|
359
|
+
}
|
270
360
|
end
|
271
361
|
|
272
362
|
def fetch_fork_branches(fork_user)
|
273
363
|
branches = Octokit.branches("#{fork_user}/#{@repo}")
|
274
364
|
end
|
275
365
|
|
276
|
-
#-----------------------------------------------------------------------------
|
277
|
-
# Git
|
278
|
-
#-----------------------------------------------------------------------------
|
279
|
-
|
280
|
-
def git(command)
|
281
|
-
`git #{command}`.chomp
|
282
|
-
end
|
283
|
-
|
284
|
-
def github_endpoint
|
285
|
-
host = git("config --get-all github.host")
|
286
|
-
if host.size > 0
|
287
|
-
host
|
288
|
-
else
|
289
|
-
'https://github.com'
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
366
|
#-----------------------------------------------------------------------------
|
294
367
|
# Display Helper Functions
|
295
368
|
#-----------------------------------------------------------------------------
|
@@ -320,6 +393,10 @@ class GitForks
|
|
320
393
|
end
|
321
394
|
end
|
322
395
|
|
396
|
+
#-----------------------------------------------------------------------------
|
397
|
+
# Git
|
398
|
+
#-----------------------------------------------------------------------------
|
399
|
+
|
323
400
|
#def github_login
|
324
401
|
# git("config --get-all github.user")
|
325
402
|
#end
|
@@ -362,4 +439,61 @@ class GitForks
|
|
362
439
|
return nil, nil
|
363
440
|
end
|
364
441
|
|
442
|
+
def git(command)
|
443
|
+
`git #{command}`.chomp
|
444
|
+
end
|
445
|
+
|
446
|
+
def github_endpoint
|
447
|
+
host = git("config --get-all github.host")
|
448
|
+
if host.size > 0
|
449
|
+
host
|
450
|
+
else
|
451
|
+
'https://github.com'
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
def config_get_forks
|
456
|
+
git("config --get-all github.forks.owner")
|
457
|
+
end
|
458
|
+
|
459
|
+
def config_get_fork(owner)
|
460
|
+
git("config --get-all github.forks.owner \"^#{owner}$\"")
|
461
|
+
end
|
462
|
+
|
463
|
+
def config_add_fork(owner)
|
464
|
+
git("config --add github.forks.owner #{owner}")
|
465
|
+
end
|
466
|
+
|
467
|
+
# (Forces cache update.)
|
468
|
+
def config_remove_fork(owner)
|
469
|
+
git("config --unset github.forks.owner \"^#{owner}$\"")
|
470
|
+
git_remove_fork(owner)
|
471
|
+
update # TODO: optimize by only updating if fork existed
|
472
|
+
end
|
473
|
+
|
474
|
+
# Remove a fork's git-refs.
|
475
|
+
#
|
476
|
+
# Directory: refs/forks/rose-compiler/ <-- notice the trailing slash
|
477
|
+
# Single: refs/forks/rose-compiler/master
|
478
|
+
def git_remove_fork(owner)
|
479
|
+
refdir = "refs/forks/#{owner}"
|
480
|
+
gitdir = ".git/#{refdir}"
|
481
|
+
|
482
|
+
if Dir.exists?(gitdir)
|
483
|
+
Dir.foreach(gitdir) do |ref|
|
484
|
+
next if ref == '.' or ref == '..'
|
485
|
+
# delete each individual ref
|
486
|
+
git("update-ref -d #{refdir}/#{ref}")
|
487
|
+
end
|
488
|
+
|
489
|
+
# delete the ref directory
|
490
|
+
git("update-ref -d #{refdir}")
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
def git_fetch_fork(owner)
|
495
|
+
git("fetch --prune " +
|
496
|
+
"#{github_endpoint}/#{owner}/#{@repo}.git " +
|
497
|
+
"+refs/heads/*:refs/forks/#{owner}/*")
|
498
|
+
end
|
365
499
|
end # GitForks
|