git_multicast 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +11 -0
  3. data/Gemfile.lock +17 -1
  4. data/README.md +3 -3
  5. data/git_multicast.gemspec +29 -18
  6. data/lib/git_multicast/.rubocop.yml +11 -0
  7. data/lib/git_multicast/adapters/bitbucket.rb +35 -0
  8. data/lib/git_multicast/adapters/github.rb +17 -0
  9. data/lib/git_multicast/adapters.rb +5 -0
  10. data/lib/git_multicast/cli.rb +9 -2
  11. data/lib/git_multicast/cloner.rb +3 -3
  12. data/lib/git_multicast/output_formatter.rb +12 -10
  13. data/lib/git_multicast/repository_fetcher/bitbucket.rb +34 -0
  14. data/lib/git_multicast/repository_fetcher/github.rb +25 -0
  15. data/lib/git_multicast/repository_fetcher.rb +33 -14
  16. data/lib/git_multicast/version.rb +1 -1
  17. data/lib/git_multicast.rb +1 -3
  18. data/spec/fixtures/vcr_cassettes/bitbucket_all_user_repos.yml +170 -0
  19. data/spec/fixtures/vcr_cassettes/bitbucket_repo.yml +79 -0
  20. data/spec/fixtures/vcr_cassettes/github_all_user_repos.yml +107 -0
  21. data/spec/fixtures/vcr_cassettes/github_repo.yml +77 -0
  22. data/spec/fixtures/vcr_cassettes/github_repo_parent.yml +79 -0
  23. data/spec/fixtures/vcr_cassettes/repos_from_all_services.yml +274 -0
  24. data/spec/git_multicast/adapters/bitbucket_spec.rb +25 -0
  25. data/spec/git_multicast/puller_spec.rb +4 -0
  26. data/spec/git_multicast/repository_fetcher/bitbucket_spec.rb +80 -0
  27. data/spec/git_multicast/repository_fetcher/github_spec.rb +81 -0
  28. data/spec/git_multicast/repository_fetcher_spec.rb +101 -18
  29. data/spec/spec_helper.rb +5 -3
  30. metadata +76 -9
  31. data/lib/git_multicast/bitbucket_adapter.rb +0 -33
  32. data/lib/git_multicast/bitbucket_fetcher.rb +0 -36
  33. data/lib/git_multicast/github_fetcher.rb +0 -31
  34. data/spec/git_multicast/bitbucket_adapter_spec.rb +0 -25
  35. data/spec/git_multicast/bitbucket_fetcher_spec.rb +0 -97
  36. data/spec/git_multicast/github_fetcher_spec.rb +0 -74
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5eca79b00b499527dc9359976cad0a78a1afbbf9
4
- data.tar.gz: a1acf00d101c7da203d4eabf3698efdec8388e7e
3
+ metadata.gz: 5a9ce770391d551120cec8646c9960fc45aa7471
4
+ data.tar.gz: ed4ac6bd223ad655bd0d83ed0ce3bd6576329354
5
5
  SHA512:
6
- metadata.gz: 6831a8e7da65b6fd156ccb81266296ae5c3f3b7a452e0e3a5388ceca4bd8c443dd0598ab4aeabc82a49a8a3dcac3324e5fe9646cfd07d97cedfdde6a46bfe073
7
- data.tar.gz: 88140e231eb521a6d9fac0450cf015f0a7d91d9c1e799037e4b196228be0b5faf2d73f363d59f781f595f7c44aee7aa5a1ab643700964c6164393cd5109b9d5f
6
+ metadata.gz: 56165a2911f3039b28111770c85bcc90445f622bc2ec1d24eb6fbb69b4f92f6dd4b6cf93865c94ef9bfab2c62d86755b7e7c991a3048d45831d53149ba1cb642
7
+ data.tar.gz: fe5b862932a72ef2a505187d44f9ed51480abb60e55d4f7ee48765652983cd4471c4d2033562c1582c8d55bf68a742bb1761986d8e4cca9d7d9356027b4eedca
data/.rubocop.yml ADDED
@@ -0,0 +1,11 @@
1
+ Documentation:
2
+ Enabled: false
3
+
4
+ AllCops:
5
+ # Include gemspec and Rakefile
6
+ Include:
7
+ - '**/*.gemspec'
8
+ - '**/Rakefile'
9
+
10
+ Style/Encoding:
11
+ Enabled: false
data/Gemfile.lock CHANGED
@@ -1,20 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- git_multicast (0.0.4.pre)
4
+ git_multicast (0.0.6.pre)
5
5
  recursive-open-struct (~> 0.5.0)
6
6
  thor (~> 0.19)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
+ addressable (2.3.6)
11
12
  coderay (1.1.0)
