quandl 0.3.7 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|