quandl 0.3.7 → 0.4.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 +8 -8
- data/Rakefile +0 -4
- data/UPGRADE.md +8 -0
- data/VERSION +1 -1
- data/dist/resources/pkg/Distribution.erb +1 -1
- data/dist/resources/pkg/{postinstall → postinstall.erb} +3 -1
- data/dist/resources/pkg/quandl +2 -2
- data/dist/resources/windows/quandl +25 -0
- data/lib/quandl/command.rb +1 -1
- data/lib/quandl/command/config.rb +4 -0
- data/lib/quandl/command/task/configurable.rb +1 -1
- data/lib/quandl/command/task/dependable.rb +1 -0
- data/lib/quandl/command/task/updatable.rb +5 -5
- data/lib/quandl/command/tasks/schedule.rb +59 -51
- data/lib/quandl/command/tasks/update.rb +159 -105
- data/quandl.gemspec +4 -4
- data/scripts/win/quandl_toolbelt.iss +10 -5
- data/spec/factories/dataset.rb +10 -0
- data/spec/factories/source.rb +10 -0
- data/spec/fixtures/{scraper.rb → scraper-test-file.rb} +0 -0
- data/spec/lib/quandl/command/delete_spec.rb +7 -1
- data/spec/lib/quandl/command/replace_spec.rb +1 -1
- data/spec/lib/quandl/command/schedule_spec.rb +33 -2
- data/spec/lib/quandl/command/superset_spec.rb +2 -2
- data/spec/lib/quandl/command/upload_spec.rb +3 -3
- data/spec/lib/quandl/command_spec.rb +3 -3
- data/spec/spec_helper.rb +14 -3
- data/tasks/toolbelt.rake +27 -18
- data/tasks/toolbelt.rb +26 -2
- data/tasks/toolbelt/build/darwin.rb +59 -12
- data/tasks/toolbelt/build/tarball.rb +9 -3
- metadata +18 -13
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MWZhODVmN2E1YzI4MTVhNDdlZDBjNmExOWUzNDYzMDM3M2IwNTNhMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZTNhZmQ0OGI3MmNiNzQyZTQxYTA5YzYzMjQzMzcyN2QxNDVmMWNiOA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MDI5MjJhNDQwZjU5YTE1MmU0YTJjN2FiNDAwYWFkNmY2YTA2NTk3YzQ4ZTM5
|
10
|
+
OTIyYzAzZjhmNjYyNjJiYWNiYzBjOTgwMzA2OTkzZGIxMzkwOGVhODU0MGY1
|
11
|
+
MmEzNmZmZGZjZjJhZTA1ZmFhZGU2MjhhZTcwYzM1YmUwMDhkMDc=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MDM2MDRhOTRlMTkzN2I4ZTJlZGI0MGEwNGExMjVmNGE5MzdkMzYzOWRmN2Uy
|
14
|
+
Zjk1MDRlOTJkNmZjZTVjYmJmODRiNTE5MzczNDhlMGE4OTExMjI1NTQ0OGI4
|
15
|
+
ODBiMzA4ZjNjOTFjOWEzNTllMTU1ZTc2YzVhZDU0Zjc2YzRhMDY=
|
data/Rakefile
CHANGED
data/UPGRADE.md
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
2
2
|
<installer-script minSpecVersion="1.000000" authoringTool="org.ruby-lang.rake" authoringToolVersion="10.1.1">
|
3
|
-
<title>Quandl Toolbelt <%= version %></title>
|
3
|
+
<title>Quandl Toolbelt <%= version %> <%= prerelease_information %></title>
|
4
4
|
<options customize="allow" allow-external-scripts="no"/>
|
5
5
|
<domains enable_localSystem="true"/>
|
6
6
|
<choices-outline>
|
@@ -42,4 +42,6 @@ case $(which quandl) in
|
|
42
42
|
esac
|
43
43
|
|
44
44
|
# symlink binary to /usr/bin/quandl
|
45
|
-
ln -sf /usr/local/quandl/
|
45
|
+
ln -sf /usr/local/quandl/releases/<%= timestamp %> /usr/local/quandl/current
|
46
|
+
chown -h $USER /usr/local/quandl/current
|
47
|
+
ln -sf /usr/local/quandl/bin/quandl /usr/bin/quandl
|
data/dist/resources/pkg/quandl
CHANGED
@@ -5,7 +5,7 @@ require "pathname"
|
|
5
5
|
bin_file = Pathname.new(__FILE__).realpath
|
6
6
|
|
7
7
|
# vendored gems path
|
8
|
-
gem_dir = File.expand_path("../../vendor/gems", bin_file)
|
8
|
+
gem_dir = File.expand_path("../../current/vendor/gems", bin_file)
|
9
9
|
# vendored gems?
|
10
10
|
if Dir.exists?(gem_dir)
|
11
11
|
Dir["#{gem_dir}/**/lib"].each do |libdir|
|
@@ -16,7 +16,7 @@ else
|
|
16
16
|
end
|
17
17
|
|
18
18
|
# add self to libpath
|
19
|
-
$:.unshift File.expand_path("../../lib", bin_file)
|
19
|
+
$:.unshift File.expand_path("../../current/lib", bin_file)
|
20
20
|
|
21
21
|
require 'quandl/command'
|
22
22
|
require 'commander/import'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require "pathname"
|
5
|
+
bin_file = Pathname.new(__FILE__).realpath
|
6
|
+
|
7
|
+
# vendored gems path
|
8
|
+
gem_dir = File.expand_path("../../current/vendor/gems", bin_file)
|
9
|
+
# vendored gems?
|
10
|
+
if Dir.exists?(gem_dir)
|
11
|
+
Dir["#{gem_dir}/**/lib"].each do |libdir|
|
12
|
+
$:.unshift libdir
|
13
|
+
end
|
14
|
+
else
|
15
|
+
require 'rubygems'
|
16
|
+
end
|
17
|
+
|
18
|
+
# add self to libpath
|
19
|
+
$:.unshift File.expand_path("../../current/lib", bin_file)
|
20
|
+
|
21
|
+
require 'quandl/command'
|
22
|
+
require 'commander/import'
|
23
|
+
require 'commander/command/quandl_ext'
|
24
|
+
|
25
|
+
include Quandl::Command
|
data/lib/quandl/command.rb
CHANGED
@@ -38,7 +38,7 @@ module Quandl::Command
|
|
38
38
|
global_option '--stdout STRING', 'where to redirect stdout'
|
39
39
|
global_option '--stderr STRING', 'where to redirect stderr'
|
40
40
|
global_option '--force-yes', 'force y/n with yes'
|
41
|
-
global_option '--
|
41
|
+
global_option '--sandbox', 'sandbox specific default options'
|
42
42
|
|
43
43
|
Tasks.each{|t| t.configure(self) }
|
44
44
|
|
@@ -6,7 +6,7 @@ module Updatable
|
|
6
6
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
|
-
VERSION_URL="https://
|
9
|
+
VERSION_URL="https://s3.amazonaws.com/quandl-command/VERSION"
|
10
10
|
|
11
11
|
included do
|
12
12
|
before_execute :check_for_update_once_daily
|
@@ -14,7 +14,7 @@ module Updatable
|
|
14
14
|
|
15
15
|
def check_for_update_once_daily
|
16
16
|
# short circuit
|
17
|
-
return if options.
|
17
|
+
return if options.sandbox
|
18
18
|
# onwards
|
19
19
|
check_time = config.last_checked_for_update
|
20
20
|
# check time present?
|
@@ -38,8 +38,8 @@ module Updatable
|
|
38
38
|
# handle output
|
39
39
|
handle_update_response(response)
|
40
40
|
rescue => err
|
41
|
-
|
42
|
-
|
41
|
+
info("An unexpected error occured while checking for updates ... #{err}")
|
42
|
+
info err.backtrace.join("\n") if trace?
|
43
43
|
ensure
|
44
44
|
config.last_checked_for_update = Time.now
|
45
45
|
end
|
@@ -64,7 +64,7 @@ module Updatable
|
|
64
64
|
# send request
|
65
65
|
response = http.request(request)
|
66
66
|
# fetch version number
|
67
|
-
response.body.
|
67
|
+
response.body.strip.rstrip
|
68
68
|
end
|
69
69
|
|
70
70
|
def handle_update_response(response)
|
@@ -1,34 +1,30 @@
|
|
1
1
|
class Quandl::Command::Tasks::Schedule < Quandl::Command::Task
|
2
2
|
|
3
|
-
depends 'chronic', 'whedon', 'open-uri'
|
3
|
+
depends 'chronic', 'whedon', 'open-uri', 'zlib', 'archive/tar/minitar'
|
4
4
|
|
5
5
|
autoload_quandl_client
|
6
6
|
authenticated_users_only!
|
7
7
|
|
8
8
|
description "Schedule a script to be run in the quandl cloud."
|
9
|
-
syntax %{quandl schedule command [file]
|
9
|
+
syntax %{quandl schedule command [file(s)]
|
10
10
|
|
11
11
|
COMMANDS:
|
12
12
|
|
13
|
-
schedule list [
|
14
|
-
schedule add
|
15
|
-
schedule delete
|
16
|
-
|
17
|
-
|
13
|
+
schedule list [FILE]
|
14
|
+
schedule add RUN_FILE [DEPENDENT_FILE1] [DEPENDENT_FILE2] [--at TIME]
|
15
|
+
schedule delete FILE
|
16
|
+
|
18
17
|
EXAMPLES:
|
19
18
|
|
20
19
|
$ quandl schedule add scraper.rb
|
21
20
|
You have successfully scheduled scraper.rb.
|
22
21
|
|
23
|
-
$ quandl schedule add scraper.rb
|
24
|
-
You have successfully scheduled scraper.rb. [weekly scraper]
|
25
|
-
|
26
|
-
|
27
|
-
You have successfully replaced scraper.rb. [daily scraper]}
|
28
|
-
|
22
|
+
$ quandl schedule add scraper.rb helper.txt helper2.txt --at "7pm Monday"
|
23
|
+
You have successfully scheduled scraper.rb to run alongside helper.txt, helper2.txt. [weekly scraper]
|
24
|
+
}
|
25
|
+
|
29
26
|
options({
|
30
27
|
String => {
|
31
|
-
:'remote-name' => "The name used to reference your scraper in the quandl cloud.",
|
32
28
|
at: "Time to run your script in UTC timezone. e.g. '14:30','7pm Monday', 'friday 13:00'"
|
33
29
|
}
|
34
30
|
})
|
@@ -41,7 +37,7 @@ class Quandl::Command::Tasks::Schedule < Quandl::Command::Task
|
|
41
37
|
# fire a subcommand if specified
|
42
38
|
return self.send(args.shift) if args.first.present? && self.respond_to?(args.first)
|
43
39
|
# otherwise fire add
|
44
|
-
return add if args.first.present?
|
40
|
+
return add if args.first.present? && args.first.downcase != "help"
|
45
41
|
# otherwise display syntax
|
46
42
|
info(syntax)
|
47
43
|
end
|
@@ -56,18 +52,24 @@ class Quandl::Command::Tasks::Schedule < Quandl::Command::Task
|
|
56
52
|
end
|
57
53
|
|
58
54
|
def add
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
55
|
+
upload_file = Tempfile.new('temp')
|
56
|
+
begin
|
57
|
+
result=Quandl::Client::Scraper.create( name: name, scraper: file_to_send(args, upload_file), schedule_at: cron_at_utc)
|
58
|
+
if result.valid?
|
59
|
+
info("You have successfully scheduled '#{scraper.name}'.")
|
60
|
+
info("#{schedule_message}")
|
61
|
+
else
|
62
|
+
error "#{Quandl::Command::Presenter.pretty_errors(result.errors.messages).to_s.gsub("\n", ' ')}"
|
63
|
+
end
|
64
|
+
ensure
|
65
|
+
upload_file.close!
|
65
66
|
end
|
66
67
|
end
|
67
68
|
|
68
69
|
def download
|
69
70
|
begin
|
70
|
-
$stdout
|
71
|
+
$stdout.binmode
|
72
|
+
$stdout << open(scraper.scraper_url, "rb", {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
|
71
73
|
rescue => err
|
72
74
|
present err
|
73
75
|
end
|
@@ -87,44 +89,41 @@ class Quandl::Command::Tasks::Schedule < Quandl::Command::Task
|
|
87
89
|
end
|
88
90
|
|
89
91
|
|
92
|
+
#not supported for now
|
93
|
+
=begin
|
90
94
|
def replace
|
91
|
-
(
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
95
|
+
upload_file = Tempfile.new('temp')
|
96
|
+
begin
|
97
|
+
(info("'#{name}' does not exist "); return;) if scraper.blank?
|
98
|
+
info("You are about to replace '#{scraper.name}'")
|
99
|
+
return unless confirmed?
|
100
|
+
scraper.scraper = file_to_send(args, upload_file)
|
101
|
+
scraper.schedule_at = cron_at_utc
|
102
|
+
scraper.save
|
103
|
+
if scraper.valid?
|
104
|
+
info("You have successfully replaced '#{scraper.name}'.")
|
105
|
+
info("#{schedule_message}") if cron_at
|
106
|
+
else
|
107
|
+
error "#{Quandl::Command::Presenter.pretty_errors(scraper.errors.messages).to_s.gsub("\n", ' ')}"
|
108
|
+
end
|
109
|
+
ensure
|
110
|
+
upload_file.close!
|
102
111
|
end
|
103
112
|
end
|
113
|
+
=end
|
104
114
|
|
105
115
|
private
|
106
116
|
|
107
117
|
def script_info(script)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
|
116
|
-
def script_run_time(cron_time)
|
117
|
-
"every #{cron_time.ends_with?('*') ? 'day' : DAYS_OF_THE_WEEK[cron_time[-1].to_i]} at #{script_next_run(cron_time).strftime("%H:%M (UTC)")}"
|
118
|
-
end
|
119
|
-
|
120
|
-
def script_next_run(cron_time)
|
121
|
-
Whedon::Schedule.new(cron_time).next
|
118
|
+
message = script.name.to_s.ljust(20)
|
119
|
+
message += " Scheduled: #{script.schedule_run_time.to_s.ljust(30)}"
|
120
|
+
message += " Next: in #{script.schedule_next}" if script.schedule_next.present?
|
121
|
+
info message
|
122
122
|
end
|
123
123
|
|
124
|
-
|
125
124
|
def schedule_message
|
126
125
|
if options.at
|
127
|
-
"Your script first run will happen #{
|
126
|
+
"Your script first run will happen in #{scraper.schedule_next}. It will continue to run #{scraper.schedule_run_time}
|
128
127
|
Check your scrapers run status at #{quandl_url.gsub(/\/api\/?/,'')}/scrapers"
|
129
128
|
else
|
130
129
|
"It will run 3 times a day starting immediately.\nCheck your scrapers run status at #{quandl_url.gsub(/\/api\/?/,'')}/scrapers"
|
@@ -159,11 +158,10 @@ Check your scrapers run status at #{quandl_url.gsub(/\/api\/?/,'')}/scrapers"
|
|
159
158
|
|
160
159
|
def time_to_cron(time_value)
|
161
160
|
day_of_the_week = options.at =~ (/Mon|Tue|Wed|Thu|Fri|Sat|Sun/i) ? time_value.wday : '*'
|
162
|
-
"#{time_value.min} #{time_value.hour} * * #{day_of_the_week}"
|
161
|
+
"* #{time_value.min} #{time_value.hour} * * #{day_of_the_week}"
|
163
162
|
end
|
164
163
|
|
165
164
|
def name
|
166
|
-
return options.remote_name if options.remote_name.present?
|
167
165
|
return File.basename(args.first) if args.first.present?
|
168
166
|
end
|
169
167
|
|
@@ -175,5 +173,15 @@ Check your scrapers run status at #{quandl_url.gsub(/\/api\/?/,'')}/scrapers"
|
|
175
173
|
true
|
176
174
|
end
|
177
175
|
|
176
|
+
def file_to_send(values, upload_file)
|
177
|
+
if [*values].count > 1
|
178
|
+
file = upload_file
|
179
|
+
Archive::Tar::Minitar.pack( values, Zlib::GzipWriter.new( File.new( file, 'wb' ) ) )
|
180
|
+
else
|
181
|
+
file = [*values].first
|
182
|
+
end
|
183
|
+
file
|
184
|
+
end
|
185
|
+
|
178
186
|
|
179
187
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
class Quandl::Command::Tasks::Update < Quandl::Command::Task
|
2
2
|
|
3
3
|
depends 'uri', 'net/http', 'quandl/utility/config', 'zlib', 'archive/tar/minitar'
|
4
|
-
|
5
|
-
# curl -s https://s3.amazonaws.com/quandl-command/install.sh | bash
|
6
4
|
|
7
5
|
description "Update Quandl Toolbelt to the latest version."
|
8
6
|
syntax %Q{quandl update [revision]
|
@@ -10,12 +8,12 @@ class Quandl::Command::Tasks::Update < Quandl::Command::Task
|
|
10
8
|
EXAMPLES:
|
11
9
|
|
12
10
|
$ quandl update
|
13
|
-
Updating from
|
14
|
-
You are up to date! (
|
11
|
+
Updating from a.b.c ...
|
12
|
+
You are up to date! ( x.y.z )
|
15
13
|
|
16
|
-
$ quandl update
|
17
|
-
Updating from
|
18
|
-
You are up to date! (
|
14
|
+
$ quandl update prerelease
|
15
|
+
Updating from x.y.z ...
|
16
|
+
You are up to date! ( x.y.z-prerelease )}
|
19
17
|
|
20
18
|
PACKAGE_URL = 'http://s3.amazonaws.com/quandl-command/'
|
21
19
|
|
@@ -33,6 +31,22 @@ class Quandl::Command::Tasks::Update < Quandl::Command::Task
|
|
33
31
|
end
|
34
32
|
|
35
33
|
def execute
|
34
|
+
if args[0] == 'rollback'
|
35
|
+
execute_rollback
|
36
|
+
else
|
37
|
+
execute_update
|
38
|
+
end
|
39
|
+
rescue => err
|
40
|
+
# log error
|
41
|
+
error(err)
|
42
|
+
debug(err.backtrace.join("\n"))
|
43
|
+
# report failure and rollback
|
44
|
+
error("----\nAn error has occured! Rolling back to previous version ... ")
|
45
|
+
error("If the problem persists reinstall with: #{installer_url}")
|
46
|
+
rollback_update
|
47
|
+
end
|
48
|
+
|
49
|
+
def execute_update
|
36
50
|
info "Updating from #{Quandl::Command::VERSION} ... "
|
37
51
|
# wipe update/ and backup/ folders
|
38
52
|
prepare_for_update
|
@@ -41,22 +55,26 @@ class Quandl::Command::Tasks::Update < Quandl::Command::Task
|
|
41
55
|
return error("'#{package_url}' not found") unless File.exists?(tarball_path)
|
42
56
|
# install
|
43
57
|
extract_tarball
|
44
|
-
copy_windows_specific_files if Quandl::Utility::Config.windows?
|
45
58
|
install_update
|
46
|
-
|
47
|
-
ensure_correct_permissions
|
59
|
+
install_executable
|
48
60
|
# success
|
49
61
|
version = %x{quandl -v}.to_s.strip.rstrip
|
50
|
-
|
62
|
+
cleanup_releases
|
51
63
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
64
|
+
info "You are up to date! ( #{version} )"
|
65
|
+
end
|
66
|
+
|
67
|
+
def execute_rollback
|
68
|
+
info "Rolling back from #{current_timestamp} ... "
|
69
|
+
previous_timestamp = find_timestamp_before(current_timestamp)
|
70
|
+
if previous_timestamp.blank?
|
71
|
+
info("nothing to rollback to!")
|
72
|
+
return false
|
73
|
+
end
|
74
|
+
info "to: #{previous_timestamp}"
|
75
|
+
install_timestamp( previous_timestamp )
|
76
|
+
version = %x{quandl -v}.to_s.strip.rstrip
|
77
|
+
info "You have rolled back! ( #{version} )"
|
60
78
|
end
|
61
79
|
|
62
80
|
def installer_url
|
@@ -64,40 +82,12 @@ class Quandl::Command::Tasks::Update < Quandl::Command::Task
|
|
64
82
|
return File.join(PACKAGE_URL, "quandl-toolbelt.pkg") if Quandl::Utility::Config.macosx?
|
65
83
|
end
|
66
84
|
|
67
|
-
|
68
|
-
@package_path ||= File.join(update_path, "quandl-command")
|
69
|
-
end
|
70
|
-
|
71
|
-
def tarball_path
|
72
|
-
@tarball_path ||= File.join(update_path, "update.tar.gz")
|
73
|
-
end
|
74
|
-
|
75
|
-
def package_url
|
76
|
-
@package_url ||= self.class.package_url(args.first)
|
77
|
-
end
|
78
|
-
|
79
|
-
def update_path
|
80
|
-
@update_path ||= File.join( root_path, 'update' )
|
81
|
-
end
|
82
|
-
|
83
|
-
def backup_path
|
84
|
-
@backup_path ||= File.join( root_path, 'backup' )
|
85
|
-
end
|
86
|
-
|
87
|
-
def root_path
|
88
|
-
Quandl::Command::Tasks.root
|
89
|
-
end
|
85
|
+
private
|
90
86
|
|
87
|
+
delegate :chmod, :cp, :ln_sf, :mv, :rm_rf, :rm, :mkdir_p, :cp_r, to: :qu
|
91
88
|
|
92
|
-
private
|
93
|
-
|
94
89
|
def prepare_for_update
|
95
|
-
|
96
|
-
# remove previous directory if present
|
97
|
-
rm_rf(path) if Dir.exists?(path)
|
98
|
-
# create new directory
|
99
|
-
mkdir_p(path) unless Dir.exists?(path)
|
100
|
-
end
|
90
|
+
FileUtils.mkdir_p(releases_path) unless Dir.exists?(releases_path)
|
101
91
|
end
|
102
92
|
|
103
93
|
def download_tarball
|
@@ -114,82 +104,146 @@ class Quandl::Command::Tasks::Update < Quandl::Command::Task
|
|
114
104
|
end
|
115
105
|
|
116
106
|
def extract_tarball
|
117
|
-
debug "Archive::Tar::Minitar.unpack( '#{tarball_path}', '#{
|
118
|
-
# extract into
|
119
|
-
Archive::Tar::Minitar.unpack( Zlib::GzipReader.open(tarball_path),
|
107
|
+
debug "Archive::Tar::Minitar.unpack( '#{tarball_path}', '#{releases_path}' )"
|
108
|
+
# extract into releases_path
|
109
|
+
Archive::Tar::Minitar.unpack( Zlib::GzipReader.open(tarball_path), releases_path )
|
110
|
+
# rename quandl-command to release name
|
111
|
+
mv( package_path, timestamp_path )
|
120
112
|
end
|
121
113
|
|
122
|
-
def
|
123
|
-
|
124
|
-
files.each do |file|
|
125
|
-
source_path = File.join(root_path, file)
|
126
|
-
cp source_path, File.join(package_path, file) if File.exists?(source_path)
|
127
|
-
end
|
114
|
+
def install_update
|
115
|
+
install_timestamp(new_timestamp)
|
128
116
|
end
|
129
117
|
|
130
|
-
def
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
118
|
+
def rollback_update
|
119
|
+
# remove the failed release
|
120
|
+
rm_rf(timestamp_path) if Dir.exists?(timestamp_path)
|
121
|
+
# install previous release
|
122
|
+
install_timestamp(current_timestamp)
|
123
|
+
end
|
124
|
+
|
125
|
+
def install_executable
|
126
|
+
new_executable = File.join(timestamp_path, 'pkg', 'quandl')
|
127
|
+
return unless File.exists?(new_executable)
|
128
|
+
rm executable_path if File.exists?(executable_path)
|
129
|
+
cp new_executable, executable_path
|
130
|
+
end
|
131
|
+
|
132
|
+
def install_timestamp(stamp)
|
133
|
+
# remove previous
|
134
|
+
rm_rf(current_path) if File.exists?(current_path)
|
135
|
+
# install timestamp
|
136
|
+
path = File.join( releases_path, stamp.to_s )
|
137
|
+
# copy or link
|
138
|
+
if Quandl::Utility::Config.windows?
|
139
|
+
cp_r(path, current_path)
|
140
|
+
|
141
|
+
else
|
142
|
+
ln_sf(path, current_path)
|
143
|
+
|
142
144
|
end
|
145
|
+
update_current_timestamp(stamp)
|
143
146
|
end
|
144
147
|
|
145
|
-
def
|
146
|
-
|
147
|
-
bin_file = File.read("#{root_path}/bin/quandl")
|
148
|
-
bin_file.gsub!("#!/usr/bin/env ruby", "#!/#{root_path}/ruby/bin/ruby")
|
149
|
-
File.write("#{root_path}/bin/quandl", bin_file)
|
150
|
-
end
|
148
|
+
def update_current_timestamp(stamp)
|
149
|
+
File.open( timestamp_release_path, 'wb' ){|f| f.write(stamp.to_s) }
|
151
150
|
end
|
152
151
|
|
153
|
-
def
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
152
|
+
def delete_timestamp(stamp)
|
153
|
+
path = File.join(releases_path, stamp.to_s)
|
154
|
+
rm_rf(path) if Dir.exists?(path)
|
155
|
+
end
|
156
|
+
|
157
|
+
def cleanup_releases
|
158
|
+
return unless release_timestamps.count > 5
|
159
|
+
release_timestamps.reverse[5..-1].each{|stamp| delete_timestamp(stamp) }
|
160
|
+
end
|
161
|
+
|
162
|
+
def executable_path
|
163
|
+
@executable_path ||= File.join(root_path, 'bin', 'quandl')
|
164
164
|
end
|
165
165
|
|
166
|
-
def
|
167
|
-
|
166
|
+
def timestamp_release_path
|
167
|
+
@timestamp_release_path ||= File.join(root_path, '.timestamp')
|
168
168
|
end
|
169
169
|
|
170
|
-
def
|
171
|
-
|
172
|
-
|
170
|
+
def timestamp_path
|
171
|
+
@timestamp_path ||= File.join( releases_path, new_timestamp )
|
172
|
+
end
|
173
|
+
|
174
|
+
def tarball_path
|
175
|
+
@tarball_path ||= File.join(releases_path, "update.tar.gz")
|
176
|
+
end
|
177
|
+
|
178
|
+
def package_path
|
179
|
+
@package_path ||= File.join(releases_path, "quandl-command")
|
180
|
+
end
|
181
|
+
|
182
|
+
def releases_path
|
183
|
+
@releases_path ||= File.expand_path(File.join( root_path, 'releases' ))
|
184
|
+
end
|
185
|
+
|
186
|
+
def package_url
|
187
|
+
@package_url ||= self.class.package_url(args.first)
|
188
|
+
end
|
189
|
+
|
190
|
+
def current_path
|
191
|
+
@current_path ||= File.join(root_path, 'current')
|
192
|
+
end
|
193
|
+
|
194
|
+
def root_path
|
195
|
+
return @root_path if defined?(@root_path)
|
196
|
+
parent_root = File.expand_path(File.join(Quandl::Command::Tasks.root, '../'))
|
197
|
+
if Dir.exists?(File.join(parent_root, 'releases')) && Dir.exists?(File.join(parent_root, 'bin'))
|
198
|
+
@root_path = parent_root
|
199
|
+
else
|
200
|
+
@root_path = Quandl::Command::Tasks.root
|
201
|
+
end
|
202
|
+
@root_path
|
173
203
|
end
|
174
204
|
|
175
|
-
def
|
176
|
-
|
177
|
-
|
205
|
+
def new_timestamp
|
206
|
+
@new_timestamp ||= (Time.now.getutc.to_f * 10000).to_i.to_s.gsub('.','')
|
207
|
+
end
|
208
|
+
|
209
|
+
def find_timestamp_before(stamp)
|
210
|
+
release_timestamps.sort.each do |rstamp|
|
211
|
+
return rstamp if rstamp.to_i < stamp.to_i
|
212
|
+
end
|
213
|
+
nil
|
214
|
+
end
|
215
|
+
|
216
|
+
def current_timestamp
|
217
|
+
# largest to smallest
|
218
|
+
@current_timestamp ||= File.read(timestamp_release_path).strip.rstrip.to_i if File.exists?(timestamp_release_path)
|
219
|
+
@current_timestamp ||= release_timestamps.sort.reverse.detect{|t| t < new_timestamp.to_i }
|
178
220
|
end
|
179
221
|
|
180
|
-
def
|
181
|
-
|
182
|
-
FileUtils.mv( old_path, new_path )
|
222
|
+
def release_timestamps
|
223
|
+
@release_timestamps ||= Dir["#{releases_path}/*"].select{|f| File.directory?(f) }.collect{|f| File.basename(f).to_i }
|
183
224
|
end
|
184
225
|
|
185
|
-
def
|
186
|
-
|
187
|
-
FileUtils.rm_rf(*args)
|
226
|
+
def qu
|
227
|
+
@qu ||= QuandlUtils.new(self)
|
188
228
|
end
|
189
229
|
|
190
|
-
|
191
|
-
|
192
|
-
|
230
|
+
class QuandlUtils
|
231
|
+
attr_accessor :task
|
232
|
+
|
233
|
+
def initialize(task=nil)
|
234
|
+
self.task = task
|
235
|
+
end
|
236
|
+
|
237
|
+
def method_missing(method_name, *args, &block)
|
238
|
+
fu(method_name, *args, &block)
|
239
|
+
end
|
240
|
+
|
241
|
+
private
|
242
|
+
|
243
|
+
def fu(method_name, *args, &block)
|
244
|
+
task.debug("#{method_name} #{args}") unless task.nil?
|
245
|
+
FileUtils.send(method_name, *args, &block)
|
246
|
+
end
|
193
247
|
end
|
194
248
|
|
195
249
|
end
|