td 0.10.75 → 0.10.76

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,3 +1,11 @@
1
+ == 2013-04-22 version 0.10.76
2
+
3
+ * Add auto update feature for td-toolbelt
4
+ * Add -T to specify query type
5
+ * Include Ruby binary for Mac TD toolbelt
6
+ * td-client v0.8.48
7
+
8
+
1
9
  == 2013-04-09 version 0.10.75
2
10
 
3
11
  * Fix unparsed regexp pattern in Ruby 1.8
data/README.rdoc CHANGED
@@ -33,11 +33,11 @@ You need to authorize the account, before executing any other commands.
33
33
 
34
34
  == Mac OS X
35
35
 
36
- Disable RVM or rbenv and use system ruby (/usr/bin/ruby).
36
+ Disable RVM or rbenv and use ruby.pkg's ruby (/usr/local/td/ruby/bin/ruby).
37
37
  And then run following commands:
38
38
 
39
- $ sudo gem install bundler
40
- $ rake pkg:build
39
+ $ /usr/local/td/ruby/bin/gem install bundler rubyzip
40
+ $ /usr/local/td/ruby/bin/rake pkg:build
41
41
 
42
42
  == Windows
43
43
 
@@ -52,7 +52,7 @@ Then run following commands on MinGW Shell:
52
52
 
53
53
  $ mingw-get install msys-vim
54
54
  $ mingw-get install msys-wget
55
- $ gem install bundler
55
+ $ gem install bundler rubyzip
56
56
  $ bundle install # don't use "--path" option
57
57
  $ rake exe:build # don't use "bundle exec"
58
58
 
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'bundler'
3
+ require 'zip/zip'
3
4
  Bundler::GemHelper.install_tasks
4
5
 
5
6
  task :default => :build
@@ -49,7 +50,8 @@ def install_use_gems(target_dir)
49
50
  end
50
51
  }
51
52
  FileUtils.mv Dir.glob("#{target_dir}/gems/*"), target_dir
