Class: GitForks

Inherits:
Object
  • Object
show all
Defined in:
lib/git-forks.rb

Constant Summary collapse

CACHE_FILE =
'.git/forks_cache.json'
NO_UPDATE_ACTIONS =
['help', 'usage', 'update', 'config']

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args) ⇒ GitForks

Returns a new instance of GitForks.



17
18
19
20
21
22
# File 'lib/git-forks.rb', line 17

def initialize(args)
  @command = args.shift
  @user, @repo = repo_info
  @args = args
  @updated = false
end

Class Attribute Details

.debugObject

Set debug to true to log everything



50
51
52
# File 'lib/git-forks.rb', line 50

def debug
  @debug
end

.loggerObject

The standard logger for debugging - this defaults to a plain STDOUT logger



53
54
55
# File 'lib/git-forks.rb', line 53

def logger
  @logger
end

Class Method Details

.log(str) ⇒ Object



54
55
56
# File 'lib/git-forks.rb', line 54

def log(str)
  logger.debug { str }
end

.start(args) ⇒ Object



24
25
26
# File 'lib/git-forks.rb', line 24

def self.start(args)
  GitForks.new(args).run
end

Instance Method Details

#browseObject



251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/git-forks.rb', line 251

def browse
  owner = @args.shift
  if owner
    owner, ref = owner.split(':')

    if f = fork(owner)
      url = f['html_url']

      if ref
        if ref.match(/[A-Za-z0-9]{40}/)
          url << "/commits/#{ref}"
        else
          url << "/tree/#{ref}"
        end
      end

      return Launchy.open(url)
    elsif owner == "network"
    else
      puts "No such fork: '#{owner}/#{@repo}'. Maybe you need to run git-forks update?"
      puts
      list
    end
  else
    puts "<owner> argument missing"
    puts
    usage
  end
end

#cache(group, json) ⇒ Object


Cache




325
326
327
# File 'lib/git-forks.rb', line 325

def cache(group, json)
  save_data({group => json}, CACHE_FILE)
end

#clean(info) ⇒ Object



378
379
380
# File 'lib/git-forks.rb', line 378

def clean(info)
  info.to_s.gsub("\n", ' ')
end

#configObject

list get add remove



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/git-forks.rb', line 71

def config
  action = @args.shift
  owner  = @args.shift

  if action
    if owner || action == "list"
      case action
      when "list"
        if (f = config_get_forks).size > 0
          puts f
        end
      when "get"
        if (v = config_get_fork(owner)).size > 0
          puts v
        end
      when "add"
        if config_get_fork(owner).size > 0
          puts "#{owner} already exists."
        else
          config_add_fork(owner)
          puts "Added #{owner}."
        end
      when "remove"
        if config_get_fork(owner).empty?
          puts "#{owner} not found."
        else
          # (Forces cache update.)
          config_remove_fork(owner)
          puts "Removed #{owner}."
        end
      else
        puts "<action> '#{action}' unknown"
        puts
        usage
      end
    else
      puts "<owner> argument missing"
      puts
      usage
    end
  else
    puts "<action> argument missing"
    puts
    usage
  end
end

#fetchObject

git-fetch from the fork’s GitHub repository. (Forces cache update.)



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/git-forks.rb', line 145

def fetch
  target_owners = @args

  update if not @updated # force cache update

  cached_owners = []
  get_cached_data('forks').each do |fork|
    cached_owners << fork['owner']['login']
  end

  # fetch all configured forks by default
  target_owners = cached_owners if target_owners.empty?

  target_owners.each do |owner|
    if cached_owners.include?(owner)
      puts '-' * 80
      puts "Fething Git data from fork '#{owner}/#{@repo}'"
      git_fetch_fork(owner)
    else
      # TODO: add --force => add owner to config automatically
      puts '-' * 80
      puts "'#{owner}/#{@repo}' is not in your forks whitelist."
      puts
      puts "Run:  $ git forks config add #{owner}"
      puts "and then try again, if you really want to pull from this fork."
      puts
      print "This is your current forks whitelist: "
      if (f = config_get_forks).size > 0
        puts f.gsub("\n", ', ')
      else
        puts "<empty>"
      end
      exit 1
    end
  end
end

#fetch_fork_branches(fork_user) ⇒ Object



362
363
364
# File 'lib/git-forks.rb', line 362

def fetch_fork_branches(fork_user)
  branches = Octokit.branches("#{fork_user}/#{@repo}")
end

#fetch_fork_infoObject


GitHub API v3 (using Octokit gem)




355
356
357
358
359
360
# File 'lib/git-forks.rb', line 355

def fetch_fork_info
  targets = config_get_forks # optional fork targets
  forks = Octokit.forks("#{@user}/#{@repo}").select {|f|
    targets.empty? or targets.include?(f.owner.)
  }
end

#fork(owner) ⇒ Object

Get a fork by owner name.



346
347
348
349
# File 'lib/git-forks.rb', line 346

def fork(owner)
  forks = get_cached_data('forks')
  forks.select {|f| f['owner']['login'] == owner }.first
end

#get_cached_data(group = nil) ⇒ Object

get_cached_data(‘forks’)



330
331
332
333
334
335
336
337
# File 'lib/git-forks.rb', line 330

def get_cached_data(group=nil)
  data = JSON.parse(File.read(CACHE_FILE))
  if group
    data[group]
  else
    data
  end
end

#helpObject



281
282
283
284
285
# File 'lib/git-forks.rb', line 281

