Software maintenance would be much easier if each package was installed in its own directory, but that would greatly complicate things for the users because they would need to list a large number of directories in their PATH. It would also cause complications when copying software from another Unix system, since the use of /usr/local is a well-established convention.
Encap is an attempt to solve this dilemma.
/usr/local/encap/sed-3.02/bin/sed /usr/local/encap/sed-3.02/man/man1/sed.1Once these files have been installed, the Encap package manager will create the following symlinks:
/usr/local/bin/sed -> ../encap/sed-3.02/bin/sed /usr/local/man/man1/sed.1 -> ../../encap/sed-3.02/man/man1/sed.1The normal user will have /usr/local/bin in his PATH and /usr/local/man in his MANPATH, so he will not even know that the Encap system is being used.
| Date | Event |
|---|---|
| 1992-1994 | Early development of Encap at various research labs at UIUC by Chuck Thompson, Steve March, Doug Bogia, and Jason Wessel. |
| 1995 | Jason Wessel does initial development of encap.pl, first popular Encap package manager. |
| 1996-1997 | Encap spreads to CCSO and is deployed on UIArchive, the Staff/Student Cluster, and EWS. |
| Brian Swetland writes encapper.c, which operates on individual packages rather than batch mode like encap.pl. | |
| 1998 | Mark Roth develops epkg, which combines features from both encap.pl and encapper, as well as adding many extentions to the classic Encap package format. |
| 1999 | The Encap Specification is written to formally define the Encap 2.0 package format. |
| 2002 | The Encap 2.1 specification is written. |
http://www.encap.org/epkg/There are two ways to install epkg:
For example, to install an Encap of GNU sed-3.02, you would first download the Encap package and extract it into /usr/local/encap. This will create the following files:
/usr/local/encap/sed-3.02/bin/sed /usr/local/encap/sed-3.02/man/man1/sed.1To install these files, run this command:
epkg sed-3.02This will create the following symlinks:
/usr/local/bin/sed -> ../encap/sed-3.02/bin/sed /usr/local/man/man1/sed.1 -> ../../encap/sed-3.02/man/man1/sed.1Back
For example, say that you already have the package sed-2.0 installed, but you want to upgrade to sed-3.02. After you extract the sed-3.02 files into /usr/local/encap, you should have these files:
/usr/local/encap/sed-2.0/bin/sed /usr/local/encap/sed-2.0/man/man1/sed.1 /usr/local/encap/sed-3.02/bin/sed /usr/local/encap/sed-3.02/man/man1/sed.1 /usr/local/bin/sed -> ../encap/sed-2.0/bin/sed /usr/local/man/man1/sed.1 -> ../../encap/sed-2.0/man/man1/sed.1With epkg's versioning capability, you can simply say epkg sed. That will cause epkg to scan the Source Directory, find both versions of sed, and determine which one is the newest. Then it will remove the symbolic links for all of the old versions and install the symbolic links for the newest version automaticly.
Note: Because there's no standard way to do version numbering, epkg uses fuzzy logic to determine which version is newer. It almost always guesses right, but when it doesn't you can use the -S flag to tell it to operate only on a specific package. In the example above, this would be epkg -Sr sed-2.0; epkg -S sed-3.02.
epkg /scratch/sed-3.02.tar.gzThis will tell epkg to extract the package archive into the Encap Source Directory before installing the package.
Note: If epkg was built without libtar and/or zlib support, you will need to have your system's tar and/or gzip binaries in your PATH when you invoke epkg.
ENCAP_UPDATE_PATH="http://www.encap.org/search/search.fcgi?results_only=yes&no_detail_links=on&search_string=all&search_platform=%p"Then, to automatically upgrade all packages to their latest versions, use this command:
epkg -uIf you want to upgrade only the package GNU sed, use this:
epkg -u sedBack
Conversely, here are some situations in which epkg will not remove the pre-existing file:
If you encounter one of these situations and you want to force epkg to remove the pre-existing file anyway, you can use the -f flag.
For example, to remove an Encap of GNU sed-3.02, execute this command:
epkg -r sed-3.02This will remove the following symlinks:
/usr/local/bin/sed -> ../encap/sed-3.02/bin/sed /usr/local/man/man1/sed.1 -> ../../encap/sed-3.02/man/man1/sed.1Back
epkg -cBack
By default, there is only one package on the override list, old_local. To use this package as a way to transition to Encap, do something like this:
cd /usr/local
mkdir -p encap/old_local
for n in `ls -a | egrep -v 'src|etc|encap|^\.{1,2}$|lost\+found'`; do \
mv ${n} encap/old_local; \
done
epkg old_local
Back
./configure --prefix=/usr/local/encap/pkgspecFor software which doesn't use autoconf, you will need to edit the Makefile by hand.
Once the software has been compiled and has installed its files into the Package Directory, you can create the Encap package with this command:
mkencap pkgspecBy default, mkencap will create a new encapinfo file in the Package Directory, and create a .tar.gz archive of the Package Directory which can be installed on other machines which use Encap. For more information, see the mkencap man page.
| Script | Description |
|---|---|
| preinstall | Executed before installation. |
| postinstall | Executed after installation. |
| preremove | Executed before removal. |
| postremove | Executed after removal. |
If a preprocessing script returns a non-zero exit code, the package manager must immediately abort processing the package. A postprocessing script will only be executed if at least one link has been successfully created or removed, as appropriate, during the processing of the package.
Package scripts must adhere to the following guidelines:
To facilitate this, an Encap package may look for its own files directly in its package directory, but it should look for all other files in the Encap target (/usr/local). This is an extremely critical thing to keep in mind when building Encap packages.
For example, say you have a system with perl 5.003 installed and you're installing a new package which contains some perl scripts. If you tell it the path to perl in perl's package directory, the perl scripts will have #!/usr/local/encap/perl-5.003/bin/perl at the top. If you later want to upgrade to perl 5.004, all of these scripts will have to be changed. But if they all say #!/usr/local/bin/perl, the upgrade should be completely transparent to them.
To avoid this when Encapping these applications, it's important to configure them to look directly in the Encap target for their "site" directory instead of in their package directory. Good examples of this are perl's site_perl directory and emacs's site-lisp directory. Let's look at the latter example in detail.
Say you have a system with emacs 19.34 installed, and all of your locally installed elisp code is in emacs's package directory (/usr/local/encap/emacs-19.34/share/emacs/site-lisp). When it comes time to upgrade to emacs 20.3, you can't remove the old version of emacs without losing all of your elisp files. To solve this problem, emacs should be told to look for its site-lisp files in the Encap target (/usr/local/share/emacs/site-lisp), and any locally-installed elisp files should be placed in their own Encap packages and linked into the Encap target. An example of this is the elisp file which comes with the ispell Encap package, which is installed as /usr/local/share/emacs/site-lisp/ispell.el -> /usr/local/encap/ispell-3.1.20/share/emacs/site-lisp/ispell.el.
http://www.encap.org/cpanencap/See the enclosed documentation for more information.
The Encap system doesn't have any built-in limitations with respect to directories. It allows you to specify any arbitrary directories as the Encap source and Encap target areas. However, individual packages often use hard-coded paths to find auxiliury files, and these paths are no longer correct when you install the software in a different location.
It is not always possible to build a relocatable package. For example, packages that contain binaries that hard-code paths at compile time cannot be changed at install time. However, for packages that contain only scripts, it is often quite useful.
Let's say that the package foo-1.0 contains the following files:
bin/foo.pl share/foo/foo.datThe foo.pl script looks like this:
#!/usr/local/bin/perl $data = `cat /usr/local/share/foo/foo.dat`; print "$data\n";If the package is installed into the Encap target directory /usr/local, it will work fine. However, if it's installed in the Encap target directory /home/user, it won't be able to find the foo.dat file.
To solve this problem, we can do the following:
echo "Creating bin/foo.pl...";
sed -e "s|@ENCAP_TARGET@|${ENCAP_TARGET}|g" \
"${ENCAP_SOURCE}/${ENCAP_PKGNAME}/bin/foo.pl.in" \
> "${ENCAP_SOURCE}/${ENCAP_PKGNAME}/bin/foo.pl";
Note that the ENCAP_SOURCE, ENCAP_TARGET, and
ENCAP_PKGNAME variables are all set to the correct values
by the package manager so that they can be used by the package
scripts. Therefore, this preinstall code will dynamically create
the foo.pl file from the foo.pl.in file using the
correct path at the time that the package is installed.
echo "Removing bin/foo.pl...";
rm -f "{ENCAP_SOURCE}/${ENCAP_PKGNAME}/bin/foo.pl";
This cleans up the foo.pl file when the package is removed. This
isn't strictly necessary, but it is convenient for two reasons.
First, it saves disk space. Second, it restores the package to a
"pristine" state so that you can create a tar archive of it without
needing to distribute a second copy of each file. (This means that
you should remove the package with epkg -r before you create the
tar archive.)
exclude bin/foo.pl.inThis tells the package manager not to create a symlink for the .in version of the file, since all you need is the dynamically-generated copy. Again, this isn't strictly necessary, but it does keep things clean.
for INFILE in `find ${ENCAP_SOURCE}/${ENCAP_PKGNAME} -name '*.in'`; do
OUTFILE=`echo ${INFILE} | sed 's|\.in$||'`;
if [ ! -f ${OUTFILE} ]; then
echo "Creating: ${OUTFILE}";
sed -e "s|@ENCAP_TARGET@|${ENCAP_TARGET}|g" \
< ${INFILE} > ${OUTFILE};
if [ -x ${INFILE} ]; then
chmod a+x ${OUTFILE};
fi
fi
done
Back
foo-1.0/
COPYRIGHT
ChangeLog
TODO
preinstall
postremove
bin/
foo.pl.in
share/
foo/
foo.dat
Back
For example, if the package foo-1.0 contained a config file called etc/foo.conf, we would need to do the following:
exclude etc
if [ ! -f "${ENCAP_TARGET}/etc/foo.conf" ]; then
echo "Installing ${ENCAP_TARGET}/etc/foo.conf...";
cp "${ENCAP_SOURCE}/${ENCAP_PKGNAME}/etc/foo.conf" \
"${ENCAP_TARGET}/etc/foo.conf";
fi
lib/site_perl/Foo.pmYou can modify the top of foo.pl.in to look like this:
#!/usr/local/bin/perl -I@ENCAP_TARGET@/lib/site_perl use Foo;That will ensure that the right path is always added to @INC.
This limitation should be addressed in the future, but for now you can work around this in one of the following ways: