File tree Expand file tree Collapse file tree 2 files changed +51
-5
lines changed
lib/octocatalog-diff/util
spec/octocatalog-diff/tests/util Expand file tree Collapse file tree 2 files changed +51
-5
lines changed Original file line number Diff line number Diff line change @@ -68,14 +68,27 @@ def self.temp_dir(prefix = 'ocd-', basedir = ENV['OCTOCATALOG_DIFF_TEMPDIR'])
6868 # If the base directory was not specified, then create a temporary directory, and
6969 # send the `at_exit` to clean it up at the conclusion.
7070 the_dir = Dir . mktmpdir ( prefix )
71- at_exit do
71+ at_exit { remove_temp_dir ( the_dir ) }
72+ the_dir
73+ end
74+
75+ # Utility method!
76+ # Remove a directory recursively that has been used as a temporary directory. This
77+ # should be called within an `at_exit` handler, and is only intended to be called via the
78+ # `temp_dir` method above.
79+ #
80+ # dir - A String with the directory to remove.
81+ def self . remove_temp_dir ( dir )
82+ retries = 0
83+ while File . directory? ( dir ) && retries < 10
84+ retries += 1
7285 begin
73- FileUtils . remove_entry_secure ( the_dir ) if File . directory? ( the_dir )
74- rescue Errno ::ENOENT # rubocop:disable Lint/HandleExceptions
75- # OK if the directory doesn't exist since we're trying to remove it anyway
86+ FileUtils . remove_entry_secure ( dir )
87+ rescue Errno ::ENOTEMPTY , Errno ::ENOENT # rubocop:disable Lint/HandleExceptions
88+ # Errno::ENOTEMPTY will trigger a retry because the directory exists
89+ # Errno::ENOENT will break the loop because the directory won't exist next time it's checked
7690 end
7791 end
78- the_dir
7992 end
8093 end
8194 end
Original file line number Diff line number Diff line change 109109 expect { described_class . temp_dir } . to raise_error ( Errno ::ENOENT , /temp_dir: Base dir/ )
110110 end
111111 end
112+
113+ describe '#remove_temp_dir' do
114+ let ( :dir ) { '/var/tmp/abcd/efgh/ijkl' }
115+
116+ it 'should do nothing if the directory does not exist' do
117+ allow ( File ) . to receive ( :directory? ) . and_call_original
118+ allow ( File ) . to receive ( :directory? ) . with ( dir ) . and_return ( false )
119+ expect ( FileUtils ) . not_to receive ( :remove_entry_secure ) . with ( dir )
120+ described_class . remove_temp_dir ( dir )
121+ end
122+
123+ it 'should do nothing if Errno::ENOENT is raised due to race conditions' do
124+ allow ( File ) . to receive ( :directory? ) . and_call_original
125+ allow ( File ) . to receive ( :directory? ) . with ( dir ) . and_return ( true , false )
126+ expect ( FileUtils ) . to receive ( :remove_entry_secure ) . with ( dir ) . exactly ( 1 ) . times . and_raise ( Errno ::ENOENT )
127+ described_class . remove_temp_dir ( dir )
128+ end
129+
130+ it 'should retry if Errno::ENOTEMPTY is raised' do
131+ allow ( File ) . to receive ( :directory? ) . and_call_original
132+ allow ( File ) . to receive ( :directory? ) . with ( dir ) . and_return ( true , false )
133+
134+ call_count = 0
135+ allow ( FileUtils ) . to receive ( :remove_entry_secure ) . with ( dir ) do
136+ call_count += 1
137+ raise Errno ::ENOTEMPTY if call_count == 1
138+ raise 'This should not occur' unless call_count == 2
139+ true
140+ end
141+
142+ described_class . remove_temp_dir ( dir )
143+ end
144+ end
112145end
You can’t perform that action at this time.
0 commit comments