nsrr 0.2.0 → 0.3.0.beta1
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 +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
|