def help
  puts "No command: #{@command}" if not @command == 'help'
  puts "Try: browse, config, fetch, list, show, update;"
  puts "     or call with '-h' for usage information"
end

#l(info, size) ⇒ Object


Display Helper Functions




370
371
372
# File 'lib/git-forks.rb', line 370

def l(info, size)
  clean(info)[0, size].ljust(size)
end

#listObject

List all forks.

TODO: add sorting by column



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/git-forks.rb', line 186

def list
  forks = get_cached_data('forks')
  forks.reverse! if @args.shift == '--reverse'

  whitelist = config_get_forks.split("\n")

  output = forks.collect do |f|
    owner = f['owner']['login']
    whitelist.delete(owner)

    line = ""
    line << l(owner, 25)
    line << l(f['branches'].size, 12)
    line << strftime(clean(f['updated_at']))
  end

  if output.compact.empty?
    puts "No forks of '#{@user}/#{@repo}'."
  else
    puts '-' * 80
    puts "Forks of '#{@user}/#{@repo}':"
    puts
    puts l('Owner', 25) + l('Branches', 12) + 'Updated'
    puts l('------', 25) + l('--------', 12) + '-------'
    puts output.compact
    if whitelist.size > 0
      whitelist.each do |f|
        puts l(f, 25) + l('*', 12) + '*'
      end

      puts
      puts '* no cache data available; may require `update`'
    end
    puts '-' * 80
  end
end

#r(info, size) ⇒ Object



374
375
376
# File 'lib/git-forks.rb', line 374

def r(info, size)
  clean(info)[0, size].rjust(size)
end

#runObject



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/git-forks.rb', line 28

def run
  configure
  if @command && self.respond_to?(@command)
    # If the cache file doesn't exist, make sure we run update
    # before any other command. git-forks will otherwise crash
    # with an exception.
    update unless File.exists?(CACHE_FILE) || NO_UPDATE_ACTIONS.include?(@command)

    self.send @command
  elsif %w(-h --help).include?(@command)
    usage
  else
    help
  end
end

#save_data(data, file) ⇒ Object



339
340
341
342
343
# File 'lib/git-forks.rb', line 339

def save_data(data, file)
  File.open(file, "w+") do |f|
    f.puts data.to_json
  end
end

#showObject

Show details of one fork.



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/git-forks.rb', line 224

def show
  owner = @args.shift
  option = @args.shift
  if owner
    if f = fork(owner)
      puts '-' * 80
      puts "Owner    : #{f['owner']['login']}"
      puts "Repo     : #{@repo}"
      puts "Created  : #{strftime(f['created_at'])}"
      puts "Updated  : #{strftime(f['updated_at'])}"
      puts "Branches : #{f['branches'].size}"
      f['branches'].each do |b|
        puts "  #{b['commit']['sha']} #{b['name']}"
      end
      puts '-' * 80
    else
      puts "No such fork: '#{owner}/#{@repo}'. Maybe you need to run git-forks update?"
      puts
      list
    end
  else
      puts "<owner> argument missing"
      puts
      usage
  end
end

#strftime(time_string) ⇒ Object



382
383
384
# File 'lib/git-forks.rb', line 382

def strftime(time_string)
  Time.parse(time_string).strftime('%d-%b-%y')
end

#updateObject

Get the latest GitHub data.



119
120
121
122
123
124
125
126
# File 'lib/git-forks.rb', line 119

def update
  puts 'Retrieving the latest GitHub data...'

  cache('forks', fetch_fork_info)
  update_branches

  @updated = true
end

#update_branchesObject

Fetch and cache all branches for each fork.



129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/git-forks.rb', line 129

def update_branches
  forks = get_cached_data('forks')

  forks.each do |fork|
    fork_user = fork['owner']['login']
    GitForks.log "Fetching branches in '#{fork_user}/#{@repo}'" if GitForks.debug

    branches = fetch_fork_branches(fork_user)

    fork['branches'] = branches
  end

  cache('forks', forks)
end

#usageObject

Show a quick reference of available commands.



288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'lib/git-forks.rb', line 288

def usage
  puts 'Usage: git forks [-h] <command>'
  puts
  puts 'Manage your GitHub project\'s forks.'
  puts
  puts 'Available commands:'
  puts '  browse <owner>[:<ref>]  Show fork in web browser.'
  puts '                          <ref> denotes a Git Tree or a Git Commit.'
  puts '  config <action> [owner] Configure which forks you are interested in (all by default).'
  puts
  puts '                          Available actions:                          '
  puts '                            list            List all forks.'
  puts '                            get <owner>     Check for <owner>.'
  puts '                            add <owner>     Add <owner>.'
  puts '                            remove <owner>  Remove <owner>. (Forces cache update.)'
  puts
  puts '                                            The associated git-ref data is also removed.'
  puts
  puts '                                            You may want to run `git gc --prune=now` to'
  puts '                                            remove stale objects that you fetched from'
  puts '                                            your forks. (Also, see git-reflog.)'
  puts
  puts '                                            You can run `git fsck` to list dangling objects.'
  puts
  puts '                                            (git-gc does have various default expiry times.)'
  puts '  fetch [<owners>]        git-fetch fork data from GitHub. (Forces cache update.)'
  puts '                          <owners> is a space separate list.'
  puts '  list [--reverse]        List all forks.'
  puts '  show <owner>            Show details for a single fork.'
  puts '  update                  Retrieve fork info from GitHub API v3.'
  puts '  usage                   Show this usage information.'
end