Closed rchl closed 4 years ago
Linux tested OK.
BTW, the official release of PC not only removes all files within the symlinked directory but also fails to remove the symlink itself:
Exception in thread Thread-5:
Traceback (most recent call last):
File "./python3.3/threading.py", line 901, in _bootstrap_inner
File "/home/me/.config/sublime-text-3/Packages/Package Control/package_control/commands/remove_package_command.py", line 84, in run
self.result = self.manager.remove_package(self.package)
File "/home/me/.config/sublime-text-3/Packages/Package Control/package_control/package_manager.py", line 1960, in remove_package
os.rmdir(package_dir)
NotADirectoryError: [Errno 20] Not a directory: '/home/me/.config/sublime-text-3/Packages/TrailingSpaces'
This PR obviously fixes that issue.
So I could work on that but I'd like some assurance first that it's gonna be handled and integrated in not too long.
It's not that I'm impatient but I don't want to waste my time on something that will linger for months and potentially will need to be picked up again later anyway.
I know you are around @wbond and the project is well alive but I would prefer to handle this when you are available to handle feedback and integration. So let me know when is a good time please.
(I'm basing this comment mostly on the fact that no PRs were integrated in over 6 months.)
I will definitely look into this when I'm nest working on the PC codebase. That should probably be relatively soon (maybe a few weeks to a month?) since I need to work out how dependencies are going to work with Python 3.8 and all.
Pushed what I believe is a better fix and updated my initial comment with a list of all affected places.
Windows and macOs tested OK too.
Fixes #1476?
I think that delete_directory()
should be renamed to something like unlink_or_delete_directory()
to make it clear in usage that it will unlink a symlink if possible.
Note, that stdlib functions of python 3.8 are said to handle symlinks/junctions correctly, even on Windows OS. So once the transition has been made, only parts of this PR might be relevant then.
Note, that stdlib functions of python 3.8 are said to handle symlinks/junctions correctly, even on Windows OS. So once the transition has been made, only parts of this PR might be relevant then.
Then it would probably help this case:
if sys.platform == 'win32':
os.rmdir(path)
else:
os.unlink(path)
but probably (speculating) none of the other changes as it seems to me more like a logic error than deficiency of the the python API.
What will shutil.rmtree
do in py38 for a directory symlink? Will it still remove the target of the symlink or the symlink itself?
shutil.rmtree
throws OSError: Cannot call rmtree on a symbolic link
when path
is a symlink or junction. I guess it is a relic of older python not handling symlinks well. Maybe should open a bug report if not yet exists.
For details see: https://bugs.python.org/issue1669
os.rmdir()
removes the junction/symlink but leaves the source directory intact.
Thanks for your work on this!
Thanks everyone for this. Losing hours of work on a package was really demotivating, and I'm glad to see this particular failure mode won't happen again.
@sparr I'm sure you've figured this out already, but if you are working on a package, make sure it is not being managed by Package Control. Look for package-metadata.json
. If that exists, Package Control will treat it as managed, and will perform standard operations like removing orphaned packages, whether they are symlinks or not.
I think that triggering remove package
has deleted it whether it was managed or not. That's how I lost some of my work as I wanted to test something but forgot that I was using local package.
Don't remove the package directory that is pointed to by a symlink. Instead, remove the symlink itself.
Handle symlink case from delete_directory() and in various places where clear_directory() is used so that directory pointed to by a symlink is never cleared.
Here is a list of all the places that deal with removal:
clear_directory()
bootstrap_dependency()
https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/bootstrap.py#L139-L142 Handle symlink? Yes, delete the symlink before trying to upgrade dependency. Not likely to ever trigger with symlinks IMO.PackageCleanup.run()
https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/package_cleanup.py#L177-L182 Handle symlink? No, since this affects packages that have been re-installed so potential symlink was already removed at some previous step.PackageManager.install_package()
https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/package_manager.py#L1238-L1248 Handle symlink? Yes since if the user's package is being updated to unpacked one from PC, we should not delete user files.PackageManager.install_package()
https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/package_manager.py#L1395-L1403 Handle symlink? No, at this stage symlink was already removed before and we are not working with symlink anymore.PackageManager.install_package()
https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/package_manager.py#L1414-L1417 Handle symlink? No, at this stage symlink was already removed before and we are not working with symlink anymore.package_manager.PackageManager.remove_package()
https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/package_manager.py#L1931-L1935 Handle symlink? Yes!delete_directory()
PackageCleanup.run()
https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/package_cleanup.py#L121-L125 https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/package_cleanup.py#L155-L158 https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/package_cleanup.py#L215-L221 https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/package_cleanup.py#L240-L247 Handle symlink? Yes, all automatically through changeddelete_directory()
PackageManager.install_package()
https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/package_manager.py#L1533-L1536 Handle symlink? Yes, but tmpdir shouldn't be a symlinkPackageManager.backup_package_dir()
https://github.com/wbond/package_control/blob/b3045d11480c49f1b9895729e40da300881f5525/package_control/package_manager.py#L1709-L1711 Handle symlink? Yes, but it's a backup dir so not a symlinkResolves #1460