Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 145 lines (122 sloc) 4.848 kB
5005747 @pr1001 We've got the basics of a working tool!
authored
1 #!/usr/bin/env ruby
2
3 require "rubygems"
4 require 'optparse'
5 require 'octokit'
6 require 'fileutils'
7 require 'json'
8 require 'nokogiri'
9 require 'open-uri'
10 require 'net/http'
11
12 options = {}
13
14 optparse = OptionParser.new do|opts|
15 # Set a banner, displayed at the top
16 # of the help screen.
17 opts.banner = "Usage: gitback.rb [options] username/rep /destination/directory"
18
19 options[:username] = nil
20 opts.on('-u', '--username username', 'GitHub username') do |username|
21 options[:username] = username
22 end
23
24 options[:password] = nil
25 opts.on('-p', '--password password', 'GitHub password') do |password|
26 options[:password] = password
27 end
28
29 # This displays the help screen, all programs are
30 # assumed to have this option.
31 opts.on('-h', '--help', 'Display this screen') do
32 puts opts
33 exit
34 end
35 end
36
37 # Parse the command-line. Remember there are two forms
38 # of the parse method. The 'parse' method simply parses
39 # ARGV, while the 'parse!' method parses ARGV and removes
40 # any options found there, as well as any parameters for
41 # the options. What's left is the list of files to resize.
42 optparse.parse!
43
44 reponame = ARGV[0]
45 path = ARGV[1]
46 if not reponame
47 puts "A repo name in the format username/repo is required."
48 exit
49 end
50 if not path
51 puts "A path in the format /destination/directory is required."
52 exit
53 end
54
55 client = (options[:username] and options[:password]) ? Octokit::Client.new(:login => options[:username], :password => options[:password]) : Octokit::Client.new()
56
57 # username, name = reponame.split('/')
58
59 repo = client.repo(reponame)
60
61 puts "Found repo " + repo["name"]
62
63 # make dir
64 FileUtils.mkdir_p(path)
65
66 clone_url = repo["private"] ? repo["ssh_url"] : repo["clone_url"]
67 git_path = path + "/" + repo["name"]
68 git_dir = git_path + "/.git"
69
70 system("git clone #{clone_url} #{git_path}")
71 # don't userstand why it's not picking up the work-tree param, so just cd to the dir first
72 system("cd #{git_path}; git --git-dir=#{git_dir} --work-tree=#{git_path} pull --all")
73
74 if repo["has_issues"]
75 puts "We've got issues! Downloading them now..."
76
77 # get the issues
78 issues = client.list_issues(reponame)
79 # can create the directory without checking because we know there are issues?
80 FileUtils.mkdir_p(path + "/issues") unless issues.empty?
81 issues.each do |issue|
82 # write json issue to path + "/issues/" + issue["number"]
83 FileUtils.mkdir_p(path + "/issues/" + issue["number"].to_s)
84 File.open(path + "/issues/" + issue["number"].to_s + "/" + issue["number"].to_s + ".json", 'w') do |f|
85 f.write(JSON.generate(issue))
86 end
87 if (issue["comments"] > 0)
88 puts "Downloading " + issue["comments"].to_s + " comments"
89 FileUtils.mkdir_p(path + "/issues/" + issue["number"].to_s + "/comments")
90 comments = client.issue_comments(reponame, issue["number"])
91 comments.each do |comment|
92 # write json comment to path + "/issues/" + issue["number"] + "/comments/" + comment["id"]
93 File.open(path + "/issues/" + issue["number"].to_s + "/comments/" + comment["id"].to_s + ".json", 'w') do |f|
94 f.write(JSON.generate(comment))
95 end
96 end
97 end
98 end
99 end
100
101 if repo["has_wiki"]
102 # not worth doing anything here since the wiki is already in the main repo?
103 puts "This repo has a wiki. Remember, it's just a branch of your normal repo."
104 end
105
106 # FIXME: This only works for public repos
107 if repo["has_downloads"] and not repo["private"]
108 downloads_url = repo["html_url"] + "/downloads"
109
110 # get html, extract "#manual_downloads a[href]"
111 page = Nokogiri::HTML(open(downloads_url))
112 links = page.css("#manual_downloads a")
113
114 # repo["has_downloads"] seems to always be true, so actually check first
115 if links.length > 0
116 puts "We've got downloads!"
117 FileUtils.mkdir_p(path + "/downloads/")
118 end
119
120 # can we do this in parallel?
121 links.each do |link|
122 download_url = "https://github.com" + link["href"]
123 puts "Downloading #{download_url}"
124 # code to write the stream directly into the file and not store in memory first
125 # from http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html
126 uri = URI(download_url)
127 Net::HTTP.start(uri.host, uri.port) do |http|
128 request = Net::HTTP::Get.new uri.request_uri
129 http.request request do |response|
130 open(path + "/downloads/" + link.inner_text, 'w') do |io|
131 response.read_body do |chunk|
132 io.write chunk
133 end
134 end
135 end
136 end
137 end
138 elsif repo["has_downloads"] and repo["private"]
139 downloads_url = repo["html_url"] + "/downloads"
140 downloads_path = path + "/downloads/"
141 FileUtils.mkdir_p(downloads_path)
142 puts "This repo is private so we can't download the files for you (yet!)."
143 puts "We've created the folder #{downloads_path} so you can manually download the files listed at #{downloads_url} into it."
144 end
Something went wrong with that request. Please try again.