stow
stow copied to clipboard
find_stow_path returns name of stow directory not name of package
Once /usr/local/stow starts filling up with packages, it is useful to organize packages into categories under /usr/local/stow, eg Audio, Desktop, Utilities, Video etc
If packages under these sub-directories, which of course should get marked as being STOW directories with the presence of a .stow file, contain common target directories, then these should be folded/unfolded as appropriate on stowing and unstowing.
However when find_stow_path is called with the path to a target link to be changed in a sub-directory, it returns the name of the package as just the sub-directory category name eg Audio, or Desktop or whatever and not the category plus package name relative to the top stow directory. Of cours unlinking/mkdir then fails because the combined full stow path is wrong as it does not contain the actual package name and thus does not exist, causing stow to exist with the error message that it was called with non-directory path.
This is rectified with the following patch to Stow.pm for find_stow_path
--- Stow.pm.ORIG 2014-10-28 21:02:46.397092559 +0100
+++ Stow.pm 2014-10-28 21:02:46.397092559 +0100
@@ -911,7 +911,7 @@
if $i == $#path;
debug(4, " yes - $dir was marked as a stow dir");
- my $package = $path[$i + 1];
+ my $package = "$path[$i + 1]/$path[$i + 2]";
return ($path, $dir, $package);
}
}
In fact the above patch is not good enough for the more general case where packages may be located at different levels in the stow tree, eg an "uncategorized" package in /usr/local/stow and a categorized package in /usr/local/stow/Category in the simple case.
What is required is for find_stow_path to step down each sub-directory until it no longer finds a .stow file and then use just that first non stow directory as the package name, and return the path to the directory above it as the existing stow path.
So the section in Stow.pm needs to be changed to
# Search for .stow files - this allows us to detect links
# owned by stow directories other than the current one.
my $dir = '';
my $subdir = '';
my $package = '';
my @path = split m{/+}, $path;
for my $i (0 .. $#path) {
$subdir = join_paths($subdir, $path[$i]);
if ($self->marked_stow_dir($subdir)) {
# FIXME - not sure if this can ever happen
internal_error("find_stowed_path() called directly on stow dir")
if $i == $#path;
$dir = $subdir;
debug(4, " yes - $dir was marked as a stow dir");
$package = "$path[$i + 1]";
}
else {
last;
}
}
return ($path, $dir, $package) if $package;
and the subsequent
my $package = shift @path;
change to just
$package = shift @path;
Thanks for the feature request. I think I understand what you are trying to do, but I don't see why it shouldn't already work correctly, assuming that you pass -d /usr/local/stow/Audio
or similar as an option to stow
. Your proposed changes sound like they would break the normal case, which is of course unacceptable. However to be sure I full understand you, I really need:
- the output of running
tree /usr/local/stow
- the exact stow commands you are running
- the desired results
Sorry for the delay in getting back to this.
Yes I do use the -d /usr/local/stow/Category parameter when trying to stow, but because the value discussed above does not return the full subdirectory tree to the lowest sub-directory which has a .stow file, it fails in cases where another package in another Category has a conflicting item. Incidentally xstow appears to have similar problems with this type of arrangement even if the Category/sub-Category directories are specified in xstow.ini
The change I suggested does not break the normal case of everything in /usr/local/stow because there is no searching of any sub-directories.
I have been running the above patch on stow for the last six months with quite a lot of usage and have not run into any problems.
Today I have upgraded to the latest stow-r99b6699 from stow-r07a8454
First I use the unpatched version to unstow midori-0.5.10 in /usr/local/stow/Network (which has a .stow file)
stow -d /usr/local/stow/Network -t /usr/local -v -D midori-0.5.10
UNLINK: share/doc/midori-0.5.10
UNLINK: X11R6/bin/midori
UNLINK: X11R6/etc/xdg/midori
UNLINK: X11R6/share/gtk-doc/html/midori-0-5
UNLINK: X11R6/share/appdata/midori.appdata.xml
UNLINK: X11R6/share/icons/hicolor/scalable/apps/midori.svg
UNLINK: X11R6/share/icons/hicolor/scalable/status
UNLINK: X11R6/share/icons/hicolor/scalable/categories/extension.svg
UNLINK: X11R6/share/icons/hicolor/scalable/categories/awn-plugins.svg
RMDIR X11R6/share/icons/hicolor/scalable/categories
LINK: X11R6/share/icons/hicolor/scalable/categories => ../../../../../stow/Desktop/awn-0.4.2/X11R6/share/icons/hicolor/scalable/categories
... etc
and that works okay.
I then try to stow it again but it fails because the path returned in the unpatched version does not include the package name "midori-0.5.10" in the constructed path
stow -d /usr/local/stow/Network -t /usr/local -v midori-0.5.10
LINK: share/doc/midori-0.5.10 => ../../stow/Network/midori-0.5.10/share/doc/midori-0.5.10
LINK: X11R6/bin/midori => ../../stow/Network/midori-0.5.10/X11R6/bin/midori
LINK: X11R6/etc/xdg/midori => ../../../stow/Network/midori-0.5.10/X11R6/etc/xdg/midori
LNK: X11R6/share/gtk-doc/html/midori-0-5 => ../../../../stow/Network/midori-0.5.10/X11R6/share/gtk-doc/html/midori-0-5
LINK: X11R6/share/appdata/midori.appdata.xml => ../../../stow/Network/midori-0.5.10/X11R6/share/appdata/midori.appdata.xml
LINK: X11R6/share/icons/hicolor/scalable/apps/midori.svg => ../../../../../../stow/Network/midori-0.5.10/X11R6/share/icons/hicolor/scalable/apps/midori.svg
LINK: X11R6/share/icons/hicolor/scalable/status => ../../../../../stow/Network/midori-0.5.10/X11R6/share/icons/hicolor/scalable/status
UNLINK: X11R6/share/icons/hicolor/scalable/categories
MKDIR: X11R6/share/icons/hicolor/scalable/categories
stow: ERROR: stow_contents() called with non-directory path: stow/Desktop/X11R6/share/icons/hicolor/scalable/categories
The directory path is stow/Desktop/midor-0.5.10/X11R6/share/icons/hicolor/scalable/categories but the above routine failed to include the "package" name in the returned value of the search.
I then apply my patch and try to restow, and the function returns the correct full path and the "conflict" with the icons from the awn package is resolved by the replacement of that stow link with the creation of a directory and then in that directory appropriate links to the icons in the awn package and the midori package.
stow -d /usr/local/stow/Network -t /usr/local -v midori-0.5.10
LINK: share/doc/midori-0.5.10 => ../../stow/Network/midori-0.5.10/share/doc/midori-0.5.10
LINK: X11R6/bin/midori => ../../stow/Network/midori-0.5.10/X11R6/bin/midori
LINK: X11R6/etc/xdg/midori => ../../../stow/Network/midori-0.5.10/X11R6/etc/xdg/midori
LINK: X11R6/share/gtk-doc/html/midori-0-5 => ../../../../stow/Network/midori-0.5.10/X11R6/share/gtk-doc/html/midori-0-5
LINK: X11R6/share/appdata/midori.appdata.xml => ../../../stow/Network/midori-0.5.10/X11R6/share/appdata/midori.appdata.xml
LINK: X11R6/share/icons/hicolor/scalable/apps/midori.svg => ../../../../../../stow/Network/midori-0.5.10/X11R6/share/icons/hicolor/scalable/apps/midori.svg
LINK: X11R6/share/icons/hicolor/scalable/status => ../../../../../stow/Network/midori-0.5.10/X11R6/share/icons/hicolor/scalable/status
UNLINK: X11R6/share/icons/hicolor/scalable/categories
MKDIR: X11R6/share/icons/hicolor/scalable/categories
LINK: X11R6/share/icons/hicolor/scalable/categories/awn-plugins.svg => ../../../../../../stow/Desktop/awn-0.4.2/X11R6/share/icons/hicolor/scalable/categories/awn-plugins.svg
LINK: X11R6/share/icons/hicolor/scalable/categories/extension.svg => ../../../../../../stow/Network/midori-0.5.10/X11R6/share/icons/hicolor/scalable/categories/extension.svg
... etc
Hopefully from this practical example you will be able to understand the bug in the currently published function because stow_contents is called with the wrong path
stow/Desktop/X11R6/share/icons/hicolor/scalable/categories
and not the correct path
stow/Desktop/midori-0.5.10/X11R6/share/icons/hicolor/scalable/categories
because the "package" name is missing.
Thanks, this is super helpful and I think I understand now. Please could you submit your patch as a pull request and I will review it?