github_copier 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rubocop.yml +10 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +203 -0
- data/Rakefile +26 -0
- data/bin/github_copier +66 -0
- data/github_copier.gemspec +42 -0
- data/lib/github_copier/github_copier.rb +102 -0
- data/lib/github_copier/opt_parser.rb +82 -0
- data/lib/github_copier/version.rb +3 -0
- data/lib/github_copier.rb +7 -0
- data/test/lib/github_copier/test_github_copier.rb +8 -0
- data/test/test_helper.rb +8 -0
- metadata +261 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f4f993114e8a40461a5937d56f84b580d62062fa
|
4
|
+
data.tar.gz: 3dd6b2ef0b3d636610f30e2ce226d2e5c167b3a7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ab4869300def7a4754ab104c1ae87cbffe02a83756bb402ed7123acf7c3d97b87e403933bc6c5e762af2021f257c53146ea123423c9643ab745a0a15c3c69a84
|
7
|
+
data.tar.gz: 1422f1b597e56ce3fabafdde1fb3bf1ce678bfec128ee813922dd8d12cc543cbce7ff6f2155e95041ae918f1da758b3dd12cd5765090886b4de0d0820b7ce37b
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 Burin Choomnuan
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
## GithubCopier
|
2
|
+
|
3
|
+
Export/clone Github repository (public/private) by user or organization name
|
4
|
+
|
5
|
+
[][gem]
|
6
|
+
[][gemnasium]
|
7
|
+
[][codeclimate]
|
8
|
+
|
9
|
+
[gem]: http://badge.fury.io/rb/github_copier
|
10
|
+
[gemnasium]: https://gemnasium.com/agilecreativity/github_copier
|
11
|
+
[codeclimate]: https://codeclimate.com/github/agilecreativity/github_copier
|
12
|
+
|
13
|
+
### Why
|
14
|
+
|
15
|
+
- Be able to get grab all of interesting codes from a given user quickly
|
16
|
+
- Be able to clone specific language for a given user/organization
|
17
|
+
- Be able to clone all of organization/users in one go if desired
|
18
|
+
- Be able to clone private/public repositories for a given user/organization
|
19
|
+
- Be able to learn quickly or look at how something works from the source code
|
20
|
+
- I am too lazy to do this manually or through some other shell script
|
21
|
+
|
22
|
+
### Installation
|
23
|
+
|
24
|
+
```sh
|
25
|
+
# Install the gem
|
26
|
+
gem install github_copier
|
27
|
+
|
28
|
+
# refresh your gem just in case
|
29
|
+
rbenv rehash
|
30
|
+
|
31
|
+
# Get list of options just type the name of the gem
|
32
|
+
github_copier
|
33
|
+
```
|
34
|
+
|
35
|
+
You should see something like
|
36
|
+
|
37
|
+
```
|
38
|
+
Usage: github_copier [options]
|
39
|
+
|
40
|
+
Specific options:
|
41
|
+
-b, --base-dir BASE_DIR Output directory where the repository will be cloned to
|
42
|
+
-u, --user USER The github USER that will be cloned from
|
43
|
+
-o, --org [ORG] The Github's organization name to be used if specified
|
44
|
+
(where ORG is the organization that the user belongs to)
|
45
|
+
-t, --oauth-token [OAUTH_TOKEN] The Github's oauth_token for authentication (required to list/clone private repositories)
|
46
|
+
(where OAUTH_TOKEN is from the user's Github setting)
|
47
|
+
-l, --language [LANG] Clone only project of type LANG
|
48
|
+
(where LANG is main language as shown on Github)
|
49
|
+
-a, --[no-]all-repos All repository only (optional)
|
50
|
+
(default to original/non-fork repositories only)
|
51
|
+
-c, --[no-]clone Clone the repositories to the path specified (optional)
|
52
|
+
(default to --no-clone e.g. dry-run only)
|
53
|
+
|
54
|
+
Common options:
|
55
|
+
-h, --help Show this message
|
56
|
+
```
|
57
|
+
|
58
|
+
- List repositories by user or organization id
|
59
|
+
|
60
|
+
```sh
|
61
|
+
# List all original/non-forked repositories by `awesome_user`
|
62
|
+
$github_copier --user awesome_user
|
63
|
+
|
64
|
+
## List all original/non-forked repositories of a user `awesome_user` that belongs to `AwesomeCo`
|
65
|
+
$github_copier --user awesome_user --org AwesomeCo
|
66
|
+
|
67
|
+
## List all origina/non-forked repositories by user `awesome_user` including private repository
|
68
|
+
# Note: for this to work you will need to have the proper access with the right token
|
69
|
+
$github_copier --user awesome_user --oauth-token GITHUB_TOKEN_FOR_THIS_USER
|
70
|
+
|
71
|
+
## List all repositories by user `awesome_user` include forked repositories
|
72
|
+
$github_copier --user awesome_user --oauth-token GITHUB_TOKEN_FOR_THIS_USER
|
73
|
+
```
|
74
|
+
|
75
|
+
- List and clone repositories by user or organization id using `--clone` option
|
76
|
+
|
77
|
+
```sh
|
78
|
+
## Clone all original (non-fork) public `JavaScript` repositores for user `awesome_user` to `~/Desktop/github`
|
79
|
+
# Note: --base-dir is optional, if not specified then the current directory will be used
|
80
|
+
# --language must be quoted if the value include any spaces e.g. "Emacs Lisp" for this to to work properly
|
81
|
+
$github_copier --user awesome_user \
|
82
|
+
--base-dir ~/Desktop/github \
|
83
|
+
--language "JavaScript" \
|
84
|
+
--clone
|
85
|
+
|
86
|
+
## Clone all public/private repositories for `awesome_user` which are member of `AwesomeCo` organization to `~/Desktop/github`
|
87
|
+
# Note: the option `--all` to include all forked repositories
|
88
|
+
$github_copier --user awesome_user \
|
89
|
+
--org AwesomeCo \
|
90
|
+
--all-repos \
|
91
|
+
--base-dir ~/Desktop/github \
|
92
|
+
--oauth-token GITHUB_TOKEN_FOR_AWESOME_USER \
|
93
|
+
--clone
|
94
|
+
|
95
|
+
## Clone specific type of project (e.g. `Java` in this case) public/private repositories for `awesome_user`
|
96
|
+
## which are member of `AwesomeCo` organization to `~/Desktop/github`
|
97
|
+
$github_copier --user awesome_user \
|
98
|
+
--org AwesomeCo \
|
99
|
+
--all-repos \
|
100
|
+
--language "Java" \
|
101
|
+
--base-dir ~/Desktop/github \
|
102
|
+
--oauth-token GITHUB_TOKEN_FOR_AWESOME_USER \
|
103
|
+
--clone
|
104
|
+
```
|
105
|
+
|
106
|
+
### Example Sessions
|
107
|
+
|
108
|
+
- List repositories by a given user (dry-run)
|
109
|
+
|
110
|
+
```
|
111
|
+
# Dry run option (list only)
|
112
|
+
$github_copier -b ~/Desktop/projects -u littlebee -l CoffeeScript
|
113
|
+
------------------------------------------
|
114
|
+
List of languages by littlebee
|
115
|
+
Makefile
|
116
|
+
CoffeeScript
|
117
|
+
Ruby
|
118
|
+
JavaScript
|
119
|
+
Arduino
|
120
|
+
------------------------------------------
|
121
|
+
------------------------------------------
|
122
|
+
List of all repositories by littlebee
|
123
|
+
1/15: littlebee/Makefile/arduino-mk
|
124
|
+
2/15: littlebee/CoffeeScript/bumble-build
|
125
|
+
3/15: littlebee/CoffeeScript/bumble-docs
|
126
|
+
4/15: littlebee/CoffeeScript/bumble-strings
|
127
|
+
5/15: littlebee/CoffeeScript/bumble-test
|
128
|
+
6/15: littlebee/CoffeeScript/bumble-util
|
129
|
+
7/15: littlebee/CoffeeScript/git-log-utils
|
130
|
+
8/15: littlebee/CoffeeScript/git-status-utils
|
131
|
+
9/15: littlebee/CoffeeScript/git-time-machine
|
132
|
+
10/15: littlebee/CoffeeScript/notjs
|
133
|
+
11/15: littlebee/CoffeeScript/publish
|
134
|
+
12/15: littlebee/CoffeeScript/react-focus-trap-amd
|
135
|
+
13/15: littlebee/Ruby/got
|
136
|
+
14/15: littlebee/JavaScript/selectable-collection
|
137
|
+
15/15: littlebee/Arduino/solar-sunflower
|
138
|
+
------------------------------------------
|
139
|
+
Dry-run only, no action taken!
|
140
|
+
```
|
141
|
+
|
142
|
+
- List and clone repositories for a given user (e.g. `--clone` option used)
|
143
|
+
|
144
|
+
```
|
145
|
+
$github_copier git:(master) ✗ github_copier -b ~/Desktop/projects -u littlebee -l CoffeeScript -c
|
146
|
+
------------------------------------------
|
147
|
+
List of languages by littlebee
|
148
|
+
Makefile
|
149
|
+
CoffeeScript
|
150
|
+
Ruby
|
151
|
+
JavaScript
|
152
|
+
Arduino
|
153
|
+
------------------------------------------
|
154
|
+
------------------------------------------
|
155
|
+
List of all repositories by littlebee
|
156
|
+
1/15: littlebee/Makefile/arduino-mk
|
157
|
+
2/15: littlebee/CoffeeScript/bumble-build
|
158
|
+
3/15: littlebee/CoffeeScript/bumble-docs
|
159
|
+
4/15: littlebee/CoffeeScript/bumble-strings
|
160
|
+
5/15: littlebee/CoffeeScript/bumble-test
|
161
|
+
6/15: littlebee/CoffeeScript/bumble-util
|
162
|
+
7/15: littlebee/CoffeeScript/git-log-utils
|
163
|
+
8/15: littlebee/CoffeeScript/git-status-utils
|
164
|
+
9/15: littlebee/CoffeeScript/git-time-machine
|
165
|
+
10/15: littlebee/CoffeeScript/notjs
|
166
|
+
11/15: littlebee/CoffeeScript/publish
|
167
|
+
12/15: littlebee/CoffeeScript/react-focus-trap-amd
|
168
|
+
13/15: littlebee/Ruby/got
|
169
|
+
14/15: littlebee/JavaScript/selectable-collection
|
170
|
+
15/15: littlebee/Arduino/solar-sunflower
|
171
|
+
------------------------------------------
|
172
|
+
Process 1 of 11 => git clone git@github.com:littlebee/bumble-build.git /Users/bchoomnuan/Desktop/projects/littlebee/CoffeeScript/bumble-build
|
173
|
+
Process 2 of 11 => git clone git@github.com:littlebee/bumble-docs.git /Users/bchoomnuan/Desktop/projects/littlebee/CoffeeScript/bumble-docs
|
174
|
+
Process 3 of 11 => git clone git@github.com:littlebee/bumble-strings.git /Users/bchoomnuan/Desktop/projects/littlebee/CoffeeScript/bumble-strings
|
175
|
+
Process 4 of 11 => git clone git@github.com:littlebee/bumble-test.git /Users/bchoomnuan/Desktop/projects/littlebee/CoffeeScript/bumble-test
|
176
|
+
Process 5 of 11 => git clone git@github.com:littlebee/bumble-util.git /Users/bchoomnuan/Desktop/projects/littlebee/CoffeeScript/bumble-util
|
177
|
+
Process 6 of 11 => git clone git@github.com:littlebee/git-log-utils.git /Users/bchoomnuan/Desktop/projects/littlebee/CoffeeScript/git-log-utils
|
178
|
+
Process 7 of 11 => git clone git@github.com:littlebee/git-status-utils.git /Users/bchoomnuan/Desktop/projects/littlebee/CoffeeScript/git-status-utils
|
179
|
+
Process 8 of 11 => git clone git@github.com:littlebee/git-time-machine.git /Users/bchoomnuan/Desktop/projects/littlebee/CoffeeScript/git-time-machine
|
180
|
+
Process 9 of 11 => git clone git@github.com:littlebee/notjs.git /Users/bchoomnuan/Desktop/projects/littlebee/CoffeeScript/notjs
|
181
|
+
Process 10 of 11 => git clone git@github.com:littlebee/publish.git /Users/bchoomnuan/Desktop/projects/littlebee/CoffeeScript/publish
|
182
|
+
Process 11 of 11 => git clone git@github.com:littlebee/react-focus-trap-amd.git /Users/bchoomnuan/Desktop/projects/littlebee/CoffeeScript/react-focus-trap-amd
|
183
|
+
```
|
184
|
+
|
185
|
+
### TODO
|
186
|
+
|
187
|
+
- Replace system call with the ruby library like [grit](https://github.com/mojombo/grit) or something similar
|
188
|
+
|
189
|
+
### Contributing
|
190
|
+
|
191
|
+
1. Fork it
|
192
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
193
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
194
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
195
|
+
5. Create new Pull Request
|
196
|
+
|
197
|
+
[Thor]: https://github.com/erikhuda/thor
|
198
|
+
[Minitest]: https://github.com/seattlerb/minitest
|
199
|
+
[RSpec]: https://github.com/rspec
|
200
|
+
[Guard]: https://github.com/guard/guard
|
201
|
+
[Yard]: https://github.com/lsegal/yard
|
202
|
+
[Pry]: https://github.com/pry/pry
|
203
|
+
[Rubocop]: https://github.com/bbatsov/rubocop
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
project_name = 'github_copier'
|
4
|
+
Rake::TestTask.new do |t|
|
5
|
+
t.libs << "lib/#{project_name}"
|
6
|
+
t.test_files = FileList["test/lib/#{project_name}/test_*.rb"]
|
7
|
+
t.verbose = true
|
8
|
+
end
|
9
|
+
task default: [:test, :rubocop]
|
10
|
+
task :pry do
|
11
|
+
require 'pry'
|
12
|
+
require 'awesome_print'
|
13
|
+
require_relative 'lib/github_copier'
|
14
|
+
include GithubCopier
|
15
|
+
ARGV.clear
|
16
|
+
Pry.start
|
17
|
+
end
|
18
|
+
require 'rubocop/rake_task'
|
19
|
+
desc 'Run RuboCop on the lib directory'
|
20
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
21
|
+
task.patterns = ['lib/**/*.rb']
|
22
|
+
# only show the files with failures
|
23
|
+
task.formatters = ['files']
|
24
|
+
# don't abort rake on failure
|
25
|
+
task.fail_on_error = false
|
26
|
+
end
|
data/bin/github_copier
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative '../lib/github_copier'
|
3
|
+
|
4
|
+
if ARGV.empty?
|
5
|
+
OptParser.parse(%w[--help])
|
6
|
+
end
|
7
|
+
|
8
|
+
include GithubCopier
|
9
|
+
|
10
|
+
# Now we are ready to take the order
|
11
|
+
# Show help if user forgot to type anything
|
12
|
+
options = OptParser.parse(ARGV)
|
13
|
+
|
14
|
+
# Mandatory options
|
15
|
+
raise "base_dir is required" if options.base_dir.nil?
|
16
|
+
raise "user is required" if options.user.nil?
|
17
|
+
|
18
|
+
# Make use of the user name
|
19
|
+
gh_id = options.user
|
20
|
+
|
21
|
+
# Note: set to specific language to limit the cloning
|
22
|
+
if options.language
|
23
|
+
language = options.language #'Emacs Lisp'
|
24
|
+
end
|
25
|
+
|
26
|
+
args = {
|
27
|
+
base_dir: options.base_dir, # mandatory
|
28
|
+
oauth_token: options.oauth_token, # optional
|
29
|
+
user: options.user, # optional if org is used?
|
30
|
+
org: options.org, # optional if user is used?
|
31
|
+
all_repos: options.all_repos, # optional
|
32
|
+
clone_repos: options.clone_repos # optional
|
33
|
+
}
|
34
|
+
|
35
|
+
repos = GithubCopier::GithubUtils.list_all(args)
|
36
|
+
|
37
|
+
# List of language that have been used by the given user/organization
|
38
|
+
languages = repos.map(&:language).uniq.compact
|
39
|
+
puts "------------------------------------------"
|
40
|
+
puts "List of languages by #{gh_id}"
|
41
|
+
puts languages
|
42
|
+
puts "------------------------------------------"
|
43
|
+
|
44
|
+
repos_hash = GithubCopier::GithubUtils.repos_by_language(repos, languages)
|
45
|
+
|
46
|
+
result = GithubCopier::GithubUtils.repos_as_list(repos_hash)
|
47
|
+
|
48
|
+
if result && !result.empty?
|
49
|
+
puts "------------------------------------------"
|
50
|
+
puts "List of all repositories by #{gh_id}"
|
51
|
+
result.each_with_index do |r,i|
|
52
|
+
puts "#{i+1}/#{result.size}: #{r}"
|
53
|
+
end
|
54
|
+
puts "------------------------------------------"
|
55
|
+
|
56
|
+
if args[:clone_repos]
|
57
|
+
if language
|
58
|
+
GithubCopier::GithubUtils.clone_all(result.keep_if { |i| i.split(File::SEPARATOR)[1] == language }, options.base_dir)
|
59
|
+
else
|
60
|
+
GithubCopier::GithubUtils.clone_all(result, options.base_dir)
|
61
|
+
end
|
62
|
+
else
|
63
|
+
puts "Dry-run only, no action taken!"
|
64
|
+
puts "------------------------------------------"
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'github_copier/version'
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'github_copier'
|
7
|
+
spec.version = GithubCopier::VERSION
|
8
|
+
spec.authors = ['Burin Choomnuan']
|
9
|
+
spec.email = ['agilecreativity@gmail.com']
|
10
|
+
spec.summary = %q{Clone/list Github repository for a given user/organization include private/public in one go}
|
11
|
+
spec.description = %q{Clone/list Github repository for any user/organization including private repositories}
|
12
|
+
spec.homepage = 'https://github.com/agilecreativity/github_copier'
|
13
|
+
spec.required_ruby_version = ">= 2.0.0"
|
14
|
+
spec.license = 'MIT'
|
15
|
+
spec.files = Dir.glob('{bin,lib,spec,test}/**/*') + %w(Gemfile
|
16
|
+
Rakefile
|
17
|
+
github_copier.gemspec
|
18
|
+
README.md
|
19
|
+
CHANGELOG.md
|
20
|
+
LICENSE
|
21
|
+
.rubocop.yml
|
22
|
+
.gitignore)
|
23
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
24
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
25
|
+
spec.require_paths = ['lib']
|
26
|
+
|
27
|
+
spec.add_runtime_dependency 'github_api', '~> 0.13'
|
28
|
+
spec.add_runtime_dependency 'awesome_print', '~> 1.6'
|
29
|
+
spec.add_runtime_dependency 'filename_cleaner', '~> 0.4'
|
30
|
+
|
31
|
+
spec.add_development_dependency 'bundler', '~> 1.10'
|
32
|
+
spec.add_development_dependency 'gem-ctags', '~> 1.0'
|
33
|
+
spec.add_development_dependency 'guard', '~> 2.12'
|
34
|
+
spec.add_development_dependency 'guard-minitest', '~> 2.4'
|
35
|
+
spec.add_development_dependency 'minitest', '~> 5.6'
|
36
|
+
spec.add_development_dependency 'minitest-spec-context', '~> 0.0'
|
37
|
+
spec.add_development_dependency 'pry', '~> 0.10'
|
38
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.1' if RUBY_VERSION >= '2.0.0'
|
39
|
+
spec.add_development_dependency 'rake', '~> 10.4'
|
40
|
+
spec.add_development_dependency 'rubocop', '~> 0.31'
|
41
|
+
spec.add_development_dependency 'yard', '~> 0.8'
|
42
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module GithubCopier
|
2
|
+
class GithubUtils
|
3
|
+
class << self
|
4
|
+
# List all repositories
|
5
|
+
def list_all(opts = {})
|
6
|
+
repos = []
|
7
|
+
begin
|
8
|
+
args = {
|
9
|
+
per_page: opts[:per_page] || 100,
|
10
|
+
all_repos: opts[:all_repos]
|
11
|
+
}.merge!(opts)
|
12
|
+
|
13
|
+
# If we are using :org then we must delete :user from the options
|
14
|
+
if args[:org]
|
15
|
+
args.merge!(org: opts[:org])
|
16
|
+
args.delete(:user)
|
17
|
+
else
|
18
|
+
args.merge!(user: opts[:user])
|
19
|
+
args.delete(:org)
|
20
|
+
end
|
21
|
+
|
22
|
+
# require this for only with org and with private repos
|
23
|
+
args.merge!(oauth_token: args[:oauth_token]) if args[:oauth_token]
|
24
|
+
|
25
|
+
# Only required if we use oauth_token which allow use to list private repositories
|
26
|
+
github = Github.new(args)
|
27
|
+
|
28
|
+
# List all repositories
|
29
|
+
page = 1
|
30
|
+
loop do
|
31
|
+
args.merge!(page: page)
|
32
|
+
|
33
|
+
list = github.repos.list(args)
|
34
|
+
|
35
|
+
break if list.empty?
|
36
|
+
page += 1
|
37
|
+
repos << list.select do |r|
|
38
|
+
if !args[:fork]
|
39
|
+
r if !r['fork']
|
40
|
+
else
|
41
|
+
r
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
repos.flatten!
|
46
|
+
rescue => e
|
47
|
+
puts "Error getting getting repository for user/org #{e}"
|
48
|
+
exit(1)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Clone list of repos of the following forms
|
53
|
+
#
|
54
|
+
# @params [Array<string>] projects list of project of the form '{org|user}/{language}/{repo_name}'
|
55
|
+
# [ "magnars/clojure/project1", "magnars/clojure/tools.macro", ...]
|
56
|
+
# @param [String] base_dir the base directory to save the clone result
|
57
|
+
# default to current directory
|
58
|
+
# The result will be saved to '/path/to/base_dir/{org_name}/{language}/{repo_name}'
|
59
|
+
def clone_all(projects, base_dir = ".")
|
60
|
+
base_path = File.expand_path(base_dir)
|
61
|
+
|
62
|
+
FileUtils.mkdir_p(base_path)
|
63
|
+
|
64
|
+
projects.each_with_index do |project, i|
|
65
|
+
org_name, language, repo_name = project.split(File::SEPARATOR)
|
66
|
+
|
67
|
+
# Note: need to cleanup the language like 'Emacs Lisp' to 'Emacs_Lisp' or 'emacs_lisp'
|
68
|
+
language = FilenameCleaner.sanitize(language, '_', false)
|
69
|
+
|
70
|
+
output_path = [base_path, org_name, language, repo_name].join(File::SEPARATOR)
|
71
|
+
puts "Process #{i+1} of #{projects.size} => git clone git@github.com:#{[org_name, repo_name].join(File::SEPARATOR)}.git #{output_path}"
|
72
|
+
# TODO: may be allow `https` as well as `git`?
|
73
|
+
output = system("git clone git@github.com:#{[org_name, repo_name].join(File::SEPARATOR)}.git #{output_path} 2> /dev/null")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def repos_as_list(repos)
|
78
|
+
# Store the result in this list
|
79
|
+
list = []
|
80
|
+
repos.each do |k,v|
|
81
|
+
v.each do |i|
|
82
|
+
user_name, repo_name = i.split(File::SEPARATOR)
|
83
|
+
list << [user_name, k, repo_name].join(File::SEPARATOR)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
list
|
87
|
+
end
|
88
|
+
|
89
|
+
# Map of repository by language
|
90
|
+
#
|
91
|
+
# Map language to list of repository
|
92
|
+
# @return [Hash<String, Array<String>>] map of language to repos
|
93
|
+
def repos_by_language(repos, languages)
|
94
|
+
hash = {}
|
95
|
+
languages.each do |l|
|
96
|
+
hash[l] = repos.collect { |r| r['full_name'] if r['language'] == l }.compact
|
97
|
+
end
|
98
|
+
hash
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
module GithubCopier
|
4
|
+
class OptParser
|
5
|
+
# Return a structure describing the options.
|
6
|
+
def self.parse(args)
|
7
|
+
# The options specified on the command line will be collected in *options*.
|
8
|
+
# We set default values here.
|
9
|
+
options = OpenStruct.new
|
10
|
+
|
11
|
+
# The mandatory arguments
|
12
|
+
options.base_dir = "."
|
13
|
+
|
14
|
+
# The option arguments
|
15
|
+
options.verbose = false
|
16
|
+
|
17
|
+
# The parser
|
18
|
+
opt_parser = OptionParser.new do |opts|
|
19
|
+
opts.banner = "Usage: github_copier [options]"
|
20
|
+
|
21
|
+
opts.separator ""
|
22
|
+
opts.separator "Specific options:"
|
23
|
+
|
24
|
+
# Mandatory argument
|
25
|
+
opts.on("-b", "--base-dir BASE_DIR",
|
26
|
+
"Output directory where the repository will be cloned to") do |dir|
|
27
|
+
options.base_dir = dir
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on("-u", "--user USER",
|
31
|
+
"The github USER that will be cloned from") do |user|
|
32
|
+
# By default the id is assumed to be of a normal user not as organization
|
33
|
+
options.user = user
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("-o", "--org [ORG]",
|
37
|
+
"The Github's organization name to be used if specified",
|
38
|
+
"(where ORG is the organization that the user belongs to)") do |org|
|
39
|
+
options.org = org
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on("-t", "--oauth-token [OAUTH_TOKEN]",
|
43
|
+
"The Github's oauth_token for authentication (required to list/clone private repositories)",
|
44
|
+
"(where OAUTH_TOKEN is from the user's Github setting)") do |token|
|
45
|
+
options.oauth_token = token
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on("-l", "--language [LANG]",
|
49
|
+
"Clone only project of type LANG",
|
50
|
+
"(where LANG is main language as shown on Github)") do |lang|
|
51
|
+
options.language = lang
|
52
|
+
end
|
53
|
+
|
54
|
+
# Boolean switch.
|
55
|
+
opts.on("-a", "--[no-]all-repos",
|
56
|
+
"All repository only (optional)",
|
57
|
+
"(default to original/non-fork repositories only)") do |a|
|
58
|
+
options.all_repos = a
|
59
|
+
end
|
60
|
+
|
61
|
+
opts.on( "-c", "--[no-]clone",
|
62
|
+
"Clone the repositories to the path specified (optional)",
|
63
|
+
"(default to --no-clone e.g. dry-run only)") do |c|
|
64
|
+
options.clone_repos = c
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.separator ""
|
68
|
+
opts.separator "Common options:"
|
69
|
+
|
70
|
+
# No argument, shows at tail. This will print an options summary.
|
71
|
+
# Try it and see!
|
72
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
73
|
+
puts opts
|
74
|
+
exit
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
opt_parser.parse!(args)
|
79
|
+
options
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,261 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: github_copier
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Burin Choomnuan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: github_api
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.13'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.13'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: awesome_print
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: filename_cleaner
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.4'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.10'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.10'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: gem-ctags
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.12'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.12'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: guard-minitest
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '2.4'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '2.4'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: minitest
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '5.6'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '5.6'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: minitest-spec-context
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: pry
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.10'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.10'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: pry-byebug
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '3.1'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '3.1'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: rake
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '10.4'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '10.4'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: rubocop
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0.31'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0.31'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: yard
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - "~>"
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0.8'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - "~>"
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0.8'
|
209
|
+
description: Clone/list Github repository for any user/organization including private
|
210
|
+
repositories
|
211
|
+
email:
|
212
|
+
- agilecreativity@gmail.com
|
213
|
+
executables:
|
214
|
+
- github_copier
|
215
|
+
extensions: []
|
216
|
+
extra_rdoc_files: []
|
217
|
+
files:
|
218
|
+
- ".gitignore"
|
219
|
+
- ".rubocop.yml"
|
220
|
+
- CHANGELOG.md
|
221
|
+
- Gemfile
|
222
|
+
- LICENSE
|
223
|
+
- README.md
|
224
|
+
- Rakefile
|
225
|
+
- bin/github_copier
|
226
|
+
- github_copier.gemspec
|
227
|
+
- lib/github_copier.rb
|
228
|
+
- lib/github_copier/github_copier.rb
|
229
|
+
- lib/github_copier/opt_parser.rb
|
230
|
+
- lib/github_copier/version.rb
|
231
|
+
- test/lib/github_copier/test_github_copier.rb
|
232
|
+
- test/test_helper.rb
|
233
|
+
homepage: https://github.com/agilecreativity/github_copier
|
234
|
+
licenses:
|
235
|
+
- MIT
|
236
|
+
metadata: {}
|
237
|
+
post_install_message:
|
238
|
+
rdoc_options: []
|
239
|
+
require_paths:
|
240
|
+
- lib
|
241
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
242
|
+
requirements:
|
243
|
+
- - ">="
|
244
|
+
- !ruby/object:Gem::Version
|
245
|
+
version: 2.0.0
|
246
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
251
|
+
requirements: []
|
252
|
+
rubyforge_project:
|
253
|
+
rubygems_version: 2.4.5.1
|
254
|
+
signing_key:
|
255
|
+
specification_version: 4
|
256
|
+
summary: Clone/list Github repository for a given user/organization include private/public
|
257
|
+
in one go
|
258
|
+
test_files:
|
259
|
+
- test/lib/github_copier/test_github_copier.rb
|
260
|
+
- test/test_helper.rb
|
261
|
+
has_rdoc:
|