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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZDJmODE5YjMxZDJlNjFiNTZiN2I0NmVhMGYzMTIwZjU2YWFjZDIyYQ==
4
+ MWZhODVmN2E1YzI4MTVhNDdlZDBjNmExOWUzNDYzMDM3M2IwNTNhMw==
5
5
  data.tar.gz: !binary |-
6
- NDEwZmVhNGQ2YWE1YmYwYzM5ODZhY2I5MDI4N2Y5YjU1MmMyOWU0Mw==
6
+ ZTNhZmQ0OGI3MmNiNzQyZTQxYTA5YzYzMjQzMzcyN2QxNDVmMWNiOA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZDE4YjcyM2Y0MTExMDE1MTYzZmY5ZDE1YzAzMTU1NmNhNzY0YTdiMmUwZjdj
10
- NzhiMjVjYmI4MWY5YzU5Y2U1NjE1MzRlZDU3ZDc5NmIwNDRlZTczNWQ4ODE5
11
- ODBlMDg1MzYzM2EyYmFlMzA5NmIzN2M5ZDJiZDNjOTUyZGI1YWE=
9
+ MDI5MjJhNDQwZjU5YTE1MmU0YTJjN2FiNDAwYWFkNmY2YTA2NTk3YzQ4ZTM5
10
+ OTIyYzAzZjhmNjYyNjJiYWNiYzBjOTgwMzA2OTkzZGIxMzkwOGVhODU0MGY1
11
+ MmEzNmZmZGZjZjJhZTA1ZmFhZGU2MjhhZTcwYzM1YmUwMDhkMDc=
12
12
  data.tar.gz: !binary |-
13
- YWYzYTViMWEzZjIxMTMzYzJhOWJjMDY3NDQ3NjdlYzhkMzAxMGJmZGFiNTkw
14
- MGRmM2Y3ODk4NzZlYjJiNDA0YmM4MzM5ODU2MTUwMTc0MWZiMTI0MDBiNjEw
15
- ZWZjNWNhN2UxN2ZiYzhmZWYwYjQxYTI5YzEzYjFkNTdjYTNmMTg=
13
+ MDM2MDRhOTRlMTkzN2I4ZTJlZGI0MGEwNGExMjVmNGE5MzdkMzYzOWRmN2Uy
14
+ Zjk1MDRlOTJkNmZjZTVjYmJmODRiNTE5MzczNDhlMGE4OTExMjI1NTQ0OGI4
15
+ ODBiMzA4ZjNjOTFjOWEzNTllMTU1ZTc2YzVhZDU0Zjc2YzRhMDY=
data/Rakefile CHANGED
@@ -12,10 +12,6 @@ Dir[File.expand_path("../tasks/*.rake", __FILE__)].each do |task|
12
12
  load task
13
13
  end
14
14
 
15
- task :console do |t,args|
16
- binding.pry
17
- end
18
-
19
15
  desc "Run all specs"
20
16
  RSpec::Core::RakeTask.new(:spec) do |task|
21
17
  task.pattern = "spec/**/*_spec.rb"
data/UPGRADE.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.4.0
2
+
3
+ * QUGC-166 fix quandl schedule list --token incorrect_token
4
+ * QUGC-182. OK -> Updated
5
+ * QUGC-164 fixes the issue
6
+
7
+
8
+
1
9
  ## 0.3.7
2
10
 
3
11
  * add production flag
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.7
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/bin/quandl /usr/bin/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
@@ -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
@@ -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 '--production', 'skip extra output'
41
+ global_option '--sandbox', 'sandbox specific default options'
42
42
 
43
43
  Tasks.each{|t| t.configure(self) }
44
44
 
@@ -44,6 +44,10 @@ class Config
44
44
  @auth_token = read_attribute(:token) if @auth_token.blank?
45
45
  @auth_token
46
46
  end
47
+
48
+ def request_platform
49
+ 'sandbox' if options[:sandbox].present?
50
+ end
47
51
 
48
52
  def file_path
49
53
  options[:file_path]
@@ -7,7 +7,7 @@ module Configurable
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
- delegate :auth_token, :quandl_url, to: :config
10
+ delegate :auth_token, :request_platform, :quandl_url, to: :config
11
11
  end
12
12
 
13
13
  module ClassMethods
@@ -61,6 +61,7 @@ module Dependable
61
61
  Quandl::Client.token = auth_token
62
62
  Quandl::Client.request_source = 'quandl_command'
63
63
  Quandl::Client.request_version = Quandl::Command::VERSION
64
+ Quandl::Client.request_platform = request_platform
64
65
  end
65
66
 
66
67
  end
@@ -6,7 +6,7 @@ module Updatable
6
6
 
7
7
  extend ActiveSupport::Concern
8
8
 
