[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Help-stow] A tip, a question, and feature request ...
From: |
Magnus Thor Torfason |
Subject: |
[Help-stow] A tip, a question, and feature request ... |
Date: |
Tue, 09 Apr 2013 15:45:17 -0400 |
User-agent: |
Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/20130328 Thunderbird/17.0.5 |
Dear Adam (and others),
I recently came across stow, and it is a real life-saver. Thank you!
So, I guess this mail is part tip, part question, and part feature
request. So here goes ...
THE TIP
In the documentation, there is some discussion about the issues with
compiling software for a different location than it is eventually going
to be installed with (Section 12, Compile-time vs Install-time). But it
seems to me that instead of waiting for emacs and others to individually
fix this, it is better to just make stow work with the programs as they
function today. Here's how:
We assume that we want to use /usr/local for the target directory and
/opt/stow for the stow directory. First, we initialize stow by cleaning
out any old crud that already exists in /usr/local using the following
command:
> stow --adopt-all orphans
We now have a stow package (in /opt/stow/orphans) containing all the
crud, and /usr/local is clean. When we want to install a new package,
say, the moe text editor, we first make sure that there is definitely no
crud in /usr/local (and it should all be gone now):
> chkstow -a
and then we type:
> cd src
> wget http://ftp.gnu.org/gnu/moe/moe-1.5.tar.gz
> tar zxvf moe-1.5.tar.gz
> cd moe-1.5
> ./configure
> make
> make install
Whoa! This installed moe into /usr/local, not stow. That's OK, though,
because now we are going to do this:
> stow --adopt-all moe-1.5
Boom, we are done, now we have a stow package for moe in
/opt/stow/moe-1.5 and we can uninstall, reinstall or upgrade moe
whenever we want.
QUESTION
Is there any reason one should not follow this approach?
ANSWER (*)
Why, yes there is a good reason: stow does not accept the --adopt-all
switch! Which is why I actually do this instead:
> stow.adopt.all moe-1.5
Where stow.adopt.all is a bash function:
stow.adopt.all ()
{
if [ "$1" == "" ] || [ "$2" != "" ]; then
echo "Incorrect number of arguments to stow.adopt.all (expected
exactly one).";
return 1;
fi;
DIR=/opt/stow;
TARGET=/usr/local;
PACKAGE="$1";
chkstow -t $TARGET -a | sed "s+^Unstowed file:
$TARGET+$DIR/$PACKAGE+" | xargs -l mktouch;
stow --adopt -vv $PACKAGE
}
This requires mktouch, which is a shell script:
#!/bin/sh
if [ "$1" == "" ] || [ "$2" != "" ]; then
echo "Incorrect number of arguments to mktouch (expected exactly one)."
exit 1
fi
mkdir -p "$(dirname "$1")"
touch "$1"
# end of mktouch
So the deal here? Find all aliens in /usr/local and touch their
equivalent in the stow package directory of choice, because "stow
--adopt" (the real one, that currently exists) will only adopt files if
it is trying to install those specific files. Only after creating the
structure (of empty files) within the package directory do we run "stow
--adopt", which then replaces all these empty files with the recently
installed files.
This takes care of most of the work, but there are two more caveats.
First, for this to work, one must not use the (awesome) folding feature
of stow, because if there are directory symlinks in /usr/local, "make
install" will probably end up installing stuff into the stow package
directories, which will screw everything up. So my .stowrc looks like
this (I've elected to keep my stow packages in /opt/stow instead of
/usr/local/stow partly because of personal preference, but also because
it makes some of my workarounds simpler, since I can then assume that
there should be absolutely nothing inside /usr/local apart from symlinks
that point to .../opt/stow/...). So again, here is my .stowrc:
-d /opt/stow
-t /usr/local
--no-folding
Now we are 95% there. The only other issue is that "stow --adopt" (and
"chkstow -a") does not correctly handle alien symlinks. For example,
mc-4.6.1 installs the following symlinks in bin: "mcedit -> mc" and
"mcview -> mc". Stow will not detect these as aliens. So I have one more
addition in my profile:
alias stow.aliens='find /usr/local -type f -o -type l | xargs ls -l |
grep -v "opt/stow"'
I have not implemented this into my stow.adopt.all function, so I need
to manually run this after any installation to make sure that there are
no symlinks, and if there are I have to manually move them from the stow
directory, and then reinstall the package.
Now, this takes me to my actual question: "If we had a 'stow --adopt-all
<package>' command, would this then not be a pretty good way to do stow
installations?"
FEATURE REQUEST
And finally, assuming that the answer to my last question is yes, here
are some feature requests that, if implemented, would make this a robust
usage pattern:
- Add a --adopt-all switch to stow, which would cause stow to adopt
any alien file in the target directory. In this case, one might
even imagine that the existence of a corresponding file in the
stow/package directory would be perceived to be a conflict (I
would expect the actual use case for this switch to always or
almost always be executed with an empty or (even better) absent
stow/package directory).
- Update stow and chkstow so that they correctly handle alien symlinks.
This would apply to the following commands at least:
> stow --adopt <package>
> stow --adopt-all <package>
> chkstow -a
It seems to me that chkstow -a would have to be aware of the
location of the stow directory to be able to do this,
probably by adding a --dir param to chkstow.
And then a few other, lower priority, feature requests
while I am at it:
- Update chkstow -l so that it works with a custom stow
directory location (this would also require awareness of
stow directory location)
- It would be very nice if chkstow had the same default
options for target dir as stow does, and perhaps if
it could even have a .chkstowrc file?
- And even nicer would be if ther was a --rcfile param
to stow, maybe even for chkstow as well:
> stow --rcfile=~/my-stowrc-for-homedir <...>
> stow --rcfile=~/my-stowrc-for-usrlocal <...>
> chkstow --rcfile=~/my-chkstowrc-for-homedir <...>
> chkstow --rcfile=~/my-chkstowrc-for-usrlocal <...>
Well, that's asking for a lot, I know! But please take this and use as
an input to future development in whatever way you want. I think that
this would be a neat way to get out of the dependency on programs
playing nice with different compile and install locations, and so
increase the number of situations where stow could be used. Also, since
the default install location (/usr/local) is typically simpler to
configure in any randomly downloaded source package, it would make
compilation even easier.
I hope you find these thoughts and suggestions useful.
Best,
Magnus
- [Help-stow] A tip, a question, and feature request ...,
Magnus Thor Torfason <=