devver-germinate 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/History.txt +12 -0
  2. data/README.rdoc +26 -4
  3. data/TODO +80 -8
  4. data/bin/germ +162 -38
  5. data/examples/basic.rb +14 -9
  6. data/examples/short.rb +2 -0
  7. data/features/author-formats-article.feature +3 -3
  8. data/features/{author-lists-info.feature → author-lists-info.pending_feature} +3 -0
  9. data/features/author-publishes-article.feature +52 -0
  10. data/features/author-selects-hunks.feature +1 -1
  11. data/features/author-sets-variables.feature +88 -0
  12. data/features/{author-views-stuff.feature → author-views-stuff.pending_feature} +4 -0
  13. data/features/example_articles/escaping.txt +1 -0
  14. data/features/example_articles/specials.rb +3 -3
  15. data/features/example_output/specials.txt +9 -5
  16. data/features/step_definitions/germinate.rb +9 -0
  17. data/germinate.gemspec +3 -3
  18. data/lib/germinate.rb +1 -1
  19. data/lib/germinate/application.rb +82 -31
  20. data/lib/germinate/hunk.rb +20 -0
  21. data/lib/germinate/insertion.rb +10 -2
  22. data/lib/germinate/librarian.rb +129 -31
  23. data/lib/germinate/origin.rb +5 -0
  24. data/lib/germinate/pipeline.rb +2 -0
  25. data/lib/germinate/publisher.rb +57 -0
  26. data/lib/germinate/reader.rb +51 -8
  27. data/lib/germinate/selector.rb +18 -6
  28. data/lib/germinate/shared_style_attributes.rb +18 -1
  29. data/lib/germinate/{process.rb → shell_process.rb} +27 -8
  30. data/lib/germinate/shell_publisher.rb +19 -0
  31. data/lib/germinate/simple_publisher.rb +7 -0
  32. data/lib/germinate/source_file.rb +41 -0
  33. data/lib/germinate/text_transforms.rb +38 -9
  34. data/lib/germinate/transform_process.rb +25 -0
  35. data/lib/germinate/variable.rb +23 -0
  36. data/sample.rb +14 -0
  37. data/spec/germinate/application_spec.rb +18 -1
  38. data/spec/germinate/article_editor_spec.rb +3 -3
  39. data/spec/germinate/code_hunk_spec.rb +28 -0
  40. data/spec/germinate/file_hunk_spec.rb +1 -0
  41. data/spec/germinate/hunk_spec.rb +1 -0
  42. data/spec/germinate/insertion_spec.rb +2 -1
  43. data/spec/germinate/librarian_spec.rb +280 -85
  44. data/spec/germinate/pipeline_spec.rb +10 -0
  45. data/spec/germinate/process_spec.rb +31 -6
  46. data/spec/germinate/publisher_spec.rb +130 -0
  47. data/spec/germinate/reader_spec.rb +58 -2
  48. data/spec/germinate/selector_spec.rb +34 -14
  49. data/spec/germinate/shell_publisher_spec.rb +61 -0
  50. data/spec/germinate/source_file_spec.rb +99 -0
  51. data/spec/germinate/text_hunk_spec.rb +45 -0
  52. data/spec/germinate/text_transforms_spec.rb +90 -2
  53. data/spec/germinate/transform_process_spec.rb +50 -0
  54. data/spec/germinate/variable_spec.rb +14 -0
  55. metadata +19 -7
  56. data/lib/germinate/article_formatter.rb +0 -75
  57. data/spec/germinate/article_formatter_spec.rb +0 -153
@@ -21,4 +21,14 @@ module Germinate
21
21
  @it.call(@input).should == @output3
22
22
  end
23
23
  end
24
+
25
+ describe Pipeline, "given no processes" do
26
+ before :each do
27
+ @it = Pipeline.new([])
28
+ end
29
+
30
+ it "should pass input through unchanged" do
31
+ @it.call(["foo", "bar"]).should == ["foo", "bar"]
32
+ end
33
+ end
24
34
  end
@@ -2,21 +2,46 @@ require File.expand_path(
2
2
  File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
3
 
4
4
  module Germinate
5
- describe Process do
5
+ describe ShellProcess do
6
6
  before :each do
7
7
  @input = Germinate::Hunk.new(
8
8
  ["line 1\n", "line 2\n"],
9
9
  :comment_prefix => "//")
10
10
  @output = ["1 enil\n", "2 enil\n"]
11
11
  @command = stub("Command", :readlines => @output).as_null_object
12
+ @tempfile = stub("Temp File", :path => "TEMP_PATH").as_null_object
13
+ @status = stub("Child Status", :success => true)
12
14
  IO.stub!(:popen).and_yield(@command)
15
+ Tempfile.stub!(:open).and_yield(@tempfile)
16
+ end
17
+
18
+ context "given a command and some variables" do
19
+ before :each do
20
+ @it = Germinate::ShellProcess.new(
21
+ "myproc", "mycommand", { "FOO" => 123, "BAR" => 456 })
22
+ ENV["FOO"] = "xxx"
23
+ end
24
+
25
+ it "should set the variables in the environment before execution" do
26
+ IO.should_receive(:popen) do
27
+ ENV["FOO"].should == "123"
28
+ ENV["BAR"].should == "456"
29
+ end
30
+ @it.call(@input)
31
+ end
32
+
33
+ it "should reset the environment after execution" do
34
+ @it.call(@input)
35
+ ENV["FOO"].should == "xxx"
36
+ ENV["BAR"].should be_nil
37
+ end
13
38
  end
14
39
 
15
40
  context "given a command 'mycommand'" do
16
41
  before :each do
17
- @it = Germinate::Process.new("myproc", "mycommand")
42
+ @it = Germinate::ShellProcess.new("myproc", "mycommand")
18
43
  end
19
-
44
+
20
45
  context "when called on a hunk of text" do
21
46
  it "should pipe the input through the command" do
22
47
  @command.should_receive(:<<).with("line 1\n").ordered
@@ -33,16 +58,16 @@ module Germinate
33
58
  output = @it.call(@input)
34
59
  output.comment_prefix.should == "//"
35
60
  end
61
+
36
62
  end
37
63
  end
38
64
 
39
65
  context "given a command 'mycommand %f' and called on some text" do
40
66
  before :each do
41
- @it = Germinate::Process.new("myproc", "mycommand %f")
67
+ @it = Germinate::ShellProcess.new("myproc", "mycommand %f")
42
68
  end
43
69
 
44
70
  it "should create a temporary file and pass the name to the command" do
45
- @tempfile = stub("Temp File", :path => "TEMP_PATH")
46
71
  Tempfile.should_receive(:open).with("germinate_hunk").and_yield(@tempfile)
47
72
  @tempfile.should_receive(:<<).with("line 1\n").ordered
48
73
  @tempfile.should_receive(:<<).with("line 2\n").ordered
@@ -66,7 +91,7 @@ module Germinate
66
91
  @input = Germinate::FileHunk.new(
67
92
  ["line 1\n", "line 2\n"],
68
93
  {:source_path => "SOURCE_PATH"})
69
- @it = Germinate::Process.new("myproc", "mycommand %f")
94
+ @it = Germinate::ShellProcess.new("myproc", "mycommand %f")
70
95
  end
71
96
 
72
97
  it "should pass the source file path to the command" do
@@ -0,0 +1,130 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe Publisher do
6
+ before :each do
7
+ @name = "my_pub"
8
+ @hunk = stub("Input Hunk")
9
+ @output = stub("Pipeline Output")
10
+ @pipeline = stub("Pipeline", :call => @output)
11
+ @librarian = stub("Librarian",
12
+ :make_pipeline => @pipeline,
13
+ :[] => @hunk ).as_null_object
14
+ @options = {:a => 'b'}
15
+ end
16
+
17
+ context "when a new publisher type 'foo' is defined" do
18
+ before :each do
19
+ @it = Germinate::Publisher
20
+ @subclass = Class.new(Publisher) do
21
+ identifier "foo"
22
+ end
23
+ end
24
+
25
+ it "should be able to make 'foo' publishers" do
26
+ @publisher = stub("Publisher")
27
+ @subclass.should_receive(:new).with(@name, @librarian, @options).
28
+ and_return(@publisher)
29
+
30
+ @it.make(@name, "foo", @librarian, @options)
31
+ end
32
+
33
+ end
34
+
35
+ context "when an anonymous publisher subclass is defined" do
36
+ before :each do
37
+ @it = Germinate::Publisher
38
+ @subclass = Class.new(Publisher) do
39
+ self.identifier = nil
40
+ end
41
+ end
42
+
43
+ it "should not make the publisher available as an instantiable type" do
44
+ @librarian = stub("Librarian")
45
+ @options = {:a => 'b'}
46
+ @publisher = stub("Publisher")
47
+
48
+ lambda do
49
+ @it.make("mypub", nil, @librarian, @options)
50
+ end.should raise_error(IndexError)
51
+ end
52
+
53
+ end
54
+
55
+ context "given name, librarian, and options" do
56
+ before :each do
57
+ @name = "frank"
58
+ @librarian = stub("Librarian").as_null_object
59
+ @options = {:foo => "bar"}
60
+ @it = Publisher.new(@name, @librarian, @options)
61
+ end
62
+
63
+ it "should know its name" do
64
+ @it.name.should == @name
65
+ end
66
+
67
+ it "should know its librarian" do
68
+ @it.librarian.should == @librarian
69
+ end
70
+
71
+ it "should know its options" do
72
+ @it.options.should == @options
73
+ end
74
+ end
75
+
76
+ context "given a pipeline option" do
77
+ before :each do
78
+ @name = "frank"
79
+ @librarian = stub("Librarian").as_null_object
80
+ @options = {:pipeline => "foo|bar"}
81
+ end
82
+
83
+ it "should have a pipeline" do
84
+ @it = Publisher.new(@name, @librarian, @options)
85
+ @it.pipeline.should_not be_nil
86
+ end
87
+
88
+ it "should use the librarian to construct a pipeline" do
89
+ @librarian.should_receive(:make_pipeline).with("foo|bar")
90
+ @it = Publisher.new(@name, @librarian, @options)
91
+ end
92
+ end
93
+
94
+ context "with no selector specified" do
95
+ before :each do
96
+ @it = Publisher.new(@name, @librarian, @options)
97
+ end
98
+
99
+ it "should select $TEXT|_transform" do
100
+ @it.selector.should == "$TEXT|_transform"
101
+ end
102
+
103
+ end
104
+
105
+ context "with a custom selector specified" do
106
+ before :each do
107
+ @it = Publisher.new(@name, @librarian, { :selector => "@sec1|myproc" })
108
+ end
109
+
110
+ it "should have the specified selector" do
111
+ @it.selector.should == "@sec1|myproc"
112
+ end
113
+
114
+ it "should use the selector to get a hunk to process" do
115
+ @librarian.should_receive(:[]).
116
+ with("@sec1|myproc", anything)
117
+ @it.input
118
+ end
119
+
120
+ it "should pass the selected hunk through the pipeline to get input" do
121
+ @pipeline.should_receive(:call).with(@hunk)
122
+ @it.input
123
+ end
124
+
125
+ it "should use pipeline output as input to publisher process" do
126
+ @it.input.should == @output
127
+ end
128
+ end
129
+ end
130
+ end
@@ -45,8 +45,8 @@ module Germinate
45
45
  CONTROL_LINES = [
46
46
  # Line Comment Args
47
47
  [":TEXT:\n", nil, []],
48
- ["# :CUT: \n", "#", []],
49
- [" ; :TEXT: foo\n", ";", ["foo"]],
48
+ ["# :CUT: \n", "# ", []],
49
+ [" ; :TEXT: foo\n", " ; ", ["foo"]],
50
50
  ["//:SAMPLE:\n", "//", []],
51
51
  ["$>:END: ", "$>", []],
52
52
  [":SAMPLE: bar, { a: 1, b: 2 }", nil, ["bar", {"a"=>1, "b"=>2}]],
@@ -225,6 +225,19 @@ module Germinate
225
225
  end
226
226
  end
227
227
 
228
+ context "given a :SAMPLE: after a TEXT section with the same name" do
229
+ before :each do
230
+ @it << ":TEXT: foobar\n"
231
+ @it << "This is the text\n"
232
+ end
233
+
234
+ it "should add an implicit insertion to the TEXT section" do
235
+ @librarian.should_receive(:add_insertion!).with("foobar", "@foobar", {})
236
+ @it << ":SAMPLE: foobar\n"
237
+ end
238
+
239
+ end
240
+
228
241
  context "given a :SAMPLE: keyword with custom brackets" do
229
242
  before :each do
230
243
  @line = ':SAMPLE: foobar, { brackets: ["<<", ">>"] }'
@@ -314,6 +327,25 @@ module Germinate
314
327
 
315
328
  end
316
329
 
330
+ context "given an insertion with the special disable_transforms attr" do
331
+ before :each do
332
+ @it << ":TEXT: mysection"
333
+ @line = ":INSERT: foo, { disable_transforms: true } "
334
+ end
335
+
336
+ it "should disable all transforms in the options" do
337
+ @librarian.should_receive(:add_insertion!) do
338
+ |section, selector, options|
339
+
340
+ TextTransforms.singleton_methods.each do |transform|
341
+ options[transform.to_sym].should be_false
342
+ end
343
+ end
344
+ @it << @line
345
+ end
346
+
347
+ end
348
+
317
349
  context "given a process directive" do
318
350
  before :each do
319
351
  @line = ' # :PROCESS: sortail, "sort | tail"'
@@ -325,5 +357,29 @@ module Germinate
325
357
  end
326
358
  end
327
359
 
360
+ context "given a publisher directive" do
361
+ before :each do
362
+ @line = ' # :PUBLISHER: source, shell, { command: "cat %f" }'
363
+ end
364
+
365
+ it "should add the publisher to the librarian" do
366
+ @librarian.should_receive(:add_publisher!).
367
+ with("source", "shell", { :command => "cat %f" })
368
+ @it << @line
369
+ end
370
+ end
371
+
372
+ context "given a set directive" do
373
+ before :each do
374
+ @line = ' # :SET: name, value'
375
+ end
376
+
377
+ it "should set a variable on the librarian" do
378
+ @librarian.should_receive(:set_variable!).
379
+ with(@line, 1, "name", "value")
380
+ @it << @line
381
+ end
382
+ end
383
+
328
384
  end
329
385
  end
@@ -3,6 +3,11 @@ require File.expand_path(
3
3
 
4
4
  module Germinate
5
5
  describe Selector do
6
+
7
+ it "should be comparable to a string" do
8
+ Selector.new("@A:1..5").should be == "@A:1..5"
9
+ Selector.new("@A:1..5").should_not be == "@A:1..6"
10
+ end
6
11
 
7
12
  context "given a subscript" do
8
13
  before :each do
@@ -31,21 +36,36 @@ module Germinate
31
36
  specify { @it.should be_whole }
32
37
  end
33
38
 
39
+ context "given no type sigil or key" do
40
+ before :each do
41
+ @it = Selector.new(":2..5")
42
+ end
43
+
44
+ it "should have type code" do
45
+ @it.selector_type.should == :special
46
+ end
47
+
48
+ it "should have key SOURCE" do
49
+ @it.key.should == "SOURCE"
50
+ end
51
+ end
52
+
34
53
  EXAMPLE_SELECTORS = [
35
- # selector type key delim start end length pipeline excerpt_output?
36
- [ "@A", :code, "A", '..', 1, -1, nil, [] ,false],
37
- [ "@A:1", :code, "A", nil, 1, 1, nil, [] ,false],
38
- [ "", :code, "DEFAULT", '..', 1, -1, nil, [] ,false],
39
- [ nil, :code, "DEFAULT", '..', 1, -1, nil, [] ,false],
40
- [ ":2..4", :code, "DEFAULT", '..', 2, 4, nil, [] ,false],
41
- [ ":2...4", :code, "DEFAULT", '...', 2, 4, nil, [] ,false],
42
- [ "@B:2,5", :code, "B", ',', 2, nil,5, [] ,false],
43
- [ "@B:/z/,6", :code, "B", ',', /z/, nil,6, [] ,false],
44
- [ "@_:/z/../x/", :code, "_", '..', /z/, /x/,nil, [] ,false],
45
- [ "@B:2,4|fnord",:code, "B", ',', 2, nil,4, ["fnord"],false],
46
- [ "$FOO", :special, "FOO", '..', 1, -1, nil, [] ,false],
47
- [ "@A|foo|bar", :code, "A", '..', 1, -1, nil, ["foo", "bar"],false],
48
- [ "@B|fnord:2,4",:code, "B", ',', 2, nil,4, ["fnord"],true],
54
+ # selector type key delim start end length pipeline excerpt_output?
55
+ [ "@A", :code, "A", '..', 1, -1, nil, %w[_transform] ,false],
56
+ [ "@A:1", :code, "A", nil, 1, 1, nil, %w[_transform] ,false],
57
+ [ "", :code, "DEFAULT", '..', 1, -1, nil, %w[_transform] ,false],
58
+ [ nil, :code, "DEFAULT", '..', 1, -1, nil, %w[_transform] ,false],
59
+ [ ":2..4", :code, "DEFAULT", '..', 2, 4, nil, %w[_transform] ,false],
60
+ [ ":2...4", :code, "DEFAULT", '...', 2, 4, nil, %w[_transform] ,false],
61
+ [ "@B:2,5", :code, "B", ',', 2, nil,5, %w[_transform] ,false],
62
+ [ "@B:/z/,6", :code, "B", ',', /z/, nil,6, %w[_transform] ,false],
63
+ [ "@_:/z/../x/", :code, "_", '..', /z/, /x/,nil, %w[_transform] ,false],
64
+ [ "@B:2,4|fnord",:code, "B", ',', 2, nil,4, %w[_transform fnord] ,false],
65
+ [ "$FOO", :special, "FOO", '..', 1, -1, nil, %w[_transform] ,false],
66
+ [ "@A|foo|bar", :code, "A", '..', 1, -1, nil, %w[_transform foo bar],false],
67
+ [ "@B|fnord:2,4",:code, "B", ',', 2, nil,4, %w[_transform fnord],true],
68
+ [ "@B|_transform",:code, "B", '..', 1, -1, nil, %w[_transform], false]
49
69
  ]
50
70
 
51
71
  EXAMPLE_SELECTORS.each do |selector_attributes|
@@ -0,0 +1,61 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe ShellPublisher do
6
+ before :each do
7
+ @name = "frank"
8
+ @pipeline_output = ["* line 1\n", "* line 2\n"]
9
+ @pipeline = stub("Pipeline", :call => @pipeline_output)
10
+ @variables = stub("Variables")
11
+ @librarian = stub("Librarian",
12
+ :make_pipeline => @pipeline,
13
+ :variables => @variables)
14
+ @command = "cat %f"
15
+ @options = {:command => @command}
16
+ @it = ShellPublisher.new(@name, @librarian, @options)
17
+ end
18
+
19
+ it "should have identifier 'shell'" do
20
+ ShellPublisher.identifier.should == "shell"
21
+ end
22
+
23
+ context "on publish" do
24
+ before :each do
25
+ @result = ["line 1\n", "line 2\n"]
26
+ @output = StringIO.new
27
+ @process = stub("ShellProcess", :call => @result).as_null_object
28
+ @source = stub("Source").as_null_object
29
+ @librarian.stub!(:[]).and_return(@source)
30
+ ShellProcess.stub!(:new).and_return(@process)
31
+ end
32
+
33
+ it "should create a new process" do
34
+ ShellProcess.should_receive(:new).with(@name, @command, @variables)
35
+ @it.publish!(@output)
36
+ end
37
+
38
+ it "should execute the created process" do
39
+ @process.should_receive(:call).with(anything).and_return(@result)
40
+ @it.publish!(@output)
41
+ end
42
+
43
+ it "should pass the pipeline output to the created process" do
44
+ @process.should_receive(:call).with(@pipeline_output).and_return(@result)
45
+ @it.publish!(@output)
46
+ end
47
+
48
+ it "should ask the librarian for the source file" do
49
+ @librarian.should_receive(:[]).with("$TEXT|_transform", anything)
50
+ @it.publish!(@output)
51
+ end
52
+
53
+ it "should write process output to given output stream" do
54
+ @it.publish!(@output)
55
+ @output.rewind
56
+ @output.read.should == "line 1\nline 2\n"
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,99 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe SourceFile do
6
+ before :each do
7
+ @it = SourceFile.new("DIR/SOURCE_PATH.EXT")
8
+ @file = stub("File", :flock => 0)
9
+ @lines = ["Line 1\n", "Line 2\n"]
10
+ File.stub!(:new).and_return(@file)
11
+ FileUtils.stub!(:cp)
12
+ end
13
+
14
+ it "should have a source path" do
15
+ @it.path.to_s.should == "DIR/SOURCE_PATH.EXT"
16
+ end
17
+
18
+ it "should append .germ.back for the backup path" do
19
+ @it.backup_path.to_s.should == "DIR/SOURCE_PATH.EXT.germ.bak"
20
+ end
21
+
22
+ context "when writing" do
23
+ before :each do
24
+ @open_file = stub("Open File", :write => nil)
25
+ @path = stub("Source Path", :read => "...")
26
+ @path.stub!(:open).and_yield(@open_file)
27
+ @backup_path = stub("BACKUP_PATH", :read => "...")
28
+ @it.backup_path = @backup_path
29
+ @it.path = @path
30
+ end
31
+
32
+ it "should lock and unlock the source path" do
33
+ File.should_receive(:new).with(@it.path).and_return(@file)
34
+ @file.should_receive(:flock).with(File::LOCK_EX).ordered.and_return(0)
35
+ @file.should_receive(:flock).with(File::LOCK_UN).ordered
36
+ @it.write!(@lines)
37
+ end
38
+
39
+ it "should raise error if locking fails" do
40
+ @file.should_receive(:flock).with(File::LOCK_EX).ordered.and_return(1)
41
+ @file.should_receive(:flock).with(File::LOCK_UN).ordered
42
+
43
+ lambda do
44
+ @it.write!(@lines)
45
+ end.should raise_error(RuntimeError)
46
+ end
47
+
48
+ it "should make a backup copy after locking the file" do
49
+ @file.should_receive(:flock).with(File::LOCK_EX).ordered.and_return(0)
50
+ FileUtils.should_receive(:cp).with(@it.path, @backup_path).ordered
51
+ @it.write!(@lines)
52
+ end
53
+
54
+ it "should make no backup if locking fails" do
55
+ @file.should_receive(:flock).with(File::LOCK_EX).ordered.and_return(1)
56
+ FileUtils.should_not_receive(:cp)
57
+ @it.write!(@lines) rescue nil
58
+ end
59
+
60
+ it "should unlock the file if backup fails" do
61
+ FileUtils.should_receive(:cp).and_raise("Some Error")
62
+ @file.should_receive(:flock).with(File::LOCK_UN)
63
+ @it.write!(@lines) rescue nil
64
+ end
65
+
66
+ it "should raise error if source file and backup are not equal" do
67
+ @path.should_receive(:read).and_return("...")
68
+ @backup_path.should_receive(:read).and_return("....")
69
+ lambda do @it.write!(@lines) end.should raise_error(RuntimeError)
70
+ end
71
+
72
+ it "should not open the source file if comparison fails" do
73
+ @path.should_receive(:read).and_return("...")
74
+ @backup_path.should_receive(:read).and_return("....")
75
+ @path.should_not_receive(:open)
76
+ lambda do @it.write!(@lines) end.should raise_error(RuntimeError)
77
+ end
78
+
79
+ it "should open the source file for overwriting after backing up" do
80
+ FileUtils.should_receive(:cp).ordered
81
+ @path.should_receive(:open).with('w+').ordered
82
+ @it.write!(@lines)
83
+ end
84
+
85
+ it "should write lines to the source file" do
86
+ @open_file.should_receive(:write).with("Line 1\n").ordered
87
+ @open_file.should_receive(:write).with("Line 2\n").ordered
88
+ @it.write!(@lines)
89
+ end
90
+
91
+ it "should restore backup if write fails" do
92
+ @open_file.should_receive(:write).and_raise("Some Failure")
93
+ FileUtils.should_receive(:cp).with(@backup_path, @path)
94
+ lambda do @it.write!(@lines) end.should raise_error(RuntimeError)
95
+ end
96
+
97
+ end
98
+ end
99
+ end