gitload 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eae65fffc20fb78620aab8974a15a20daacee260
4
- data.tar.gz: 022a121055c47e217b1fd85f5dd6c445db098843
3
+ metadata.gz: 42e39c1c4506254e1123f86afed50db8703bdd9e
4
+ data.tar.gz: fd301486eae7240f101a18346c3a340d259ce66f
5
5
  SHA512:
6
- metadata.gz: 3f50d5f9f939f0946df260b6611a4a3f7f884fda61ecdddd0b336d393797a9eb57d9de1d53acfed46f11fd4b8a3afde3595ae2338a7beb0282b4a66d71cc1817
7
- data.tar.gz: 312316480862831c155929f3272899e250818986fe2f0896eba4fa1d653123185dc56cd3d2e6e20ddc4ca7500bca01c754a73bb0fb1722870b8913f9d5bda048
6
+ metadata.gz: 4ebf0e8443d745ad42ead6a87aeb24cdce2a1f32e3d7830931bb68c9ceec1a5cf1adccd45e6c9ed5b60e6d8923dac42d7224a6cd9c4235833016fc66868ec1a0
7
+ data.tar.gz: 593ec1df8d4d5d2fbf68f713b4e514cb6e6625dab903a80b942d90b2361c8c286ba8e4bec9960cb34c83b1b6ad5a5422047071e86bf1bdc2316768dd4d8eca19
data/Gemfile CHANGED
@@ -5,7 +5,10 @@ source "http://rubygems.org"
5
5
 
6
6
  gem 'paint', '~> 1.0'
7
7
  gem 'commander', '~> 4.2'
8
+
8
9
  gem 'octokit', '~> 4.6'
10
+ gem 'bitbucket_rest_api', '~> 0.1.7'
11
+ gem 'gitlab', '~> 3.7'
9
12
 
10
13
  # Add dependencies to develop your gem here.
11
14
  # Include everything needed to run rake, tests, features, etc.
@@ -14,6 +17,7 @@ group :development do
14
17
  gem 'rake', '~> 11.0'
15
18
  gem 'rspec', '~> 3.1'
16
19
  gem 'rspec-its', '~> 1.1'
20
+ gem 'rspec-collection_matchers', '~> 1.1'
17
21
  gem 'fakefs', '~> 0.9.0', :require => 'fakefs/safe'
18
22
  gem 'jeweler', '~> 2.0'
19
23
  gem 'rake-version', '~> 1.0'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -0,0 +1,29 @@
1
+ require 'shellwords'
2
+
3
+ module Gitload
4
+ module CommandLine
5
+ class << self
6
+ def execute *args
7
+ system escape_args(args.flatten)
8
+ end
9
+
10
+ def escape args
11
+ args.collect{ |arg| Shellwords.shellescape arg.to_s }.join(' ')
12
+ end
13
+
14
+ def print message, options = {}
15
+ if options[:color]
16
+ paint_args = options[:color].kind_of?(Array) ? options[:color] : [ options[:color] ]
17
+ paint_args.unshift message
18
+ message = Paint[*paint_args]
19
+ end
20
+
21
+ if options.fetch :new_line, true
22
+ puts message
23
+ else
24
+ print message
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,21 +1,14 @@
1
- require 'octokit'
1
+ require 'forwardable'
2
2
 
3
3
  module Gitload
4
4
  module Commands
5
5
  class Load
6
6
  def initialize options = {}
7
+ @config = Config.new options
7
8
  end
8
9
 
9
10
  def run
10
-
11
- Octokit.configure do |c|
12
- c.access_token = ENV['GITLOAD_TOKEN']
13
- c.auto_paginate = true
14
- end
15
-
16
- repos = Octokit.repositories ENV['GITLOAD_GITHUB_USER']
17
-
18
- puts repos.collect{ |r| r.to_attrs[:name] }
11
+ @config.apply
19
12
  end
20
13
  end
21
14
  end
