nsrr 0.2.0 → 0.3.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/LICENSE +1 -1
- data/README.md +47 -10
- data/Rakefile +3 -0
- data/bin/nsrr +1 -0
- data/lib/nsrr.rb +10 -9
- data/lib/nsrr/commands/console.rb +4 -2
- data/lib/nsrr/commands/download.rb +20 -20
- data/lib/nsrr/commands/update.rb +7 -7
- data/lib/nsrr/helpers/authorization.rb +11 -9
- data/lib/nsrr/helpers/constants.rb +2 -0
- data/lib/nsrr/helpers/download_request.rb +31 -33
- data/lib/nsrr/helpers/hash_helper.rb +3 -0
- data/lib/nsrr/helpers/json_request.rb +70 -20
- data/lib/nsrr/models/all.rb +2 -0
- data/lib/nsrr/models/dataset.rb +41 -28
- data/lib/nsrr/models/file.rb +32 -36
- data/lib/nsrr/version.rb +4 -2
- data/nsrr.gemspec +13 -14
- metadata +14 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47192f16e29c8348a3806bf5b664d6f122772460
|
4
|
+
data.tar.gz: 2eb61ae1eb977358192775ca3fb4970eab77fe27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c18289ef636386f3bfa9160ae229df05d6601db3f6160a0ce4143d26c04debc94afb0fb29d00feec8fedcc03e990f5010d2015ca63e64911b690045c1f3cbf6d
|
7
|
+
data.tar.gz: e9f5a51cd80df55a8a0fbad3651ee93222e890e5a1220b328507d98a69fe75db75e7fec8c94e7139accaf572c2886d0fac420802574ccb9d0d9ea2ba05169c67
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 0.3.0
|
2
|
+
|
3
|
+
### Enhancements
|
4
|
+
- **Download Command**
|
5
|
+
- The `nsrr download` command can now download single files
|
6
|
+
- Ex: `nsrr download shhs/datasets/CHANGELOG.md`
|
7
|
+
- User tokens are stripped of extra whitespace to avoid common authentication
|
8
|
+
issues
|
9
|
+
- **Gem Changes**
|
10
|
+
- Updated to Ruby 2.3.0
|
11
|
+
- Updated to colorize 0.7.7
|
12
|
+
- Updated to simplecov 0.11.2
|
13
|
+
- Removed minitest-reporters
|
14
|
+
- Bundler is now a required dependency
|
15
|
+
|
16
|
+
### Bug Fix
|
17
|
+
- Fixed an issue that flooded test output with uninitialized string class instance variable `@disable_colorization`
|
18
|
+
|
1
19
|
## 0.2.0 (May 29, 2015)
|
2
20
|
|
3
21
|
### Enhancements
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -8,7 +8,7 @@ The official ruby gem built to simplify file downloads and dataset integration t
|
|
8
8
|
|
9
9
|
## Prerequisites
|
10
10
|
|
11
|
-
You must have **Ruby 2.
|
11
|
+
You must have **Ruby 2.2+ installed** on your system to use the NSRR gem.
|
12
12
|
|
13
13
|
- [Install Ruby on Windows](http://rubyinstaller.org/)
|
14
14
|
- [Install Ruby on Mac](https://github.com/remomueller/documentation/blob/master/macosx/140-install-ruby.md)
|
@@ -24,19 +24,14 @@ Install it yourself as:
|
|
24
24
|
gem install nsrr --no-ri --no-rdoc
|
25
25
|
```
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
gem 'nsrr'
|
31
|
-
```
|
32
|
-
|
33
|
-
And then execute:
|
27
|
+
**NOTE:** There is a bug in newer versions of RubyGems that prevent the NSRR gem
|
28
|
+
from running correctly. If you run into issues, downgrade RubyGems using the
|
29
|
+
following command:
|
34
30
|
|
35
31
|
```console
|
36
|
-
|
32
|
+
gem update --system 2.4.8 --no-ri --no-rdoc
|
37
33
|
```
|
38
34
|
|
39
|
-
|
40
35
|
## Usage
|
41
36
|
|
42
37
|
### Download files from a dataset
|
@@ -200,3 +195,45 @@ nsrr version
|
|
200
195
|
```console
|
201
196
|
nsrr help
|
202
197
|
```
|
198
|
+
|
199
|
+
## Common Issues
|
200
|
+
|
201
|
+
### Errors Running Ruby in Windows Command Prompt
|
202
|
+
|
203
|
+
In some cases when using Ruby on Windows through the Command Prompt, it is
|
204
|
+
necessary to open the Command Prompt in **administrator mode** for the NSRR gem
|
205
|
+
to work. This may be due to how Ruby was installed (for admins only), or the
|
206
|
+
location the files are being downloaded to (a root directory C: for example).
|
207
|
+
|
208
|
+
It is recommended to use the gem without elevated privileges first in any case
|
209
|
+
(to download directly to Desktop for example) before using admin privileges for
|
210
|
+
the Ruby gem.
|
211
|
+
|
212
|
+
### Issue "'method_missing': undefined method 'this'" when running NSRR commands
|
213
|
+
|
214
|
+
There is a bug in newer versions of RubyGems that prevent the NSRR gem
|
215
|
+
from running correctly. If you run into issues, downgrade RubyGems using the
|
216
|
+
following command:
|
217
|
+
|
218
|
+
The following versions of RubyGems cause issues while running NSRR commands:
|
219
|
+
|
220
|
+
- `2.5.0`
|
221
|
+
- `2.5.1`
|
222
|
+
- `2.5.2`
|
223
|
+
- `2.6.0`
|
224
|
+
- `2.6.1`
|
225
|
+
- `2.6.2`
|
226
|
+
|
227
|
+
You can check which version you have installed by typing:
|
228
|
+
|
229
|
+
```console
|
230
|
+
gem -v
|
231
|
+
```
|
232
|
+
|
233
|
+
You can fix this error by reverting to the last stable version of RubyGems,
|
234
|
+
`2.4.8`.
|
235
|
+
|
236
|
+
```console
|
237
|
+
gem update --system 2.4.8 --no-ri --no-rdoc
|
238
|
+
```
|
239
|
+
|
data/Rakefile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rake/testtask'
|
2
4
|
|
3
5
|
Rake::TestTask.new(:test) do |t|
|
@@ -5,6 +7,7 @@ Rake::TestTask.new(:test) do |t|
|
|
5
7
|
t.libs << 'test'
|
6
8
|
t.pattern = 'test/**/*_test.rb'
|
7
9
|
t.verbose = false
|
10
|
+
t.warning = false
|
8
11
|
end
|
9
12
|
|
10
13
|
task default: :test
|
data/bin/nsrr
CHANGED
data/lib/nsrr.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'colorize'
|
4
|
+
require 'nsrr/version'
|
4
5
|
|
5
6
|
Nsrr::COMMANDS = {
|
6
7
|
'c' => :console,
|
7
8
|
'd' => :download,
|
8
9
|
'u' => :update,
|
9
10
|
'v' => :version
|
10
|
-
}
|
11
|
+
}.freeze
|
11
12
|
|
13
|
+
# Exposes certain commands for access from the command line.
|
12
14
|
module Nsrr
|
13
15
|
def self.launch(argv)
|
14
|
-
|
16
|
+
send((Nsrr::COMMANDS[argv.first.to_s.scan(/\w/).first] || :help), argv)
|
15
17
|
end
|
16
18
|
|
17
19
|
def self.console(argv)
|
@@ -29,7 +31,7 @@ module Nsrr
|
|
29
31
|
Nsrr::Commands::Update.start(argv)
|
30
32
|
end
|
31
33
|
|
32
|
-
def self.help(
|
34
|
+
def self.help(_)
|
33
35
|
puts <<-EOT
|
34
36
|
|
35
37
|
Usage: nsrr COMMAND [ARGS]
|
@@ -45,13 +47,12 @@ Commands can be referenced by the first letter:
|
|
45
47
|
Ex: `nsrr v`, for version
|
46
48
|
|
47
49
|
EOT
|
48
|
-
puts
|
49
|
-
puts
|
50
|
+
puts 'Read more on the download command here:'
|
51
|
+
puts ' ' + 'https://github.com/nsrr/nsrr-gem'.colorize(:blue).on_white.underline
|
50
52
|
puts "\n"
|
51
53
|
end
|
52
54
|
|
53
|
-
def self.version(
|
55
|
+
def self.version(_)
|
54
56
|
puts "Nsrr #{Nsrr::VERSION::STRING}"
|
55
57
|
end
|
56
|
-
|
57
58
|
end
|
@@ -1,9 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'irb'
|
2
4
|
require 'irb/completion'
|
3
5
|
require 'nsrr/models/all'
|
4
6
|
|
5
7
|
module Nsrr
|
6
8
|
module Commands
|
9
|
+
# Allows console to be started with the NSRR environment.
|
7
10
|
class Console
|
8
11
|
class << self
|
9
12
|
def start(*args)
|
@@ -13,7 +16,7 @@ module Nsrr
|
|
13
16
|
|
14
17
|
attr_reader :console
|
15
18
|
|
16
|
-
def initialize(
|
19
|
+
def initialize(_argv)
|
17
20
|
ARGV.clear
|
18
21
|
@console = IRB
|
19
22
|
end
|
@@ -22,7 +25,6 @@ module Nsrr
|
|
22
25
|
puts "Loading environment (Nsrr #{Nsrr::VERSION::STRING})"
|
23
26
|
@console.start
|
24
27
|
end
|
25
|
-
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -1,10 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'colorize'
|
3
4
|
require 'nsrr/models/all'
|
4
5
|
require 'nsrr/helpers/authorization'
|
5
6
|
|
6
7
|
module Nsrr
|
7
8
|
module Commands
|
9
|
+
# Downloads a folder or a file from the NSRR webserver. Folders can be
|
10
|
+
# downloaded recursively.
|
8
11
|
class Download
|
9
12
|
class << self
|
10
13
|
def run(*args)
|
@@ -12,38 +15,35 @@ module Nsrr
|
|
12
15
|
end
|
13
16
|
end
|
14
17
|
|
15
|
-
attr_reader :token, :dataset_slug, :
|
18
|
+
attr_reader :token, :dataset_slug, :full_path, :file_comparison, :depth
|
16
19
|
|
17
20
|
def initialize(argv)
|
18
21
|
(@token, argv) = parse_parameter_with_value(argv, ['token'], '')
|
19
22
|
(@file_comparison, argv) = parse_parameter(argv, ['fast', 'fresh', 'md5'], 'md5')
|
20
23
|
(@depth, argv) = parse_parameter(argv, ['shallow', 'recursive'], 'recursive')
|
21
24
|
@dataset_slug = argv[1].to_s.split('/').first
|
22
|
-
@
|
25
|
+
@full_path = (argv[1].to_s.split('/')[1..-1] || []).join('/')
|
23
26
|
end
|
24
27
|
|
25
28
|
# Run with Authorization
|
26
29
|
def run
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
if @dataset_slug.nil?
|
31
|
+
puts 'Please specify a dataset: ' + 'nsrr download DATASET'.colorize(:white)
|
32
|
+
puts 'Read more on the download command here:'
|
33
|
+
puts ' ' + 'https://github.com/nsrr/nsrr-gem'.colorize(:blue).on_white.underline
|
34
|
+
else
|
35
|
+
@token = Nsrr::Helpers::Authorization.get_token(@token) if @token.to_s == ''
|
36
|
+
@dataset = Dataset.find(@dataset_slug, @token)
|
37
|
+
if @dataset
|
38
|
+
@dataset.download(@full_path, depth: @depth, method: @file_comparison)
|
32
39
|
else
|
33
|
-
|
34
|
-
|
35
|
-
if
|
36
|
-
@dataset.download(@folder, depth: @depth, method: @file_comparison)
|
37
|
-
else
|
38
|
-
puts "\nThe dataset " + "#{@dataset_slug}".colorize(:white) + " was not found."
|
39
|
-
auth_section = (@token.to_s == '' ? '' : "/a/#{@token}" )
|
40
|
-
datasets = Nsrr::Helpers::JsonRequest.get("#{Nsrr::WEBSITE}#{auth_section}/datasets.json")
|
41
|
-
puts "Did you mean one of: #{datasets.collect{|d| d['slug'].colorize(:white)}.sort.join(', ')}" if datasets and datasets.size > 0
|
42
|
-
end
|
40
|
+
puts "\nThe dataset " + @dataset_slug.to_s.colorize(:white) + ' was not found.'
|
41
|
+
(datasets, _status) = Nsrr::Helpers::JsonRequest.get("#{Nsrr::WEBSITE}/datasets.json", auth_token: @token)
|
42
|
+
puts "Did you mean one of: #{datasets.collect { |d| d['slug'].colorize(:white)}.sort.join(', ') }" if datasets && datasets.size > 0
|
43
43
|
end
|
44
|
-
rescue Interrupt
|
45
|
-
puts "\nINTERRUPTED".colorize(:red)
|
46
44
|
end
|
45
|
+
rescue Interrupt
|
46
|
+
puts "\nINTERRUPTED".colorize(:red)
|
47
47
|
end
|
48
48
|
|
49
49
|
private
|
data/lib/nsrr/commands/update.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'colorize'
|
3
4
|
require 'nsrr/helpers/json_request'
|
4
5
|
|
5
6
|
module Nsrr
|
6
7
|
module Commands
|
8
|
+
# Command to check if there is an updated version of the gem available.
|
7
9
|
class Update
|
8
10
|
class << self
|
9
11
|
def start(*args)
|
@@ -15,23 +17,21 @@ module Nsrr
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def start
|
18
|
-
json = Nsrr::Helpers::JsonRequest.get(
|
19
|
-
|
20
|
+
(json, _status) = Nsrr::Helpers::JsonRequest.get('https://rubygems.org/api/v1/gems/nsrr.json')
|
20
21
|
if json
|
21
22
|
if json['version'] == Nsrr::VERSION::STRING
|
22
|
-
puts
|
23
|
+
puts 'The nsrr gem is ' + 'up-to-date'.colorize(:green) + '!'
|
23
24
|
else
|
24
25
|
puts
|
25
26
|
puts "A newer version (v#{json['version']}) is available! Type the following command to update:"
|
26
27
|
puts
|
27
|
-
puts
|
28
|
+
puts ' gem install nsrr --no-ri --no-rdoc'.colorize(:white)
|
28
29
|
puts
|
29
30
|
end
|
30
31
|
else
|
31
|
-
puts
|
32
|
+
puts 'Unable to connect to RubyGems.org. Please try again later.'
|
32
33
|
end
|
33
34
|
end
|
34
|
-
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -1,20 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'nsrr/helpers/json_request'
|
2
4
|
|
3
5
|
module Nsrr
|
4
6
|
module Helpers
|
7
|
+
# Helper to verify that user is authenticated.
|
5
8
|
class Authorization
|
6
9
|
def self.get_token(token)
|
7
|
-
puts
|
8
|
-
puts
|
9
|
-
print
|
10
|
+
puts ' Get your token here: ' + "#{Nsrr::WEBSITE}/token".colorize(:blue).on_white.underline
|
11
|
+
puts ' Your input is hidden while entering token.'.colorize(:white)
|
12
|
+
print ' Enter your token: '
|
10
13
|
token = STDIN.noecho(&:gets).chomp if token.to_s.strip == ''
|
11
|
-
|
12
|
-
response = Nsrr::Helpers::JsonRequest.get("#{Nsrr::WEBSITE}/account
|
13
|
-
|
14
|
-
|
15
|
-
puts "AUTHORIZED".colorize(:green) + " as " + "#{response['first_name']} #{response['last_name']}".colorize( :white )
|
14
|
+
token.strip!
|
15
|
+
(response, _status) = Nsrr::Helpers::JsonRequest.get("#{Nsrr::WEBSITE}/api/v1/account/profile.json", auth_token: token)
|
16
|
+
if response.is_a?(Hash) && response['authenticated']
|
17
|
+
puts 'AUTHORIZED'.colorize(:green) + ' as ' + "#{response['first_name']} #{response['last_name']}".colorize(:white)
|
16
18
|
else
|
17
|
-
puts
|
19
|
+
puts 'UNAUTHORIZED'.colorize(:red) + ' Public Access Only'
|
18
20
|
end
|
19
21
|
token
|
20
22
|
end
|
@@ -1,9 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'openssl'
|
2
4
|
require 'net/http'
|
3
5
|
require 'uri'
|
4
6
|
|
5
7
|
module Nsrr
|
6
8
|
module Helpers
|
9
|
+
# Downloads a file to a specified folder.
|
7
10
|
class DownloadRequest
|
8
11
|
class << self
|
9
12
|
def get(*args)
|
@@ -14,49 +17,44 @@ module Nsrr
|
|
14
17
|
attr_reader :url, :error, :file_size
|
15
18
|
|
16
19
|
def initialize(url, download_folder)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
24
|
-
end
|
25
|
-
@download_folder = download_folder
|
26
|
-
@file_size = 0
|
27
|
-
rescue => e
|
28
|
-
@error = 'Invalid Token'
|
20
|
+
escaped_url = URI.escape(url)
|
21
|
+
@url = URI.parse(escaped_url)
|
22
|
+
@http = Net::HTTP.new(@url.host, @url.port)
|
23
|
+
if @url.scheme == 'https'
|
24
|
+
@http.use_ssl = true
|
25
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
29
26
|
end
|
27
|
+
@download_folder = download_folder
|
28
|
+
@file_size = 0
|
29
|
+
rescue
|
30
|
+
@error = 'Invalid Token'
|
30
31
|
end
|
31
32
|
|
32
33
|
# Writes file segments to disk immediately instead of storing in memory
|
33
34
|
def get
|
35
|
+
return unless @error.nil?
|
34
36
|
local_file = ::File.open(@download_folder, 'wb')
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
@file_size = ::File.size(@download_folder)
|
43
|
-
partial = false
|
44
|
-
when '302'
|
45
|
-
@error = 'Token Not Authorized to Access Specified File'
|
46
|
-
else
|
47
|
-
@error = "#{response.code} #{response.class.name}"
|
37
|
+
partial = true
|
38
|
+
@http.request_get(@url.path) do |response|
|
39
|
+
case response.code
|
40
|
+
when '200'
|
41
|
+
response.read_body do |segment|
|
42
|
+
local_file.write(segment)
|
48
43
|
end
|
44
|
+
@file_size = ::File.size(@download_folder)
|
45
|
+
partial = false
|
46
|
+
when '302'
|
47
|
+
@error = 'Token Not Authorized to Access Specified File'
|
48
|
+
else
|
49
|
+
@error = "#{response.code} #{response.class.name}"
|
49
50
|
end
|
50
|
-
rescue => e # Net::ReadTimeout, SocketError
|
51
|
-
@error = "(#{e.class}) #{e.message}"
|
52
|
-
ensure
|
53
|
-
local_file.close()
|
54
|
-
::File.delete(@download_folder) if partial and ::File.exist?(@download_folder)
|
55
51
|
end
|
52
|
+
rescue => e # Net::ReadTimeout, SocketError
|
53
|
+
@error = "(#{e.class}) #{e.message}"
|
54
|
+
ensure
|
55
|
+
local_file.close if local_file
|
56
|
+
::File.delete(@download_folder) if partial && ::File.exist?(@download_folder)
|
56
57
|
end
|
57
|
-
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
62
|
-
|
@@ -1,43 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'openssl'
|
2
4
|
require 'net/http'
|
3
5
|
require 'json'
|
6
|
+
require 'cgi'
|
4
7
|
|
5
8
|
module Nsrr
|
6
9
|
module Helpers
|
10
|
+
# Aids in generating JSON requests for GET, POST, and PATCH.
|
7
11
|
class JsonRequest
|
8
12
|
class << self
|
9
|
-
def get(*args)
|
10
|
-
new(*args).get
|
13
|
+
def get(url, *args)
|
14
|
+
new(url, *args).get
|
15
|
+
end
|
16
|
+
|
17
|
+
def post(url, *args)
|
18
|
+
new(url, *args).post
|
19
|
+
end
|
20
|
+
|
21
|
+
def patch(url, *args)
|
22
|
+
new(url, *args).patch
|
11
23
|
end
|
12
24
|
end
|
13
25
|
|
14
26
|
attr_reader :url
|
15
27
|
|
16
|
-
def initialize(url)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
rescue
|
28
|
+
def initialize(url, args = {})
|
29
|
+
@params = nested_hash_to_params(args)
|
30
|
+
@url = URI.parse(url)
|
31
|
+
|
32
|
+
@http = Net::HTTP.new(@url.host, @url.port)
|
33
|
+
if @url.scheme == 'https'
|
34
|
+
@http.use_ssl = true
|
35
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
25
36
|
end
|
37
|
+
rescue
|
38
|
+
@error = "Invalid URL: #{url.inspect}"
|
39
|
+
puts @error.colorize(:red)
|
26
40
|
end
|
27
41
|
|
28
42
|
def get
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
43
|
+
return unless @error.nil?
|
44
|
+
full_path = @url.path
|
45
|
+
query = ([@url.query] + @params).flatten.compact.join('&')
|
46
|
+
full_path += "?#{query}" if query.to_s != ''
|
47
|
+
response = @http.start do |http|
|
48
|
+
http.get(full_path)
|
49
|
+
end
|
50
|
+
[JSON.parse(response.body), response]
|
51
|
+
rescue => e
|
52
|
+
puts "GET Error: #{e}".colorize(:red)
|
53
|
+
end
|
54
|
+
|
55
|
+
def post
|
56
|
+
return unless @error.nil?
|
57
|
+
response = @http.start do |http|
|
58
|
+
http.post(@url.path, @params.flatten.compact.join('&'))
|
59
|
+
end
|
60
|
+
[JSON.parse(response.body), response]
|
61
|
+
rescue => e
|
62
|
+
puts "POST ERROR: #{e}".colorize(:red)
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def patch
|
67
|
+
@params << '_method=patch'
|
68
|
+
post
|
69
|
+
end
|
70
|
+
|
71
|
+
def nested_hash_to_params(args)
|
72
|
+
args.collect do |key, value|
|
73
|
+
key_value_to_string(key, value, nil)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def key_value_to_string(key, value, scope = nil)
|
78
|
+
current_scope = (scope ? "#{scope}[#{key}]" : key)
|
79
|
+
if value.is_a? Hash
|
80
|
+
value.collect do |k,v|
|
81
|
+
key_value_to_string(k, v, current_scope)
|
82
|
+
end.join('&')
|
83
|
+
elsif value.is_a? Array
|
84
|
+
value.collect do |v|
|
85
|
+
key_value_to_string('', v, current_scope)
|
33
86
|
end
|
34
|
-
|
35
|
-
|
36
|
-
nil
|
87
|
+
else
|
88
|
+
"#{current_scope}=#{CGI.escape(value.to_s)}"
|
37
89
|
end
|
38
90
|
end
|
39
91
|
end
|
40
92
|
end
|
41
93
|
end
|
42
|
-
|
43
|
-
|
data/lib/nsrr/models/all.rb
CHANGED
data/lib/nsrr/models/dataset.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'colorize'
|
2
4
|
require 'fileutils'
|
3
5
|
require 'irb'
|
@@ -12,10 +14,11 @@ require 'nsrr/models/file'
|
|
12
14
|
|
13
15
|
module Nsrr
|
14
16
|
module Models
|
17
|
+
# Allows dataset and dataset file information to be retrieved, as well as
|
18
|
+
# allowing dataset files to be downloaded.
|
15
19
|
class Dataset
|
16
20
|
def self.find(slug, token = nil)
|
17
|
-
|
18
|
-
json = Nsrr::Helpers::JsonRequest.get("#{Nsrr::WEBSITE}#{auth_section}/datasets/#{slug}.json")
|
21
|
+
(json, _status) = Nsrr::Helpers::JsonRequest.get("#{Nsrr::WEBSITE}/api/v1/datasets/#{slug}.json", auth_token: token)
|
19
22
|
if json
|
20
23
|
new(json, token)
|
21
24
|
else
|
@@ -31,18 +34,20 @@ module Nsrr
|
|
31
34
|
@name = json['name']
|
32
35
|
@files = {}
|
33
36
|
@download_token = token
|
37
|
+
@downloaded_folders = []
|
34
38
|
end
|
35
39
|
|
36
40
|
def files(path = nil)
|
37
41
|
@files[path] ||= begin
|
38
|
-
|
39
|
-
|
40
|
-
(json
|
42
|
+
url = "#{Nsrr::WEBSITE}/api/v1/datasets/#{@slug}/files.json"
|
43
|
+
params = { auth_token: @download_token, path: path }
|
44
|
+
(json, _status) = Nsrr::Helpers::JsonRequest.get(url, params)
|
45
|
+
(json || []).collect { |file_json| Nsrr::Models::File.new(file_json) }
|
41
46
|
end
|
42
47
|
end
|
43
48
|
|
44
49
|
def folders(path = nil)
|
45
|
-
|
50
|
+
files(path).select { |f| !f.is_file }.collect(&:file_name)
|
46
51
|
end
|
47
52
|
|
48
53
|
# Options include:
|
@@ -53,7 +58,7 @@ module Nsrr
|
|
53
58
|
# depth:
|
54
59
|
# 'recursive' => [default] Downloads files in selected path folder and all subfolders
|
55
60
|
# 'shallow' => Only downloads files in selected path folder
|
56
|
-
def download(
|
61
|
+
def download(full_path = nil, *args)
|
57
62
|
options = Nsrr::Helpers::HashHelper.symbolize_keys(args.first || {})
|
58
63
|
options[:method] ||= 'md5'
|
59
64
|
options[:depth] ||= 'recursive'
|
@@ -64,16 +69,16 @@ module Nsrr
|
|
64
69
|
@files_failed = 0
|
65
70
|
|
66
71
|
begin
|
67
|
-
puts
|
68
|
-
puts
|
69
|
-
puts
|
70
|
-
if @download_token
|
72
|
+
puts ' File Check: ' + options[:method].to_s.colorize(:white)
|
73
|
+
puts ' Depth: ' + options[:depth].to_s.colorize(:white)
|
74
|
+
puts ''
|
75
|
+
if @download_token.nil?
|
71
76
|
@download_token = Nsrr::Helpers::Authorization.get_token(@download_token)
|
72
77
|
end
|
73
78
|
|
74
79
|
@start_time = Time.now
|
75
80
|
|
76
|
-
download_helper(
|
81
|
+
download_helper(full_path, options)
|
77
82
|
rescue Interrupt, IRB::Abort
|
78
83
|
puts "\n Interrupted".colorize(:red)
|
79
84
|
end
|
@@ -81,21 +86,25 @@ module Nsrr
|
|
81
86
|
@downloaded_megabytes = @downloaded_bytes / (1024 * 1024)
|
82
87
|
|
83
88
|
puts "\nFinished in #{Time.now - @start_time} seconds." if @start_time
|
84
|
-
puts "\n#{@folders_created} folder#{
|
85
|
-
"#{@files_downloaded} file#{
|
86
|
-
"#{@downloaded_megabytes} MiB#{
|
87
|
-
"#{@files_skipped} file#{
|
88
|
-
"#{@files_failed} file#{
|
89
|
+
puts "\n#{@folders_created} folder#{'s' if @folders_created != 1} created".colorize(:white) + ', ' +
|
90
|
+
"#{@files_downloaded} file#{'s' if @files_downloaded != 1} downloaded".colorize(:green) + ', ' +
|
91
|
+
"#{@downloaded_megabytes} MiB#{'s' if @downloaded_megabytes != 1} downloaded".colorize(:green) + ', ' +
|
92
|
+
"#{@files_skipped} file#{'s' if @files_skipped != 1} skipped".colorize(:light_blue) + ', ' +
|
93
|
+
"#{@files_failed} file#{'s' if @files_failed != 1} failed".colorize(@files_failed == 0 ? :white : :red) + "\n\n"
|
89
94
|
nil
|
90
95
|
end
|
91
96
|
|
92
|
-
def download_helper(
|
93
|
-
|
94
|
-
|
97
|
+
def download_helper(full_path, options)
|
98
|
+
return if @downloaded_folders.include?(full_path)
|
99
|
+
@downloaded_folders << full_path
|
100
|
+
|
101
|
+
create_folder_for_path(full_path)
|
95
102
|
|
96
|
-
|
103
|
+
files(full_path).select(&:is_file).each do |file|
|
104
|
+
current_folder = ::File.join(slug.to_s, file.folder.to_s)
|
97
105
|
result = file.download(options[:method], current_folder, @download_token)
|
98
|
-
case result
|
106
|
+
case result
|
107
|
+
when 'fail'
|
99
108
|
@files_failed += 1
|
100
109
|
when 'skip'
|
101
110
|
@files_skipped += 1
|
@@ -104,21 +113,25 @@ module Nsrr
|
|
104
113
|
@downloaded_bytes += result
|
105
114
|
end
|
106
115
|
end
|
107
|
-
|
108
116
|
if options[:depth] == 'recursive'
|
109
|
-
|
110
|
-
|
111
|
-
self.download_helper(folder, options)
|
117
|
+
files(full_path).reject(&:is_file).each do |file|
|
118
|
+
download_helper(file.full_path, options)
|
112
119
|
end
|
113
120
|
end
|
114
121
|
end
|
115
122
|
|
123
|
+
def create_folder_for_path(full_path)
|
124
|
+
files(full_path).collect(&:folder).uniq.each do |folder|
|
125
|
+
current_folder = ::File.join(slug.to_s, folder.to_s)
|
126
|
+
create_folder(current_folder)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
116
130
|
def create_folder(folder)
|
117
|
-
puts
|
131
|
+
puts ' create'.colorize(:white) + " #{folder}"
|
118
132
|
FileUtils.mkdir_p folder
|
119
133
|
@folders_created += 1
|
120
134
|
end
|
121
|
-
|
122
135
|
end
|
123
136
|
end
|
124
137
|
end
|
data/lib/nsrr/models/file.rb
CHANGED
@@ -1,22 +1,25 @@
|
|
1
|
-
#
|
2
|
-
require 'digest/md5'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
3
|
+
require 'digest/md5'
|
4
4
|
require 'nsrr/helpers/constants'
|
5
5
|
require 'nsrr/helpers/download_request'
|
6
6
|
|
7
7
|
module Nsrr
|
8
8
|
module Models
|
9
|
+
# Models a downloadable file or folder
|
9
10
|
class File
|
10
|
-
attr_reader :
|
11
|
+
attr_reader :dataset_slug, :full_path, :folder, :file_name, :is_file, :file_size, :file_checksum_md5, :archived
|
11
12
|
|
12
13
|
def initialize(json = {})
|
13
|
-
@name = json['file_name']
|
14
|
-
@web_checksum = json['checksum']
|
15
|
-
@is_file = json['is_file']
|
16
|
-
@web_file_size = json['file_size']
|
17
14
|
@dataset_slug = json['dataset']
|
18
|
-
@
|
19
|
-
@
|
15
|
+
@full_path = json['full_path']
|
16
|
+
@folder = json['folder']
|
17
|
+
@file_name = json['file_name']
|
18
|
+
@is_file = json['is_file']
|
19
|
+
@file_size = json['file_size']
|
20
|
+
@file_checksum_md5 = json['file_checksum_md5']
|
21
|
+
@archived = json['archived']
|
22
|
+
@latest_checksum = ''
|
20
23
|
@latest_file_size = -1
|
21
24
|
end
|
22
25
|
|
@@ -51,78 +54,73 @@ module Nsrr
|
|
51
54
|
# If the file check fails, the file is downloaded a second time and rechecked.
|
52
55
|
# If the second download and check fail, the file is marked as failed, and the downloader continues to the subsequent file.
|
53
56
|
def force_download(path, token, method)
|
54
|
-
download_folder = ::File.join(Dir.pwd, path.to_s, @
|
57
|
+
download_folder = ::File.join(Dir.pwd, path.to_s, @file_name.to_s)
|
55
58
|
auth_section = (token.to_s == '' ? '' : "/a/#{token}")
|
56
|
-
download_url = "#{Nsrr::WEBSITE}/datasets/#{@dataset_slug}/files#{auth_section}/m/nsrr-gem-v#{Nsrr::VERSION::STRING.gsub('.', '-')}/#{@
|
59
|
+
download_url = "#{Nsrr::WEBSITE}/datasets/#{@dataset_slug}/files#{auth_section}/m/nsrr-gem-v#{Nsrr::VERSION::STRING.gsub('.', '-')}/#{@full_path.to_s}"
|
57
60
|
download_request = Nsrr::Helpers::DownloadRequest.new(download_url, download_folder)
|
58
61
|
download_request.get
|
59
|
-
|
60
62
|
download_success = false
|
61
|
-
|
62
63
|
if download_request.error.to_s == ''
|
63
64
|
# Check to see if the file downloaded correctly
|
64
65
|
# If the file size doesn't match, attempt one additional download
|
65
66
|
download_success = did_download_succeed?(method, path)
|
66
|
-
|
67
67
|
unless download_success
|
68
68
|
download_request = Nsrr::Helpers::DownloadRequest.new(download_url, download_folder)
|
69
69
|
download_request.get
|
70
|
-
|
71
70
|
download_success = did_download_succeed?(method, path)
|
72
71
|
end
|
73
72
|
end
|
74
|
-
|
75
73
|
if download_request.error.to_s == '' and download_success
|
76
|
-
puts " downloaded".colorize(:green) + " #{@
|
74
|
+
puts " downloaded".colorize(:green) + " #{@file_name}"
|
77
75
|
download_request.file_size
|
78
76
|
elsif download_request.error.to_s == ''
|
79
|
-
puts " failed".colorize(:red) + " #{@
|
77
|
+
puts " failed".colorize(:red) + " #{@file_name}"
|
80
78
|
if method == 'fast'
|
81
|
-
puts " File size mismatch, expected: #{@
|
79
|
+
puts " File size mismatch, expected: #{@file_size}"
|
82
80
|
puts " actual: #{@latest_file_size}"
|
83
81
|
else
|
84
|
-
puts " File checksum mismatch, expected: #{@
|
82
|
+
puts " File checksum mismatch, expected: #{@file_checksum_md5}"
|
85
83
|
puts " actual: #{@latest_checksum}"
|
86
84
|
end
|
87
85
|
::File.delete(download_folder) if ::File.exist?(download_folder)
|
88
86
|
'fail'
|
89
87
|
else
|
90
|
-
puts
|
88
|
+
puts ' failed'.colorize(:red) + " #{@file_name}"
|
91
89
|
puts " #{download_request.error}"
|
92
90
|
'fail'
|
93
91
|
end
|
94
92
|
end
|
95
93
|
|
96
94
|
def skip
|
97
|
-
puts
|
95
|
+
puts ' identical'.colorize(:light_blue) + " #{file_name}"
|
98
96
|
'skip'
|
99
97
|
end
|
100
98
|
|
101
99
|
def md5_matches?(path)
|
102
|
-
@
|
100
|
+
@file_checksum_md5 == local_checksum(path)
|
103
101
|
end
|
104
102
|
|
105
103
|
def local_checksum(path)
|
106
|
-
download_folder = ::File.join(Dir.pwd, path.to_s,
|
104
|
+
download_folder = ::File.join(Dir.pwd, path.to_s, file_name.to_s)
|
107
105
|
@latest_checksum = if ::File.exist?(download_folder)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
106
|
+
Digest::MD5.file(download_folder).hexdigest
|
107
|
+
else
|
108
|
+
''
|
109
|
+
end
|
112
110
|
@latest_checksum
|
113
111
|
end
|
114
112
|
|
115
113
|
def file_size_matches?(path)
|
116
|
-
@
|
114
|
+
@file_size == local_filesize(path)
|
117
115
|
end
|
118
116
|
|
119
117
|
def local_filesize(path)
|
120
|
-
download_folder = ::File.join(Dir.pwd, path.to_s,
|
118
|
+
download_folder = ::File.join(Dir.pwd, path.to_s, file_name.to_s)
|
121
119
|
@latest_file_size = if ::File.exist?(download_folder)
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
120
|
+
::File.size(download_folder)
|
121
|
+
else
|
122
|
+
-1
|
123
|
+
end
|
126
124
|
@latest_file_size
|
127
125
|
end
|
128
126
|
|
@@ -133,8 +131,6 @@ module Nsrr
|
|
133
131
|
md5_matches?(path)
|
134
132
|
end
|
135
133
|
end
|
136
|
-
|
137
134
|
end
|
138
135
|
end
|
139
136
|
end
|
140
|
-
|
data/lib/nsrr/version.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Nsrr
|
2
4
|
module VERSION #:nodoc:
|
3
5
|
MAJOR = 0
|
4
|
-
MINOR =
|
6
|
+
MINOR = 3
|
5
7
|
TINY = 0
|
6
|
-
BUILD =
|
8
|
+
BUILD = 'beta1' # 'pre', 'beta1', 'beta2', 'rc', 'rc2', nil
|
7
9
|
|
8
10
|
STRING = [MAJOR, MINOR, TINY, BUILD].compact.join('.')
|
9
11
|
end
|
data/nsrr.gemspec
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
# Compiling the Gem
|
4
5
|
# gem build nsrr.gemspec
|
@@ -12,24 +13,22 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
12
13
|
require 'nsrr/version'
|
13
14
|
|
14
15
|
Gem::Specification.new do |spec|
|
15
|
-
spec.name =
|
16
|
+
spec.name = 'nsrr'
|
16
17
|
spec.version = Nsrr::VERSION::STRING
|
17
|
-
spec.authors = [
|
18
|
-
spec.email = [
|
19
|
-
spec.summary =
|
20
|
-
spec.description =
|
21
|
-
spec.homepage =
|
22
|
-
spec.license =
|
18
|
+
spec.authors = ['Remo Mueller']
|
19
|
+
spec.email = ['remosm@gmail.com']
|
20
|
+
spec.summary = 'The official ruby gem to simplify file downloads and dataset integration tasks for the NSRR website, https://sleepdata.org'
|
21
|
+
spec.description = 'The official ruby gem to simplify file downloads and dataset integration tasks for the NSRR website, https://sleepdata.org'
|
22
|
+
spec.homepage = 'https://github.com/nsrr/nsrr-gem'
|
23
|
+
spec.license = 'CC BY-NC-SA 3.0'
|
23
24
|
|
24
25
|
spec.files = Dir['{bin,lib}/**/*'] + ['CHANGELOG.md', 'LICENSE', 'Rakefile', 'README.md', 'nsrr.gemspec']
|
25
26
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
26
27
|
spec.test_files = spec.files.grep(%r{^(test)/})
|
27
|
-
spec.require_paths = [
|
28
|
+
spec.require_paths = ['lib']
|
28
29
|
|
29
|
-
spec.add_dependency
|
30
|
-
spec.add_dependency
|
31
|
-
spec.add_dependency
|
32
|
-
spec.add_dependency
|
33
|
-
|
34
|
-
spec.add_development_dependency "bundler", "~> 1.6"
|
30
|
+
spec.add_dependency 'bundler', '~> 1.11'
|
31
|
+
spec.add_dependency 'rake'
|
32
|
+
spec.add_dependency 'minitest'
|
33
|
+
spec.add_dependency 'colorize', '~> 0.7.7'
|
35
34
|
end
|
metadata
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nsrr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Remo Mueller
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.11'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.11'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: minitest
|
42
|
+
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -58,28 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.7.
|
61
|
+
version: 0.7.7
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.7.
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: bundler
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '1.6'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '1.6'
|
68
|
+
version: 0.7.7
|
83
69
|
description: The official ruby gem to simplify file downloads and dataset integration
|
84
70
|
tasks for the NSRR website, https://sleepdata.org
|
85
71
|
email:
|
@@ -123,12 +109,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
123
109
|
version: '0'
|
124
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
111
|
requirements:
|
126
|
-
- - "
|
112
|
+
- - ">"
|
127
113
|
- !ruby/object:Gem::Version
|
128
|
-
version:
|
114
|
+
version: 1.3.1
|
129
115
|
requirements: []
|
130
116
|
rubyforge_project:
|
131
|
-
rubygems_version: 2.4.
|
117
|
+
rubygems_version: 2.4.8
|
132
118
|
signing_key:
|
133
119
|
specification_version: 4
|
134
120
|
summary: The official ruby gem to simplify file downloads and dataset integration
|