stow icon indicating copy to clipboard operation
stow copied to clipboard

find_stow_path returns name of stow directory not name of package

Open Corin-EU opened this issue 10 years ago • 4 comments

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);
         }
     }

Corin-EU avatar Oct 31 '14 01:10 Corin-EU

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;

Corin-EU avatar Oct 31 '14 19:10 Corin-EU

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

aspiers avatar Jan 01 '15 19:01 aspiers

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.

Corin-EU avatar Jun 03 '15 00:06 Corin-EU

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?

aspiers avatar Oct 02 '16 23:10 aspiers