@@ -0,0 +1,127 @@
1
+ require 'fileutils'
2
+
3
+ module Gitload
4
+ class Config
5
+ attr_accessor :root
6
+ attr_accessor :cache
7
+ attr_accessor :clear_cache
8
+ attr_accessor :dry_run
9
+ attr_accessor :clone_url_type
10
+
11
+ def initialize options = {}
12
+ @root = options[:root]
13
+ @cache = options.cache
14
+ @clear_cache = options.clear_cache
15
+ @dry_run = options.dry_run
16
+ @clone_url_type = options[:clone_url_type]
17
+ end
18
+
19
+ def apply
20
+ filename = File.expand_path '~/.gitload.rb'
21
+ DSL.new(self).instance_eval File.read(filename), filename
22
+ end
23
+
24
+ def clone_options
25
+ {
26
+ dry_run: @dry_run,
27
+ clone_url_type: @clone_url_type
28
+ }
29
+ end
30
+
31
+ def load_or_cache_data relative_path
32
+ delete relative_path if @clear_cache
33
+
34
+ if @cache
35
+ data = self.load relative_path
36
+ end
37
+
38
+ unless data
39
+ data = yield
40
+ end
41
+
42
+ if @cache
43
+ save relative_path, data
44
+ end
45
+
46
+ data
47
+ end
48
+
49
+ def load relative_path
50
+ file = data_file relative_path
51
+ File.exist?(file) ? JSON.parse(File.read(file)) : nil
52
+ end
53
+
54
+ def save relative_path, contents
55
+ file = data_file relative_path
56
+ FileUtils.mkdir_p File.dirname(file)
57
+ File.open(file, 'w'){ |f| f.write JSON.dump(contents) }
58
+ end
59
+
60
+ def delete relative_path
61
+ FileUtils.rm_f data_file(relative_path)
62
+ end
63
+
64
+ class DSL
65
+ extend Forwardable
66
+
67
+ attr_reader :repos
68
+
69
+ def initialize config
70
+ @config = config
71
+ @repos = RepoChain.new @config
72
+ end
73
+
74
+ def chain repos = [], options = {}
75
+ RepoChain.new @config, repos, options
76
+ end
77
+
78
+ def cache
79
+ @config.cache = true
80
+ end
81
+
82
+ def root dest, &block
83
+
84
+ previous_root = @config.root
85
+ @config.root = dest
86
+
87
+ if block
88
+ instance_eval &block
89
+ @config.root = previous_root
90
+ end
91
+ end
92
+
93
+ def clone_url_type type, &block
94
+
95
+ previous_type = @config.clone_url_type
96
+ @config.clone_url_type = type
97
+
98
+ if block
99
+ instance_eval &block
100
+ @config.clone_url_type = previous_type
101
+ end
102
+ end
103
+
104
+ alias_method :into, :root
105
+
106
+ def_delegator :@repos, :add
107
+
108
+ def method_missing symbol, *args, &block
109
+ if Sources.sources.key? symbol
110
+ Sources.sources[symbol].source *args.unshift(@config), &block
111
+ else
112
+ super symbol, *args, &block
113
+ end
114
+ end
115
+ end
116
+
117
+ private
118
+
119
+ def data_file relative_path
120
+ File.join data_dir, "#{relative_path}.json"
121
+ end
122
+
123
+ def data_dir
124
+ File.join File.expand_path('~'), '.gitload'
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,46 @@
1
+ require 'shellwords'
2
+
3
+ module Gitload
4
+ class Repo
5
+ attr_reader :clone_urls
6
+ attr_accessor :source, :api_data, :name, :fork, :owner, :owner_type, :cloned
7
+
8
+ def initialize source, api_data
9
+ @source = source
10
+ @api_data = api_data
11
+ @cloned = false
12
+ @clone_urls = {}
13
+ end
14
+
15
+ def cloned?
16
+ !!@cloned
17
+ end
18
+
19
+ def fork?
20
+ !!@fork
21
+ end
22
+
23
+ def clone_url type = nil
24
+ @clone_urls[type || :http]
25
+ end
26
+
27
+ def clone_to dest, options = {}
28
+ if @cloned && !options[:force]
29
+ return
30
+ elsif File.exists? dest
31
+ CommandLine.print "#{dest} already exists", color: :green
32
+ return
33
+ end
34
+
35
+ command = [ :git, :clone, clone_url(options[:clone_url_type]), dest ]
36
+
37
+ if options[:dry_run]
38
+ CommandLine.print CommandLine.escape(command), color: :yellow
39
+ else
40
+ CommandLine.execute command
41
+ end
42
+
43
+ @cloned = true
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,121 @@
1
+ module Gitload
2
+ class RepoChain
3
+ extend Forwardable
4
+
5
+ attr_reader :config
6
+ attr_reader :repos
7
+
8
+ def initialize config, repos = [], options = {}
9
+ @config = config
10
+ @repos = repos
11
+ @rename = options[:rename]
12
+ end
13
+
14
+ def << repo
15
+ @repos << repo
16
+ self
17
+ end
18
+
19
+ def add repos
20
+ # TODO: remove
21
+ repos = repos.repos while repos.respond_to? :repos
22
+ @repos += repos
23
+ self
24
+ end
25
+
26
+ def by *owners
27
+ normalized_owners = owners.collect{ |owner| owner.to_s.downcase }
28
+ select{ |repo| normalized_owners.include? repo.owner.to_s.downcase }
29
+ end
30
+
31
+ def from *sources
32
+ select{ |repo| sources.include? repo.source }
33
+ end
34
+
35
+ def named *criteria
36
+ compiled_criteria = criteria.collect do |criterion|
37
+ if criterion.kind_of? Regexp
38
+ Proc.new{ |repo| repo.name.match criterion }
39
+ else
40
+ Proc.new{ |repo| repo.name.downcase == criterion.to_s.downcase }
41
+ end
42
+ end
43
+
44
+ select do |repo|
45
+ compiled_criteria.any? do |criterion|
46
+ criterion.call repo
47
+ end
48
+ end
49
+ end
50
+
51
+ def forks
52
+ select &:fork?
53
+ end
54
+
55
+ def select &block
56
+ dup @repos.select(&block)
57
+ end
58
+
59
+ def reject &block
60
+ dup @repos.reject(&block)
61
+ end
62
+
63
+ def rename pattern = nil, replacement = nil, &block
64
+ @rename_block = block || Proc.new{ |name| name.sub pattern, replacement }
65
+ self
66
+ end
67
+
68
+ def prefix prefix
69
+ @prefix = prefix
70
+ self
71
+ end
72
+
73
+ def clone
74
+ clone_into
75
+ end
76
+
77
+ def clone_to dest = nil
78
+ clone_repos :to, dest
79
+ end
80
+
81
+ def clone_into dest = nil
82
+ clone_repos :into, dest
83
+ end
84
+
85
+ def_delegator :@config, :root
86
+
87
+ private
88
+
89
+ def dup repos = nil
90
+ RepoChain.new @config, repos || @repos, rename: @rename
91
+ end
92
+
93
+ def clone_repos method, dest
94
+ dest = if !dest
95
+ File.expand_path(root.to_s)
96
+ elsif root
97
+ File.expand_path(dest.to_s, File.expand_path(root.to_s))
98
+ else
99
+ File.expand_path(dest.to_s)
100
+ end
101
+
102
+ puts dest
103
+ dir = File.dirname dest
104
+ #FileUtils.mkdir_p unless File.exists? dir
105
+
106
+ @repos.each do |repo|
107
+
108
+ repo_dest = if method == :into
109
+ name = repo.name
110
+ name = name.index(@prefix) == 0 ? name : "#{@prefix}#{name}" if @prefix
111
+ name = @rename_block.call name if @rename_block
112
+ File.join dest, name
113
+ else
114
+ dest
115
+ end
116
+
117
+ repo.clone_to repo_dest, @config.clone_options
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,44 @@
1
+ require 'bitbucket_rest_api'
2
+ require 'json'
3
+
4
+ module Gitload
5
+ module Sources
6
+ class Bitbucket
7
+ include Source
8
+
9
+ def initialize config, options = {}
10
+
11
+ @config = config
12
+
13
+ user = options.fetch :user, ENV['GITLOAD_BITBUCKET_USER']
14
+ password = options.fetch :password, ENV['GITLOAD_BITBUCKET_TOKEN']
15
+ @bitbucket_api = ::BitBucket.new basic_auth: "#{user}:#{password}"
16
+ end
17
+
18
+ def repos
19
+
20
+ data = @config.load_or_cache_data 'bitbucket' do
21
+ Utils.stringify_keys(@bitbucket_api.repos.list)
22
+ end
23
+
24
+ data = data.select{ |repo| repo['scm'] == 'git' }
25
+
26
+ data.collect{ |d| Repo.new d }
27
+ end
28
+
29
+ class Repo < Gitload::Repo
30
+ def initialize api_data
31
+ super :bitbucket, api_data
32
+
33
+ @name = api_data['slug']
34
+ @owner = api_data['owner']
35
+
36
+ @fork = api_data['is_fork']
37
+
38
+ @clone_urls[:ssh] = "git@bitbucket.org:#{@owner}/#{@name}.git"
39
+ @clone_urls[:http] = "https://AlphaHydrae@bitbucket.org/#{@owner}/#{@name}.git"
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ require 'json'
2
+ require 'octokit'
3
+
4
+ module Gitload
5
+ module Sources
6
+ class GitHub
7
+ include Source
8
+
9
+ def initialize config, options = {}
10
+ @config = config
11
+
12
+ ::Octokit.configure do |c|
13
+ c.auto_paginate = true
14
+ c.access_token = options.fetch :access_token, ENV['GITLOAD_GITHUB_TOKEN']
15
+ end
16
+ end
17
+
18
+ def repos
19
+
20
+ data = @config.load_or_cache_data 'github' do
21
+ Utils.stringify_keys ::Octokit.repositories.collect(&:to_attrs)
22
+ end
23
+
24
+ data.collect{ |d| Repo.new d }
25
+ end
26
+
27
+ class Repo < Gitload::Repo
28
+ def initialize api_data
29
+ super :github, api_data
30
+
31
+ @name = api_data['name']
32
+ @owner = api_data['owner']['login']
33
+ @owner_type = api_data['owner']['type']
34
+
35
+ @fork = api_data['fork']
36
+
37
+ @clone_urls[:git] = api_data['git_url']
38
+ @clone_urls[:ssh] = api_data['ssh_url']
39
+ @clone_urls[:http] = api_data['clone_url']
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,40 @@
1
+ require 'gitlab'
2
+ require 'json'
3
+
4
+ module Gitload
5
+ module Sources
6
+ class GitLab
7
+ include Source
8
+
9
+ def initialize config, options = {}
10
+ @config = config
11
+
12
+ ::Gitlab.configure do |c|
13
+ c.endpoint = 'https://gitlab.com/api/v3'
14
+ c.private_token = options.fetch :private_token, ENV['GITLOAD_GITLAB_TOKEN']
15
+ end
16
+ end
17
+
18
+ def repos
19
+
20
+ data = @config.load_or_cache_data 'gitlab' do
21
+ Utils.stringify_keys(::Gitlab.projects.auto_paginate.collect(&:to_h))
22
+ end
23
+
24
+ data.collect{ |d| Repo.new d }
25
+ end
26
+
27
+ class Repo < Gitload::Repo
28
+ def initialize api_data
29
+ super :gitlab, api_data
30
+
31
+ @name = api_data['path']
32
+ @owner = api_data['namespace']['path']
33
+
34
+ @clone_urls[:ssh] = api_data['ssh_url_to_repo']
35
+ @clone_urls[:http] = api_data['http_url_to_repo']
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,28 @@
1
+ module Gitload
2
+ module Sources
3
+ def self.sources
4
+ @sources ||= {}
5
+ end
6
+
7
+ module Source
8
+ def self.included base
9
+ base.extend ClassMethods
10
+ end
11
+
12
+ module ClassMethods
13
+ def source options = {}
14
+ new options
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ Dir[File.join File.dirname(__FILE__), File.basename(__FILE__, '.*'), '*.rb'].each{ |lib| require lib }
22
+
23
+ module Gitload::Sources
24
+ constants.collect{ |c| const_get(c) }.select{ |c| Class === c && c.respond_to?(:source) }.each do |factory|
25
+ factory_name = factory.respond_to?(:source_name) ? factory.source_name : factory.name.to_s.downcase.sub(/.*::/, '').to_sym
26
+ sources[factory_name] = factory
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ module Gitload
2
+ module Utils
3
+ def self.stringify_keys object
4
+ if object.kind_of? Hash
5
+ object.inject({}) do |memo,(key,value)|
6
+ memo[key.to_s] = stringify_keys value
7
+ memo
8
+ end
9
+ elsif object.kind_of? Array
10
+ object.collect do |value|
11
+ stringify_keys value
12
+ end
13
+ else
14
+ object
15
+ end
16
+ end
17
+ end
18
+ end
data/lib/gitload.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  require 'paint'
3
3
 
