Created
April 12, 2011 21:19
-
-
Save cowboy/916434 to your computer and use it in GitHub Desktop.
Ruby: Clone Yer GitHub Repos, Fast!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# /usr/bin/env ruby | |
puts <<-EOF | |
Clone Yer GitHub Repos, Fast! - v0.2.1 - 4/13/2011 | |
http://benalman.com/ | |
For when you're on a new computer and need all your stuff, fast! | |
EOF | |
copyright = <<-EOF | |
Copyright (c) 2011 "Cowboy" Ben Alman | |
Dual licensed under the MIT and GPL licenses. | |
http://benalman.com/about/license/ | |
EOF | |
help = <<-EOF | |
Usage: | |
ruby #{File.basename($0)} [ filter [, filter... ] ] | |
Notes: | |
* All forks are cloned into a "forks" subdir. | |
* Pre-existing repos are skipped. | |
* Any filter arg can contain ? and * wildcard characters. Wrap args in quotes | |
if * is used! | |
EOF | |
# User wants help? User gets help. | |
if !ARGV.empty? && %w{-h --help}.find {|a| a == ARGV[0]} | |
puts "\n#{help}\n#{copyright}" | |
exit | |
end | |
# Handle ctrl-c abort. | |
trap('INT') do | |
puts "\nAborted!" | |
exit 1 | |
end | |
user = '' # Set this if you don't want to be asked every time! | |
puts "\n" if user.empty? | |
while user.empty? | |
print 'GitHub username: ' | |
user = STDIN.gets.chomp | |
end | |
puts <<-EOF | |
If you would like private repos to be cloned, you can enter the password for | |
GitHub user "#{user}" now. | |
If this is the wrong user, press Ctrl-C, and try again. | |
Note that this password is only used to authenticate to GitHub for downloading | |
private repos, and is not stored anywhere. If you don't have any private repos, | |
just press ENTER. | |
EOF | |
print 'GitHub password: ' | |
# Get password. Should be invisible on systems that support stty, YMMV. | |
system 'stty -echo' | |
pass = STDIN.gets.chomp | |
system 'stty echo' | |
require 'open-uri' | |
require 'json' | |
require 'fileutils' | |
# Fetch and parse user JSON. | |
print "\n\nFetching repository list... " | |
options = pass.empty? ? {} : {:http_basic_authentication => [user, pass]} | |
json = open("http://github.com/api/v1/json/#{user}", options).read | |
data = JSON.parse(json) | |
# Create an array of filters from command line arguments, converting wildcard | |
# * and ? chars to their regex equivalent. | |
filters = ARGV.map do |a| | |
Regexp.new('^' + Regexp.escape(a).gsub(/\\\*/, '.*').gsub(/\\\?/, '.') + '$') | |
end | |
# If args were passed, filter out any repos whose names don't match any of the | |
# passed args. | |
repos = data['user']['repositories'].select do |r| | |
filters.empty? || filters.find {|re| r['name'] =~ re} | |
end.compact | |
# No matching repos? FAIL. | |
if repos.empty? | |
puts "No repos found, exiting!" | |
exit 1 | |
end | |
puts "#{repos.length} repo#{repos.length == 1 ? '' : 's'} found.\n\n" | |
# Clone all matching repos that haven't already been cloned. | |
repos.each do |r| | |
path = (r['fork'] ? 'forks/' : '') + r['name'] | |
uri = "[email protected]:#{user}/#{r['name']}.git" | |
if File.exist?(path) | |
puts "Skipping #{path} (clone already exists).\n" | |
else | |
unless system %Q{git clone "#{uri}" "#{path}"} | |
# Cleanup potentially broken git clone. | |
FileUtils.rm_rf path | |
puts "\nAn error or abort ocurred!" | |
exit 1 | |
end | |
end | |
end | |
puts "\nDone!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment