handbrake 0.1.0 → 0.2.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.
- data/CHANGELOG.md +7 -0
- data/README.md +7 -0
- data/lib/handbrake.rb +6 -0
- data/lib/handbrake/cli.rb +83 -2
- data/lib/handbrake/version.rb +1 -1
- data/spec/handbrake/cli_spec.rb +156 -3
- data/spec/spec_helper.rb +17 -14
- metadata +49 -87
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -126,6 +126,13 @@ To put it more technically, the chain object returned from each
|
|
126
126
|
intermediate configuration step returns an independent copy of the
|
127
127
|
configuration chain.
|
128
128
|
|
129
|
+
### Output options
|
130
|
+
|
131
|
+
By default, the `output` execution method behaves just like invoking
|
132
|
+
HandBrakeCLI directly. `handbrake.rb` also supports a couple of
|
133
|
+
additional behaviors, including overwrite detection and atomic output
|
134
|
+
file creation. See {HandBrake::CLI#output} for more details.
|
135
|
+
|
129
136
|
Additional resources
|
130
137
|
--------------------
|
131
138
|
|
data/lib/handbrake.rb
CHANGED
@@ -8,4 +8,10 @@ module HandBrake
|
|
8
8
|
autoload :Titles, 'handbrake/titles'
|
9
9
|
autoload :Title, 'handbrake/titles'
|
10
10
|
autoload :Chapter, 'handbrake/titles'
|
11
|
+
|
12
|
+
##
|
13
|
+
# The exception thrown when a file exists that shouldn't.
|
14
|
+
#
|
15
|
+
# @see CLI#output
|
16
|
+
class FileExistsError < StandardError; end;
|
11
17
|
end
|
data/lib/handbrake/cli.rb
CHANGED
@@ -59,11 +59,88 @@ module HandBrake
|
|
59
59
|
# Performs a conversion. This method immediately begins the
|
60
60
|
# transcoding process; set all other options first.
|
61
61
|
#
|
62
|
+
# @param [String] filename the desired name for the final output
|
63
|
+
# file
|
64
|
+
# @param [Hash] options additional options to control the behavior
|
65
|
+
# of the output process
|
66
|
+
# @option options [Boolean,:ignore] :overwrite (true) determines
|
67
|
+
# the behavior if the desired output file already exists. If
|
68
|
+
# `true`, the file is replaced. If `false`, an exception is
|
69
|
+
# thrown. If `:ignore`, the file is skipped; i.e., HandBrakeCLI
|
70
|
+
# is not invoked.
|
71
|
+
# @option options [Boolean] :atomic (false) provides a
|
72
|
+
# pseudo-atomic mode for transcoded output. If true, the
|
73
|
+
# transcode will go into a temporary file and only be copied to
|
74
|
+
# the specified filename if it completes. The temporary filename
|
75
|
+
# is the target filename with `.handbraking` inserted before the
|
76
|
+
# extension. Any `:overwrite` checking will be applied to the
|
77
|
+
# target filename both before and after the transcode happens
|
78
|
+
# (the temporary file will always be overwritten). This option
|
79
|
+
# is intended to aid in writing automatically resumable batch
|
80
|
+
# scripts.
|
81
|
+
#
|
62
82
|
# @return [void]
|
63
|
-
def output(filename)
|
64
|
-
|
83
|
+
def output(filename, options={})
|
84
|
+
overwrite = options.delete :overwrite
|
85
|
+
case overwrite
|
86
|
+
when true, nil
|
87
|
+
# no special behavior
|
88
|
+
when false
|
89
|
+
raise FileExistsError, filename if File.exist?(filename)
|
90
|
+
when :ignore
|
91
|
+
if File.exist?(filename)
|
92
|
+
trace "Ignoring transcode to #{filename.inspect} because it already exists"
|
93
|
+
return
|
94
|
+
end
|
95
|
+
else
|
96
|
+
raise "Unsupported value for :overwrite: #{overwrite.inspect}"
|
97
|
+
end
|
98
|
+
|
99
|
+
atomic = options.delete :atomic
|
100
|
+
interim_filename =
|
101
|
+
if atomic
|
102
|
+
partial_filename(filename)
|
103
|
+
else
|
104
|
+
filename
|
105
|
+
end
|
106
|
+
|
107
|
+
unless options.empty?
|
108
|
+
raise "Unknown options for output: #{options.keys.inspect}"
|
109
|
+
end
|
110
|
+
|
111
|
+
run('--output', interim_filename)
|
112
|
+
|
113
|
+
if filename != interim_filename
|
114
|
+
replace =
|
115
|
+
if File.exist?(filename)
|
116
|
+
trace "#{filename.inspect} showed up during transcode"
|
117
|
+
case overwrite
|
118
|
+
when false
|
119
|
+
raise FileExistsError, filename
|
120
|
+
when :ignore
|
121
|
+
trace "- will leave #{filename.inspect} as is; copy #{interim_filename.inspect} manually if you want to replace it"
|
122
|
+
false
|
123
|
+
else
|
124
|
+
trace '- will replace with new transcode'
|
125
|
+
true
|
126
|
+
end
|
127
|
+
else
|
128
|
+
true
|
129
|
+
end
|
130
|
+
FileUtils.mv interim_filename, filename if replace
|
131
|
+
end
|
65
132
|
end
|
66
133
|
|
134
|
+
def partial_filename(name)
|
135
|
+
if File.basename(name).index '.'
|
136
|
+
dot_at = name.rindex '.'
|
137
|
+
name.dup.insert dot_at, '.handbraking'
|
138
|
+
else
|
139
|
+
name + '.handbraking'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
private :partial_filename
|
143
|
+
|
67
144
|
##
|
68
145
|
# Performs a title scan. Unlike HandBrakeCLI, if you do not
|
69
146
|
# specify a title, this method will return information for all
|
@@ -136,6 +213,10 @@ module HandBrake
|
|
136
213
|
end
|
137
214
|
end
|
138
215
|
|
216
|
+
def trace(msg)
|
217
|
+
$stderr.puts msg if trace?
|
218
|
+
end
|
219
|
+
|
139
220
|
##
|
140
221
|
# Copies this CLI instance and appends another command line switch
|
141
222
|
# plus optional arguments.
|
data/lib/handbrake/version.rb
CHANGED
data/spec/handbrake/cli_spec.rb
CHANGED
@@ -71,14 +71,167 @@ module HandBrake
|
|
71
71
|
end
|
72
72
|
|
73
73
|
it 'works' do
|
74
|
-
lambda { cli.
|
74
|
+
lambda { cli.preset_list }.should_not raise_error
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
78
|
describe '#output' do
|
79
|
+
let(:filename) { File.join(tmpdir, 'foo.m4v') }
|
80
|
+
|
81
|
+
def it_should_have_run(expected_fn=filename)
|
82
|
+
runner.actual_arguments.should == ['--output', expected_fn]
|
83
|
+
end
|
84
|
+
|
85
|
+
def it_should_not_have_run
|
86
|
+
runner.actual_arguments.should be_nil
|
87
|
+
end
|
88
|
+
|
79
89
|
it 'uses the --output argument' do
|
80
|
-
cli.output(
|
81
|
-
runner.actual_arguments.should ==
|
90
|
+
cli.output(filename)
|
91
|
+
runner.actual_arguments.should == ['--output', filename]
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'fails for an unknown option' do
|
95
|
+
lambda { cli.output(filename, :quux => 'zap') }.
|
96
|
+
should raise_error('Unknown options for output: [:quux]')
|
97
|
+
end
|
98
|
+
|
99
|
+
describe ':overwrite' do
|
100
|
+
context 'true' do
|
101
|
+
it 'executes when the file does not exist' do
|
102
|
+
cli.output(filename, :overwrite => true)
|
103
|
+
it_should_have_run
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'executes when the file exists' do
|
107
|
+
FileUtils.touch filename
|
108
|
+
cli.output(filename, :overwrite => true)
|
109
|
+
it_should_have_run
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'is the default' do
|
113
|
+
FileUtils.touch filename
|
114
|
+
cli.output(filename)
|
115
|
+
it_should_have_run
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'false' do
|
120
|
+
it 'executes when the file does not exist' do
|
121
|
+
cli.output(filename, :overwrite => false)
|
122
|
+
it_should_have_run
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'throws an exception when the file does exist' do
|
126
|
+
FileUtils.touch filename
|
127
|
+
lambda { cli.output(filename, :overwrite => false) }.
|
128
|
+
should raise_error(HandBrake::FileExistsError)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context ':ignore' do
|
133
|
+
it 'executes when the file does not exist' do
|
134
|
+
cli.output(filename, :overwrite => :ignore)
|
135
|
+
it_should_have_run
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'does nothing when the file does exist' do
|
139
|
+
FileUtils.touch filename
|
140
|
+
cli.output(filename, :overwrite => :ignore)
|
141
|
+
it_should_not_have_run
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'other value' do
|
146
|
+
it 'throws an exception' do
|
147
|
+
lambda { cli.output(filename, :overwrite => 'flip') }.
|
148
|
+
should raise_error('Unsupported value for :overwrite: "flip"')
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe ':atomic' do
|
154
|
+
context 'false' do
|
155
|
+
it 'executes normally' do
|
156
|
+
cli.output(filename, :atomic => false)
|
157
|
+
it_should_have_run
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'is the default' do
|
161
|
+
cli.output(filename)
|
162
|
+
it_should_have_run
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'true' do
|
167
|
+
let(:expected_temporary_file) { File.join(tmpdir, "foo.handbraking.m4v") }
|
168
|
+
|
169
|
+
it 'outputs to the temporary file with ".handbraking" inserted before the extension' do
|
170
|
+
cli.output(filename, :atomic => true)
|
171
|
+
it_should_have_run(expected_temporary_file)
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'appends .handbraking if the output file does not have an extension' do
|
175
|
+
cli.output(File.join(tmpdir('a.b.c'), 'foo'), :atomic => true)
|
176
|
+
it_should_have_run(File.join(tmpdir('a.b.c'), 'foo.handbraking'))
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'copies the output to the desired filename' do
|
180
|
+
cli.output(filename, :atomic => true)
|
181
|
+
File.read(filename).should == 'This is the file created by --output'
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'removes the temporary file' do
|
185
|
+
cli.output(filename, :atomic => true)
|
186
|
+
File.exist?(expected_temporary_file).should be_false
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'overwrites the temporary file if it exists' do
|
190
|
+
FileUtils.touch expected_temporary_file
|
191
|
+
cli.output(filename, :atomic => true)
|
192
|
+
it_should_have_run(expected_temporary_file)
|
193
|
+
end
|
194
|
+
|
195
|
+
describe 'and :overwrite' do
|
196
|
+
describe 'false' do
|
197
|
+
it 'throws an exception if the target filename exists initially' do
|
198
|
+
FileUtils.touch filename
|
199
|
+
lambda { cli.output(filename, :atomic => true, :overwrite => false) }.
|
200
|
+
should raise_error(HandBrake::FileExistsError)
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'throws an exception if the target filename exists after output' do
|
204
|
+
runner.behavior = lambda { FileUtils.touch filename }
|
205
|
+
lambda { cli.output(filename, :atomic => true, :overwrite => false) }.
|
206
|
+
should raise_error(HandBrake::FileExistsError)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe ':ignore' do
|
211
|
+
it 'does nothing if the target filename exists initially' do
|
212
|
+
FileUtils.touch filename
|
213
|
+
cli.output(filename, :atomic => true, :overwrite => :ignore)
|
214
|
+
it_should_not_have_run
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'does not copy the output if the target filename exists after encoding' do
|
218
|
+
runner.behavior = lambda {
|
219
|
+
File.open(filename, 'w') { |f| f.write 'Other process result' }
|
220
|
+
}
|
221
|
+
cli.output(filename, :atomic => true, :overwrite => :ignore)
|
222
|
+
File.read(filename).should == 'Other process result'
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'does not remove the temporary output if the target filename exists after encoding' do
|
226
|
+
runner.behavior = lambda {
|
227
|
+
File.open(filename, 'w') { |f| f.write 'Other process result' }
|
228
|
+
}
|
229
|
+
cli.output(filename, :atomic => true, :overwrite => :ignore)
|
230
|
+
File.exist?(expected_temporary_file).should be_true
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
82
235
|
end
|
83
236
|
end
|
84
237
|
|
data/spec/spec_helper.rb
CHANGED
@@ -2,38 +2,29 @@ require 'bundler'
|
|
2
2
|
Bundler.setup
|
3
3
|
|
4
4
|
require 'rspec'
|
5
|
+
require 'fileutils'
|
5
6
|
|
6
7
|
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
7
8
|
|
8
9
|
require 'handbrake'
|
9
10
|
|
10
11
|
RSpec.configure do |config|
|
11
|
-
# Captures everything printed to stdout during the block
|
12
|
-
# and returns it as a string.
|
13
|
-
def capture_stdout
|
14
|
-
old_stdout, $stdout = $stdout, StringIO.new
|
15
|
-
begin
|
16
|
-
yield
|
17
|
-
$stdout.string
|
18
|
-
ensure
|
19
|
-
$stdout = old_stdout
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
12
|
def tmpdir(sub=nil)
|
24
13
|
@tmpdir ||= begin
|
25
14
|
dirname = File.expand_path("../tmp", __FILE__)
|
26
|
-
mkdir_p dirname
|
15
|
+
FileUtils.mkdir_p dirname
|
27
16
|
dirname
|
28
17
|
end
|
29
18
|
if sub
|
30
19
|
full = File.join(@tmpdir, sub)
|
31
|
-
mkdir_p full
|
20
|
+
FileUtils.mkdir_p full
|
32
21
|
full
|
33
22
|
else
|
34
23
|
@tmpdir
|
35
24
|
end
|
36
25
|
end
|
26
|
+
|
27
|
+
config.after { FileUtils.rm_rf @tmpdir if @tmpdir }
|
37
28
|
end
|
38
29
|
|
39
30
|
module HandBrake
|
@@ -42,10 +33,22 @@ module HandBrake
|
|
42
33
|
# A stub implementation of the runner for HandBrake::CLI.
|
43
34
|
class StaticRunner
|
44
35
|
attr_accessor :output, :status
|
36
|
+
##
|
37
|
+
# A lambda that specifies desired side effects of execution or
|
38
|
+
# simulates things happening outside the execution but
|
39
|
+
# simultaneous with it.
|
40
|
+
attr_accessor :behavior
|
45
41
|
attr_reader :actual_arguments
|
46
42
|
|
47
43
|
def run(args)
|
48
44
|
@actual_arguments = args
|
45
|
+
if i = args.index('--output')
|
46
|
+
fn = args[i + 1]
|
47
|
+
File.open(fn, 'w') { |f| f.write 'This is the file created by --output' }
|
48
|
+
end
|
49
|
+
if behavior
|
50
|
+
behavior.call
|
51
|
+
end
|
49
52
|
HandBrake::CLI::RunnerResult.new(output, status)
|
50
53
|
end
|
51
54
|
|
metadata
CHANGED
@@ -1,96 +1,68 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: handbrake
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 0
|
10
|
-
version: 0.1.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Rhett Sutphin
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-08-07 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: rubytree
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &2153799900 !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
18
|
+
requirements:
|
27
19
|
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
hash: 61
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
- 8
|
33
|
-
- 1
|
20
|
+
- !ruby/object:Gem::Version
|
34
21
|
version: 0.8.1
|
35
22
|
type: :runtime
|
36
|
-
version_requirements: *id001
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: rspec
|
39
23
|
prerelease: false
|
40
|
-
|
24
|
+
version_requirements: *2153799900
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &2153799400 !ruby/object:Gem::Requirement
|
41
28
|
none: false
|
42
|
-
requirements:
|
29
|
+
requirements:
|
43
30
|
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
|
46
|
-
segments:
|
47
|
-
- 2
|
48
|
-
- 5
|
49
|
-
version: "2.5"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.5'
|
50
33
|
type: :development
|
51
|
-
version_requirements: *id002
|
52
|
-
- !ruby/object:Gem::Dependency
|
53
|
-
name: rake
|
54
34
|
prerelease: false
|
55
|
-
|
35
|
+
version_requirements: *2153799400
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &2153798940 !ruby/object:Gem::Requirement
|
56
39
|
none: false
|
57
|
-
requirements:
|
40
|
+
requirements:
|
58
41
|
- - ~>
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
hash: 59
|
61
|
-
segments:
|
62
|
-
- 0
|
63
|
-
- 9
|
64
|
-
- 0
|
42
|
+
- !ruby/object:Gem::Version
|
65
43
|
version: 0.9.0
|
66
44
|
type: :development
|
67
|
-
version_requirements: *id003
|
68
|
-
- !ruby/object:Gem::Dependency
|
69
|
-
name: yard
|
70
45
|
prerelease: false
|
71
|
-
|
46
|
+
version_requirements: *2153798940
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: yard
|
49
|
+
requirement: &2153798480 !ruby/object:Gem::Requirement
|
72
50
|
none: false
|
73
|
-
requirements:
|
51
|
+
requirements:
|
74
52
|
- - ~>
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
hash: 3
|
77
|
-
segments:
|
78
|
-
- 0
|
79
|
-
- 7
|
80
|
-
- 0
|
53
|
+
- !ruby/object:Gem::Version
|
81
54
|
version: 0.7.0
|
82
55
|
type: :development
|
83
|
-
|
84
|
-
|
85
|
-
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2153798480
|
58
|
+
description: A lightweight literate ruby wrapper for HandBrakeCLI, the command-line
|
59
|
+
interface for the HandBrake video transcoder.
|
60
|
+
email:
|
86
61
|
- rhett@detailedbalance.net
|
87
62
|
executables: []
|
88
|
-
|
89
63
|
extensions: []
|
90
|
-
|
91
64
|
extra_rdoc_files: []
|
92
|
-
|
93
|
-
files:
|
65
|
+
files:
|
94
66
|
- .gitignore
|
95
67
|
- .rvmrc
|
96
68
|
- .travis.yml
|
@@ -112,41 +84,31 @@ files:
|
|
112
84
|
- spec/handbrake/titles_spec.rb
|
113
85
|
- spec/handbrake/version_spec.rb
|
114
86
|
- spec/spec_helper.rb
|
115
|
-
has_rdoc: true
|
116
87
|
homepage: https://github.com/rsutphin/handbrake.rb
|
117
88
|
licenses: []
|
118
|
-
|
119
89
|
post_install_message:
|
120
90
|
rdoc_options: []
|
121
|
-
|
122
|
-
require_paths:
|
91
|
+
require_paths:
|
123
92
|
- lib
|
124
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
94
|
none: false
|
126
|
-
requirements:
|
127
|
-
- -
|
128
|
-
- !ruby/object:Gem::Version
|
129
|
-
|
130
|
-
|
131
|
-
- 0
|
132
|
-
version: "0"
|
133
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
100
|
none: false
|
135
|
-
requirements:
|
136
|
-
- -
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
|
139
|
-
segments:
|
140
|
-
- 0
|
141
|
-
version: "0"
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
142
105
|
requirements: []
|
143
|
-
|
144
106
|
rubyforge_project:
|
145
|
-
rubygems_version: 1.
|
107
|
+
rubygems_version: 1.8.6
|
146
108
|
signing_key:
|
147
109
|
specification_version: 3
|
148
110
|
summary: A ruby wrapper for HandBrakeCLI
|
149
|
-
test_files:
|
111
|
+
test_files:
|
150
112
|
- spec/handbrake/cli_spec.rb
|
151
113
|
- spec/handbrake/sample-preset-list.out
|
152
114
|
- spec/handbrake/sample-titles-scan.err
|