unix_utils 0.0.14 → 0.0.15

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.
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ 0.0.15 / 2012-11-09
2
+
3
+ * Enhancements
4
+
5
+ * Back to stdlib open3 because C extension support is not enabled by default in JRuby 1.7+
6
+
7
+ * Known issues
8
+
9
+ * stderr is not captured in JRuby 1.7.0 because of https://jira.codehaus.org/browse/JRUBY-6986
10
+
1
11
  0.0.14 / 2012-07-06
2
12
 
3
13
  * Breaking changes
data/Gemfile CHANGED
@@ -1,9 +1,3 @@
1
1
  source :rubygems
2
2
 
3
3
  gemspec
4
-
5
- # development dependencies
6
- gem 'minitest'
7
- gem 'minitest-reporters'
8
- gem 'yard'
9
- # gem 'ruby-prof'
@@ -2,7 +2,9 @@
2
2
 
3
3
  Like FileUtils, but provides zip, unzip, bzip2, bunzip2, tar, untar, sed, du, md5sum, shasum, cut, head, tail, wc, unix2dos, dos2unix, iconv, curl, perl, etc.
4
4
 
5
- Works in MRI 1.8.7+, MRI 1.9.2+, and JRuby 1.6.7+
5
+ You must have these binaries in your `PATH`. _Not_ a pure-ruby implementation of all these UNIX greats!
6
+
7
+ Works in MRI 1.8.7+, MRI 1.9.2+, and JRuby 1.6.7+. No gem dependencies; uses stdlib
6
8
 
7
9
  ## Real-world usage
8
10
 
@@ -79,13 +81,18 @@ This will load an entire file into memory before it can be processed...
79
81
 
80
82
  You get the same low memory footprint with
81
83
 
82
- str = UnixUtils.shasum('kittens.zip', 256)
84
+ str = UnixUtils.shasum 'kittens.zip', 256
83
85
 
84
86
  ## Compatibility
85
87
 
