automateit 0.70923

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.
Files changed (119) hide show
  1. data.tar.gz.sig +1 -0
  2. data/CHANGES.txt +100 -0
  3. data/Hoe.rake +35 -0
  4. data/Manifest.txt +111 -0
  5. data/README.txt +44 -0
  6. data/Rakefile +284 -0
  7. data/TESTING.txt +57 -0
  8. data/TODO.txt +26 -0
  9. data/TUTORIAL.txt +390 -0
  10. data/bin/ai +3 -0
  11. data/bin/aifield +82 -0
  12. data/bin/aitag +128 -0
  13. data/bin/automateit +117 -0
  14. data/docs/friendly_errors.txt +50 -0
  15. data/docs/previews.txt +86 -0
  16. data/env.sh +4 -0
  17. data/examples/basic/Rakefile +26 -0
  18. data/examples/basic/config/automateit_env.rb +16 -0
  19. data/examples/basic/config/fields.yml +3 -0
  20. data/examples/basic/config/tags.yml +13 -0
  21. data/examples/basic/dist/README.txt +9 -0
  22. data/examples/basic/dist/myapp_server.erb +30 -0
  23. data/examples/basic/install.log +15 -0
  24. data/examples/basic/lib/README.txt +10 -0
  25. data/examples/basic/recipes/README.txt +4 -0
  26. data/examples/basic/recipes/install.rb +53 -0
  27. data/examples/basic/recipes/uninstall.rb +6 -0
  28. data/gpl.txt +674 -0
  29. data/lib/automateit.rb +66 -0
  30. data/lib/automateit/account_manager.rb +106 -0
  31. data/lib/automateit/account_manager/linux.rb +171 -0
  32. data/lib/automateit/account_manager/passwd.rb +69 -0
  33. data/lib/automateit/account_manager/portable.rb +136 -0
  34. data/lib/automateit/address_manager.rb +165 -0
  35. data/lib/automateit/address_manager/linux.rb +80 -0
  36. data/lib/automateit/address_manager/portable.rb +37 -0
  37. data/lib/automateit/cli.rb +80 -0
  38. data/lib/automateit/common.rb +65 -0
  39. data/lib/automateit/constants.rb +33 -0
  40. data/lib/automateit/edit_manager.rb +292 -0
  41. data/lib/automateit/error.rb +10 -0
  42. data/lib/automateit/field_manager.rb +103 -0
  43. data/lib/automateit/interpreter.rb +641 -0
  44. data/lib/automateit/package_manager.rb +242 -0
  45. data/lib/automateit/package_manager/apt.rb +63 -0
  46. data/lib/automateit/package_manager/egg.rb +64 -0
  47. data/lib/automateit/package_manager/gem.rb +179 -0
  48. data/lib/automateit/package_manager/portage.rb +69 -0
  49. data/lib/automateit/package_manager/yum.rb +65 -0
  50. data/lib/automateit/platform_manager.rb +47 -0
  51. data/lib/automateit/platform_manager/darwin.rb +30 -0
  52. data/lib/automateit/platform_manager/debian.rb +26 -0
  53. data/lib/automateit/platform_manager/freebsd.rb +25 -0
  54. data/lib/automateit/platform_manager/gentoo.rb +26 -0
  55. data/lib/automateit/platform_manager/lsb.rb +40 -0
  56. data/lib/automateit/platform_manager/struct.rb +78 -0
  57. data/lib/automateit/platform_manager/uname.rb +29 -0
  58. data/lib/automateit/platform_manager/windows.rb +33 -0
  59. data/lib/automateit/plugin.rb +7 -0
  60. data/lib/automateit/plugin/base.rb +32 -0
  61. data/lib/automateit/plugin/driver.rb +218 -0
  62. data/lib/automateit/plugin/manager.rb +232 -0
  63. data/lib/automateit/project.rb +460 -0
  64. data/lib/automateit/root.rb +14 -0
  65. data/lib/automateit/service_manager.rb +79 -0
  66. data/lib/automateit/service_manager/chkconfig.rb +39 -0
  67. data/lib/automateit/service_manager/rc_update.rb +37 -0
  68. data/lib/automateit/service_manager/sysv.rb +126 -0
  69. data/lib/automateit/service_manager/update_rcd.rb +35 -0
  70. data/lib/automateit/shell_manager.rb +261 -0
  71. data/lib/automateit/shell_manager/base_link.rb +67 -0
  72. data/lib/automateit/shell_manager/link.rb +24 -0
  73. data/lib/automateit/shell_manager/portable.rb +421 -0
  74. data/lib/automateit/shell_manager/symlink.rb +32 -0
  75. data/lib/automateit/shell_manager/which.rb +25 -0
  76. data/lib/automateit/tag_manager.rb +63 -0
  77. data/lib/automateit/tag_manager/struct.rb +101 -0
  78. data/lib/automateit/tag_manager/tag_parser.rb +91 -0
  79. data/lib/automateit/tag_manager/yaml.rb +29 -0
  80. data/lib/automateit/template_manager.rb +55 -0
  81. data/lib/automateit/template_manager/base.rb +172 -0
  82. data/lib/automateit/template_manager/erb.rb +17 -0
  83. data/lib/ext/metaclass.rb +17 -0
  84. data/lib/ext/object.rb +18 -0
  85. data/lib/hashcache.rb +22 -0
  86. data/lib/helpful_erb.rb +63 -0
  87. data/lib/nested_error.rb +33 -0
  88. data/lib/queued_logger.rb +68 -0
  89. data/lib/tempster.rb +239 -0
  90. data/misc/index_gem_repository.rb +303 -0
  91. data/misc/setup_egg.rb +12 -0
  92. data/misc/setup_gem_dependencies.sh +7 -0
  93. data/misc/setup_rubygems.sh +21 -0
  94. data/misc/which.cmd +6 -0
  95. data/spec/extras/automateit_service_sysv_test +50 -0
  96. data/spec/extras/scratch.rb +15 -0
  97. data/spec/extras/simple_recipe.rb +8 -0
  98. data/spec/integration/account_manager_spec.rb +218 -0
  99. data/spec/integration/address_manager_linux_spec.rb +119 -0
  100. data/spec/integration/address_manager_portable_spec.rb +30 -0
  101. data/spec/integration/cli_spec.rb +215 -0
  102. data/spec/integration/examples_spec.rb +54 -0
  103. data/spec/integration/examples_spec_editor.rb +71 -0
  104. data/spec/integration/package_manager_spec.rb +104 -0
  105. data/spec/integration/platform_manager_spec.rb +69 -0
  106. data/spec/integration/service_manager_sysv_spec.rb +115 -0
  107. data/spec/integration/shell_manager_spec.rb +471 -0
  108. data/spec/integration/template_manager_erb_spec.rb +31 -0
  109. data/spec/spec_helper.rb +23 -0
  110. data/spec/unit/edit_manager_spec.rb +162 -0
  111. data/spec/unit/field_manager_spec.rb +79 -0
  112. data/spec/unit/hashcache_spec.rb +28 -0
  113. data/spec/unit/interpreter_spec.rb +98 -0
  114. data/spec/unit/platform_manager_spec.rb +44 -0
  115. data/spec/unit/plugins_spec.rb +253 -0
  116. data/spec/unit/tag_manager_spec.rb +189 -0
  117. data/spec/unit/template_manager_erb_spec.rb +137 -0
  118. metadata +249 -0
  119. metadata.gz.sig +0 -0
@@ -0,0 +1,17 @@
1
+ # == TemplateManager::ERB
2
+ #
3
+ # Renders ERB templates for TemplateManager.
4
+ class AutomateIt::TemplateManager::ERB < AutomateIt::TemplateManager::BaseDriver
5
+ depends_on :nothing
6
+
7
+ def suitability(method, *args) # :nodoc:
8
+ return 1
9
+ end
10
+
11
+ # See documentation for TemplateManager#render
12
+ def render(*options)
13
+ return _render_helper(*options) do |o|
14
+ HelpfulERB.new(o[:text], o[:filename]).result(o[:binder])
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
2
+
3
+ class Object
4
+ # The hidden singleton lurks behind everyone
5
+ def metaclass; class << self; self; end; end
6
+ def meta_eval &blk; metaclass.instance_eval &blk; end
7
+
8
+ # Adds methods to a metaclass
9
+ def meta_def name, &blk
10
+ meta_eval { define_method name, &blk }
11
+ end
12
+
13
+ # Defines an instance method within a class
14
+ def class_def name, &blk
15
+ class_eval { define_method name, &blk }
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ class Object
2
+ # Lists methods unique to an instance.
3
+ def unique_methods
4
+ (public_methods - Object.methods).sort
5
+ end
6
+
7
+ # Lists methods unique to a class.
8
+ def self.unique_methods
9
+ (public_methods - Object.methods).sort
10
+ end
11
+
12
+ # Returns a list of arguments and an options hash. Source taken from RSpec.
13
+ def args_and_opts(*args)
14
+ options = Hash === args.last ? args.pop : {}
15
+ return args, options
16
+ end
17
+ end
18
+
@@ -0,0 +1,22 @@
1
+ # A very simple cache. Works just like a Hash, but can optionally store values
2
+ # during the fetch process.
3
+ #
4
+ # Example:
5
+ # hc = HashCache.new
6
+ # hc.fetch("foo")
7
+ # => nil
8
+ # hc.fetch("foo"){:bar} # Block gets called because 'foo' is nil
9
+ # => :bar
10
+ # hc.fetch("foo"){raise "Block won't be called because 'foo' is cached"}
11
+ # => :bar
12
+ class HashCache < Hash
13
+ def fetch(key, &block)
14
+ if has_key?(key)
15
+ self[key]
16
+ elsif block
17
+ self[key] = block.call
18
+ else
19
+ nil
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,63 @@
1
+ require 'erb'
2
+ require 'nested_error'
3
+
4
+ class HelpfulERB
5
+ class Error < ::NestedError; end
6
+
7
+ # ERB object
8
+ attr_accessor :erb
9
+
10
+ attr_accessor :lines_before
11
+
12
+ attr_accessor :lines_after
13
+
14
+ # Template filename
15
+ attr_accessor :filename
16
+
17
+ def initialize(text, filename=nil, opts={})
18
+ @text = text
19
+ @filename = filename
20
+ @lines_before = opts[:before] || 5
21
+ @lines_after = opts[:before] || 1
22
+
23
+ @erb = ::ERB.new(@text, nil, '-')
24
+ @erb.filename = @filename if @filename
25
+ end
26
+
27
+ def result(binder=nil)
28
+ begin
29
+ return @erb.result(binder)
30
+ rescue Exception => e
31
+ stack = caller 0
32
+ for i in 0..e.backtrace.size
33
+ l = e.backtrace[i]
34
+ #puts "%s %s" % [i, l];
35
+ break if l =~ /^([^:]+):(\d+):in `(render|result)'$/
36
+ end
37
+ template = $1
38
+ line_number = $2.to_i
39
+ raise Exception.new("Caught ERB error but couldn't find line number in backtrace:\n#{e.backtrace.join("\n")}") unless line_number
40
+
41
+ lines = @text.split(/\n/)
42
+
43
+ min = line_number - @lines_before
44
+ min = 0 if min < 0
45
+
46
+ max = line_number + @lines_after
47
+ max = lines.size if max > lines.size
48
+
49
+ width = max.to_s.size
50
+
51
+ msg = "Problem with template '#{template}' at line #{line_number}:\n"
52
+ for i in min..max
53
+ n = i+1
54
+ marker = n == line_number ? "*" : ""
55
+ msg << "\n%2s %#{width}i %s" % [marker, n, lines[i]]
56
+ end
57
+ msg << "\n\n(#{e.exception.class}) #{e.message}"
58
+
59
+
60
+ raise NestedError.new(msg, e)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,33 @@
1
+ # == NestedError
2
+ #
3
+ # An exception class that records the cause of another error. Useful when you
4
+ # need to raise a general kind of error, yet still be able to determine the
5
+ # underlying cause.
6
+ #
7
+ # Example:
8
+ #
9
+ # class MyGeneralError < NestedError; end
10
+ #
11
+ # begin
12
+ # begin
13
+ # # Cause a specific error
14
+ # 1/0 # Divide by zero error
15
+ # rescue Exception => e
16
+ # # Wrap the specific error in a general, nested error
17
+ # raise MyGeneralError("Something bad happened!", e)
18
+ # end
19
+ # rescue MyGeneralError => e
20
+ # # Intercept the nested error and inspect the cause
21
+ # puts e.message # => "Something bad happened!"
22
+ # puts e.cause.message # => "divided by 0"
23
+ # end
24
+ class NestedError < StandardError
25
+ attr_accessor :cause
26
+
27
+ # Create a NestedObject with a +message+ String and a +cause+ Exception.
28
+ def initialize(message, cause)
29
+ self.cause = cause
30
+ super(message)
31
+ end
32
+ end
33
+
@@ -0,0 +1,68 @@
1
+ require 'logger'
2
+
3
+ class QueuedLogger < Logger
4
+ def initialize(*args)
5
+ super(*args)
6
+ @queue = []
7
+ @emitted = false
8
+ end
9
+
10
+ def process_queue
11
+ if queued?
12
+ while true
13
+ entry = @queue.shift or break
14
+ severity, message = entry
15
+ raw_method = "#{severity}_without_queue"
16
+ severity_i = self.class.send(:const_get, severity.to_s.upcase)
17
+ send(raw_method, message)
18
+ end
19
+ end
20
+ end
21
+
22
+ def enqueue(level, message)
23
+ @queue << [level, message]
24
+ @emitted = false
25
+ end
26
+
27
+ def dequeue(level=nil, message=nil)
28
+ if queued?
29
+ @queue.clear
30
+ elsif level and message
31
+ send("%s_without_queue"%level, message) if @emitted
32
+ end
33
+ @emitted = false
34
+ end
35
+
36
+ def queued?
37
+ ! @queue.empty?
38
+ end
39
+
40
+ for level in %w(debug info warn error fatal) do
41
+ class_eval <<-EOB
42
+ def #{level}_with_queue(*args)
43
+ severity = self.class.send(:const_get, "#{level.upcase}")
44
+ process_queue if severity >= self.level
45
+ @emitted = true
46
+ #{level}_without_queue(*args)
47
+ end
48
+ alias_method_chain :#{level}, :queue
49
+ EOB
50
+ end
51
+
52
+ end
53
+
54
+ if __FILE__ == $0
55
+ # TODO QueuedLogger -- write a spec
56
+
57
+ q = QueuedLogger.new($stdout)
58
+ q.level = Logger::INFO
59
+ q.info("first message")
60
+ q.enqueue(:info, "queued message that'll be pushed")
61
+ q.info("second message, which pushed out queued message")
62
+ q.enqueue(:error, "ERROR: queued message that'll be discarded")
63
+ q.debug("ERROR: message that'll be discarded and won't push queue")
64
+ q.dequeue(:error, "ERROR: dequeue message that'll be discarded")
65
+ q.enqueue(:info, "queued message that'll be pushed")
66
+ q.info("message that'll push out the queue and dequeue messages")
67
+ q.dequeue(:info, "dequeue message that'll be pushed")
68
+ end
@@ -0,0 +1,239 @@
1
+ require 'tmpdir'
2
+ require 'fileutils'
3
+
4
+ # == Tempster
5
+ #
6
+ # Tempster is a pure-Ruby library for creating temporary files and directories.
7
+ # Unlike other tools, it can create both temporary files and directories, and
8
+ # is designed to be secure, thread-safe, easy-to-use, powerful thanks to
9
+ # user-configurable options, and user-friendly thanks to good defaults so you
10
+ # don't need to provide any arguments.
11
+ #
12
+ # Why write another library for this? The Tempfile standard library provides no
13
+ # way to create temporary directories and always deletes the files it creates,
14
+ # even if you want to keep them. The MkTemp gem is insecure and fails on
15
+ # collisions. Linux "mktemp" works fine but is platform-specific. Therefore, I
16
+ # had to write something.
17
+ #
18
+ # === WARNING: Using 'cd' and :noop together can be dangerous!
19
+ #
20
+ # Tempster will only *pretend* to make directories in :noop (no-operation)
21
+ # mode. In :noop mode, it will also only *pretend* to change into the directory
22
+ # when using :cd or +mktempdircd+.
23
+ #
24
+ # This can be *disastrous* if you're executing non-AutomateIt commands (e.g.
25
+ # +system+) that use *relative* *paths* and expect to be run inside the
26
+ # newly-created temporary directory because the +chdir+ didn't actually happen.
27
+ #
28
+ # Read previews.txt[link:files/docs/previews_txt.html] for instructions on how
29
+ # to write code that can be safely previewed.
30
+ #
31
+ # == Credits
32
+ # * Random string generator taken from
33
+ # http://pleac.sourceforge.net/pleac_ruby/numbers.html
34
+ class Tempster
35
+ DEFAULT_NAME = "tempster"
36
+ DEFAULT_FILE_MODE = 0600
37
+ DEFAULT_DIRECTORY_MODE = 0700
38
+ DEFAULT_ARMOR_LENGTH = 10
39
+ ARMOR_CHARACTERS = ["A".."Z","a".."z","0".."9"].collect{|r| r.to_a}.join
40
+
41
+ # Options:
42
+ # * :name -- Name prefix to usse, defaults to "tempster".
43
+ # * :kind -- Create a :file or :directory, required.
44
+ # * :dir -- Base directory to create temporary entries in, uses system-wide temporary directory (e.g., <tt>/tmp</tt>) by default.
45
+ # * :cd -- Change into the newly directory created using +ch+ within the block, and then switch back to the previous directory. Only used when a block is given and the :kind is :directory. Default is false. See WARNING at the top of this class's documentation!
46
+ # * :noop -- no-operation mode, pretends to do actions without actually creating or deleting temporary entries. Default is false. WARNING: See WARNING at the top of this class's documentation!
47
+ # * :verbose -- Print status messages about creating and deleting the temporary entries. Default is false.
48
+ # * :delete -- Delete the temporary entries when exiting block. Default is true when given a block, false otherwise. If you don't use a block, you're responsible for deleting the entries yourself.
49
+ # * :tries -- Number of tries to create a temporary entry, usually it'll succeed on the first try. Default is 10.
50
+ # * :armor -- Length of armor to add to the name. These are random characters padding out the temporary entry names to prevent them from using existing files. If you have a very short armor, you're likely to get a collision and the algorithm will have to try again for the specified number of +tries+.
51
+ # * :message_callback -- +lambda+ called when there's a message, e.g., <tt>lambda{|message| puts message}</tt>, regardless of :verbose state. By default :messaging is nil and messages are printed to STDOUT only when :verbose is true.
52
+ # * :message_prefix -- String to put in front of messages, e.g., "# "
53
+ def self._tempster(opts={}, &block)
54
+ name = opts.delete(:name) || DEFAULT_NAME
55
+ kind = opts.delete(:kind) or raise ArgumentError.new("'kind' option not specified")
56
+ dir = opts.delete(:dir) || Dir.tmpdir
57
+ cd = opts.delete(:cd) || false
58
+ noop = opts.delete(:noop) || false
59
+ verbose = opts.delete(:verbose) || false
60
+ delete = opts.delete(:delete) || block ? true : false
61
+ tries = opts.delete(:tries) || 10
62
+ armor = opts.delete(:armor) || DEFAULT_ARMOR_LENGTH
63
+ message_callback = opts.delete(:message_callback) || nil
64
+ message_prefix = opts.delete(:message_prefix) || ""
65
+ mode = opts.delete(:mode) || \
66
+ case kind
67
+ when :file
68
+ DEFAULT_FILE_MODE
69
+ when :directory
70
+ DEFAULT_DIRECTORY_MODE
71
+ else
72
+ raise ArgumentError.new("unknown kind: #{kind}")
73
+ end
74
+
75
+ raise ArgumentError.new("can only use 'delete' option with block") if delete and not block
76
+ raise ArgumentError.new("can only use 'cd' with directories and blocks") if cd and (not dir or not block)
77
+ raise ArgumentError.new("unknown extra options: #{opts.inspect}") unless opts.empty?
78
+
79
+ messager = Messager.new(verbose, message_callback, message_prefix)
80
+
81
+ path = nil
82
+ success = false
83
+ for i in 1..tries
84
+ begin
85
+ path = File.join(dir, name+"_"+_armor_string(armor))
86
+ unless noop
87
+ case kind
88
+ when :file
89
+ File.open(path, File::RDWR|File::CREAT|File::EXCL).close
90
+ File.chmod(mode, path)
91
+ when :directory
92
+ Dir.mkdir(path, mode)
93
+ else
94
+ raise ArgumentError.new("unknown kind: #{kind}")
95
+ end
96
+ end
97
+ # XXX Should we pretend that it's mktemp? Or give users something more useful?
98
+ # messager.puts("mktemp -m 0%o%s -p %s %s # => %s" % [mode, kind == :directory ? ' -d' : '', dir, name, path])
99
+ if block
100
+ messager.puts("mktempster --mode=0%o --kind=%s --dir=%s --name=%s" % [mode, kind, dir, name])
101
+ else
102
+ messager.puts("mktempster --mode=0%o --kind=%s --dir=%s --name=%s # => %s" % [mode, kind, dir, name, path])
103
+ end
104
+ success = true
105
+ break
106
+ rescue Errno::EEXIST
107
+ # Try again
108
+ end
109
+ end
110
+ raise IOError.new("couldn't create temporary #{kind}, ") unless success
111
+ if block
112
+ previous = Dir.pwd if cd
113
+ begin
114
+ if cd
115
+ Dir.chdir(path) unless noop
116
+ messager.puts("pushd #{path}")
117
+ end
118
+ block.call(path)
119
+ rescue Exception => e
120
+ # Re-throw exception after cleaning up
121
+ raise e
122
+ ensure
123
+ if cd
124
+ Dir.chdir(previous) unless noop
125
+ messager.puts("popd # => #{previous}")
126
+ end
127
+ if delete
128
+ FileUtils.rm_rf(path) unless noop
129
+ messager.puts("rm -rf #{path}")
130
+ end
131
+ end
132
+ return true
133
+ else
134
+ return path
135
+ end
136
+ end
137
+
138
+ # Returns a string of random characters.
139
+ def self._armor_string(length=DEFAULT_ARMOR_LENGTH)
140
+ (1..length).collect{ARMOR_CHARACTERS[rand(ARMOR_CHARACTERS.size)]}.pack("C*")
141
+ end
142
+
143
+ # Creates a temporary file.
144
+ def self.mktemp(opts={}, &block)
145
+ _tempster({:kind => :file}.merge(opts), &block)
146
+ end
147
+
148
+ # Creates a temporary directory.
149
+ #
150
+ # *WARNING*: See WARNING text at the top of this class's documentation!
151
+ def self.mktempdir(opts={}, &block)
152
+ _tempster({:kind => :directory}.merge(opts), &block)
153
+
154
+ end
155
+
156
+ # Creates a temporary directory and changes into it using +chdir+. This is a
157
+ # shortcut for using +mktempdir+ with the <tt>:cd => true</tt> option.
158
+ #
159
+ # *WARNING*: See WARNING text at the top of this class's documentation!
160
+ def self.mktempdircd(opts={}, &block)
161
+ _tempster({:kind => :directory, :cd => true}.merge(opts), &block)
162
+ end
163
+
164
+ class Messager
165
+ def initialize(verbose, callback=nil, prefix="")
166
+ @verbose = verbose
167
+ @callback = callback
168
+ @prefix = prefix
169
+ end
170
+
171
+ def puts(message)
172
+ if @callback
173
+ @callback.call(@prefix+message)
174
+ else
175
+ if @verbose
176
+ STDOUT.puts @prefix+message
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
182
+
183
+ if __FILE__ == $0
184
+ # TODO Tempster -- write a spec
185
+
186
+ # Show a temp file created
187
+ x = Tempster.mktemp(:verbose => true)
188
+ File.stat(x)
189
+ File.unlink(x)
190
+
191
+ # Show a temp directory created
192
+ x = Tempster.mktempdir(:verbose => true)
193
+ File.directory?(x)
194
+ FileUtils.rm_r(x)
195
+
196
+ # Show a temp file created and removed with block
197
+ path = nil
198
+ Tempster.mktemp(:verbose => true) do |file|
199
+ path = file
200
+ puts file
201
+ end
202
+ begin
203
+ File.unlink(path)
204
+ raise "temporary file wasn't deleted when block ended: #{path}"
205
+ rescue Errno::ENOENT
206
+ # Expect the error
207
+ end
208
+
209
+ # Show temp directory created and removed with block
210
+ path = nil
211
+ Tempster.mktempdir(:verbose => true) do |dir|
212
+ puts dir
213
+ path = dir
214
+ puts File.directory?(path)
215
+ end
216
+ puts File.directory?(path)
217
+
218
+ # Show temp directory created and removed with block and cd
219
+ path = nil
220
+ Tempster.mktempdircd(:verbose => true) do |dir|
221
+ path = dir
222
+ puts "block's arg: "+dir
223
+ puts "block's pwd: "+Dir.pwd
224
+ puts "block's dir exists?: %s" % File.directory?(path)
225
+ end
226
+ puts "after dir exists?: %s" % File.directory?(path)
227
+ puts "after pwd: "+Dir.pwd
228
+
229
+ # Same with message callback
230
+ path = nil
231
+ Tempster.mktempdircd(:message_callback => lambda{|message| puts "$$$ "+message}) do |dir|
232
+ path = dir
233
+ puts "block's arg: "+dir
234
+ puts "block's pwd: "+Dir.pwd
235
+ puts "block's dir exists?: %s" % File.directory?(path)
236
+ end
237
+ puts "after dir exists?: %s" % File.directory?(path)
238
+ puts "after pwd: "+Dir.pwd
239
+ end