4
4
  module Gitload
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
6
6
  end
7
7
 
8
8
  Dir[File.join File.dirname(__FILE__), File.basename(__FILE__, '.*'), '*.rb'].each{ |lib| require lib }
data/lib/program.rb CHANGED
@@ -9,7 +9,10 @@ global_option '-c', '--config PATH', 'Use a custom configuration file (defaults
9
9
 
10
10
  command :load do |c|
11
11
  c.syntax = 'gitload load'
12
- c.description = 'Downloads all configured repositories (default action)'
12
+ c.description = 'Clones all configured repositories (default action)'
13
+ c.option '--cache', 'Cache the downloaded repository data'
14
+ c.option '--clear-cache', 'Clears the latest cache data'
15
+ c.option '--dry-run', 'Show all repositories that will be cloned but without cloning them'
13
16
  c.action do |args,options|
14
17
  Gitload::Commands::Load.new(options).run
15
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitload
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Oulevay (Alpha Hydrae)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-28 00:00:00.000000000 Z
11
+ date: 2017-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: paint
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '4.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bitbucket_rest_api
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.7
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.1.7
69
+ - !ruby/object:Gem::Dependency
70
+ name: gitlab
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.7'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.7'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: rake
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +122,20 @@ dependencies:
94
122
  - - "~>"
95
123
  - !ruby/object:Gem::Version
96
124
  version: '1.1'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec-collection_matchers
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.1'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1.1'
97
139
  - !ruby/object:Gem::Dependency
98
140
  name: fakefs
99
141
  requirement: !ruby/object:Gem::Requirement
@@ -166,8 +208,17 @@ files:
166
208
  - VERSION
167
209
  - bin/gitload
168
210
  - lib/gitload.rb
211
+ - lib/gitload/command_line.rb
169
212
  - lib/gitload/commands.rb
170
213
  - lib/gitload/commands/load.rb
214
+ - lib/gitload/config.rb
215
+ - lib/gitload/repo.rb
216
+ - lib/gitload/repo_chain.rb
217
+ - lib/gitload/sources.rb
218
+ - lib/gitload/sources/bitbucket.rb
219
+ - lib/gitload/sources/github.rb
220
+ - lib/gitload/sources/gitlab.rb
221
+ - lib/gitload/utils.rb
171
222
  - lib/program.rb
172
223
  homepage: https://github.com/AlphaHydrae/gitload
173
224
  licenses: