diff options
-rw-r--r-- | .build.yml | 1 | ||||
-rw-r--r-- | .fossil-settings/ignore-glob | 1 | ||||
-rw-r--r-- | CHANGELOG.md | 39 | ||||
-rw-r--r-- | Makefile | 1 | ||||
-rwxr-xr-x | configure | 12 | ||||
-rwxr-xr-x | contrib/cpt-chbuild | 33 | ||||
-rwxr-xr-x | contrib/cpt-reset | 4 | ||||
-rw-r--r-- | docs/Makefile | 9 | ||||
-rw-r--r-- | docs/cpt.org | 85 | ||||
-rw-r--r-- | docs/cpt.texi | 115 | ||||
-rw-r--r-- | docs/cpt.txt | 188 | ||||
-rw-r--r-- | examples/hooks/clean-packages | 7 | ||||
-rw-r--r-- | examples/hooks/makewhatis | 10 | ||||
-rw-r--r-- | spec/01_lib_spec.sh | 15 | ||||
-rwxr-xr-x | src/cpt-install | 4 | ||||
-rw-r--r-- | src/cpt-lib.in | 103 | ||||
-rwxr-xr-x | src/cpt-remove | 4 |
17 files changed, 490 insertions, 141 deletions
@@ -6,6 +6,7 @@ packages: - curl - rsync - shellcheck + - emacs-nox - texinfo - gzip tasks: 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 3922eaa..79a91a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,43 @@ 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. + + [6.2.1] - 2021-09-20 ---------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- ### Fixed - `cpt-fork` follows symbolic links when forking packages. @@ -19,7 +54,7 @@ this project _somewhat_ adheres to [Semantic Versioning]. [6.2.0] - 2021-08-14 ---------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- ### BLAKE3 checksums @@ -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 $@ @@ -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/contrib/cpt-reset b/contrib/cpt-reset index 2a1b66e..85142af 100755 --- a/contrib/cpt-reset +++ b/contrib/cpt-reset @@ -17,7 +17,9 @@ exit 0 } +# shellcheck source=../src/cpt-lib . cpt-lib + base=$(pkg_get_base nonl) set -- @@ -29,7 +31,7 @@ done [ "$1" ] && { printf 'WARNING: This will remove \033[1m%s\033[m package(s).\n' "$#" - printf 'Base packages can be redefined in %s\n' "$CPT_ROOT/etc/cpt-base" + printf 'Base packages can be redefined in %s\n' "$cpt_base" printf 'Continue? [Enter/Ctrl+C]\n' read -r _ && CPT_FORCE=1 cpt-remove "$@" } 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..fc5fc8e 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,49 @@ 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_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 +1265,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..eee64d2 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 -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}. +@cindex Base packages + +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,60 @@ 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_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 +1484,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..566c388 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,50 @@ 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_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 +970,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 +997,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 +1023,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 +1044,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 +1062,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 +1070,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 +1087,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 +1110,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 +1122,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 +1136,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 +1156,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 +1164,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 +1178,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 +1186,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 +1198,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 +1218,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 +1226,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 +1244,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 +1253,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 +1284,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 +1292,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 +1300,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 +1333,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 +1363,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 +1389,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 29bd05a..c9a30db 100644 --- a/spec/01_lib_spec.sh +++ b/spec/01_lib_spec.sh @@ -165,12 +165,6 @@ Describe 'CPT Library' 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,6 +183,7 @@ 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 " diff --git a/src/cpt-install b/src/cpt-install index 44842a3..7b892ae 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 [ -f "$sys_db/$pkg/message" ] && { printf '\033[1m%s\n%s\n%s\033[m\n\n' \ diff --git a/src/cpt-lib.in b/src/cpt-lib.in index b01790d..68a611b 100644 --- a/src/cpt-lib.in +++ b/src/cpt-lib.in @@ -548,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" \ @@ -589,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. @@ -1607,7 +1613,7 @@ pkg_remove() { # shellcheck disable=2086 [ "$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 @@ -1626,7 +1632,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" } @@ -1689,7 +1695,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" @@ -1754,7 +1760,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" } @@ -1989,7 +1995,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 @@ -2003,7 +2014,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 @@ -2024,6 +2035,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" @@ -2034,18 +2052,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 @@ -2061,12 +2078,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. @@ -2077,13 +2094,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 @@ -2308,6 +2332,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 cce3739..befdfcc 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" |