13
+ crack (0.4.2)
14
+ safe_yaml (~> 1.0.0)
12
15
  diff-lcs (1.2.5)
13
16
  method_source (0.8.2)
14
17
  pry (0.10.1)
15
18
  coderay (~> 1.1.0)
16
19
  method_source (~> 0.8.1)
17
20
  slop (~> 3.4)
21
+ pry-doc (0.6.0)
22
+ pry (~> 0.9)
23
+ yard (~> 0.8)
18
24
  rake (10.3.2)
19
25
  recursive-open-struct (0.5.0)
20
26
  rspec (3.0.0)
@@ -29,8 +35,14 @@ GEM
29
35
  rspec-mocks (3.0.4)
30
36
  rspec-support (~> 3.0.0)
31
37
  rspec-support (3.0.4)
38
+ safe_yaml (1.0.3)
32
39
  slop (3.6.0)
33
40
  thor (0.19.1)
41
+ vcr (2.9.3)
42
+ webmock (1.18.0)
43
+ addressable (>= 2.3.6)
44
+ crack (>= 0.3.2)
45
+ yard (0.8.7.4)
34
46
 
35
47
  PLATFORMS
36
48
  ruby
@@ -38,6 +50,10 @@ PLATFORMS
38
50
  DEPENDENCIES
39
51
  bundler (~> 1.7)
40
52
  git_multicast!
53
+ method_source
41
54
  pry
55
+ pry-doc
42
56
  rake (~> 10.0)
43
57
  rspec (~> 3.0)
58
+ vcr
59
+ webmock
data/README.md CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  Have you ever need to clone a whole bunch of repositories? Have you forgot to pull remote changes?
4
4
 
5
- ### GitMassDo to the rescue!
5
+ ### git_multicast to the rescue!
6
6
 
7
- `git_mass_do` is a ruby gem that provides a simple `cli` for issuing commands to
7
+ `git_multicast` is a ruby gem that provides a simple `cli` for issuing commands to
8
8
  multiple git repositories, much like a multicast sends data to multiple
9
9
  recipients.
10
10
 
11
- `git_mass_do` executes actions in parallel, so cloning 30 repositories will take
11
+ `git_multicast` executes actions in parallel, so cloning 30 repositories will take
12
12
  just as long as cloning the biggest one, and nothing more.
13
13
 
14
14
  Actions currently supported:
@@ -1,23 +1,34 @@
1
- Gem::Specification.new do |s|
2
- s.name = 'git_multicast'
3
- s.version = '0.0.5'
4
- s.required_ruby_version = '~>2.0'
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
3
 
6
- s.summary = 'Execute mass actions on git repositories concurrently'
7
- s.authors = ['Renan Ranelli']
8
- s.email = ['renanranelli@gmail.com']
9
- s.homepage = 'http://github.com/rranelli/git_multicast'
10
- s.license = 'MIT'
4
+ require 'git_multicast/version'
11
5
 