86
- Now using [`posix-spawn`](https://github.com/rtomayko/posix-spawn) for speed. Thanks for the suggestion [jjb](https://github.com/jjb)!
88
+ Uses `open3` because it's in the Ruby stdlib and is consistent across MRI and JRuby.
89
+
90
+ ## Wishlist
87
91
 
88
- Previously used `open3` because it's in the Ruby stdlib and is consistent across MRI and JRuby.
92
+ * cheat sheet based on [GNU Coreutils cheat sheet](www.catonmat.net/download/gnu-coreutils-cheat-sheet.pdf)
93
+ * yarddocs
94
+ * properly use Dir.tmpdir(name), etc.
95
+ * smarter tmp file name generation - don't include url params for curl, etc.
89
96
 
90
97
  ## Authors
91
98
 
@@ -93,4 +100,4 @@ Previously used `open3` because it's in the Ruby stdlib and is consistent across
93
100
 
94
101
  ## Copyright
95
102
 
96
- Copyright (c) 2012 Brighter Planet. See LICENSE for details.
103
+ Copyright (c) 2012 Seamus Abshere
@@ -2,7 +2,7 @@ require 'fileutils'
2
2
  require 'tmpdir'
3
3
  require 'uri'
4
4
  require 'stringio'
5
- require 'posix/spawn'
5
+ require 'open3'
6
6
  require 'securerandom'
7
7
  require "unix_utils/version"
8
8
 
@@ -14,14 +14,14 @@ module UnixUtils
14
14
  outfile = tmp_path url
15
15
  if url.start_with?('file://') or not url.include?('://')
16
16
  # deal with local files
17
- infile = ::File.expand_path url.sub('file://', '')
17
+ infile = File.expand_path url.sub('file://', '')
18
18
  unless File.readable?(infile)
19
19
  raise "[unix_utils] #{url.inspect} does not exist or is not readable on the local filesystem."
20
20
  end
21
- ::FileUtils.cp infile, outfile
21
+ FileUtils.cp infile, outfile
22
22
  return outfile
23
23
  end
24
- uri = ::URI.parse url
24
+ uri = URI.parse url
25
25
  argv = [ 'curl', '--location', '--show-error', '--silent', '--compressed', '--header', 'Expect: ' ]
26
26
  if form_data
27
27
  argv += [ '--data', form_data ]
@@ -42,7 +42,7 @@ module UnixUtils
42
42
  # $ sha256sum --binary .bash_profile
43
43
  # 01b1210962b3d1e5e1ccba26f93d98efbb7b315b463f9f6bdb40ab496728d886 *.bash_profile
44
44
  def self.shasum(infile, algorithm)
45
- infile = ::File.expand_path infile
45
+ infile = File.expand_path infile
46
46
  if available?('shasum')
47
47
  argv = ['shasum', '--binary', '-a', algorithm.to_s, infile]
48
48
  stdout = spawn argv
@@ -62,7 +62,7 @@ module UnixUtils
62
62
  # $ md5sum --binary .mysql_history
63
63
  # 8d01e54ab8142d6786850e22d55a1b6c *.mysql_history
64
64
  def self.md5sum(infile)
65
- infile = ::File.expand_path infile
65
+ infile = File.expand_path infile
66
66
  if available?('md5sum')
67
67
  argv = ['md5sum', '--binary', infile]
68
68
  stdout = spawn argv
@@ -75,14 +75,14 @@ module UnixUtils
75
75
  end
76
76
 
77
77
  def self.du(srcdir)
78
- srcdir = ::File.expand_path srcdir
78
+ srcdir = File.expand_path srcdir
79
79
  argv = ['du', '-sk', srcdir]
80
80
  stdout = spawn argv
81
81
  stdout.strip.split(/\s+/).first.to_i
82
82
  end
83
83
 
84
84
  def self.wc(infile)
85
- infile = ::File.expand_path infile
85
+ infile = File.expand_path infile
86
86
  argv = ['wc', infile]
87
87
  stdout = spawn argv
88
88
  stdout.strip.split(/\s+/)[0..2].map { |s| s.to_i }
@@ -91,25 +91,25 @@ module UnixUtils
91
91
  # --
92
92
 
93
93
  def self.unzip(infile)
94
- infile = ::File.expand_path infile
94
+ infile = File.expand_path infile
95
95
  destdir = tmp_path infile
96
- ::FileUtils.mkdir destdir
96
+ FileUtils.mkdir destdir
97
97
  argv = ['unzip', '-qq', '-n', infile, '-d', destdir]
98
98
  spawn argv
99
99
  destdir
100
100
  end
101
101
 
102
102
  def self.untar(infile)
103
- infile = ::File.expand_path infile
103
+ infile = File.expand_path infile
104
104
  destdir = tmp_path infile
105
- ::FileUtils.mkdir destdir
105
+ FileUtils.mkdir destdir
106
106
  argv = ['tar', '-xf', infile, '-C', destdir]
107
107
  spawn argv
108
108
  destdir
109
109
  end
110
110
 
111
111
  def self.gunzip(infile)
112
- infile = ::File.expand_path infile
112
+ infile = File.expand_path infile
113
113
  outfile = tmp_path infile
114
114
  argv = ['gunzip', '--stdout', infile]
115
115
  spawn argv, :write_to => outfile
@@ -117,7 +117,7 @@ module UnixUtils
117
117
  end
118
118
 
119
119
  def self.bunzip2(infile)
120
- infile = ::File.expand_path infile
120
+ infile = File.expand_path infile
121
121
  outfile = tmp_path infile
122
122
  argv = ['bunzip2', '--stdout', infile]
123
123
  spawn argv, :write_to => outfile
@@ -127,7 +127,7 @@ module UnixUtils
127
127
  # --
128
128
 
129
129
  def self.bzip2(infile)
130
- infile = ::File.expand_path infile
130
+ infile = File.expand_path infile
131
131
  outfile = tmp_path infile, '.bz2'
132
132
  argv = ['bzip2', '--keep', '--stdout', infile]
133
133
  spawn argv, :write_to => outfile
@@ -135,7 +135,7 @@ module UnixUtils
135
135
  end
136
136
 
137
137
  def self.tar(srcdir)
138
- srcdir = ::File.expand_path srcdir
138
+ srcdir = File.expand_path srcdir
139
139
  outfile = tmp_path srcdir, '.tar'
140
140
  argv = ['tar', '-cf', outfile, '-C', srcdir, '.']
141
141
  spawn argv
@@ -143,7 +143,7 @@ module UnixUtils
143
143
  end
144
144
 
145
145
  def self.zip(srcdir)
146
- srcdir = ::File.expand_path srcdir
146
+ srcdir = File.expand_path srcdir
147
147
  outfile = tmp_path srcdir, '.zip'
148
148
  argv = ['zip', '-rq', outfile, '.']
149
149
  spawn argv, :chdir => srcdir
@@ -151,7 +151,7 @@ module UnixUtils
151
151
  end
152
152
 
153
153
  def self.gzip(infile)
154
- infile = ::File.expand_path infile
154
+ infile = File.expand_path infile
155
155
  outfile = tmp_path infile, '.gz'
156
156
  argv = ['gzip', '--stdout', infile]
157
157
  spawn argv, :write_to => outfile
@@ -161,7 +161,7 @@ module UnixUtils
161
161
  # --
162
162
 
163
163
  def self.awk(infile, *expr)
164
- infile = ::File.expand_path infile
164
+ infile = File.expand_path infile
165
165
  outfile = tmp_path infile
166
166
  bin = available?('gawk') ? 'gawk' : 'awk'
167
167
  argv = [bin, expr, infile].flatten
@@ -171,7 +171,7 @@ module UnixUtils
171
171
 
172
172
  # Yes, this is a very limited use of perl.
173
173
  def self.perl(infile, *expr)
174
- infile = ::File.expand_path infile
174
+ infile = File.expand_path infile
175
175
  outfile = tmp_path infile
176
176
  argv = [ 'perl', expr.map { |e| ['-pe', e] }, infile ].flatten
177
177
  spawn argv, :write_to => outfile
@@ -179,7 +179,7 @@ module UnixUtils
179
179
  end
180
180
 
181
181
  def self.unix2dos(infile)
182
- infile = ::File.expand_path infile
182
+ infile = File.expand_path infile
183
183
  if available?('gawk') or available?('awk')
184
184
  awk infile, '{ sub(/\r/, ""); printf("%s\r\n", $0) }'
185
185
  else
@@ -188,7 +188,7 @@ module UnixUtils
188
188
  end
189
189
 
190
190
  def self.dos2unix(infile)
191
- infile = ::File.expand_path infile
191
+ infile = File.expand_path infile
192
192
  if available?('gawk') or available?('awk')
193
193
  awk infile, '{ sub(/\r/, ""); printf("%s\n", $0) }'
194
194
  else
@@ -198,7 +198,7 @@ module UnixUtils
198
198
 
199
199
  # POSIX sed, whether it's provided by sed or gsed
200
200
  def self.sed(infile, *expr)
201
- infile = ::File.expand_path infile
201
+ infile = File.expand_path infile
202
202
  outfile = tmp_path infile
203
203
  bin = available?('sed') ? 'sed' : ['gsed', '--posix']
204
204
  argv = [ bin, expr.map { |e| ['-e', e] }, infile ].flatten
@@ -207,7 +207,7 @@ module UnixUtils
207
207
  end
208
208
 
209
209
  def self.tail(infile, lines)
210
- infile = ::File.expand_path infile
210
+ infile = File.expand_path infile
211
211
  outfile = tmp_path infile
212
212
  argv = ['tail', '-n', lines.to_s, infile]
213
213
  spawn argv, :write_to => outfile
@@ -215,7 +215,7 @@ module UnixUtils
215
215
  end
216
216
 
217
217
  def self.head(infile, lines)
218
- infile = ::File.expand_path infile
218
+ infile = File.expand_path infile
219
219
  outfile = tmp_path infile
220
220
  argv = ['head', '-n', lines.to_s, infile]
221
221
  spawn argv, :write_to => outfile
@@ -224,7 +224,7 @@ module UnixUtils
224
224
 
225
225
  # specify character_positions as a string like "3-5" or "3,9-10"
226
226
  def self.cut(infile, character_positions)
227
- infile = ::File.expand_path infile
227
+ infile = File.expand_path infile
228
228
  outfile = tmp_path infile
229
229
  argv = ['cut', '-c', character_positions, infile]
230
230
  spawn argv, :write_to => outfile
@@ -232,7 +232,7 @@ module UnixUtils
232
232
  end
233
233
 
234
234
  def self.iconv(infile, to, from)
235
- infile = ::File.expand_path infile
235
+ infile = File.expand_path infile
236
236
  outfile = tmp_path infile
237
237
  argv = ['iconv', '-c', '-t', to, '-f', from, infile]
238
238
  spawn argv, :write_to => outfile
@@ -241,7 +241,7 @@ module UnixUtils
241
241
 
242
242
  def self.available?(bin) # :nodoc:
243
243
  bin = bin.to_s
244
- return @@available_query[bin] if defined?(@@available_query) and @@available_query.is_a?(::Hash) and @@available_query.has_key?(bin)
244
+ return @@available_query[bin] if defined?(@@available_query) and @@available_query.is_a?(Hash) and @@available_query.has_key?(bin)
245
245
  @@available_query ||= {}
246
246
  `which #{bin}`
247
247
  @@available_query[bin] = $?.success?
@@ -249,84 +249,93 @@ module UnixUtils
249
249
 
250
250
  def self.tmp_path(ancestor, extname = nil) # :nodoc:
251
251
  ancestor = ancestor.to_s
252
- extname ||= ::File.extname ancestor
253
- basename = ::File.basename ancestor.gsub(/unix_utils_[a-f0-9]{8,}_/, '')
252
+ extname ||= File.extname ancestor
253
+ basename = File.basename ancestor.gsub(/unix_utils_[a-f0-9]{8,}_/, '')
254
254
  basename.gsub! /\W+/, '_'
255
- ::File.join ::Dir.tmpdir, "unix_utils_#{::SecureRandom.hex(4)}_#{basename[0..(234-extname.length)]}#{extname}"
255
+ File.join Dir.tmpdir, "unix_utils_#{SecureRandom.hex(4)}_#{basename[0..(234-extname.length)]}#{extname}"
256
256
  end
257
257
 
258
258
  def self.spawn(argv, options = {}) # :nodoc:
259
- options = options.dup
260
-
261
- input = if (read_from = options.delete(:read_from))
262
- ::File.open(read_from, 'r')
259
+ input = if (read_from = options[:read_from])
260
+ if RUBY_DESCRIPTION =~ /jruby 1.7.0/
261
+ raise "[unix_utils] Can't use `#{argv.first}` since JRuby 1.7.0 has a broken IO implementation!"
262
+ end
263
+ File.open(read_from, 'r')
263
264
  end
264
-
265
- output = if (write_to = options.delete(:write_to))
265
+ output = if (write_to = options[:write_to])
266
266
  output_redirected = true
267
- ::File.open(write_to, 'wb')
267
+ File.open(write_to, 'wb')
268
268
  else
269
269
  output_redirected = false
270
- ::StringIO.new
271
- end
272
-
273
- error = ::StringIO.new
274
-
275
- pid, stdin, stdout, stderr = ::POSIX::Spawn.popen4(*(argv+[options]))
276
-
277
- # lifted from posix-spawn
278
- # https://github.com/rtomayko/posix-spawn/blob/master/lib/posix/spawn/child.rb
279
- readers = [stdout, stderr]
280
- writers = if input
281
- [stdin]
282
- else
283
- stdin.close
284
- []
270
+ StringIO.new
285
271
  end
286
- while readers.any? or writers.any?
287
- ready = ::IO.select(readers, writers, readers + writers)
288
- # write to stdin stream
289
- ready[1].each do |fd|
290
- begin
291
- boom = nil
292
- size = fd.write(input.read(BUFSIZE))
293
- rescue ::Errno::EPIPE => boom
294
- rescue ::Errno::EAGAIN, ::Errno::EINTR
295
- end
296
- if boom || size < BUFSIZE
297
- stdin.close
298
- input.close
299
- writers.delete(stdin)
300
- end
301
- end
302
- # read from stdout and stderr streams
303
- ready[0].each do |fd|
304
- buf = (fd == stdout) ? output : error
305
- begin
306
- buf << fd.readpartial(BUFSIZE)
307
- rescue ::Errno::EAGAIN, ::Errno::EINTR
308
- rescue ::EOFError
309
- readers.delete(fd)
310
- fd.close
311
- end
272
+ error = StringIO.new
273
+ if (chdir = options[:chdir])
274
+ Dir.chdir(chdir) do
275
+ _spawn argv, input, output, error
312
276
  end
277
+ else
278
+ _spawn argv, input, output, error
313
279
  end
314
- # thanks @tmm1 and @rtomayko for showing how it's done!
315
-
316
- ::Process.waitpid pid
317
-
318
280
  error.rewind
319
281
  unless (whole_error = error.read).empty?
320
282
  $stderr.puts "[unix_utils] `#{argv.join(' ')}` STDERR:"
321
283
  $stderr.puts whole_error
322
284
  end
323
-
324
285
  unless output_redirected
325
286
  output.rewind
326
287
  output.read
327
288
  end
328
289
  ensure
329
- [stdin, stdout, stderr, input, output, error].each { |io| io.close if io and not io.closed? }
290
+ [input, output, error].each { |io| io.close if io and not io.closed? }
291
+ end
292
+
293
+ def self._spawn(argv, input, output, error)
294
+ # lifted from posix-spawn
295
+ # https://github.com/rtomayko/posix-spawn/blob/master/lib/posix/spawn/child.rb
296
+ Open3.popen3(*argv) do |stdin, stdout, stderr|
297
+ readers = [stdout, stderr]
298
+ if RUBY_DESCRIPTION =~ /jruby 1.7.0/
299
+ readers.delete stderr
300
+ end
301
+ writers = if input
302
+ [stdin]
303
+ else
304
+ stdin.close
305
+ []
306
+ end
307
+ while readers.any? or writers.any?
308
+ ready = IO.select(readers, writers, readers + writers)
309
+ # write to stdin stream
310
+ ready[1].each do |fd|
311
+ begin
312
+ boom = nil
313
+ size = fd.write input.read(BUFSIZE)
314
+ rescue Errno::EPIPE => boom
315
+ rescue Errno::EAGAIN, Errno::EINTR
316
+ end
317
+ if boom || size < BUFSIZE
318
+ stdin.close
319
+ input.close
320
+ writers.delete stdin
321
+ end
322
+ end
323
+ # read from stdout and stderr streams
324
+ ready[0].each do |fd|
325
+ buf = (fd == stdout) ? output : error
326
+ if fd.eof?
327
+ readers.delete fd
328
+ fd.close
329
+ else
330
+ begin
331
+ buf << fd.readpartial(BUFSIZE)
332
+ rescue Errno::EAGAIN, Errno::EINTR
333
+ end
334
+ end
335
+ end
336
+ end
337
+ # thanks @tmm1 and @rtomayko for showing how it's done!
338
+ end
330
339
  end
331
340
 
332
341
  def self.method_missing(method_id, *args)
@@ -334,9 +343,9 @@ module UnixUtils
334
343
  if respond_to?(base_method_id)
335
344
  begin
336
345
  outfile = send(*([base_method_id]+args))
337
- ::File.read outfile
346
+ File.read outfile
338
347
  ensure
339
- ::FileUtils.rm_f outfile
348
+ FileUtils.rm_f outfile
340
349
  end
341
350
  else
342
351
  super
@@ -1,3 +1,3 @@
1
1
  module UnixUtils
2
- VERSION = "0.0.14"
2
+ VERSION = "0.0.15"
3
3
  end
@@ -1,11 +1,13 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
+ require 'pry'
3
4
 
4
5
  require 'minitest/spec'
5
6
  require 'minitest/autorun'
6
- require 'minitest/reporters'
7
- MiniTest::Unit.runner = MiniTest::SuiteRunner.new
8
- MiniTest::Unit.runner.reporters << MiniTest::Reporters::SpecReporter.new
7
+ if RUBY_VERSION >= '1.9'
8
+ require 'minitest/reporters'
9
+ MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
10
+ end
9
11
 
10
12
  require 'unix_utils'
11
13
 
@@ -17,5 +17,10 @@ Gem::Specification.new do |gem|
17
17
  gem.version = UnixUtils::VERSION
18
18
  gem.license = 'MIT'
19
19
 
20
- gem.add_runtime_dependency 'posix-spawn'
20
+ gem.add_development_dependency 'minitest'
21
+ if RUBY_VERSION >= '1.9'
22
+ gem.add_development_dependency 'minitest-reporters'
23
+ end
24
+ gem.add_development_dependency 'yard'
25
+ gem.add_development_dependency 'pry'
21
26
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unix_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.14
4
+ version: 0.0.15
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,17 +9,65 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-06 00:00:00.000000000 Z
12
+ date: 2012-11-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: posix-spawn
15
+ name: minitest
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: '0'
22
- type: :runtime
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: minitest-reporters
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: yard
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: pry
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
23
71
  prerelease: false
24
72
  version_requirements: !ruby/object:Gem::Requirement
25
73
  none: false