<br>Hi Alexander,<br><br>Thanks. You are right. All three exceptions are a WindowsError. The first two are access denied (Windows system error 0x05) and the third one is the sharing violation (Windows system error 0x20 = the 32 (decimal) reported when bzr passes it through). Although I have not gone so far as to see what process is holding the files -- and the directory -- but its pretty obvious that it must be BeyondCompare. Here is the actual output I generated from _win32_delete_readonly:<br>
<br><span style="font-family: courier new,monospace;">Path: C:/docume~1/martitza/locals~1/temp/bzr-diff-yribs_\new\IssueTrackingNeeds.txt</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Exception Type: <type 'exceptions.WindowsError'> ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', 'args', 'errno', 'filename', 'message', 'strerror', 'winerror']</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Exception Attributes:5</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">Path: C:/docume~1/</span><span style="font-family: courier new,monospace;">martitza</span><span style="font-family: courier new,monospace;">/locals~1/temp/bzr-diff-yribs_\old\IssueTrackingNeeds.txt</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">Exception Type: <type 'exceptions.WindowsError'> ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', 'args', 'errno', 'filename', 'message', ' strerror', 'winerror']</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Exception Attributes:5</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">Path: C:/docume~1/</span><span style="font-family: courier new,monospace;">martitza</span><span style="font-family: courier new,monospace;">/locals~1/temp/bzr-diff-yribs_</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">Exception Type: <type 'exceptions.WindowsError'> ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', 'args', 'errno', 'filename', 'message', ' strerror', 'winerror']</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Exception Attributes:32</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
So the options to make _win32_delete_readonly more fine grained remain either an ugly delay (like my first patch) which may break later or some awkward code to try to figure out what process (BC3 in this case) is at fault. Seems like a lot of work for the reward. <br>
<br>I think it's still best to just wrap the osutils.rmtree in diff.py (line 734) in a try/except:<br><br><span style="font-family: courier new,monospace;"> def finish(self):</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> try:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> osutils.rmtree(self._root)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> except:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> note("The temporary directory [%s] was not cleanly removed." % self._root)</span><br style="font-family: courier new,monospace;">
<br>The result is output which looks like this:<br><br><span style="font-family: courier new,monospace;">The temporary directory [C:/docume~1/kferrio/locals~1/temp/bzr-diff-yribs_] was not cleanly removed.</span><br><br>instead of this:<br>
<br><span style="font-family: courier new,monospace;">bzr: ERROR: [Error 32] The process cannot access the file because it is being used by another process: 'C:/docume~1/martitza/locals~1/temp/bzr-diff-yribs_'</span><br>
<br>I would rather make this a debug-level error than an info-level error, so that it does not show up on stderr by default. As I read trace.py it is not obvious to me what is the preferred way to create debug-level logging. So rather than violate that convention, I opted for note/info. I may look through the sources for examples of text which get printed only to bzr.log to figure out the debug level.<br>
<br>Thanks again. I will test a bit more before submitting a merge request.<br><br>-M<br><br><br><br><br><br><div class="gmail_quote">2009/5/7 Alexander Belchenko <span dir="ltr"><<a href="mailto:bialix@ukr.net">bialix@ukr.net</a>></span><br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Hi Maritza,<br>
<br>
Because I'm the one who was involved in writing _win32_delete_readonly,<br>
I'll try to provide some hints for you.<br>
<br>
def _win32_delete_readonly(function, path, excinfo):<br>
"""Error handler for shutil.rmtree function [for win32]<br>
Helps to remove files and dirs marked as read-only.<br>
"""<br>
exception = excinfo[1]<br>
if function in (os.remove, os.rmdir) \<br>
and isinstance(exception, OSError) \<br>
and exception.errno == errno.EACCES:<br>
make_writable(path)<br>
function(path)<br>
else:<br>
raise<br>
<br>
The problem in the code above is that it used too-broad testing for error, e.g.<br>
<br>
and exception.errno == errno.EACCES:<br>
<br>
errno.EACCES it's a POSIX-style error constant, IIUC it's about Access Denied.<br>
<br>
Fortunately it seems like actually we have there WindowsError exception, and therefore can get real Windows Error Code (as of GetLastError() returns).<br>
<br>
So, if you're adding following debugging prints to the function:<br>
<br>
def _win32_delete_readonly(function, path, excinfo):<br>
"""Error handler for shutil.rmtree function [for win32]<br>
Helps to remove files and dirs marked as read-only.<br>
"""<br>
exception = excinfo[1]<br>
<br>
+ print type(exception), dir(exception)<br>
+ print getattr(exception, 'winerror', None)<br>
<br>
if function in (os.remove, os.rmdir) \<br>
and isinstance(exception, OSError) \<br>
and exception.errno == errno.EACCES:<br>
make_writable(path)<br>
function(path)<br>
else:<br>
raise<br>
<br>
<br>
You will obtain additional information about your error with BeyondCompare3. Especially the second print should print to you actual Windows error code (<a href="http://msdn.microsoft.com/en-us/library/ms681381%28VS.85%29.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/ms681381(VS.85).aspx</a>)<br>
<br>
Knowing actual error code there is possible to imprtove _win32_delete_readonly function to make more fine-grained analysis why deletion of file fails and provide appropriate solution for different cases: deleting read-only files, files currently in use etc.<br>
<br>
HTH<br>
<br>
Maritza Mendez ΠΙΫΕΤ:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="im">
<br>
<br>
On Wed, May 6, 2009 at 2:01 AM, Alexander Belchenko <<a href="mailto:bialix@ukr.net" target="_blank">bialix@ukr.net</a> <mailto:<a href="mailto:bialix@ukr.net" target="_blank">bialix@ukr.net</a>>> wrote:<br>
<br>
Maritza Mendez ΠΙΫΕΤ:<br>
<br>
<br>
<br>
On Tue, May 5, 2009 at 8:54 AM, Aaron Bentley<br>
<<a href="mailto:aaron@aaronbentley.com" target="_blank">aaron@aaronbentley.com</a> <mailto:<a href="mailto:aaron@aaronbentley.com" target="_blank">aaron@aaronbentley.com</a>><br></div>
<mailto:<a href="mailto:aaron@aaronbentley.com" target="_blank">aaron@aaronbentley.com</a> <mailto:<a href="mailto:aaron@aaronbentley.com" target="_blank">aaron@aaronbentley.com</a>>>><div><div></div>
<div class="h5"><br>
wrote:<br>
<br>
-----BEGIN PGP SIGNED MESSAGE-----<br>
Hash: SHA1<br>
<br>
Maritza Mendez wrote:<br>
> The more I think about this, the more I think that a cure<br>
may be<br>
worse<br>
> than the problem. So I am leaning toward...<br>
<br>
> bzr would catch the exception, print a polite message<br>
> about the external misbehavior, and just keep going.<br>
<br>
I think that this would be fine, so long as it's an opt-in<br>
behaviour.<br>
If you do it as an onerror callback, note that problems may<br>
cascade,<br>
because failure to delete a file can cause failure to delete its<br>
containing directory.<br>
<br>
Aaron<br>
<br>
I think it is "opt-in" enough to limit the response to catching<br>
OSError and ignoring all other exceptions. What do you think?<br>
At worst, bzr would continue to miss some things it misses now.<br>
<br>
I have to remind myself that this whole discussion comes from<br>
the fact that _win32_delete_readonly does not robustly handle<br>
failures in osutils.rmtree call to shutil.rmtree. Since that<br>
seems to be the whole purpose of _win32_delete_readonly, I might<br>
suggest that osutils.rmtree and _win32_delete_readonly do not<br>
meet design requirements.<br>
<br>
<br>
Which one design requirements?<br>
<br>
The _win32_delete_readonly function intended to help in the cases<br>
where bzr need to remove file marked as read-only. Nothing more.<br>
There is special test in test_osutils.py to ensure this behavior.<br>
<br>
<br>
Point taken. I have not seen any design document for bzr, unless email archives count. I'm just saying that the purpose of osutils.rmtree _appears_ to be to deal with files which are (for whatever reason) readonly on Windows and need to be rendered into a removable state. If that is the (derived) requirement, then the current implemnatation is good, but not foolproof, as we see.<br>
<br>
-M<br>
<br>
</div></div></blockquote>
<br>
<br>
</blockquote></div><br>