52
- %W(bin cache doc gems specifications).each { |dir|
53
+ FileUtils.rm_f Dir.glob("#{target_dir}/*.gem")
54
+ %W(bin cache doc gems specifications build_info).each { |dir|
53
55
  FileUtils.remove_dir("#{target_dir}/#{dir}", true)
54
56
  }
55
57
  end
@@ -119,6 +121,15 @@ def download_resource(url)
119
121
  path
120
122
  end
121
123
 
124
+ def zip_files(zip_name, target_dir)
125
+ Zip::ZipFile.open(zip_name, Zip::ZipFile::CREATE) do |zip|
126
+ Dir["#{target_dir}/**/*"].each do |file|
127
+ zipped_path = file[target_dir.length + 1..-1]
128
+ zip.add(zipped_path, file) { true }
129
+ end
130
+ end
131
+ end
132
+
122
133
  Dir[File.expand_path("../dist/**/*.rake", __FILE__)].each do |rake|
123
134
  import rake
124
135
  end
data/bin/td CHANGED
@@ -5,6 +5,13 @@ gem 'td-client'
5
5
  here = File.dirname(__FILE__)
6
6
  $LOAD_PATH << File.expand_path(File.join(here, '..', 'lib'))
7
7
 
8
+ require 'td/updater'
9
+ TreasureData::Updater.disable(<<EOS
10
+ `td update` is only available from Treasure Data Toolbelt.
11
+ Download and install from http://toolbelt.treasure-data.com
12
+ EOS
13
+ )
14
+
8
15
  require 'td/command/runner'
9
16
  TreasureData::Command::Runner.new.run ARGV
10
17
 
data/dist/exe.rake CHANGED
@@ -23,6 +23,8 @@ task 'exe:build' => :build do
23
23
  install_resource 'exe/td-cmd.bat', 'td-cmd.bat', 0755
24
24
  end
25
25
 
26
+ zip_files(project_root_path('pkg/td-update-exe.zip'), 'td')
27
+
26
28
  # create td.iss and run Inno Setup
27
29
  install_erb_resource 'exe/td.iss', 'td.iss', 0644, variables
28
30
 
@@ -38,6 +40,7 @@ end
38
40
  desc "clean Windows exe package"
39
41
  task "exe:clean" do
40
42
  FileUtils.rm_rf build_dir_path('exe')
41
- FileUtils.rm_rf project_root_path("exe/td-#{version}.exe")
43
+ FileUtils.rm_rf project_root_path("pkg/td-#{version}.exe")
44
+ FileUtils.rm_rf project_root_path("pkg/td-update-exe.zip")
42
45
  end
43
46
 
data/dist/pkg.rake CHANGED
@@ -16,6 +16,8 @@ task 'pkg:build' => :build do
16
16
  sh "pax -wz -x cpio . > ../bundle/td-client.pkg/Payload"
17
17
  end
18
18
 
19
+ zip_files(project_root_path('pkg/td-update-pkg.zip'), 'td-client.build')
20
+
19
21
  # crete ./bundle/td-client.pkg/Bom
20
22
  sh "mkbom -s td-client.build bundle/td-client.pkg/Bom"
21
23
 
@@ -34,6 +36,9 @@ task 'pkg:build' => :build do
34
36
  # create ./bundle/Distribution
35
37
  install_erb_resource('pkg/Distribution.erb', 'bundle/Distribution', 0644, variables)
36
38
 
39
+ sh "pkgutil --expand #{project_root_path('dist/resources/pkg/ruby-2.0.0-p0.pkg')} ruby"
40
+ mv "ruby/ruby-2.0.0-p0.pkg", "bundle/ruby.pkg"
41
+
37
42
  # create td-a.b.c.pkg
38
43
  sh "pkgutil --flatten bundle td-#{version}.pkg"
39
44
  FileUtils.cp "td-#{version}.pkg", project_root_path("pkg/td-#{version}.pkg")
@@ -44,5 +49,6 @@ desc "clean Mac OS X pkg package"
44
49
  task "pkg:clean" do
45
50
  FileUtils.rm_rf build_dir_path('pkg')
46
51
  FileUtils.rm_rf project_root_path("pkg/td-#{version}.pkg")
52
+ FileUtils.rm_rf project_root_path("pkg/td-update-pkg.zip")
47
53
  end
48
54
 
@@ -21,6 +21,10 @@ Dir["#{gem_dir}/**/lib"].each do |libdir|
21
21
  $:.unshift libdir
22
22
  end
23
23
 
24
+ # inject any code in ~/.td/updated/vendor/gems over top
25
+ require 'td/updater'
26
+ TreasureData::Updater.inject_libpath
27
+
24
28
  # start up the CLI
25
29
  require 'td/command/runner'
26
30
  TreasureData::Command::Runner.new.run ARGV
@@ -8,6 +8,8 @@
8
8
  </choices-outline>
9
9
  <choice id="td-client" title="TreasureData Client">
10
10
  <pkg-ref id="com.td.client"/>
11
+ <pkg-ref id="org.ruby-lang.installer"/>
11
12
  </choice>
12
13
  <pkg-ref id="com.td.client" installKBytes="<%= kbytes %>" version="<%= version %>" auth="Root">#td-client.pkg</pkg-ref>
14
+ <pkg-ref id="org.ruby-lang.installer" installKBytes="12868" auth="Root">#ruby.pkg</pkg-ref>
13
15
  </installer-script>
@@ -1,4 +1,4 @@
1
- #!/usr/bin/ruby
1
+ #!/usr/local/td/ruby/bin/ruby
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  # avoid conflicts with rvm
@@ -21,6 +21,10 @@ Dir["#{gem_dir}/**/lib"].each do |libdir|
21
21
  $:.unshift libdir
22
22
  end
23
23
 
24
+ # inject any code in ~/.td/updated/vendor/gems over top
25
+ require 'td/updater'
26
+ TreasureData::Updater.inject_libpath
27
+
24
28
  # start up the CLI
25
29
  require "td/command/runner"
26
30
  TreasureData::Command::Runner.new.run ARGV
@@ -324,6 +324,8 @@ module List
324
324
  add_list 'help:all', %w[], 'Show usage of all commands'
325
325
  add_list 'help', %w[command], 'Show usage of a command'
326
326
 
327
+ add_list 'update', %w[], 'Update td and related libraries for TreasureData toolbelt'
328
+
327
329
  # aliases
328
330
  add_alias 'db', 'db:show'
329
331
  add_alias 'dbs', 'db:list'
@@ -60,7 +60,7 @@ module Command
60
60
  op.on('-q', '--query PATH', 'use file instead of inline query') {|s|
61
61
  query = File.open(s) { |f| f.read.strip }
62
62
  }
63
- op.on('-t', '--type TYPE', 'set query type (hive or pig)') {|s|
63
+ op.on('-T', '--type TYPE', 'set query type (hive or pig)') {|s|
64
64
  type = s.to_sym
65
65
  }
66
66
  op.on('--sampling DENOMINATOR', 'enable random sampling to reduce records 1/DENOMINATOR', Integer) {|i|
@@ -34,6 +34,7 @@ module Command
34
34
  result_ask_password = false
35
35
  priority = nil
36
36
  retry_limit = nil
37
+ type = nil
37
38
 
38
39
  op.on('-g', '--org ORGANIZATION', "create the schedule under this organization") {|s|
39
40
  org = s
@@ -65,6 +66,9 @@ module Command
65
66
  op.on('-R', '--retry COUNT', 'automatic retrying count', Integer) {|i|
66
67
  retry_limit = i
67
68
  }
69
+ op.on('-T', '--type TYPE', 'set query type (hive or pig)') {|s|
70
+ type = s
71
+ }
68
72
 
69
73
  name, cron, sql = op.cmd_parse
70
74
 
@@ -84,7 +88,7 @@ module Command
84
88
  get_database(client, db_name)
85
89
 
86
90
  begin
87
- first_time = client.create_schedule(name, :cron=>cron, :query=>sql, :database=>db_name, :result=>result_url, :timezone=>timezone, :delay=>delay, :priority=>priority, :retry_limit=>retry_limit, :organization=>org)
91
+ first_time = client.create_schedule(name, :cron=>cron, :query=>sql, :database=>db_name, :result=>result_url, :timezone=>timezone, :delay=>delay, :priority=>priority, :retry_limit=>retry_limit, :organization=>org, :type=>type)
88
92
  rescue AlreadyExistsError
89
93
  cmd_debug_error $!
90
94
  $stderr.puts "Schedule '#{name}' already exists."
@@ -120,6 +124,7 @@ module Command
120
124
  delay = nil
121
125
  priority = nil
122
126
  retry_limit = nil
127
+ type = nil
123
128
 
124
129
  op.on('-s', '--schedule CRON', 'change the schedule') {|s|
125
130
  cron = s
@@ -148,6 +153,9 @@ module Command
148
153
  op.on('-R', '--retry COUNT', 'automatic retrying count', Integer) {|i|
149
154
  retry_limit = i
150
155
  }
156
+ op.on('-T', '--type TYPE', 'set query type (hive or pig)') {|s|
157
+ type = s
158
+ }
151
159
 
152
160
 
153
161
  name = op.cmd_parse
@@ -161,6 +169,7 @@ module Command
161
169
  params['delay'] = delay.to_s if delay
162
170
  params['priority'] = priority.to_s if priority
163
171
  params['retry_limit'] = retry_limit.to_s if retry_limit
172
+ params['type'] = type.to_s if type
164
173
 
165
174
  if params.empty?
166
175
  $stderr.puts op.to_s
@@ -0,0 +1,26 @@
1
+ require "td/updater"
2
+
3
+ module TreasureData
4
+ module Command
5
+
6
+ def update(op)
7
+ if TreasureData::Updater.disable?
8
+ $stderr.puts TreasureData::Updater.disable_message
9
+ exit
10
+ end
11
+
12
+ $stderr.puts <<EOS
13
+ Updating started at #{Time.now}
14
+ from #{TreasureData::VERSION}
15
+ EOS
16
+ if new_version = TreasureData::Updater.update
17
+ $stderr.puts "updated to #{new_version}"
18
+ else
19
+ $stderr.puts "nothing to update"
20
+ end
21
+ $stderr.puts "ended at #{Time.now}"
22
+ end
23
+
24
+ end
25
+ end
26
+
data/lib/td/helpers.rb CHANGED
@@ -11,8 +11,16 @@ module TreasureData
11
11
  end
12
12
  end
13
13
 
14
+ def home_directory
15
+ on_windows? ? ENV['USERPROFILE'].gsub("\\","/") : ENV['HOME']
16
+ end
17
+
14
18
  def on_windows?
15
19
  RUBY_PLATFORM =~ /mswin32|mingw32/
16
20
  end
21
+
22
+ def on_mac?
23
+ RUBY_PLATFORM =~ /-darwin\d/
24
+ end
17
25
  end
18
26
  end
data/lib/td/updater.rb ADDED
@@ -0,0 +1,230 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "fileutils"
3
+ require "shellwords"
4
+ require "zip/zip"
5
+
6
+ module TreasureData
7
+ # This architecture is based on Heroku command
8
+ module Updater
9
+ def self.raise_error(message)
10
+ # TODO: Replace better Exception class
11
+ raise RuntimeError.new(message)
12
+ end
13
+
14
+ # copied from TreasureData::Helpers to avoid load issue.
15
+ def self.home_directory
16
+ on_windows? ? ENV['USERPROFILE'].gsub("\\","/") : ENV['HOME']
17
+ end
18
+
19
+ def self.on_windows?
20
+ RUBY_PLATFORM =~ /mswin32|mingw32/
21
+ end
22
+
23
+ def self.on_mac?
24
+ RUBY_PLATFORM =~ /-darwin\d/
25
+ end
26
+
27
+ def self.updating_lock_path
28
+ File.join(home_directory, ".td", "updating")
29
+ end
30
+
31
+ def self.installed_client_path
32
+ File.expand_path("../../..", __FILE__)
33
+ end
34
+
35
+ def self.updated_client_path
36
+ File.join(home_directory, ".td", "updated")
37
+ end
38
+
39
+ def self.latest_local_version
40
+ installed_version = client_version_from_path(installed_client_path)
41
+ updated_version = client_version_from_path(updated_client_path)
42
+ if compare_versions(updated_version, installed_version) > 0
43
+ updated_version
44
+ else
45
+ installed_version
46
+ end
47
+ end
48
+
49
+ def self.get_client_version_file(path)
50
+ td_gems = Dir[File.join(path, "vendor/gems/td-*")]
51
+ td_gems.each { |td_gem|
52
+ if td_gem =~ /#{"#{path}\/vendor\/gems\/td-\\d*.\\d*.\\d*"}/
53
+ return File.join(td_gem, "/lib/td/version.rb")
54
+ end
55
+ }
56
+
57
+ nil
58
+ end
59
+
60
+ def self.client_version_from_path(path)
61
+ if version_file = get_client_version_file(path)
62
+ File.read(version_file).match(/VERSION = '([^']+)'/)[1]
63
+ else
64
+ '0.0.0'
65
+ end
66
+ end
67
+
68
+ def self.disable(message)
69
+ @disable = message
70
+ end
71
+
72
+ def self.disable?
73
+ !@disable.nil?
74
+ end
75
+
76
+ def self.disable_message
77
+ @disable
78
+ end
79
+
80
+ def self.wait_for_lock(path, wait_for = 5, check_every = 0.5)
81
+ start = Time.now.to_i
82
+ while File.exists?(path)
83
+ sleep check_every
84
+ if (Time.now.to_i - start) > wait_for
85
+ raise_error "Unable to acquire update lock"
86
+ end
87
+ end
88
+ begin
89
+ FileUtils.touch(path)
90
+ ret = yield
91
+ ensure
92
+ FileUtils.rm_f(path)
93
+ end
94
+ ret
95
+ end
96
+
97
+ def self.package_category
98
+ case
99
+ when on_windows?
100
+ 'exe'
101
+ when on_mac?
102
+ 'pkg'
103
+ else
104
+ raise_error "Non supported environment"
105
+ end
106
+ end
107
+
108
+ def self.fetch(uri)
109
+ require 'net/http'
110
+ require 'openssl'
111
+
112
+ # open-uri can't treat 'http -> https' redirection and
113
+ # Net::HTTP.get_response can't get response from HTTPS endpoint.
114
+ # So we use following code to avoid above issues.
115
+ u = URI(uri)
116
+ response = if u.scheme == 'https'
117
+ http = Net::HTTP.new(u.host, u.port)
118
+ http.use_ssl = true
119
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
120
+ http.request(Net::HTTP::Get.new(u.path))
121
+ else
122
+ Net::HTTP.get_response(u)
123
+ end
124
+
125
+ case response
126
+ when Net::HTTPSuccess then response.body
127
+ when Net::HTTPRedirection then fetch(response['Location'])
128
+ else
129
+ response.error!
130
+ end
131
+ end
132
+
133
+ def self.version_endpoint
134
+ "http://toolbelt.treasure-data.com/version.#{package_category}"
135
+ end
136
+
137
+ def self.update_package_endpoint
138
+ "http://toolbelt.treasure-data.com/td-update-#{package_category}.zip"
139
+ end
140
+
141
+ def self.update(autoupdate = false)
142
+ wait_for_lock(updating_lock_path, 5) do
143
+ require "td"
144
+ require 'open-uri'
145
+ require "tmpdir"
146
+ require "zip/zip"
147
+
148
+ latest_version = fetch(version_endpoint)
149
+
150
+ if compare_versions(latest_version, latest_local_version) > 0
151
+ Dir.mktmpdir do |download_dir|
152
+ File.open("#{download_dir}/td-update.zip", "wb") do |file|
153
+ file.print fetch(update_package_endpoint)
154
+ end
155
+
156
+ Zip::ZipFile.open("#{download_dir}/td-update.zip") do |zip|
157
+ zip.each do |entry|
158
+ target = File.join(download_dir, entry.to_s)
159
+ FileUtils.mkdir_p(File.dirname(target))
160
+ zip.extract(entry, target) { true }
161
+ end
162
+ end
163
+
164
+ FileUtils.rm "#{download_dir}/td-update.zip"
165
+
166
+ old_version = latest_local_version
167
+ new_version = client_version_from_path(download_dir)
168
+
169
+ if compare_versions(new_version, old_version) < 0 && !autoupdate
170
+ raise_error "Installed version (#{old_version}) is newer than the latest available update (#{new_version})"
171
+ end
172
+
173
+ FileUtils.rm_rf updated_client_path
174
+ FileUtils.mkdir_p File.dirname(updated_client_path)
175
+ FileUtils.cp_r(download_dir, updated_client_path)
176
+
177
+ new_version
178
+ end
179
+ else
180
+ false # already up to date
181
+ end
182
+ end
183
+ ensure
184
+ FileUtils.rm_f(updating_lock_path)
185
+ end
186
+
187
+ def self.compare_versions(first_version, second_version)
188
+ first_version.split('.').map { |part| Integer(part) rescue part } <=> second_version.split('.').map { |part| Integer(part) rescue part }
189
+ end
190
+
191
+ def self.inject_libpath
192
+ old_version = client_version_from_path(installed_client_path)
193
+ new_version = client_version_from_path(updated_client_path)
194
+
195
+ if compare_versions(new_version, old_version) > 0
196
+ vendored_gems = Dir[File.join(updated_client_path, "vendor", "gems", "*")]
197
+ vendored_gems.each do |vendored_gem|
198
+ $:.unshift File.join(vendored_gem, "lib")
199
+ end
200
+ load('td/updater.rb') # reload updated updater
201
+ end
202
+
203
+ background_update!
204
+ end
205
+
206
+ def self.last_autoupdate_path
207
+ File.join(home_directory, ".td", "autoupdate.last")
208
+ end
209
+
210
+ def self.background_update!
211
+ if File.exists?(last_autoupdate_path)
212
+ return if (Time.now.to_i - File.mtime(last_autoupdate_path).to_i) < 60 * 60 * 1 # every 1 hours
213
+ end
214
+ log_path = File.join(home_directory, '.td', 'autoupdate.log')
215
+ FileUtils.mkdir_p File.dirname(log_path)
216
+ td_binary = File.expand_path($0)
217
+ pid = if defined?(RUBY_VERSION) and RUBY_VERSION =~ /^1\.8\.\d+/
218
+ fork do
219
+ exec("#{Shellwords.escape(td_binary)} update &> #{Shellwords.escape(log_path)} 2>&1")
220
+ end
221
+ else
222
+ log_file = File.open(log_path, "w")
223
+ spawn(td_binary, 'update', :err => log_file, :out => log_file)
224
+ end
225
+ Process.detach(pid)
226
+ FileUtils.mkdir_p File.dirname(last_autoupdate_path)
227
+ FileUtils.touch last_autoupdate_path
228
+ end
229
+ end
230
+ end
data/lib/td/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module TreasureData
2
2
 
3
- VERSION = '0.10.75'
3
+ VERSION = '0.10.76'
4
4
 
5
5
  end
data/td.gemspec CHANGED
@@ -20,8 +20,9 @@ Gem::Specification.new do |gem|
20
20
  gem.add_dependency "yajl-ruby", "~> 1.1.0"
21
21
  gem.add_dependency "hirb", ">= 0.4.5"
22
22
  gem.add_dependency "parallel", "~> 0.5.19"
23
- gem.add_dependency "td-client", "~> 0.8.46"
23
+ gem.add_dependency "td-client", "~> 0.8.48"
24
24
  gem.add_dependency "td-logger", "~> 0.3.16"
25
+ gem.add_dependency "rubyzip", "~> 0.9.9"
25
26
  gem.add_development_dependency "rake", "~> 0.9"
26
27
  gem.add_development_dependency "rspec", "~> 2.11.0"
27
28
  gem.add_development_dependency "simplecov", "~> 0.5.4"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: td
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.75
4
+ version: 0.10.76
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-09 00:00:00.000000000 Z
12
+ date: 2013-04-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: msgpack
@@ -82,7 +82,7 @@ dependencies:
82
82
  requirements:
83
83
  - - ~>
84
84
  - !ruby/object:Gem::Version
85
- version: 0.8.46
85
+ version: 0.8.48
86
86
  type: :runtime
87
87
  prerelease: false
88
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -90,7 +90,7 @@ dependencies:
90
90
  requirements:
91
91
  - - ~>
92
92
  - !ruby/object:Gem::Version
93
- version: 0.8.46
93
+ version: 0.8.48
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: td-logger
96
96
  requirement: !ruby/object:Gem::Requirement
@@ -107,6 +107,22 @@ dependencies:
107
107
  - - ~>
108
108
  - !ruby/object:Gem::Version
109
109
  version: 0.3.16
110
+ - !ruby/object:Gem::Dependency
111
+ name: rubyzip
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 0.9.9
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: 0.9.9
110
126
  - !ruby/object:Gem::Dependency
111
127
  name: rake
112
128
  requirement: !ruby/object:Gem::Requirement
@@ -182,6 +198,7 @@ files:
182
198
  - dist/resources/pkg/Distribution.erb
183
199
  - dist/resources/pkg/PackageInfo.erb
184
200
  - dist/resources/pkg/postinstall
201
+ - dist/resources/pkg/ruby-2.0.0-p0.pkg
185
202
  - dist/resources/pkg/td
186
203
  - java/td-bulk-import-0.1.2-SNAPSHOT.jar
187
204
  - java/td-bulk-import-java.version
@@ -211,6 +228,7 @@ files:
211
228
  - lib/td/command/server.rb
212
229
  - lib/td/command/status.rb
213
230
  - lib/td/command/table.rb
231
+ - lib/td/command/update.rb
214
232
  - lib/td/command/user.rb
215
233
  - lib/td/compat_core.rb
216
234
  - lib/td/compat_gzip_reader.rb
@@ -218,6 +236,7 @@ files:
218
236
  - lib/td/distribution.rb
219
237
  - lib/td/file_reader.rb
220
238
  - lib/td/helpers.rb
239
+ - lib/td/updater.rb
221
240
  - lib/td/version.rb
222
241
  - spec/file_reader/filter_spec.rb
223
242
  - spec/file_reader/io_filter_spec.rb
@@ -243,7 +262,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
243
262
  version: '0'
244
263
  segments:
245
264
  - 0
246
- hash: 1038070565617120851
265
+ hash: -1565388258148285832
247
266
  required_rubygems_version: !ruby/object:Gem::Requirement
248
267
  none: false
249
268
  requirements:
@@ -252,7 +271,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
252
271
  version: '0'
253
272
  segments:
254
273
  - 0
255
- hash: 1038070565617120851
274
+ hash: -1565388258148285832
256
275
  requirements: []
257
276
  rubyforge_project:
258
277
  rubygems_version: 1.8.23