12
- s.files = `git ls-files -z`.split("\x0")
13
- s.executables = s.files.grep(/^bin\//) { |f| File.basename(f) }
14
- s.require_paths = ['lib']
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'git_multicast'
8
+ spec.version = GitMulticast::VERSION
9
+ spec.required_ruby_version = '~>2.0'
15
10
 
16
- s.add_dependency 'recursive-open-struct', '~> 0.5.0'
17
- s.add_dependency 'thor', '~> 0.19'
11
+ spec.summary = 'Execute mass actions on git repositories concurrently'
12
+ spec.authors = ['Renan Ranelli']
13
+ spec.email = ['renanranelli@gmail.com']
14
+ spec.homepage = 'http://github.com/rranelli/git_multicast'
15
+ spec.license = 'DWTF'
18
16
 
19
- s.add_development_dependency 'bundler', '~> 1.7'
20
- s.add_development_dependency 'rspec', '~> 3.0'
21
- s.add_development_dependency 'rake', '~> 10.0'
22
- s.add_development_dependency 'pry'
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'recursive-open-struct', '~> 0.5.0'
22
+ spec.add_dependency 'thor', '~> 0.19'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.7'
25
+ spec.add_development_dependency 'rspec', '~> 3.0'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'vcr'
28
+ spec.add_development_dependency 'webmock'
29
+
30
+ # these gems are required by emacs' robe-package
31
+ spec.add_development_dependency 'pry'
32
+ spec.add_development_dependency 'pry-doc'
33
+ spec.add_development_dependency 'method_source'
23
34
  end
@@ -0,0 +1,11 @@
1
+ Documentation:
2
+ Enabled: false
3
+
4
+ AllCops:
5
+ # Include gemspec and Rakefile
6
+ Include:
7
+ - '**/*.gemspec'
8
+ - '**/Rakefile'
9
+
10
+ Style/Encoding:
11
+ Enabled: false
@@ -0,0 +1,35 @@
1
+ module GitMulticast
2
+ module Adapters
3
+ class Bitbucket
4
+ def initialize(repo)
5
+ @repo = repo
6
+ end
7
+
8
+ def adapt
9
+ make_struct(repo_hash)
10
+ end
11
+
12
+ protected
13
+
14
+ attr_reader :repo
15
+
16
+ def repo_hash
17
+ @repo_hash ||= make_repo_hash
18
+ end
19
+
20
+ def make_repo_hash
21
+ {
22
+ fork: !repo.parent.nil?,
23
+ ssh_url: repo.links._clone.last.href,
24
+ url: repo.links.self.href,
25
+ parent: nil,
26
+ name: repo.name
27
+ }
28
+ end
29
+
30
+ def make_struct(hash)
31
+ RecursiveOpenStruct.new(hash, recurse_over_arrays: true)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ module GitMulticast
2
+ module Adapters
3
+ class Github
4
+ def initialize(repo)
5
+ @repo = repo
6
+ end
7
+
8
+ def adapt
9
+ repo
10
+ end
11
+
12
+ protected
13
+
14
+ attr_reader :repo
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ require_relative 'adapters/bitbucket'
2
+ require_relative 'adapters/github'
3
+
4
+ module Adapters
5
+ end
@@ -4,14 +4,21 @@ require_relative '../git_multicast'
4
4
 
5
5
  module GitMulticast
6
6
  class Cli < Thor
7
- desc 'git_multicast pull', 'Git pulls all repositories contained in current directory.'
7
+ desc 'git_multicast pull', 'Git pulls all repositories contained in\
8
+ current directory.'
8
9
  def pull
9
10
  Puller.new(Dir.pwd).pull
10
11
  end
11
12
 
12
- desc 'git_multicast clone :username', 'Git pulls all repositories contained in current directory.'
13
+ desc 'git_multicast clone :username', 'Git pulls all repositories\
14
+ contained in current directory.'
13
15
  def clone(username)
14
16
  Cloner.new(username, Dir.pwd).clone!
15
17
  end
18
+
19
+ desc 'git_multicast version', 'Shows currently installed version'
20
+ def version
21
+ puts GitMulticast::VERSION
22
+ end
16
23
  end
17
24
  end
@@ -32,11 +32,11 @@ module GitMulticast
32
32
  def make_command(repo)
33
33
  if repo.fork
34
34
  parent_repo = RepositoryFetcher.get_repo_parent(repo.url)
35
- "git clone #{repo.ssh_url} #{ File.join(dir, repo.name) } && \
36
- git -C \"#{ File.join(dir, repo.name) }\" remote add upstream \
35
+ "git clone #{repo.ssh_url} #{File.join(dir, repo.name)} && \
36
+ git -C \"#{File.join(dir, repo.name)}\" remote add upstream \
37
37
  #{parent_repo.ssh_url} --fetch"
38
38
  else
39
- "git clone #{repo.ssh_url} #{ File.join(dir, repo.name) }"
39
+ "git clone #{repo.ssh_url} #{File.join(dir, repo.name)}"
40
40
  end
41
41
  end
42
42
  end
@@ -1,15 +1,17 @@
1
- class OutputFormatter
2
- def self.format(repos, statuses, start_time = nil)
3
- repo_status_pairs = repos.zip(statuses)
1
+ module GitMulticast
2
+ class OutputFormatter
3
+ def self.format(repos, statuses, start_time = nil)
4
+ repo_status_pairs = repos.zip(statuses)
4
5
 
5
- # get successes and failures
6
- success_pairs = repo_status_pairs.select { |_, status| status.success? }
7
- failure_pairs = repo_status_pairs.reject { |_, status| status.success? }
6
+ # get successes and failures
7
+ success_pairs = repo_status_pairs.select { |_, status| status.success? }
8
+ failure_pairs = repo_status_pairs.reject { |_, status| status.success? }
8
9
 
9
- success_pairs.each { |repo, _| puts "#{repo.name} cloned successfully." }
10
- failure_pairs.each { |repo, _| puts "failure to clone #{repo.name}." }
10
+ success_pairs.each { |repo, _| puts "#{repo.name} cloned successfully." }
11
+ failure_pairs.each { |repo, _| puts "failure to clone #{repo.name}." }
11
12
 
12
- puts '=========================================='
13
- puts "Finished in #{Time.now - start_time} seconds." if start_time
13
+ puts '=========================================='
14
+ puts "Finished in #{Time.now - start_time} seconds." if start_time
15
+ end
14
16
  end
15
17
  end
@@ -0,0 +1,34 @@
1
+ module GitMulticast
2
+ class RepositoryFetcher
3
+ class Bitbucket < RepositoryFetcher
4
+ REPOS_URI = 'https://bitbucket.org/api/2.0/repositories/%{username}'
5
+
6
+ def self.get_all_repos_from_user(username)
7
+ uri_str = REPOS_URI % { username: username }
8
+ uri = URI(uri_str)
9
+
10
+ response = Net::HTTP.get_response(uri)
11
+ response_json = JSON.parse(response.body)
12
+
13
+ # Damn...
14
+ response_json['values'].each do |repo|
15
+ repo['links']['_clone'] = repo['links']['clone']
16
+ end
17
+
18
+ response_json['values'].map { |hash| make_struct(hash) }
19
+ end
20
+
21
+ def self.get_repo(url)
22
+ response = Net::HTTP.get_response(URI(url))
23
+ response_json = JSON.parse(response.body)
24
+ response_json['links']['_clone'] = response_json['links']['clone']
25
+
26
+ make_struct(response_json)
27
+ end
28
+
29
+ def self.make_struct(hash)
30
+ RecursiveOpenStruct.new(hash, recurse_over_arrays: true)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,25 @@
1
+ require 'recursive-open-struct'
2
+ require 'json'
3
+
4
+ module GitMulticast
5
+ class RepositoryFetcher
6
+ class Github < RepositoryFetcher
7
+ REPOS_URI = 'https://api.github.com/users/%{username}/repos'
8
+
9
+ def self.get_all_repos_from_user(username)
10
+ uri_str = REPOS_URI % { username: username }
11
+ uri = URI(uri_str)
12
+
13
+ response = Net::HTTP.get_response(uri)
14
+ repos = JSON.parse(response.body)
15
+
16
+ repos.map { |hash| make_struct(hash) }
17
+ end
18
+
19
+ def self.get_repo(url)
20
+ response = Net::HTTP.get_response(URI(url))
21
+ make_struct(JSON.parse(response.body))
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,33 +1,52 @@
1
+ require_relative 'repository_fetcher/github'
2
+ require_relative 'repository_fetcher/bitbucket'
3
+
1
4
  module GitMulticast
2
5
  class RepositoryFetcher
3
- FETCHERS = [
4
- GitMulticast::GithubFetcher,
5
- GitMulticast::BitbucketFetcher
6
+ FETCHER_ADAPTER_ZIP = [
7
+ [Bitbucket, Adapters::Bitbucket],
8
+ [Github, Adapters::Github]
6
9
  ]
7
10
 
11
+ FETCHERS, ADAPTERS = FETCHER_ADAPTER_ZIP.transpose
12
+
8
13
  def self.get_all_repos_from_user(username)
9
- multicast(FETCHERS, :get_all_repos_from_user, username).flatten
14
+ FETCHER_ADAPTER_ZIP.map do |fetcher, adapter|
15
+ raw_repos = fetcher.get_all_repos_from_user(username)
16
+
17
+ raw_repos.map { |raw_repo| adapter.new(raw_repo).adapt }
18
+ end.flatten
19
+ end
20
+
21
+ def self.get_repo(url)
22
+ raw_repo = fetcher_by_url(url).get_repo(url)
23
+ adapter_by_url(url).new(raw_repo).adapt
10
24
  end
11
25
 
12
26
  def self.get_repo_parent(url)
13
- fetcher_by_url(url).get_repo_parent(url)
27
+ get_repo(url).parent
14
28
  end
15
29
 
16
- def self.fetcher_by_url(url)
30
+ def self.zip_by_url(url)
17
31
  fetchers_names = FETCHERS.map do |fetcher|
18
- match = fetcher.to_s.match(/::(.*)$/)
19
- match[1].gsub('Fetcher', '').downcase if match
32
+ match = fetcher.to_s.match(/Fetcher::(.*)$/)
33
+ match[1].downcase if match
20
34
  end
21
35
 
22
- triples = ([url] * FETCHERS.count).zip(fetchers_names, FETCHERS)
36
+ triples = ([url] * FETCHERS.size).zip(fetchers_names, FETCHER_ADAPTER_ZIP)
37
+ triples.find { |u, name, _| u.match name }.last
38
+ end
23
39
 
24
- triples.select { |u, name, _| u.match name }.first.last
40
+ def self.fetcher_by_url(url)
41
+ zip_by_url(url).first
25
42
  end
26
43
 
27
- def self.multicast(list, method, *args)
28
- list.map do |e|
29
- e.send(method, *args)
30
- end
44
+ def self.adapter_by_url(url)
45
+ zip_by_url(url).last
46
+ end
47
+
48
+ def self.make_struct(hash)
49
+ RecursiveOpenStruct.new(hash, recurse_over_arrays: true)
31
50
  end
32
51
  end
33
52
  end
@@ -1,3 +1,3 @@
1
1
  module GitMulticast
2
- VERSION = '0.0.0'
2
+ VERSION = '0.0.6'
3
3
  end
data/lib/git_multicast.rb CHANGED
@@ -2,10 +2,8 @@ require_relative 'git_multicast/version'
2
2
  require_relative 'git_multicast/cloner'
3
3
  require_relative 'git_multicast/puller'
4
4
  require_relative 'git_multicast/output_formatter'
5
- require_relative 'git_multicast/bitbucket_adapter'
6
5
 
7
- require_relative 'git_multicast/github_fetcher'
8
- require_relative 'git_multicast/bitbucket_fetcher'
6
+ require_relative 'git_multicast/adapters'
9
7
  require_relative 'git_multicast/repository_fetcher'
10
8
 
11
9
  module GitMulticast
@@ -0,0 +1,170 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://bitbucket.org/api/2.0/repositories/rranelli
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - Ruby
16
+ Host:
17
+ - bitbucket.org
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Server:
24
+ - nginx/1.5.10
25
+ Date:
26
+ - Wed, 10 Sep 2014 06:04:39 GMT
27
+ Content-Type:
28
+ - application/json; charset=utf-8
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Connection:
32
+ - keep-alive
33
+ X-Served-By:
34
+ - app22
35
+ X-Render-Time:
36
+ - '0.0394489765167'
37
+ Content-Language:
38
+ - en
39
+ X-Static-Version:
40
+ - a47fb0d97df3
41
+ Expires:
42
+ - Wed, 10 Sep 2014 06:19:39 GMT
43
+ Vary:
44
+ - Authorization, Accept-Language, Cookie
45
+ Last-Modified:
46
+ - Wed, 10 Sep 2014 06:04:39 GMT
47
+ X-Version:
48
+ - a47fb0d97df3
49
+ X-Request-Count:
50
+ - '210'
51
+ Cache-Control:
52
+ - max-age=900
53
+ X-Frame-Options:
54
+ - SAMEORIGIN
55
+ Strict-Transport-Security:
56
+ - max-age=31536000
57
+ X-Content-Type-Options:
58
+ - nosniff
59
+ body:
60
+ encoding: ASCII-8BIT
61
+ string: !binary |-
62
+ eyJwYWdlbGVuIjogMTAsICJ2YWx1ZXMiOiBbeyJzY20iOiAiZ2l0IiwgImhh
63
+ c193aWtpIjogdHJ1ZSwgImRlc2NyaXB0aW9uIjogIkVzdGUgw6kgbyByZXBv
64
+ c2l0w7NyaW8gZG8gQ1BOTTIsIHVtYSBmZXJyYW1lbnRhIHBhcmEgZ2VzdMOj
65
+ byBlIGF1dG9tYcOnw6NvIGRlIGRvY3VtZW50b3MgZGUgZW5nZW5oYXJpYS4i
66
+ LCAibGlua3MiOiB7IndhdGNoZXJzIjogeyJocmVmIjogImh0dHBzOi8vYml0
67
+ YnVja2V0Lm9yZy9hcGkvMi4wL3JlcG9zaXRvcmllcy9ycmFuZWxsaS9jcG5t
68
+ djIvd2F0Y2hlcnMifSwgImNvbW1pdHMiOiB7ImhyZWYiOiAiaHR0cHM6Ly9i
69
+ aXRidWNrZXQub3JnL2FwaS8yLjAvcmVwb3NpdG9yaWVzL3JyYW5lbGxpL2Nw
70
+ bm12Mi9jb21taXRzIn0sICJzZWxmIjogeyJocmVmIjogImh0dHBzOi8vYml0
71
+ YnVja2V0Lm9yZy9hcGkvMi4wL3JlcG9zaXRvcmllcy9ycmFuZWxsaS9jcG5t
72
+ djIifSwgImh0bWwiOiB7ImhyZWYiOiAiaHR0cHM6Ly9iaXRidWNrZXQub3Jn
73
+ L3JyYW5lbGxpL2Nwbm12MiJ9LCAiYXZhdGFyIjogeyJocmVmIjogImh0dHBz
74
+ Oi8vZDNvYXhjNHE1azJkNnEuY2xvdWRmcm9udC5uZXQvbS9hNDdmYjBkOTdk
75
+ ZjMvaW1nL2xhbmd1YWdlLWF2YXRhcnMvY19zaGFycF8xNi5wbmcifSwgImZv
76
+ cmtzIjogeyJocmVmIjogImh0dHBzOi8vYml0YnVja2V0Lm9yZy9hcGkvMi4w
77
+ L3JlcG9zaXRvcmllcy9ycmFuZWxsaS9jcG5tdjIvZm9ya3MifSwgImNsb25l
78
+ IjogW3siaHJlZiI6ICJodHRwczovL2JpdGJ1Y2tldC5vcmcvcnJhbmVsbGkv
79
+ Y3BubXYyLmdpdCIsICJuYW1lIjogImh0dHBzIn0sIHsiaHJlZiI6ICJzc2g6
80
+ Ly9naXRAYml0YnVja2V0Lm9yZy9ycmFuZWxsaS9jcG5tdjIuZ2l0IiwgIm5h
81
+ bWUiOiAic3NoIn1dLCAicHVsbHJlcXVlc3RzIjogeyJocmVmIjogImh0dHBz
82
+ Oi8vYml0YnVja2V0Lm9yZy9hcGkvMi4wL3JlcG9zaXRvcmllcy9ycmFuZWxs
83
+ aS9jcG5tdjIvcHVsbHJlcXVlc3RzIn19LCAiZm9ya19wb2xpY3kiOiAiYWxs
84
+ b3dfZm9ya3MiLCAibGFuZ3VhZ2UiOiAiYyMiLCAiY3JlYXRlZF9vbiI6ICIy
85
+ MDEzLTA2LTA1VDA3OjA3OjM4LjI5MDQxOCswMDowMCIsICJmdWxsX25hbWUi
86
+ OiAicnJhbmVsbGkvY3BubXYyIiwgImhhc19pc3N1ZXMiOiB0cnVlLCAib3du
87
+ ZXIiOiB7InVzZXJuYW1lIjogInJyYW5lbGxpIiwgImRpc3BsYXlfbmFtZSI6
88
+ ICJyZW5hbiByYW5lbGxpIiwgImxpbmtzIjogeyJzZWxmIjogeyJocmVmIjog
89
+ Imh0dHBzOi8vYml0YnVja2V0Lm9yZy9hcGkvMi4wL3VzZXJzL3JyYW5lbGxp
90
+ In0sICJodG1sIjogeyJocmVmIjogImh0dHBzOi8vYml0YnVja2V0Lm9yZy9y
91
+ cmFuZWxsaSJ9LCAiYXZhdGFyIjogeyJocmVmIjogImh0dHBzOi8vc2VjdXJl
92
+ LmdyYXZhdGFyLmNvbS9hdmF0YXIvNDU2OWFlYzAwY2IyMjNiM2ZiZjQ4NGY5
93
+ ZTdiYTEyNTY/ZD1odHRwcyUzQSUyRiUyRmQzb2F4YzRxNWsyZDZxLmNsb3Vk
94
+ ZnJvbnQubmV0JTJGbSUyRmE0N2ZiMGQ5N2RmMyUyRmltZyUyRmRlZmF1bHRf
95
+ YXZhdGFyJTJGMzIlMkZ1c2VyX2JsdWUucG5nJnM9MzIifX19LCAidXBkYXRl
96
+ ZF9vbiI6ICIyMDE0LTA0LTIzVDAzOjIxOjE0LjY4NjE3NyswMDowMCIsICJz
97
+ aXplIjogMTQ5Nzg4NjgsICJpc19wcml2YXRlIjogZmFsc2UsICJuYW1lIjog
98
+ IkNQTk12MiJ9LCB7InNjbSI6ICJnaXQiLCAiaGFzX3dpa2kiOiBmYWxzZSwg
99
+ ImRlc2NyaXB0aW9uIjogIiIsICJsaW5rcyI6IHsid2F0Y2hlcnMiOiB7Imhy
100
+ ZWYiOiAiaHR0cHM6Ly9iaXRidWNrZXQub3JnL2FwaS8yLjAvcmVwb3NpdG9y
101
+ aWVzL3JyYW5lbGxpL2Nyb25vZmFrZXIvd2F0Y2hlcnMifSwgImNvbW1pdHMi
102
+ OiB7ImhyZWYiOiAiaHR0cHM6Ly9iaXRidWNrZXQub3JnL2FwaS8yLjAvcmVw
103
+ b3NpdG9yaWVzL3JyYW5lbGxpL2Nyb25vZmFrZXIvY29tbWl0cyJ9LCAic2Vs
104
+ ZiI6IHsiaHJlZiI6ICJodHRwczovL2JpdGJ1Y2tldC5vcmcvYXBpLzIuMC9y
105
+ ZXBvc2l0b3JpZXMvcnJhbmVsbGkvY3Jvbm9mYWtlciJ9LCAiaHRtbCI6IHsi
106
+ aHJlZiI6ICJodHRwczovL2JpdGJ1Y2tldC5vcmcvcnJhbmVsbGkvY3Jvbm9m
107
+ YWtlciJ9LCAiYXZhdGFyIjogeyJocmVmIjogImh0dHBzOi8vZDNvYXhjNHE1
108
+ azJkNnEuY2xvdWRmcm9udC5uZXQvbS9hNDdmYjBkOTdkZjMvaW1nL2xhbmd1
109
+ YWdlLWF2YXRhcnMvZGVmYXVsdF8xNi5wbmcifSwgImZvcmtzIjogeyJocmVm
110
+ IjogImh0dHBzOi8vYml0YnVja2V0Lm9yZy9hcGkvMi4wL3JlcG9zaXRvcmll
111
+ cy9ycmFuZWxsaS9jcm9ub2Zha2VyL2ZvcmtzIn0sICJjbG9uZSI6IFt7Imhy
112
+ ZWYiOiAiaHR0cHM6Ly9iaXRidWNrZXQub3JnL3JyYW5lbGxpL2Nyb25vZmFr
113
+ ZXIuZ2l0IiwgIm5hbWUiOiAiaHR0cHMifSwgeyJocmVmIjogInNzaDovL2dp
114
+ dEBiaXRidWNrZXQub3JnL3JyYW5lbGxpL2Nyb25vZmFrZXIuZ2l0IiwgIm5h
115
+ bWUiOiAic3NoIn1dLCAicHVsbHJlcXVlc3RzIjogeyJocmVmIjogImh0dHBz
116
+ Oi8vYml0YnVja2V0Lm9yZy9hcGkvMi4wL3JlcG9zaXRvcmllcy9ycmFuZWxs
117
+ aS9jcm9ub2Zha2VyL3B1bGxyZXF1ZXN0cyJ9fSwgImZvcmtfcG9saWN5Ijog
118
+ ImFsbG93X2ZvcmtzIiwgImxhbmd1YWdlIjogIiIsICJjcmVhdGVkX29uIjog
119
+ IjIwMTQtMDEtMjBUMDQ6MjM6MTcuNzkwODM3KzAwOjAwIiwgImZ1bGxfbmFt
120
+ ZSI6ICJycmFuZWxsaS9jcm9ub2Zha2VyIiwgImhhc19pc3N1ZXMiOiBmYWxz
121
+ ZSwgIm93bmVyIjogeyJ1c2VybmFtZSI6ICJycmFuZWxsaSIsICJkaXNwbGF5
122
+ X25hbWUiOiAicmVuYW4gcmFuZWxsaSIsICJsaW5rcyI6IHsic2VsZiI6IHsi
123
+ aHJlZiI6ICJodHRwczovL2JpdGJ1Y2tldC5vcmcvYXBpLzIuMC91c2Vycy9y
124
+ cmFuZWxsaSJ9LCAiaHRtbCI6IHsiaHJlZiI6ICJodHRwczovL2JpdGJ1Y2tl
125
+ dC5vcmcvcnJhbmVsbGkifSwgImF2YXRhciI6IHsiaHJlZiI6ICJodHRwczov
126
+ L3NlY3VyZS5ncmF2YXRhci5jb20vYXZhdGFyLzQ1NjlhZWMwMGNiMjIzYjNm
127
+ YmY0ODRmOWU3YmExMjU2P2Q9aHR0cHMlM0ElMkYlMkZkM29heGM0cTVrMmQ2
128
+ cS5jbG91ZGZyb250Lm5ldCUyRm0lMkZhNDdmYjBkOTdkZjMlMkZpbWclMkZk
129
+ ZWZhdWx0X2F2YXRhciUyRjMyJTJGdXNlcl9ibHVlLnBuZyZzPTMyIn19fSwg
130
+ InVwZGF0ZWRfb24iOiAiMjAxNC0wNC0yM1QwMzoxODo0NC42NDAyNjQrMDA6
131
+ MDAiLCAic2l6ZSI6IDQ5NjQ1ODc2LCAiaXNfcHJpdmF0ZSI6IGZhbHNlLCAi
132
+ bmFtZSI6ICJDcm9ub0Zha2VyIn0sIHsic2NtIjogImdpdCIsICJoYXNfd2lr
133
+ aSI6IGZhbHNlLCAiZGVzY3JpcHRpb24iOiAiIiwgImxpbmtzIjogeyJ3YXRj
134
+ aGVycyI6IHsiaHJlZiI6ICJodHRwczovL2JpdGJ1Y2tldC5vcmcvYXBpLzIu
135
+ MC9yZXBvc2l0b3JpZXMvcnJhbmVsbGkvcnJ3ZWJhcHBhcmNoL3dhdGNoZXJz
136
+ In0sICJjb21taXRzIjogeyJocmVmIjogImh0dHBzOi8vYml0YnVja2V0Lm9y
137
+ Zy9hcGkvMi4wL3JlcG9zaXRvcmllcy9ycmFuZWxsaS9ycndlYmFwcGFyY2gv
138
+ Y29tbWl0cyJ9LCAic2VsZiI6IHsiaHJlZiI6ICJodHRwczovL2JpdGJ1Y2tl
139
+ dC5vcmcvYXBpLzIuMC9yZXBvc2l0b3JpZXMvcnJhbmVsbGkvcnJ3ZWJhcHBh
140
+ cmNoIn0sICJodG1sIjogeyJocmVmIjogImh0dHBzOi8vYml0YnVja2V0Lm9y
141
+ Zy9ycmFuZWxsaS9ycndlYmFwcGFyY2gifSwgImF2YXRhciI6IHsiaHJlZiI6
142
+ ICJodHRwczovL2Qzb2F4YzRxNWsyZDZxLmNsb3VkZnJvbnQubmV0L20vYTQ3
143
+ ZmIwZDk3ZGYzL2ltZy9sYW5ndWFnZS1hdmF0YXJzL3J1YnlfMTYucG5nIn0s
144
+ ICJmb3JrcyI6IHsiaHJlZiI6ICJodHRwczovL2JpdGJ1Y2tldC5vcmcvYXBp
145
+ LzIuMC9yZXBvc2l0b3JpZXMvcnJhbmVsbGkvcnJ3ZWJhcHBhcmNoL2Zvcmtz
146
+ In0sICJjbG9uZSI6IFt7ImhyZWYiOiAiaHR0cHM6Ly9iaXRidWNrZXQub3Jn
147
+ L3JyYW5lbGxpL3Jyd2ViYXBwYXJjaC5naXQiLCAibmFtZSI6ICJodHRwcyJ9
148
+ LCB7ImhyZWYiOiAic3NoOi8vZ2l0QGJpdGJ1Y2tldC5vcmcvcnJhbmVsbGkv
149
+ cnJ3ZWJhcHBhcmNoLmdpdCIsICJuYW1lIjogInNzaCJ9XSwgInB1bGxyZXF1
150
+ ZXN0cyI6IHsiaHJlZiI6ICJodHRwczovL2JpdGJ1Y2tldC5vcmcvYXBpLzIu
151
+ MC9yZXBvc2l0b3JpZXMvcnJhbmVsbGkvcnJ3ZWJhcHBhcmNoL3B1bGxyZXF1
152
+ ZXN0cyJ9fSwgImZvcmtfcG9saWN5IjogImFsbG93X2ZvcmtzIiwgImxhbmd1
153
+ YWdlIjogInJ1YnkiLCAiY3JlYXRlZF9vbiI6ICIyMDE0LTA0LTA2VDE3OjMz
154
+ OjM5LjI3OTE2NSswMDowMCIsICJmdWxsX25hbWUiOiAicnJhbmVsbGkvcnJ3
155
+ ZWJhcHBhcmNoIiwgImhhc19pc3N1ZXMiOiBmYWxzZSwgIm93bmVyIjogeyJ1
156
+ c2VybmFtZSI6ICJycmFuZWxsaSIsICJkaXNwbGF5X25hbWUiOiAicmVuYW4g
157
+ cmFuZWxsaSIsICJsaW5rcyI6IHsic2VsZiI6IHsiaHJlZiI6ICJodHRwczov
158
+ L2JpdGJ1Y2tldC5vcmcvYXBpLzIuMC91c2Vycy9ycmFuZWxsaSJ9LCAiaHRt
159
+ bCI6IHsiaHJlZiI6ICJodHRwczovL2JpdGJ1Y2tldC5vcmcvcnJhbmVsbGki
160
+ fSwgImF2YXRhciI6IHsiaHJlZiI6ICJodHRwczovL3NlY3VyZS5ncmF2YXRh
161
+ ci5jb20vYXZhdGFyLzQ1NjlhZWMwMGNiMjIzYjNmYmY0ODRmOWU3YmExMjU2
162
+ P2Q9aHR0cHMlM0ElMkYlMkZkM29heGM0cTVrMmQ2cS5jbG91ZGZyb250Lm5l
163
+ dCUyRm0lMkZhNDdmYjBkOTdkZjMlMkZpbWclMkZkZWZhdWx0X2F2YXRhciUy
164
+ RjMyJTJGdXNlcl9ibHVlLnBuZyZzPTMyIn19fSwgInVwZGF0ZWRfb24iOiAi
165
+ MjAxNC0wNC0yM1QwMToyMzo0OC4xNjAwMDArMDA6MDAiLCAic2l6ZSI6IDE5
166
+ MTk2MSwgImlzX3ByaXZhdGUiOiBmYWxzZSwgIm5hbWUiOiAiUlJXZWJBcHBB
167
+ cmNoIn1dLCAicGFnZSI6IDEsICJzaXplIjogM30=
168
+ http_version:
169
+ recorded_at: Wed, 10 Sep 2014 06:04:39 GMT
170
+ recorded_with: VCR 2.9.3