9
- VERSION_URL="https://raw.github.com/quandl/quandl_command/master/lib/quandl/command/version.rb"
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.production
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
- error("An unexpected error occured while checking for updates ... #{err}")
42
- error err.backtrace.join("\n") if trace?
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.split("\n").detect{|r| r =~ /VERSION/ }.split("'").last
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 [file]
14
- schedule add file [--at TIME]
15
- schedule delete file
16
- schedule replace file [--at NEW_TIME]
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 --remote-name scraper.rb --at "7pm Monday"
24
- You have successfully scheduled scraper.rb. [weekly scraper]
25
-
26
- $ quandl schedule replace scraper.rb --at "13:00"
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
- result=Quandl::Client::Scraper.create( name: name, scraper: args.first, schedule_at: cron_at_utc)
60
- if result.valid?
61
- info("You have successfully scheduled '#{scraper.name}'.")
62
- info("#{schedule_message}")
63
- else
64
- error "#{Quandl::Command::Presenter.pretty_errors(result.errors.messages).to_s.gsub("\n", ' ')}"
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 << open(scraper.scraper_url, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
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
- (info("'#{name}' does not exist "); return;) if scraper.blank?
92
- info("You are about to replace '#{scraper.name}'")
93
- return unless confirmed?
94
- scraper.scraper = args.first
95
- scraper.schedule_at = cron_at_utc
96
- scraper.save
97
- if scraper.valid?
98
- info("You have successfully replaced '#{scraper.name}'.")
99
- info("#{schedule_message}") if cron_at
100
- else
101
- error "#{Quandl::Command::Presenter.pretty_errors(scraper.errors.messages).to_s.gsub("\n", ' ')}"
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
- unless script.schedule_at.empty?
109
- info("#{(script.name+'.').ljust(20)} Scheduled: #{script_run_time(script.schedule_at)}")
110
- else
111
- info("#{(script.name+'.').ljust(20)} Scheduled: 3 times a day")
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 #{script_next_run(cron_at).strftime("on %d %B at %H:%M")}. It will continue to run #{script_run_time(cron_at_utc)}
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 0.2.18 ...
14
- You are up to date! ( 0.3.1 )
11
+ Updating from a.b.c ...
12
+ You are up to date! ( x.y.z )
15
13
 
16
- $ quandl update beta1
17
- Updating from 0.3.1 ...
18
- You are up to date! ( 0.3.1-beta1 )}
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
- configure_update
47
- ensure_correct_permissions
59
+ install_executable
48
60
  # success
49
61
  version = %x{quandl -v}.to_s.strip.rstrip
50
- info "You are up to date! ( #{version} )"
62
+ cleanup_releases
51
63
 
52
- rescue => err
53
- # log error
54
- info(err)
55
- debug(err.backtrace.join("\n"))
56
- # report failure and rollback
57
- info("----\nAn error has occured! Rolling back to previous version ... ")
58
- info("If the problem persists reinstall with: #{installer_url}")
59
- rollback_update
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
- def package_path
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
- [backup_path, update_path].each do |path|
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}', '#{update_path}' )"
118
- # extract into update_path
119
- Archive::Tar::Minitar.unpack( Zlib::GzipReader.open(tarball_path), update_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 copy_windows_specific_files
123
- files = ['bin/quandl.bat']
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 install_update
131
- debug "Installing '#{update_path}' to '#{root_path}'"
132
- # install each folder into the live directory
133
- Dir.glob(File.join(package_path, "/*")) do |update_dir|
134
- # current folder
135
- folder_name = File.basename(update_dir)
136
- # get live dir
137
- live_dir = File.join(root_path, folder_name )
138
- # move live to backup (skip this step if it doesn't exist since it might be a new folder)
139
- mv live_dir, File.join(backup_path, folder_name) if File.exists?(live_dir)
140
- # move update to live
141
- mv update_dir, live_dir
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 configure_update
146
- if Dir.exists?("#{root_path}/ruby")
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 rollback_update
154
- Dir.glob(File.join(backup_path, "/*")) do |backup_dir|
155
- # current folder
156
- folder_name = File.basename(backup_dir)
157
- # get live dir
158
- live_dir = File.join(root_path, folder_name )
159
- # move live to update
160
- mv live_dir, File.join(package_path, folder_name)
161
- # move backup to live
162
- mv backup_dir, live_dir
163
- end
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 ensure_correct_permissions
167
- chmod("+x", File.join(root_path, 'bin/quandl'))
166
+ def timestamp_release_path
167
+ @timestamp_release_path ||= File.join(root_path, '.timestamp')
168
168
  end
169
169
 
170
- def chmod(*args)
171
- debug("FileUtils.chmod #{args.to_a.join(' ')}")
172
- FileUtils.chmod(*args)
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 cp(old_path, new_path)
176
- debug("FileUtils.cp #{old_path} #{new_path}")
177
- FileUtils.cp( old_path, new_path )
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 mv(old_path, new_path)
181
- debug("FileUtils.mv #{old_path} #{new_path}")
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 rm_rf(*args)
186
- debug( "FileUtils.rm_rf #{args.to_a.join(" ")}")
187
- FileUtils.rm_rf(*args)
226
+ def qu
227
+ @qu ||= QuandlUtils.new(self)
188
228
  end
189
229
 
190
- def mkdir_p(*args)
191
- debug( "FileUtils.mkdir_p #{args.to_a.join(" ")}")
192
- FileUtils.mkdir_p(*args)
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