aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.build.yml9
-rw-r--r--.fossil-settings/ignore-glob1
-rw-r--r--CHANGELOG.md44
-rw-r--r--Makefile1
-rwxr-xr-xconfigure14
-rwxr-xr-xcontrib/cpt-chbuild33
-rw-r--r--docs/Makefile9
-rw-r--r--docs/cpt.org88
-rw-r--r--docs/cpt.texi120
-rw-r--r--docs/cpt.txt190
-rw-r--r--examples/hooks/clean-packages7
-rw-r--r--examples/hooks/makewhatis10
-rw-r--r--spec/01_lib_spec.sh37
-rw-r--r--spec/02_src_spec.sh2
-rwxr-xr-xsrc/cpt-alternatives78
-rwxr-xr-xsrc/cpt-install4
-rw-r--r--src/cpt-lib.in313
-rwxr-xr-xsrc/cpt-remove4
-rw-r--r--tests/repository/contrib-dummy-pkg/meta1
-rw-r--r--www/index.md6
20 files changed, 749 insertions, 222 deletions
diff --git a/.build.yml b/.build.yml
index b8cf514..8011d42 100644
--- a/.build.yml
+++ b/.build.yml
@@ -5,9 +5,10 @@ packages:
- bison
- curl
- rsync
- - shellcheck
+ - emacs-nox
- texinfo
- gzip
+ - xz
tasks:
- install-pax: |
git clone --quiet https://github.com/carbslinux/otools
@@ -19,13 +20,17 @@ tasks:
git clone --quiet https://git.sr.ht/~mcf/b3sum
cd b3sum
sudo make PREFIX=/usr install
+ - install-shellspec: |
+ curl -fsSL https://git.io/shellspec | sudo sh -s -- -y -p /usr
+ - install-shellcheck: |
+ curl -fsLo- https://github.com/koalaman/shellcheck/releases/download/v0.8.0/shellcheck-v0.8.0.linux.x86_64.tar.xz | pax -Jr
+ sudo install -Dm755 shellcheck-v0.8.0/shellcheck /usr/bin/shellcheck
- build: |
cd cpt
./configure
make
- test: |
cd cpt
- curl -fsSL https://git.io/shellspec | sudo sh -s -- -y -p /usr
make test
triggers:
- action: email
diff --git a/.fossil-settings/ignore-glob b/.fossil-settings/ignore-glob
index 98cdf27..84a1fc5 100644
--- a/.fossil-settings/ignore-glob
+++ b/.fossil-settings/ignore-glob
@@ -18,3 +18,4 @@ tests/etc/cpt-hook
report
coverage
config.mk
+docs/config.org
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 46e4977..dda4498 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,46 @@ this project _somewhat_ adheres to [Semantic Versioning].
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html
+[UNRELEASED]
+--------------------------------------------------------------------------------
+
+### Configuration Directory
+- In order to simplify file locations and messing up the `/etc` directory, CPT
+ now uses the `/etc/cpt` directory for reading related files. The location of
+ your system configuration directory is defined by the `--sysconfdir` flag in
+ the `./configure` script, it uses `/etc` if the prefix is `/usr`.
+- Since the location of the configuration can differ between installations,
+ `$cpt_confdir` variable can be used in programs using `cpt-lib` to get the
+ user's configuration directory.
+- This change currently doesn't break `cpt-base`, but you are advised to
+ rename your configuration files.
+- `/etc/cpt-base` is renamed to `/etc/cpt/base` (considering `$cpt_confdir` is
+ `/etc/cpt`)
+
+### Changes on hook behaviour
+- `/etc/cpt-hook` will no longer be used.
+- User hooks (as defined by `$CPT_HOOK` will be run regardless of the hook type.
+ I have realised that overriding user hooks on some operations was a mistake.
+ If the users already have the privilege to install packages, they should also
+ be able to run hooks without an interruption of the package manager.
+- Even though `/etc/cpt-hook` file is removed, a collection of systemwide hooks
+ can be added to the `/etc/cpt/hooks`directory. Any file in this directory will
+ be sourced by the package manager when running hooks. User hooks are run
+ _after_ systemwide hooks are run.
+- Added new hooks: `end-install` and `end-remove` that are run when
+ installation/removal is complete (not per-package).
+
+### Changed
+- `cpt-update` is now re-entrant, meaning that it is no longer needed to run the
+ update twice, `cpt-update` will continue the updates with the new version of
+ itself.
+- The package manager now can handle circular dependencies and exit gracefully.
+
+### Library
+- In order to get the `$deps` variable, one now has to use the new
+ `pkg_depends_commit()` function.
+
+
[6.2.3] - 2022-02-02
--------------------------------------------------------------------------------
@@ -35,7 +75,7 @@ this project _somewhat_ adheres to [Semantic Versioning].
[6.2.1] - 2021-09-20
----------------------------------------------------------------------------------
+--------------------------------------------------------------------------------
### Fixed
- `cpt-fork` follows symbolic links when forking packages.
@@ -44,7 +84,7 @@ this project _somewhat_ adheres to [Semantic Versioning].
[6.2.0] - 2021-08-14
----------------------------------------------------------------------------------
+--------------------------------------------------------------------------------
### BLAKE3 checksums
diff --git a/Makefile b/Makefile
index 691caf6..108138c 100644
--- a/Makefile
+++ b/Makefile
@@ -13,6 +13,7 @@ src/cpt-lib: src/cpt-lib.in
sed -n '/^Copyright/{s,^, ",;s,$$," \\,;p}' LICENSE | \
sed -e '/@LICENSE@/r /dev/stdin' \
-e '/@LICENSE@/d' \
+ -e 's|@SYSCONFDIR@|${SYSCONFDIR}|g' \
-e "s|@VERSION@|${VERSION}|g" \
-e "s|@DOCSTRING@|Call functions from the library|g" src/cpt-lib.in > $@
chmod 755 $@
diff --git a/configure b/configure
index d971a9e..6268da7 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#!/bin/sh -e
-version=6.2.3
+version=Fossil
die() {
printf '%s: %s\n' "${0##*/}" "$*" >&2
@@ -28,6 +28,7 @@ usage() {
"Options:" \
" --prefix=dir Set prefix directory" \
" --bindir=dir User executables [PREFIX/bin]" \
+ " --sysconfdir=dir System configuration directory [PREFIX/etc]" \
" --datarootdir=dir Data root directory [PREFIX/share]" \
" --mandir=dir Manual pages [DATAROOTDIR/man]" \
" --infodir=dir info documentation [DATAROOTDIR/info]" \
@@ -43,6 +44,7 @@ prefix=/usr/local
# We don't want expansion
# shellcheck disable=2016
{
+sysconfdir='$(PREFIX)/etc'
bindir='$(PREFIX)/bin'
datarootdir='$(PREFIX)/share'
mandir='$(DATAROOTDIR)/man'
@@ -54,8 +56,9 @@ docs=auto
for arg; do
case $arg in
-h|--help) usage ;;
- --prefix=*) prefix=${arg#*=} ;;
- --bindir=*) bindir=${arg#*=} ;;
+ --prefix=*) prefix=${arg#*=} ;;
+ --bindir=*) bindir=${arg#*=} ;;
+ --sysconfdir=*) sysconfdir=${arg#*=} ;;
--mandir=*) mandir=${arg#*=} ;;
--infodir=*) infodir=${arg#*=} ;;
--docdir=*) docdir=${arg#*=} ;;
@@ -68,6 +71,10 @@ for arg; do
esac
done
+# If the prefix is /usr and sysconfdir is not modified, make it /etc
+# shellcheck disable=2016
+[ "$prefix" = /usr ] && [ "$sysconfdir" = '$(PREFIX)/etc' ] && sysconfdir=/etc
+
trap 'rm -f config.mk' EXIT
trap 'rm -f config.mk; exit 1' INT
@@ -78,6 +85,7 @@ out "starting configuration..."
cat <<EOF > config.mk
PREFIX = $prefix
BINDIR = $bindir
+SYSCONFDIR = $sysconfdir
DATAROOTDIR = $datarootdir
MANDIR = $mandir
INFODIR = $infodir
diff --git a/contrib/cpt-chbuild b/contrib/cpt-chbuild
index dfceab0..7a71c33 100755
--- a/contrib/cpt-chbuild
+++ b/contrib/cpt-chbuild
@@ -26,7 +26,7 @@ parser_definition() {
global_options silent
}
-# shellcheck disable=1091
+# shellcheck source=../src/cpt-lib
. cpt-lib
die() {
@@ -45,9 +45,9 @@ cd "${cac_dir:?}"
# Remove the existing tarball and the chroot directory, so that they can be
# downloaded again.
-[ "$redownload" ] && rm -rf carbs-rootfs.tar.xz \
- carbs-rootfs.tar.xz.sum \
- carbs-chroot
+[ "$redownload" ] && as_root rm -rf carbs-rootfs.tar.xz \
+ carbs-rootfs.tar.xz.sum \
+ carbs-chroot
[ -f carbs-rootfs.tar.xz ] || {
log "Downloading chroot tarball"
@@ -59,12 +59,18 @@ cd "${cac_dir:?}"
pkg_download "$url.sha256" carbs-rootfs.tar.xz.sum
}
-log "Verifying checksums"
-sh256 carbs-rootfs.tar.xz | diff - carbs-rootfs.tar.xz.sum ||
- die "Checksum verification failed"
-
+# We don't want to create the rootfs as a non-priviliged user, because there may
+# arise certain problems if the files inside the chroot don't belong to root.
+[ "$uid" = 0 ] || {
+ as_root "$0" "$@"
+ exit $?
+}
[ -d carbs-chroot ] || {
+ log "Verifying checksums"
+ sh256 carbs-rootfs.tar.xz | diff - carbs-rootfs.tar.xz.sum ||
+ die "Checksum verification failed"
+
log "Extracting chroot"
mkdir -p carbs-chroot
(cd carbs-chroot; xz -cd ../carbs-rootfs.tar.xz | pax -r)
@@ -73,7 +79,8 @@ sh256 carbs-rootfs.tar.xz | diff - carbs-rootfs.tar.xz.sum ||
mkdir -p "${tmp_dir:?}"
log "Creating temporary chroot"
-cp -a carbs-chroot "${chr_dir:=$tmp_dir/chroot}"
+mkdir -p "${chr_dir:=$tmp_dir/chroot}"
+rsync -a carbs-chroot/ "$chr_dir"
[ "$1" ] && {
log "Installing extra packages"
@@ -83,9 +90,5 @@ cp -a carbs-chroot "${chr_dir:=$tmp_dir/chroot}"
run_hook pre-chroot "" "$chr_dir"
log "Entering chroot"
-if [ "$(id -u)" -eq 0 ]; then
- cpt-chroot "$chr_dir"
- rm -rf "$chr_dir"
-else
- as_root sh -c "cpt-chroot $chr_dir; rm -rf $chr_dir"
-fi
+cpt-chroot "$chr_dir"
+rm -rf "$chr_dir"
diff --git a/docs/Makefile b/docs/Makefile
index 3a7dbf0..7c5a431 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -4,6 +4,13 @@ INSTALL_SH = ../tools/install.sh
all: cpt.txt cpt.texi cpt.info
+config.org: ../config.mk
+ printf '%s\n' '#+MACRO: version $(VERSION)' \
+ '#+MACRO: conf_dir (eval (concat "=$(SYSCONFDIR)/cpt/" $$1 "="))' \
+ '#+MACRO: data_dir (eval (concat "=$(DATAROOTDIR)/" $$1 "="))' > config.org
+
+cpt.txt cpt.texi cpt.info: cpt.org config.org
+
.SUFFIXES: .info .texi .org .txt
.org.texi:
rm -f $@
@@ -20,6 +27,6 @@ clean:
rm -f cpt.info
all-clean: clean
- rm -f cpt.texi cpt.txt
+ rm -f cpt.texi cpt.txt config.org
.PHONY: all clean all-clean install uninstall
diff --git a/docs/cpt.org b/docs/cpt.org
index adf45f7..3896909 100644
--- a/docs/cpt.org
+++ b/docs/cpt.org
@@ -6,12 +6,14 @@
#+TEXINFO_DIR_CATEGORY: Development
#+TEXINFO_DIR_TITLE: Carbs Packaging Tools: (cpt)
#+TEXINFO_DIR_DESC: Carbs Package Management Library
+#+INCLUDE: ./config.org
#+OPTIONS: html-scripts:nil todo:nil
#+MACRO: index (eval (format (if (org-export-derived-backend-p org-export-current-backend 'texinfo) "%s Index\n:PROPERTIES:\n:INDEX: %s\n:DESCRIPTION: %ss mentioned in this manual\n:END:\n" "%s%s%s :noexport:\n") $1 $2 $1))
This is a reference document containing both the user-guide and the development
-manual for *Carbs Packaging Tools*. For development logs see [[https://git.carbslinux.org/cpt][the git repository]].
+manual for *Carbs Packaging Tools* version {{{version}}}. For development logs
+see [[https://fossil.carbslinux.org/cpt][the fossil repository]].
* Copying
:PROPERTIES:
@@ -40,6 +42,10 @@ it revolves around the shell library =cpt-lib=, and many tools that wrap around
it. This document aims to document both the usage of the distributed tools and
document the library functions.
+If you happen to find something that is not properly covered by the
+documentation, or an area that can be improved, please feel free to submit a
+patch, or [[https://fossil.carbslinux.org/cpt/tktnew][open a ticket]].
+
* Usage
:PROPERTIES:
:DESCRIPTION: Basic usage of Carbs Packaging Tools
@@ -109,19 +115,32 @@ man cpt-build
The package manager does *NOT* have a configuration file, but there are a
variety of ways in order to interact with and configure the package manager.
-** CPT Base
+** Configuration directory
+
+Some features of the package manager can be configured from the files found
+under {{{conf_dir}}}. Even though this doesn't sound like the premise of "no
+configuration" files, these files are completely optional to the package
+manager, and still the majority of configuration is done through environment
+variables. The files on this directory are for configuration that don't have a
+big impact on how the package manager behaves, and are not feasible to be used
+inside simple environment variables (such as the base package list and
+package manager hooks).
+
+*** CPT Base
:PROPERTIES:
:DESCRIPTION: Defining base packages
:END:
-An =/etc/cpt-base= file can be used in order to define the base to the package
-manager. Base packages are the packages that receive special treatment by
-utilities such as =cpt-reset=, and =cpt-orphans=.
+#+CINDEX: Base packages
+
+The file {{{conf_dir(base)}}} can be used in order to define the base to the
+package manager. Base packages are the packages that receive special treatment
+by utilities such as =cpt-reset=, and =cpt-orphans=.
#+begin_example
# This file defines the base packages of the system. You can add or remove
# package names in order to redefine the base. This file will be used by
-# cpt-orphans and cpt-reset. If this file doesn't exist on /etc/cpt-base, both
+# cpt-orphans and cpt-reset. If this file doesn't exist on /etc/cpt/base, both
# of the tools will assume that there is no defined base, so use with caution.
baselayout
binutils
@@ -146,6 +165,13 @@ xz
zlib
#+end_example
+*** Systemwide hooks
+
+A collection of hooks can be installed under {{{conf_dir(hooks/)}}}. All of the
+files installed under this directory will then be sourced by the package manager
+whenever a hook is called. Some examples for system hooks can be found under the
+{{{data_dir(cpt/examples/hooks/)}}} directory.
+
** Environment Variables
:PROPERTIES:
:DESCRIPTION: Change the behaviour of cpt through environment configuration
@@ -370,8 +396,10 @@ There are a variety of package hooks, mostly self explanatory:
- test-fail :: Run if the ~test~ script fails
- pre-install :: Run before a package is installed for each package
- post-install :: Run after a package is installed for each package
+- end-install :: Run after all given packages are installed
- pre-remove :: Run before a package is removed for each package
- post-remove :: Run after a package is removed for each package
+- end-remove :: Run after all given packages are removed
- pre-fetch :: Run before all repositories are fetched
- post-fetch :: Run after all repositories are fetched
- post-package :: Run after a tarball for a package is created
@@ -825,6 +853,52 @@ files:
This will load the library inside your script, and will set some environment
variables that are used inside the package manager.
+** Variables
+
+This section lists some of the variables defined by the package manager that can
+be used in scripts. These variables usually cannot be defined by the user, so
+they are not part of the [[* Environment Variables][variables]] section above.
+
+#+VINDEX: cpt_version
+- =$cpt_version= ::
+ Package manager version.
+#+VINDEX: cpt_confdir
+- =$cpt_confdir= ::
+ Location of the CPT system configuration directory. This is usually either
+ =/etc/cpt= or =PREFIX/etc/cpt=.
+#+VINDEX: pkg_db
+- =$pkg_db= ::
+ Location of the package database without the root (=var/db/cpt/installed=).
+#+VINDEX: sys_db
+#+VINDEX: CPT_ROOT
+- =$sys_db= ::
+ Location of the package manager database, making use of the current
+ =$CPT_ROOT= (=$CPT_ROOT/$pkg_db=). This is the database you probably want to
+ use.
+#+CINDEX: Base packages
+#+VINDEX: cpt_base
+- =$cpt_base= ::
+ Location of the file that defines the base packages.
+
+#+CINDEX: Scripts that use CPT cache directories
+If for some reason, your script interacts with the directories created and
+managed by the package manager you should use the following variables instead of
+the user assigned variables such as =$CPT_CACHE= or =$CPT_TMPDIR=. The variables
+below are the ones used for package operations (which are assigned by using a
+combination of user-assigned values and their fallbacks).
+
+#+VINDEX: cac_dir
+- =$cac_dir= ::
+ Cache directory used by the package manager.
+- =$src_dir= ::
+ Directory containing downloaded sources for packages.
+- =$log_dir= ::
+ Directory where logs are saved.
+- =$bin_dir= ::
+ Directory where built package tarballs are saved.
+- =$tmp_dir= ::
+ Temporary directory for the package manager operations.
+
** Option parsing
:PROPERTIES:
:DESCRIPTION: Easy way of parsing options with cpt-lib
@@ -1194,7 +1268,7 @@ SEARCH_PATH=$PATH pkg_find 'cpt-*' all -x
:DESCRIPTION: List system base packages
:END:
-This function returns the base packages as defined in =/etc/cpt-base=. If an
+This function returns the base packages as defined in the base file. If an
optional argument is present, it will print all package names in a single line.
If it is not given any arguments, it will return one package per line. See [[CPT
Base]] for more information on base packages.
diff --git a/docs/cpt.texi b/docs/cpt.texi
index 5ff1757..5c792a9 100644
--- a/docs/cpt.texi
+++ b/docs/cpt.texi
@@ -41,7 +41,8 @@ the section entitled "GNU Free Documentation License."
@top Carbs Packaging Tools
This is a reference document containing both the user-guide and the development
-manual for @strong{Carbs Packaging Tools}. For development logs see @uref{https://git.carbslinux.org/cpt, the git repository}.
+manual for @strong{Carbs Packaging Tools} version Fossil. For development logs
+see @uref{https://fossil.carbslinux.org/cpt, the fossil repository}.
@end ifnottex
@menu
@@ -60,11 +61,16 @@ manual for @strong{Carbs Packaging Tools}. For development logs see @uref{https:
Configuration
-* CPT Base:: Defining base packages
+* Configuration directory::
* Environment Variables:: Change the behaviour of cpt through environment configuration
* Hooks:: Use hooks to customize the package manager operations
* Editing the build file during pre-build:: Modify a package build with your hooks
+Configuration directory
+
+* CPT Base:: Defining base packages
+* Systemwide hooks::
+
Environment Variables
* @samp{CPT_PATH}:: Set the locations of your repositories
@@ -97,6 +103,7 @@ Rsync Repositories
CPT Library
* Calling the library:: Including the library on your code
+* Variables::
* Option parsing:: Easy way of parsing options with cpt-lib
* Message functions:: Communicate to users
* Text functions:: Manipulate or check text
@@ -160,6 +167,10 @@ it revolves around the shell library @samp{cpt-lib}, and many tools that wrap ar
it. This document aims to document both the usage of the distributed tools and
document the library functions.
+If you happen to find something that is not properly covered by the
+documentation, or an area that can be improved, please feel free to submit a
+patch, or @uref{https://fossil.carbslinux.org/cpt/tktnew, open a ticket}.
+
@node Usage
@chapter Usage
@@ -226,23 +237,42 @@ The package manager does @strong{NOT} have a configuration file, but there are a
variety of ways in order to interact with and configure the package manager.
@menu
-* CPT Base:: Defining base packages
+* Configuration directory::
* Environment Variables:: Change the behaviour of cpt through environment configuration
* Hooks:: Use hooks to customize the package manager operations
* Editing the build file during pre-build:: Modify a package build with your hooks
@end menu
+@node Configuration directory
+@section Configuration directory
+
+Some features of the package manager can be configured from the files found
+under @samp{/etc/cpt/}. Even though this doesn't sound like the premise of "no
+configuration" files, these files are completely optional to the package
+manager, and still the majority of configuration is done through environment
+variables. The files on this directory are for configuration that don't have a
+big impact on how the package manager behaves, and are not feasible to be used
+inside simple environment variables (such as the base package list and
+package manager hooks).
+
+@menu
+* CPT Base:: Defining base packages
+* Systemwide hooks::
+@end menu
+
@node CPT Base
-@section CPT Base
+@subsection CPT Base
+
+@cindex Base packages
-An @samp{/etc/cpt-base} file can be used in order to define the base to the package
-manager. Base packages are the packages that receive special treatment by
-utilities such as @samp{cpt-reset}, and @samp{cpt-orphans}.
+The file @samp{/etc/cpt/base} can be used in order to define the base to the
+package manager. Base packages are the packages that receive special treatment
+by utilities such as @samp{cpt-reset}, and @samp{cpt-orphans}.
@example
# This file defines the base packages of the system. You can add or remove
# package names in order to redefine the base. This file will be used by
-# cpt-orphans and cpt-reset. If this file doesn't exist on /etc/cpt-base, both
+# cpt-orphans and cpt-reset. If this file doesn't exist on /etc/cpt/base, both
# of the tools will assume that there is no defined base, so use with caution.
baselayout
binutils
@@ -267,6 +297,14 @@ xz
zlib
@end example
+@node Systemwide hooks
+@subsection Systemwide hooks
+
+A collection of hooks can be installed under @samp{/etc/cpt/hooks/}. All of the
+files installed under this directory will then be sourced by the package manager
+whenever a hook is called. Some examples for system hooks can be found under the
+@samp{/usr/share/cpt/examples/hooks/} directory.
+
@node Environment Variables
@section Environment Variables
@@ -491,10 +529,14 @@ Run if the @code{test} script fails
Run before a package is installed for each package
@item post-install
Run after a package is installed for each package
+@item end-install
+Run after all given packages are installed
@item pre-remove
Run before a package is removed for each package
@item post-remove
Run after a package is removed for each package
+@item end-remove
+Run after all given packages are removed
@item pre-fetch
Run before all repositories are fetched
@item post-fetch
@@ -967,6 +1009,7 @@ package manager library.
@menu
* Calling the library:: Including the library on your code
+* Variables::
* Option parsing:: Easy way of parsing options with cpt-lib
* Message functions:: Communicate to users
* Text functions:: Manipulate or check text
@@ -989,6 +1032,65 @@ files:
This will load the library inside your script, and will set some environment
variables that are used inside the package manager.
+@node Variables
+@section Variables
+
+This section lists some of the variables defined by the package manager that can
+be used in scripts. These variables usually cannot be defined by the user, so
+they are not part of the @ref{Environment Variables, , variables} section above.
+
+@vindex cpt_version
+@table @asis
+@item @samp{$cpt_version}
+Package manager version.
+@end table
+@vindex cpt_confdir
+@table @asis
+@item @samp{$cpt_confdir}
+Location of the CPT system configuration directory. This is usually either
+@samp{/etc/cpt} or @samp{PREFIX/etc/cpt}.
+@end table
+@vindex pkg_db
+@table @asis
+@item @samp{$pkg_db}
+Location of the package database without the root (@samp{var/db/cpt/installed}).
+@end table
+@vindex sys_db
+@vindex CPT_ROOT
+@table @asis
+@item @samp{$sys_db}
+Location of the package manager database, making use of the current
+@samp{$CPT_ROOT} (@samp{$CPT_ROOT/$pkg_db}). This is the database you probably want to
+use.
+@end table
+@cindex Base packages
+@vindex cpt_base
+@table @asis
+@item @samp{$cpt_base}
+Location of the file that defines the base packages.
+@end table
+
+@cindex Scripts that use CPT cache directories
+If for some reason, your script interacts with the directories created and
+managed by the package manager you should use the following variables instead of
+the user assigned variables such as @samp{$CPT_CACHE} or @samp{$CPT_TMPDIR}. The variables
+below are the ones used for package operations (which are assigned by using a
+combination of user-assigned values and their fallbacks).
+
+@vindex cac_dir
+@table @asis
+@item @samp{$cac_dir}
+Cache directory used by the package manager.
+@item @samp{$src_dir}
+Directory containing downloaded sources for packages.
+@item @samp{$log_dir}
+Directory where logs are saved.
+@item @samp{$bin_dir}
+Directory where built package tarballs are saved.
+@item @samp{$tmp_dir}
+Temporary directory for the package manager operations.
+@end table
+
@node Option parsing
@section Option parsing
@@ -1387,7 +1489,7 @@ SEARCH_PATH=$PATH pkg_find 'cpt-*' all -x
@node @samp{pkg_get_base()}
@subsection @samp{pkg_get_base()}
-This function returns the base packages as defined in @samp{/etc/cpt-base}. If an
+This function returns the base packages as defined in the base file. If an
optional argument is present, it will print all package names in a single line.
If it is not given any arguments, it will return one package per line. See @ref{CPT Base} for more information on base packages.
diff --git a/docs/cpt.txt b/docs/cpt.txt
index e965da7..c89f02a 100644
--- a/docs/cpt.txt
+++ b/docs/cpt.txt
@@ -14,7 +14,9 @@ _________________
2. Preface
3. Usage
4. Configuration
-.. 1. CPT Base
+.. 1. Configuration directory
+..... 1. CPT Base
+..... 2. Systemwide hooks
.. 2. Environment Variables
..... 1. `CPT_PATH'
..... 2. `CPT_COMPRESS'
@@ -40,27 +42,28 @@ _________________
7. Comparison Between CPT and KISS
8. CPT Library
.. 1. Calling the library
-.. 2. Option parsing
+.. 2. Variables
+.. 3. Option parsing
..... 1. Defining a parser
..... 2. `global_options()'
-.. 3. Message functions
+.. 4. Message functions
..... 1. `out()'
..... 2. `log()'
..... 3. `die()'
..... 4. `warn()'
..... 5. `prompt()'
-.. 4. Text functions
+.. 5. Text functions
..... 1. `contains()'
..... 2. `regesc()'
..... 3. `pop()'
..... 4. `sepchar()'
-.. 5. Portability functions
+.. 6. Portability functions
..... 1. `_seq()'
..... 2. `_stat()'
..... 3. `_readlinkf()'
-.. 6. System Functions
+.. 7. System Functions
..... 1. `as_root()'
-.. 7. Package Functions
+.. 8. Package Functions
..... 1. `pkg_build()'
..... 2. `pkg_depends()'
..... 3. `pkg_order()'
@@ -74,11 +77,11 @@ _________________
This is a reference document containing both the user-guide and the
-development manual for *Carbs Packaging Tools*. For development logs see
-[the git repository].
+development manual for *Carbs Packaging Tools* version Fossil. For
+development logs see [the fossil repository].
-[the git repository] <https://git.carbslinux.org/cpt>
+[the fossil repository] <https://fossil.carbslinux.org/cpt>
1 Copying
@@ -106,9 +109,15 @@ development manual for *Carbs Packaging Tools*. For development logs see
aims to document both the usage of the distributed tools and document
the library functions.
+ If you happen to find something that is not properly covered by the
+ documentation, or an area that can be improved, please feel free to
+ submit a patch, or [open a ticket].
+
[kiss] <https://github.com/kisslinux/kiss>
+[open a ticket] <https://fossil.carbslinux.org/cpt/tktnew>
+
3 Usage
=======
@@ -178,17 +187,31 @@ development manual for *Carbs Packaging Tools*. For development logs see
package manager.
-4.1 CPT Base
-~~~~~~~~~~~~
+4.1 Configuration directory
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Some features of the package manager can be configured from the files
+ found under `/etc/cpt/'. Even though this doesn't sound like the
+ premise of "no configuration" files, these files are completely
+ optional to the package manager, and still the majority of
+ configuration is done through environment variables. The files on this
+ directory are for configuration that don't have a big impact on how
+ the package manager behaves, and are not feasible to be used inside
+ simple environment variables (such as the base package list and
+ package manager hooks).
+
+
+4.1.1 CPT Base
+--------------
- An `/etc/cpt-base' file can be used in order to define the base to the
- package manager. Base packages are the packages that receive special
- treatment by utilities such as `cpt-reset', and `cpt-orphans'.
+ The file `/etc/cpt/base' can be used in order to define the base to
+ the package manager. Base packages are the packages that receive
+ special treatment by utilities such as `cpt-reset', and `cpt-orphans'.
,----
| # This file defines the base packages of the system. You can add or remove
| # package names in order to redefine the base. This file will be used by
- | # cpt-orphans and cpt-reset. If this file doesn't exist on /etc/cpt-base, both
+ | # cpt-orphans and cpt-reset. If this file doesn't exist on /etc/cpt/base, both
| # of the tools will assume that there is no defined base, so use with caution.
| baselayout
| binutils
@@ -214,6 +237,16 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
+4.1.2 Systemwide hooks
+----------------------
+
+ A collection of hooks can be installed under `/etc/cpt/hooks/'. All of
+ the files installed under this directory will then be sourced by the
+ package manager whenever a hook is called. Some examples for system
+ hooks can be found under the `/usr/share/cpt/examples/hooks/'
+ directory.
+
+
4.2 Environment Variables
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -412,10 +445,14 @@ development manual for *Carbs Packaging Tools*. For development logs see
Run before a package is installed for each package
post-install
Run after a package is installed for each package
+ end-install
+ Run after all given packages are installed
pre-remove
Run before a package is removed for each package
post-remove
Run after a package is removed for each package
+ end-remove
+ Run after all given packages are removed
pre-fetch
Run before all repositories are fetched
post-fetch
@@ -627,7 +664,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
mandatory file for submitting packages to Carbs Linux repositories.
-[pkg_query_meta()] See section 8.7.10
+[pkg_query_meta()] See section 8.8.10
5.7 post-install
@@ -878,7 +915,52 @@ development manual for *Carbs Packaging Tools*. For development logs see
environment variables that are used inside the package manager.
-8.2 Option parsing
+8.2 Variables
+~~~~~~~~~~~~~
+
+ This section lists some of the variables defined by the package
+ manager that can be used in scripts. These variables usually cannot be
+ defined by the user, so they are not part of the [variables] section
+ above.
+
+ `$cpt_version'
+ Package manager version.
+ `$cpt_confdir'
+ Location of the CPT system configuration directory. This is
+ usually either `/etc/cpt' or `PREFIX/etc/cpt'.
+ `$pkg_db'
+ Location of the package database without the root
+ (`var/db/cpt/installed').
+ `$sys_db'
+ Location of the package manager database, making use of the
+ current `$CPT_ROOT' (`$CPT_ROOT/$pkg_db'). This is the database
+ you probably want to use.
+ `$cpt_base'
+ Location of the file that defines the base packages.
+
+ If for some reason, your script interacts with the directories created
+ and managed by the package manager you should use the following
+ variables instead of the user assigned variables such as `$CPT_CACHE'
+ or `$CPT_TMPDIR'. The variables below are the ones used for package
+ operations (which are assigned by using a combination of user-assigned
+ values and their fallbacks).
+
+ `$cac_dir'
+ Cache directory used by the package manager.
+ `$src_dir'
+ Directory containing downloaded sources for packages.
+ `$log_dir'
+ Directory where logs are saved.
+ `$bin_dir'
+ Directory where built package tarballs are saved.
+ `$tmp_dir'
+ Temporary directory for the package manager operations.
+
+
+[variables] See section 4.2
+
+
+8.3 Option parsing
~~~~~~~~~~~~~~~~~~
`cpt-lib' includes a POSIX-shell option parser inside named
@@ -890,7 +972,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
[documentation]
<https://github.com/ko1nksm/getoptions/blob/v2.5.0/README.md>
-8.2.1 Defining a parser
+8.3.1 Defining a parser
-----------------------
Some functions are called and set automatically when you call
@@ -917,7 +999,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
-8.2.2 `global_options()'
+8.3.2 `global_options()'
------------------------
The `global_options()' function is a simple convenience call to
@@ -943,13 +1025,13 @@ development manual for *Carbs Packaging Tools*. For development logs see
output of the `--help' and `--version' flags.
-8.3 Message functions
+8.4 Message functions
~~~~~~~~~~~~~~~~~~~~~
`cpt' has various functions to print information to users.
-8.3.1 `out()'
+8.4.1 `out()'
-------------
`out()' is a really simple function that prints messages to the
@@ -964,7 +1046,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
-8.3.2 `log()'
+8.4.2 `log()'
-------------
`log()' is the most commonly used message function in the package
@@ -982,7 +1064,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
above.
-8.3.3 `die()'
+8.4.3 `die()'
-------------
`die()' wraps the `log()' function and exits with an error (1). It
@@ -990,14 +1072,14 @@ development manual for *Carbs Packaging Tools*. For development logs see
function. The third argument for `log()' is set as `!>'.
-8.3.4 `warn()'
+8.4.4 `warn()'
--------------
`warn()' is another function that wraps `log()'. In place of the third
argument, it uses the word `WARNING'.
-8.3.5 `prompt()'
+8.4.5 `prompt()'
----------------
`prompt()' is an interactive function that waits for user input to
@@ -1007,14 +1089,14 @@ development manual for *Carbs Packaging Tools*. For development logs see
`CPT_PROMPT' to 0.
-8.4 Text functions
+8.5 Text functions
~~~~~~~~~~~~~~~~~~
Following functions are used to manipulate, check, or interact with
text.
-8.4.1 `contains()'
+8.5.1 `contains()'
------------------
`contains' function can be used to check whether a list variable
@@ -1030,7 +1112,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
-8.4.2 `regesc()'
+8.5.2 `regesc()'
----------------
`regesc()' can be used to escape regular expression characters that
@@ -1042,7 +1124,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
-8.4.3 `pop()'
+8.5.3 `pop()'
-------------
`pop()' can be used to remove a word from a "string list" without a
@@ -1056,7 +1138,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
-8.4.4 `sepchar()'
+8.5.4 `sepchar()'
-----------------
This function can be used to separate characters from the given string
@@ -1076,7 +1158,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
-8.5 Portability functions
+8.6 Portability functions
~~~~~~~~~~~~~~~~~~~~~~~~~
These helper functions are used so that we don't depend on non-POSIX
@@ -1084,7 +1166,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
character.
-8.5.1 `_seq()'
+8.6.1 `_seq()'
--------------
This function is similar to `seq(1)' except that it only takes a
@@ -1098,7 +1180,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
-8.5.2 `_stat()'
+8.6.2 `_stat()'
---------------
This function imitates `stat %U'. `stat' isn't defined by POSIX, and
@@ -1106,7 +1188,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
file. If the owner cannot be found, it will return `root'.
-8.5.3 `_readlinkf()'
+8.6.3 `_readlinkf()'
--------------------
This function was taken from [POSIX sh readlinkf library by Koichi
@@ -1118,10 +1200,10 @@ development manual for *Carbs Packaging Tools*. For development logs see
<https://github.com/ko1nksm/readlinkf>
-8.6 System Functions
+8.7 System Functions
~~~~~~~~~~~~~~~~~~~~
-8.6.1 `as_root()'
+8.7.1 `as_root()'
-----------------
`as_root()' calls the rest of the arguments as a different
@@ -1138,7 +1220,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
`$CPT_SU' variable.
-8.7 Package Functions
+8.8 Package Functions
~~~~~~~~~~~~~~~~~~~~~
Obviously, package functions are the most important ones for
@@ -1146,7 +1228,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
manipulate, or to otherwise interact with packages.
-8.7.1 `pkg_build()'
+8.8.1 `pkg_build()'
-------------------
This function builds all given packages. It resolves dependencies for
@@ -1164,7 +1246,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
-8.7.2 `pkg_depends()'
+8.8.2 `pkg_depends()'
---------------------
This function calculates the dependencies for the requested package,
@@ -1173,17 +1255,17 @@ development manual for *Carbs Packaging Tools*. For development logs see
packages.
-[pkg_order()] See section 8.7.3
+[pkg_order()] See section 8.8.3
-8.7.3 `pkg_order()'
+8.8.3 `pkg_order()'
-------------------
This function receives package names and returns `$order' and `$redro'
variables that can be used for building and removing packages.
-8.7.4 `pkg_owner()'
+8.8.4 `pkg_owner()'
-------------------
This function can be used to determine the owner of a package. The
@@ -1204,7 +1286,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
-8.7.5 `pkg_isbuilt()'
+8.8.5 `pkg_isbuilt()'
---------------------
This function returns with success when the given package has a built
@@ -1212,7 +1294,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
repository.
-8.7.6 `pkg_lint()'
+8.8.6 `pkg_lint()'
------------------
This function checks whether a given package fits the proper package
@@ -1220,7 +1302,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
outright* if it fails.
-8.7.7 `pkg_find()'
+8.8.7 `pkg_find()'
------------------
`pkg_find()' is the tool for searching packages. It accepts up to 3
@@ -1253,17 +1335,17 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
-8.7.8 `pkg_get_base()'
+8.8.8 `pkg_get_base()'
----------------------
- This function returns the base packages as defined in
- `/etc/cpt-base'. If an optional argument is present, it will print all
- package names in a single line. If it is not given any arguments, it
- will return one package per line. See 4.1 for more information on base
+ This function returns the base packages as defined in the base
+ file. If an optional argument is present, it will print all package
+ names in a single line. If it is not given any arguments, it will
+ return one package per line. See 4.1.1 for more information on base
packages.
-8.7.9 `pkg_gentree()'
+8.8.9 `pkg_gentree()'
---------------------
This function generates a dependency tree for the given package. The
@@ -1283,7 +1365,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
line.
-* 8.7.9.1 Examples
+* 8.8.9.1 Examples
This example uses the `cpt' package for Carbs Linux. The package
itself is listed to depend on `curl' and `rsync'. Here is the output
@@ -1309,7 +1391,7 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
-8.7.10 `pkg_query_meta()'
+8.8.10 `pkg_query_meta()'
-------------------------
This function is used to query the [meta file] inside package
diff --git a/examples/hooks/clean-packages b/examples/hooks/clean-packages
new file mode 100644
index 0000000..972eb31
--- /dev/null
+++ b/examples/hooks/clean-packages
@@ -0,0 +1,7 @@
+# -*- mode: sh; -*-
+# clean-packages -- Remove documentation, and locales from packages.
+case $TYPE in
+ post-build)
+ rm -rf "$DEST/usr/share/locale" \
+ "$DEST/usr/share/doc"
+esac
diff --git a/examples/hooks/makewhatis b/examples/hooks/makewhatis
new file mode 100644
index 0000000..5c38001
--- /dev/null
+++ b/examples/hooks/makewhatis
@@ -0,0 +1,10 @@
+# -*- mode: sh; -*-
+# Run makewhatis if a manual page is installed, or removed
+case $TYPE in
+ post-install|pre-remove)
+ grep -q "^/usr/share/man/" "$DEST/manifest" &&
+ run_makewhatis=1
+ ;;
+ end-install|end-remove)
+ [ "$run_makewhatis" ] && makewhatis "$DEST/usr/share/man"
+esac
diff --git a/spec/01_lib_spec.sh b/spec/01_lib_spec.sh
index b56ac32..6612618 100644
--- a/spec/01_lib_spec.sh
+++ b/spec/01_lib_spec.sh
@@ -162,15 +162,9 @@ Describe 'CPT Library'
End
It "doesn't log 'running hook' if no package is given"
When call run_hook 2 '' destination
- The stderr should eq "-> Running 2 hook "
+ The stderr should eq "-> Running 2 hook"
The output should eq "$CPT_HOOK 2 null destination"
End
- It "uses the /etc/cpt-hook file of the root when called with a fourth arg"
- When call run_hook 3 cpt destdir root
- The stderr should eq "-> cpt Running 3 hook"
- The output should eq "$CPT_ROOT/etc/cpt-hook 3 cpt destdir"
- The variable CPT_HOOK should eq "$PWD/tests/hook-file"
- End
It "returns with success even when the file doesn't exist"
CPT_HOOK=$PWD/some-non-existent-file
When call run_hook 4 thiswillnotrun
@@ -178,14 +172,6 @@ Describe 'CPT Library'
The stderr should eq ""
The status should be success
End
- It "restores the \$CPT_HOOK variable when called with root"
- CPT_ROOT=$PWD/nonexistentdir
- When call run_hook 5 cpt dest root
- The variable CPT_ROOT should not be exist
- The stderr should eq ""
- The status should be success
- The variable CPT_HOOK should eq "$PWD/tests/hook-file"
- End
End
Describe 'create_tmp()'
After pkg_clean
@@ -197,10 +183,31 @@ Describe 'CPT Library'
Describe 'pkg_get_base()'
CPT_ROOT=$PWD/tests
CPT_PATH=$PWD/tests/repository
+ cpt_base=$PWD/tests/etc/cpt-base
It 'returns packages defined in base'
When call pkg_get_base nonl
The output should eq "dummy-pkg contrib-dummy-pkg "
End
End
+ Describe 'pkg_query_meta()'
+ CPT_PATH=$PWD/tests/repository
+ It 'queries package meta information'
+ When call pkg_query_meta contrib-dummy-pkg description
+ The output should eq "This is a dummy package"
+ End
+ It 'returns an error if there is no meta file'
+ When call pkg_query_meta dummy-pkg description
+ The status should be failure
+ End
+ It 'returns an error if the queried key is unavailable'
+ When call pkg_query_meta contrib-dummy-pkg license
+ The status should be failure
+ End
+ It "accepts full paths to the package location"
+ When call pkg_query_meta "$PWD/tests/repository/contrib-dummy-pkg" description
+ The output should eq "This is a dummy package"
+ The status should be success
+ End
+ End
End
End
diff --git a/spec/02_src_spec.sh b/spec/02_src_spec.sh
index be81775..5286ab9 100644
--- a/spec/02_src_spec.sh
+++ b/spec/02_src_spec.sh
@@ -20,7 +20,7 @@ Describe 'Main toolchain'
Describe '--help'
It 'outputs usage information'
When run script src/cpt --help
- The line 1 of stderr should eq "-> Carbs Packaging Tool "
+ The line 1 of stderr should eq "-> Carbs Packaging Tool"
End
End
diff --git a/src/cpt-alternatives b/src/cpt-alternatives
index 3c98753..87946f0 100755
--- a/src/cpt-alternatives
+++ b/src/cpt-alternatives
@@ -2,31 +2,83 @@
# List and swap to alternatives
parser_definition() {
- setup REST help:usage -- "usage: ${0##*/} [-] [package file]"
- global_options silent
+ setup REST help:usage -- "usage: ${0##*/} package file"
+ msg -- "or: ${0##*/} [-p]"
+ msg -- "or: ${0##*/} -"
+ msg -- '' 'Options:'
+ flag preferred -p -- "List current owners of alternative files"
+ global_options
}
if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
# We don't need to be root in order to list alternatives, so skip privilege
# elevation if no arguments are passed to the script.
-[ -z "$1" ] || [ -w "$CPT_ROOT/" ] || [ "$uid" = 0 ] || {
+[ -z "$1" ] && [ -t 0 ] || [ -w "$CPT_ROOT/" ] || [ "$uid" = 0 ] || {
as_root "$0" "$@"
exit $?
}
+list_alternatives() {
+ # Go over each alternative and format the file name for listing.
+ # (pkg_name>usr>bin>ls)
+ set +f
+ for pkg in "$sys_db/../choices/"*; do
+ printf '%s\n' "${pkg##*/}"
+ done | sed 's|>|\t/|;s|>|/|g;/\*/d'
+}
+
+stdin_swap() {
+ # Swap packages by reading the standard input.
+ while IFS=$(printf '\t') read -r pkg path _; do
+ pkg_swap "$pkg" "$path"
+ done
+ exit
+}
+
case "$1" in
- -)
- while read -r pkg path; do
- pkg_swap "$pkg" "$path"
- done
- ;;
+ -) stdin_swap ;;
'')
- # Go over each alternative and format the file name for listing.
- # (pkg_name>usr>bin>ls)
- set +f; for pkg in "$sys_db/../choices/"*; do
- printf '%s\n' "${pkg##*/}"
- done | sed 's|>| /|; s|>|/|g; /\*/d'
+ # We still want to read the standard input when there are no arguments
+ # if the standard input is being used.
+ [ -t 0 ] || stdin_swap
+
+ if [ "$preferred" ]; then
+ # We are not using the pkg_owner() function here. It's much slower
+ # when searching items in bulk.
+ altlist=$(_tmp_create altlist)
+ pathlist=$(_tmp_create pathlist)
+ owners=$(_tmp_create owners)
+ list_alternatives | tee "$altlist" | sed 's,^[^\t]*\t,,' > "$pathlist"
+
+ # Save all matching items in a single file, so we don't ever read
+ # manifests again.
+ set +f
+ grep -Fxf "$pathlist" "$sys_db/"*/manifest > "$owners"
+ sys_db_esc=$(regesc "$sys_db")
+
+ while read -r pkg path; do
+ case $path in
+ # Running regesc() for each file slows us down, don't use
+ # it unless we detect a regular expression to escape.
+ *\[*|*\$*|*\\*|*.*|*^*) path_str=$(regesc "$path") ;;
+ *) path_str=$path
+ esac
+ grep_str="$sys_db_esc/[^/]*/manifest:$path_str"
+ owns=$(grep -x -- "$grep_str" "$owners") || owns=null
+ owns=${owns%:*} owns=${owns%/*} owns=${owns##*/}
+ printf '%s\t%s\t(owned by: %s)\n' "$pkg" "$path" "$owns"
+ done < "$altlist"
+
+ # We read the output of list_alternatives(), because that seems to
+ # be the faster option.
+ # list_alternatives | while read -r pkg path; do
+ # printf '%s %s (owned by: %s)\n' \
+ # "$pkg" "$path" "$(pkg_owner -lFx "$path" || out "null")"
+ # done
+ else
+ list_alternatives
+ fi
;;
*) pkg_swap "$@" ;;
esac
diff --git a/src/cpt-install b/src/cpt-install
index 78da9a8..8bafba6 100755
--- a/src/cpt-install
+++ b/src/cpt-install
@@ -27,6 +27,10 @@ for pkg in $order; do pkg_install "$pkg"; done
log "Retrieving post-installation message queue"
unset msg
+# After all the installations are finished, run an end-install hook. There may
+# be some things that we may want to run, but not per package.
+run_hook end-install "" "$CPT_ROOT"
+
for pkg in $order; do
# Ensure that we use package names itself, and not the tarball name if given.
pkg=${pkg##*/} pkg=${pkg%#*}
diff --git a/src/cpt-lib.in b/src/cpt-lib.in
index 7659e39..cfa0b18 100644
--- a/src/cpt-lib.in
+++ b/src/cpt-lib.in
@@ -9,7 +9,7 @@
# Currently maintained by Cem Keylan.
version() {
- out "Carbs Packaging Tools, version @VERSION@" \
+ out "Carbs Packaging Tools, version $cpt_version" \
@LICENSE@
exit 0
@@ -25,11 +25,12 @@ log() {
#
# All messages are printed to stderr to allow the user to hide build
# output which is the only thing printed to stdout.
- #
- # '${3:-->}': If the 3rd argument is missing, set prefix to '->'.
- # '${2:+colorb}': If the 2nd argument exists, set text style of '$1'.
- printf '%b%s %b%b%s%b %s\n' \
- "$colory" "${3:-->}" "$colre" "${2:+$colorb}" "$1" "$colre" "$2" >&2
+ case $# in
+ 1) printf '%b->%b %s\n' "$colory" "$colre" "$1" ;;
+ 2) printf '%b->%b %b%s%b %s\n' "$colory" "$colre" "$colorb" "$1" "$colre" "$2" ;;
+ 3) printf '%b%s%b %b%s%b %s\n' "$colory" "${3:-->}" "$colre" "$colorb" "$1" "$colre" "$2" ;;
+ *) return 1
+ esac >&2
}
warn() {
@@ -75,6 +76,47 @@ colors_enabled() {
esac
}
+_dep_append() {
+ dep_graph=$(printf '%s\n%s %s\n' "$dep_graph" "$@" ;)
+}
+
+_tsort() {
+ # Return a linear reverse topological sort of the piped input, so we
+ # generate a proper build order. Returns 1 if a dependency cycle occurs.
+ #
+ # I was really excited when I saw POSIX specified a tsort(1) implementation,
+ # but the specification is quite vague, it doesn't specify cycles as a
+ # reason of error, and implementations differ on how it's handled. coreutils
+ # tsort(1) exits with an error, while openbsd tsort(1) doesn't. Both
+ # implementations are correct according to the specification. This leaves us
+ # with the following awk script, because the POSIX shell is not up for the
+ # job without super ugly hacks.
+ awk 'function fv(s) {
+ for (sp in e) {
+ split (e[sp],t)
+ for (j in t) if (s == t[j]) return 0
+ } return 1
+ }
+ function el(_l) {for(i in e){_l=_l" "i;}; return _l;}
+ function ce(t) {if (!(t in e)) e[t]="";}
+ function err(s) {print "Dependency cycle deteced between: " s; exit 1;}
+ {ce($1);$1!=$2&&e[$1]=e[$1]" "$2;}
+ END {
+ do {p=el()
+ for (s in e) {
+ if (fv(s)) {
+ pr=s" "pr
+ split(e[s],t)
+ for(i in t){ce(t[i]);}
+ delete e[s]
+ }
+ } c=el()
+ } while (p != c)
+ if (length(p)!=0) err(p);
+ print pr
+ }'
+}
+
trap_set() {
# Function to set the trap value.
case ${1:-cleanup} in
@@ -90,20 +132,16 @@ trap_set() {
esac
}
-sepchar() (
+sepchar() {
# Seperate every character on the given string without resorting to external
# processes.
[ "$1" ] || return 0; str=$1; set --
while [ "$str" ]; do
- str_tmp=$str
- for i in $(_seq $(( ${#str} - 1 ))); do
- str_tmp=${str_tmp%?}
- done
- set -- "$@" "$str_tmp"
- str=${str#"$str_tmp"}
+ set -- "$@" "${str%"${str#?}"}"
+ str=${str#?}
done
printf '%s\n' "$@"
-)
+}
_re() {
# Check that the string supplied in $2 conforms to the regular expression
@@ -510,6 +548,9 @@ as_root() {
# We are exporting package manager variables, so that we still have the
# same repository paths / access to the same cache directories etc.
+ #
+ # It doesn't matter whether CPT_HOOK is defined or not.
+ # shellcheck disable=2153
set -- HOME="$HOME" \
USER="$user" \
XDG_CACHE_HOME="$XDG_CACHE_HOME" \
@@ -551,23 +592,26 @@ pop() {
}
run_hook() {
- # Store the CPT_HOOK variable so that we can revert it if it is changed.
- oldCPT_HOOK=$CPT_HOOK
-
- # If a fourth parameter 'root' is specified, source the hook from a
- # predefined location to avoid privilige escalation through user scripts.
- [ "$4" ] && CPT_HOOK=$CPT_ROOT/etc/cpt-hook
-
- [ -f "$CPT_HOOK" ] || { CPT_HOOK=$oldCPT_HOOK; return 0 ;}
-
- if [ "$2" ]; then
- logv "$2" "Running $1 hook"
- else
- logv "Running $1 hook"
- fi
+ # Check that hooks exist before announcing that we are running a hook.
+ set +f
+ for hook in "$cpt_confdir/hooks/"* "$CPT_HOOK"; do
+ [ -f "$hook" ] && {
+ if [ "$2" ]; then
+ logv "$2" "Running $1 hook"
+ else
+ logv "Running $1 hook"
+ fi
+ break
+ }
+ done
- TYPE=${1:-null} PKG=${2:-null} DEST=${3:-null} . "$CPT_HOOK"
- CPT_HOOK=$oldCPT_HOOK
+ # Run all the hooks found in the configuration directory, and the user
+ # defined hook.
+ for hook in "$cpt_confdir/hooks/"* "$CPT_HOOK"; do
+ set -f
+ [ -f "$hook" ] || continue
+ TYPE=${1:-null} PKG=${2:-null} DEST=${3:-null} . "$hook"
+ done
}
# An optional argument could be provided to enforce a compression algorithm.
@@ -844,12 +888,9 @@ pkg_depends() {
# Resolve all dependencies and generate an ordered list.
# This does a depth-first search. The deepest dependencies are
# listed first and then the parents in reverse order.
- contains "$deps" "$1" || {
- # Filter out non-explicit, aleady installed dependencies.
- # Only filter installed if called from 'pkg_build()'.
- [ "$pkg_build" ] && [ -z "$2" ] &&
- (pkg_list "$1" >/dev/null) && return
-
+ contains "$pkgs" "$1" || {
+ pkgs="$pkgs $1 "
+ [ "$2" = raw ] && _dep_append "$1" "$1"
while read -r dep type || [ "$dep" ]; do
# Skip comments and empty lines.
[ "${dep##\#*}" ] || continue
@@ -862,6 +903,16 @@ pkg_depends() {
make) [ "$2" = tree ] && [ -z "${3#first-nomake}" ] && continue
esac
+ # Filter out non-explicit, already installed dependencies if called
+ # from 'pkg_build()'.
+ [ "$pkg_build" ] && (pkg_list "$dep" >/dev/null) && continue
+
+ if [ "$2" = explicit ] || [ "$3" ]; then
+ _dep_append "$dep" "$dep"
+ else
+ _dep_append "$1" "$dep"
+ fi
+
# Recurse through the dependencies of the child packages. Forward
# the 'tree' operation.
if [ "$2" = tree ]; then
@@ -871,12 +922,14 @@ pkg_depends() {
fi
done 2>/dev/null < "$(pkg_find "$1")/depends" ||:
- # After child dependencies are added to the list,
- # add the package which depends on them.
- [ "$2" = explicit ] || [ "$3" ] || deps="$deps $1 "
}
}
+pkg_depends_commit() {
+ # Set deps, and cleanup dep_graph, pkgs
+ deps=$(printf '%s\n' "$dep_graph" | _tsort) dep_graph='' pkgs='' || warn "Dependency cycle detected"
+}
+
pkg_order() {
# Order a list of packages based on dependence and
# take into account pre-built tarballs if this is
@@ -884,9 +937,10 @@ pkg_order() {
order=; redro=; deps=
for pkg do case $pkg in
- *.tar.*) deps="$deps $pkg " ;;
+ *.tar.*) _dep_append "$pkg" "$pkg" ;;
*) pkg_depends "$pkg" raw
esac done
+ pkg_depends_commit
# Filter the list, only keeping explicit packages.
# The purpose of these two loops is to order the
@@ -945,11 +999,10 @@ pkg_fix_deps() {
# simplify path building.
cd "$pkg_dir/$1/$pkg_db/$1"
- # Make a copy of the depends file if it exists to have a
- # reference to 'diff' against.
+ # Make a copy of the depends file if it exists to have a reference to 'diff'
+ # against.
if [ -f depends ]; then
- cp -f depends "$mak_dir/d"
- dep_file=$mak_dir/d
+ dep_file=$(_tmp_cp depends)
else
dep_file=/dev/null
fi
@@ -1087,6 +1140,7 @@ pkg_build() {
# separately from those detected as dependencies.
explicit="$explicit $pkg "
} done
+ pkg_depends_commit
[ "$pkg_update" ] || explicit_build=$explicit
@@ -1321,6 +1375,9 @@ pkg_conflicts() {
# Check to see if a package conflicts with another.
log "$1" "Checking for package conflicts"
+ c_manifest=$(_tmp_create conflict-manifest)
+ c_conflicts=$(_tmp_create conflicts)
+
# Filter the tarball's manifest and select only files
# and any files they resolve to on the filesystem
# (/bin/ls -> /usr/bin/ls).
@@ -1342,7 +1399,7 @@ pkg_conflicts() {
# temporary manifest to be parsed.
printf '%s/%s\n' "${dirname#"$CPT_ROOT"}" "${file##*/}"
- done < "$tar_dir/$1/$pkg_db/$1/manifest" > "$CPT_TMPDIR/$pid/manifest"
+ done < "$tar_dir/$1/$pkg_db/$1/manifest" > "$c_manifest"
p_name=$1
@@ -1351,7 +1408,7 @@ pkg_conflicts() {
# shellcheck disable=2046,2086
set -- $(set +f; pop "$sys_db/$p_name/manifest" from "$sys_db"/*/manifest)
- [ -s "$CPT_TMPDIR/$pid/manifest" ] || return 0
+ [ -s "$c_manifest" ] || return 0
# In rare cases where the system only has one package installed
# and you are reinstalling that package, grep will try to read from
@@ -1367,12 +1424,12 @@ pkg_conflicts() {
# Store the list of found conflicts in a file as we will be using the
# information multiple times. Storing it in the cache dir allows us
# to be lazy as they'll be automatically removed on script end.
- sed '/\/$/d' "$@" | sort "$CPT_TMPDIR/$pid/manifest" - | uniq -d > "$CPT_TMPDIR/$pid/conflict" ||:
+ sed '/\/$/d' "$@" | sort "$c_manifest" - | uniq -d > "$c_conflicts" ||:
# Enable alternatives automatically if it is safe to do so.
# This checks to see that the package that is about to be installed
# doesn't overwrite anything it shouldn't in '/var/db/cpt/installed'.
- "$grep" -q "/var/db/cpt/installed/" "$CPT_TMPDIR/$pid/conflict" ||
+ "$grep" -q "/var/db/cpt/installed/" "$c_conflicts" ||
choice_auto=1
# Use 'grep' to list matching lines between the to
@@ -1423,13 +1480,13 @@ pkg_conflicts() {
log "this must be fixed in $p_name. Contact the maintainer"
die "by checking 'git log' or by running 'cpt-maintainer'"
}
- done < "$CPT_TMPDIR/$pid/conflict"
+ done < "$c_conflicts"
# Rewrite the package's manifest to update its location
# to its new spot (and name) in the choices directory.
pkg_manifest "$p_name" "$tar_dir" 2>/dev/null
- elif [ -s "$CPT_TMPDIR/$pid/conflict" ]; then
+ elif [ -s "$c_conflicts" ]; then
log "Package '$p_name' conflicts with another package" "" "!>"
log "Run 'CPT_CHOICE=1 cpt i $p_name' to add conflicts" "" "!>"
die "as alternatives."
@@ -1491,13 +1548,13 @@ pkg_etc() {
mkdir -p "$CPT_ROOT/$dir"
done
- digest=$(_get_digest "$mak_dir/c") || digest=b3sum
+ digest=$(_get_digest "$_etcsums") || digest=b3sum
# Handle files in /etc/ based on a 3-way checksum check.
find etc ! -type d | while read -r file; do
{ sum_new=$("$digest" "$file")
sum_sys=$(cd "$CPT_ROOT/"; "$digest" "$file")
- sum_old=$("$grep" "$file$" "$mak_dir/c"); } 2>/dev/null ||:
+ sum_old=$("$grep" "$file$" "$_etcsums"); } 2>/dev/null ||:
logv "$pkg_name" "Doing 3-way handshake for $file"
outv "Previous: ${sum_old:-null}"
@@ -1562,10 +1619,11 @@ pkg_remove() {
# remove anything from packages that create empty directories for a
# purpose (such as baselayout).
manifest_list="$(set +f; pop "$sys_db/$1/manifest" from "$sys_db/"*/manifest)"
+ dirs="$(_tmp_name "directories")"
# shellcheck disable=2086
- [ "$manifest_list" ] && grep -h '/$' $manifest_list | sort -ur > "$mak_dir/dirs"
+ [ "$manifest_list" ] && grep -h '/$' $manifest_list | sort -ur > "$dirs"
- run_hook pre-remove "$1" "$sys_db/$1" root
+ run_hook pre-remove "$1" "$sys_db/$1"
while read -r file; do
# The file is in '/etc' skip it. This prevents the package
@@ -1573,7 +1631,7 @@ pkg_remove() {
[ "${file##/etc/*}" ] || continue
if [ -d "$CPT_ROOT/$file" ]; then
- "$grep" -Fxq "$file" "$mak_dir/dirs" 2>/dev/null && continue
+ "$grep" -Fxq "$file" "$dirs" 2>/dev/null && continue
rmdir "$CPT_ROOT/$file" 2>/dev/null || continue
else
rm -f "$CPT_ROOT/$file"
@@ -1584,7 +1642,7 @@ pkg_remove() {
# we no longer need to block 'Ctrl+C'.
trap_set cleanup
- run_hook post-remove "$1" "$CPT_ROOT/" root
+ run_hook post-remove "$1" "$CPT_ROOT/"
log "$1" "Removed successfully"
}
@@ -1647,7 +1705,7 @@ pkg_install() {
[ "$install_dep" ] && die "$1" "Package requires ${install_dep%, }"
- run_hook pre-install "$pkg_name" "$tar_dir/$pkg_name" root
+ run_hook pre-install "$pkg_name" "$tar_dir/$pkg_name"
pkg_conflicts "$pkg_name"
log "$pkg_name" "Installing package incrementally"
@@ -1659,8 +1717,8 @@ pkg_install() {
# If the package is already installed (and this is an upgrade) make a
# backup of the manifest and etcsums files.
- cp -f "$sys_db/$pkg_name/manifest" "$mak_dir/m" 2>/dev/null ||:
- cp -f "$sys_db/$pkg_name/etcsums" "$mak_dir/c" 2>/dev/null ||:
+ _manifest=$(_tmp_cp "$sys_db/$pkg_name/manifest" 2>/dev/null) ||:
+ _etcsums=$(_tmp_cp "$sys_db/$pkg_name/etcsums" 2>/dev/null) ||:
# This is repeated multiple times. Better to make it a function.
pkg_rsync() {
@@ -1675,7 +1733,7 @@ pkg_install() {
pkg_etc
# Remove any leftover files if this is an upgrade.
- "$grep" -vFxf "$sys_db/$pkg_name/manifest" "$mak_dir/m" 2>/dev/null |
+ "$grep" -vFxf "$sys_db/$pkg_name/manifest" "$_manifest" 2>/dev/null |
while read -r file; do
file=$CPT_ROOT/$file
@@ -1712,7 +1770,7 @@ pkg_install() {
"$sys_db/$pkg_name/post-install" ||:
fi
- run_hook post-install "$pkg_name" "$sys_db/$pkg_name" root
+ run_hook post-install "$pkg_name" "$sys_db/$pkg_name"
log "$pkg_name" "Installed successfully"
}
@@ -1947,7 +2005,12 @@ pkg_updates(){
# an update.
[ "$CPT_FETCH" = 0 ] || pkg_fetch
- log "Checking for new package versions"
+ # Be quiet if we are doing self update, no need to print the same
+ # information twice. We add this basic function, because we will be using it
+ # more than once.
+ _not_update () { [ "$cpt_self_update" ] || "$@" ;}
+
+ _not_update log "Checking for new package versions"
set +f
@@ -1961,7 +2024,7 @@ pkg_updates(){
# Compare installed packages to repository packages.
[ "$db_ver-$db_rel" != "$re_ver-$re_rel" ] && {
- printf '%s\n' "$pkg_name $db_ver-$db_rel ==> $re_ver-$re_rel"
+ _not_update printf '%s\n' "$pkg_name $db_ver-$db_rel ==> $re_ver-$re_rel"
outdated="$outdated$pkg_name "
}
done
@@ -1982,6 +2045,13 @@ pkg_updates(){
exit 0
}
+ [ "$outdated" ] || {
+ log "Everything is up to date"
+ return
+ }
+
+ _not_update log "Packages to update: ${outdated% }"
+
contains "$outdated" cpt && {
log "Detected package manager update"
log "The package manager will be updated first"
@@ -1992,18 +2062,17 @@ pkg_updates(){
cpt-install cpt
log "Updated the package manager"
- log "Re-run 'cpt update' to update your system"
-
- exit 0
+ log "Re-executing the package manager to continue the update"
+
+ # We export this variable so that cpt knows it's running for the second
+ # time. We make the new process promptless, and we avoid fetching
+ # repositories. We are assuming that the user was already prompted once,
+ # and that their repositories are up to date, or they have also passed
+ # the '-y' or '-n' flags themselves which leads to the same outcome.
+ export cpt_self_update=1
+ exec cpt-update -yn
}
- [ "$outdated" ] || {
- log "Everything is up to date"
- return
- }
-
- log "Packages to update: ${outdated% }"
-
# Tell 'pkg_build' to always prompt before build.
pkg_update=1
@@ -2019,12 +2088,12 @@ pkg_updates(){
}
pkg_get_base() (
- # Print the packages defined in the /etc/cpt-base file.
+ # Print the packages defined in the CPT base file.
# If an argument is given, it prints a space seperated list instead
# of a list seperated by newlines.
- # cpt-base is an optional file, return with success if it doesn't exist.
- [ -f "$CPT_ROOT/etc/cpt-base" ] || return 0
+ # CPT base is an optional file, return with success if it doesn't exist.
+ [ -f "$cpt_base" ] || return 0
# If there is an argument, change the format to use spaces instead of
# newlines.
@@ -2035,13 +2104,20 @@ pkg_get_base() (
# subshell. That is our purpose here, thank you very much.
# shellcheck disable=SC2030
while read -r pkgname _; do
+ # Ignore comments
[ "${pkgname##\#*}" ] || continue
+
+ # Store the package list in arguments
set -- "$@" "$pkgname"
+
+ # Retrieve the dependency tree of the package, so they are listed as
+ # base packages too. This ensures that no packages are broken in a
+ # "base reset", and the user has a working base.
deps=$(pkg_gentree "$pkgname" xn)
for dep in $deps; do
contains "$*" "$dep" || set -- "$@" "$dep"
done
- done < "$CPT_ROOT/etc/cpt-base"
+ done < "$cpt_base"
# Format variable is intentional.
# shellcheck disable=2059
@@ -2116,12 +2192,36 @@ pkg_clean() {
rm -rf -- "${CPT_TMPDIR:=$cac_dir/proc}/$pid"
}
+_tmp_name() {
+ # Name a temporary file/directory
+ out "$tmp_dir/$1"
+}
+
+_tmp_cp() {
+ # Copy given file to the temporary directory and return its name. If a
+ # second argument is not given, use the basename of the copied file.
+ _ret=${2:-${1##*/}}
+ _ret=$(_tmp_name "$_ret")
+ cp "$1" "$_ret"
+ out "$_ret"
+}
+
+_tmp_create() {
+ # Create given file to the temporary directory and return its name
+ create_tmp
+ _ret=$(_tmp_name "$1")
+ # False positive, we are not reading from the file.
+ # shellcheck disable=2094
+ out "$_ret" 3>> "$_ret"
+}
+
create_tmp() {
# Create the required temporary directories and set the variables which
# point to them.
- mkdir -p "${mak_dir:=$tmp_dir/build}" \
- "${pkg_dir:=$tmp_dir/pkg}" \
- "${tar_dir:=$tmp_dir/export}"
+ mak_dir=$tmp_dir/build
+ pkg_dir=$tmp_dir/pkg
+ tar_dir=$tmp_dir/export
+ mkdir -p "$mak_dir" "$pkg_dir" "$tar_dir"
}
create_cache() {
@@ -2135,6 +2235,9 @@ create_cache() {
{
set -ef
+ # Package manager version.
+ cpt_version=@VERSION@
+
# If a parser definition exists, let's run it ourselves. This makes sure we
# get the variables as soon as possible.
command -v parser_definition >/dev/null && {
@@ -2149,25 +2252,34 @@ create_cache() {
# that it doesn't change beneath us.
pid=${CPT_PID:-$$}
- # Create the cache directories for CPT and set the variables which point
- # to them. This is seperate from temporary directories created in
- # create_cache(). That's because we need these variables set on most
- # occasions.
- #
# A temporary directory can be specified apart from the cache directory in
# order to build in a user specified directory. /tmp could be used in order
- # to build on ram, useful on SSDs. The user can specify CPT_TMPDIR for this.
- # We create the temporary directory here to avoid permission issues that can
- # arise from functions that call as_root().
- mkdir -p "${cac_dir:=${CPT_CACHE:=${XDG_CACHE_HOME:-$HOME/.cache}/cpt}}" \
- "${CPT_TMPDIR:=$cac_dir/proc}" \
- "${src_dir:=$cac_dir/sources}" \
- "${log_dir:=$cac_dir/logs}" \
- "${bin_dir:=$cac_dir/bin}"
-
- # We don't create the temporary $pid directory until `create_tmp()` is
- # called, but we still declare its variable here.
- : "${tmp_dir:=${CPT_TMPDIR:=$cac_dir/proc}/$pid}"
+ # to build on ram, useful on SSDs. The user can specify $CPT_TMPDIR for
+ # this. We now also support the usage of $XDG_RUNTIME_DIR, so the directory
+ # naming can be confusing to some. Here are possible $tdir names (by order
+ # of preference):
+ #
+ # 1. $CPT_TMPDIR
+ # 2. $XDG_RUNTIME_DIR/cpt
+ # 3. $XDG_CACHE_DIR/cpt/proc
+ # 4. $HOME/.cache/cpt/proc
+ #
+ # We create the main temporary directory here to avoid permission issues
+ # that can arise from functions that call as_root(). However, the
+ # $pid directories are special for each process and aren't created unless
+ # `create_tmp()` is used.
+ #
+ # We used to assign and create the directories at the same time using a
+ # shell hack, but it made the variables editable outside of the package
+ # manager, but we don't actually want that. Variables that are lower case
+ # aren't meant to be interacted or set by the user.
+ cac_dir=${CPT_CACHE:=${XDG_CACHE_HOME:-${HOME:?}/.cache}}/cpt
+ src_dir=$cac_dir/sources
+ log_dir=$cac_dir/logs
+ bin_dir=$cac_dir/bin
+ tdir=${CPT_TMPDIR:=${XDG_RUNTIME_DIR:-$cac_dir/proc}${XDG_RUNTIME_DIR:+/cpt}}
+ tmp_dir=$tdir/$pid
+ mkdir -p "$cac_dir" "$src_dir" "$log_dir" "$bin_dir" "$tdir"
# Set the location to the repository and package database.
pkg_db=var/db/cpt/installed
@@ -2233,6 +2345,13 @@ create_cache() {
# the get go. It will be created as needed by package installation.
sys_db=$CPT_ROOT/$pkg_db
+ # CPT system configuration directory
+ cpt_confdir=$CPT_ROOT@SYSCONFDIR@/cpt
+
+ # Backwards compatibility for the old cpt-base location
+ cpt_base=$CPT_ROOT/etc/cpt-base
+ [ -f "$cpt_confdir/base" ] && cpt_base=$cpt_confdir/base
+
# Regular expression used in pkg_checksums() and pkg_sources() in order to
# identify VCS and comments
re_vcs_or_com='^(#|(fossil|git|hg)\+)'
diff --git a/src/cpt-remove b/src/cpt-remove
index ae007eb..f5a5abf 100755
--- a/src/cpt-remove
+++ b/src/cpt-remove
@@ -20,3 +20,7 @@ if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
create_cache
pkg_order "$@"
for pkg in $redro; do pkg_remove "$pkg" "${CPT_FORCE:-check}"; done
+
+# After all the removals are finished, run an end-remove hook. There may
+# be some things that we may want to run, but not per package.
+run_hook end-remove "" "$CPT_ROOT"
diff --git a/tests/repository/contrib-dummy-pkg/meta b/tests/repository/contrib-dummy-pkg/meta
new file mode 100644
index 0000000..305bd33
--- /dev/null
+++ b/tests/repository/contrib-dummy-pkg/meta
@@ -0,0 +1 @@
+description: This is a dummy package
diff --git a/www/index.md b/www/index.md
index 2dc1fc5..eb150ee 100644
--- a/www/index.md
+++ b/www/index.md
@@ -27,12 +27,12 @@ complements the tools that come with it. It has the following features:
users with the `$PATH` variable.
- **Serve repositories with your method** - Package repositories can be served
- in a variety of formats, they can be either local, served with Git, Mercurial,
- or through the `rsync` method, with Fossil integration to be added soon.
+ in a variety of formats, they can be either local, served with `git`,
+ `mercurial`, `fossil`, or through the `rsync` method.
<hr>
-### Latest Release: 6.1.1 ([2021-08-04](/timeline?c=6.1.1))
+### Latest Release: 6.2.3 ([2022-02-02](/timeline?c=6.2.3))
- [Download](/uvlist?byage=1)
- [Changelog](/doc/trunk/CHANGELOG.md)