aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.build.yml24
-rw-r--r--.fossil-settings/ignore-glob2
-rw-r--r--CHANGELOG.md1011
-rw-r--r--LICENSE2
-rw-r--r--Makefile38
-rw-r--r--README.md (renamed from README)26
-rw-r--r--config.mk18
-rwxr-xr-xconfigure121
-rwxr-xr-xcontrib/cpt-cat32
-rwxr-xr-xcontrib/cpt-chbuild59
-rwxr-xr-xcontrib/cpt-chroot92
-rwxr-xr-xcontrib/cpt-export50
-rwxr-xr-xcontrib/cpt-fork4
-rwxr-xr-xcontrib/cpt-maintainer49
-rwxr-xr-xcontrib/cpt-manifest-tree2
-rwxr-xr-xcontrib/cpt-owns2
-rwxr-xr-xcontrib/cpt-reset24
-rwxr-xr-xcontrib/cpt-revdepends10
-rwxr-xr-xcontrib/cpt-size102
-rw-r--r--docs/Makefile19
-rw-r--r--docs/cpt.org281
-rw-r--r--docs/cpt.texi338
-rw-r--r--docs/cpt.txt369
-rw-r--r--examples/hooks/clean-packages7
-rw-r--r--examples/hooks/makewhatis10
-rw-r--r--man/cpt-build.120
-rw-r--r--man/cpt-checksum.116
-rw-r--r--man/cpt-install.18
-rw-r--r--man/cpt-list.16
-rw-r--r--man/cpt-remove.18
-rw-r--r--man/cpt-search.147
-rw-r--r--man/cpt-update.12
-rw-r--r--man/cpt.12
-rw-r--r--spec/01_lib_spec.sh107
-rw-r--r--spec/02_src_spec.sh13
-rw-r--r--spec/03_contrib_spec.sh18
-rwxr-xr-xsrc/cpt65
-rwxr-xr-xsrc/cpt-alternatives76
-rwxr-xr-xsrc/cpt-build9
-rwxr-xr-xsrc/cpt-checksum28
-rwxr-xr-xsrc/cpt-download2
-rwxr-xr-xsrc/cpt-install20
-rw-r--r--src/cpt-lib.in1302
-rwxr-xr-xsrc/cpt-list9
-rwxr-xr-xsrc/cpt-remove6
-rwxr-xr-xsrc/cpt-search66
-rwxr-xr-xsrc/cpt-update10
-rw-r--r--tests/repository/contrib-dummy-pkg/meta1
-rwxr-xr-xtools/mkdist.sh5
-rwxr-xr-xtools/tool2man.sh10
-rw-r--r--www/index.md10
51 files changed, 3655 insertions, 903 deletions
diff --git a/.build.yml b/.build.yml
index 6fda074..eba8a22 100644
--- a/.build.yml
+++ b/.build.yml
@@ -1,17 +1,37 @@
image: alpine/edge
packages:
+ - musl-dev
+ - gcc
+ - bison
- curl
+ - fossil
- rsync
- - shellcheck
+ - emacs-nox
- texinfo
- gzip
+ - xz
tasks:
+ - install-pax: |
+ git clone --quiet https://github.com/carbslinux/otools
+ cd otools
+ ./configure
+ make pax
+ sudo install -Dm755 pax /usr/bin/pax
+ - install-blake3: |
+ 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 d4cc917..84a1fc5 100644
--- a/.fossil-settings/ignore-glob
+++ b/.fossil-settings/ignore-glob
@@ -17,3 +17,5 @@ tests/etc/cpt-hook
.shellspec-quick.log
report
coverage
+config.mk
+docs/config.org
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..e7ee439
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,1011 @@
+CHANGELOG
+================================================================================
+
+This is the CHANGELOG for the Carbs Packaging Tools, initially a customised fork
+of the `kiss` package manager. The format is based on [Keep a Changelog], and
+this project _somewhat_ adheres to [Semantic Versioning].
+
+[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
+[Semantic Versioning]: https://semver.org/spec/v2.0.0.html
+
+
+[7.0.2] - 2023-02-05
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed a bug that caused extra dependencies being added to the later packages
+ during multi-package build operations.
+- Fixed file attribute issue with the `_tmp_cp()` function causing modified
+ dependency files to receive `600` permission bits.
+
+
+[7.0.1] - 2023-02-05
+--------------------------------------------------------------------------------
+
+### Fixed
+- Made the `_tsort()` function compatible with POSIX
+- Fixed dependency calculation issue in `pkg_depends()` where some packages
+ would be removed.
+- Fixed `pkg_gentree()` not generating the dependency tree due to the dependency
+ calculation changes.
+
+
+[7.0.0] - 2023-01-31
+--------------------------------------------------------------------------------
+
+### 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).
+
+### Added
+- `cpt-size` can now sort files based on size.
+- `$CPT_NOSTRIP` variable can now be set to 1 in order to disable package
+ stripping. Make sure to add `-g` to your CFLAGS in order to keep debugging
+ symbols.
+- `cpt-build` now accepts `-d` and `-S` options to enable `$CPT_DEBUG` and
+ `$CPT_NOSTRIP` respectively.
+
+### 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.
+
+### Fixed
+- Fixed the behaviour of `cpt bi` and `cpt cbi` by merging the flag usage.
+- Fixed the `aria2c` usage on `pkg_download()` function.
+
+### Library
+- In order to get the `$deps` variable, one now has to use the new
+ `pkg_depends_commit()` function.
+
+
+[6.2.4] - 2022-02-07
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed a bug in missing dependency where if the user had chosen 'ldd', it would
+ fail to fix dependencies due to a typo.
+
+
+[6.2.3] - 2022-02-02
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed a checksum verification bug where adding an extra source did not require
+ checksum verification.
+- `cpt-manifest-tree` now modifies the output of `tree(1)` according to the new
+ version.
+- `cpt-reset` is now much more verbose.
+- Fixed the displayed messages on `cpt-install` when it is given a tarball as an
+ argument.
+- Fixed a faulty implementation in `pkg_tar()` where it used `pkg_find()`
+ instead of using the built package's database directory for gathering
+ information.
+
+
+[6.2.2] - 2021-11-09
+--------------------------------------------------------------------------------
+
+### Fixed
+- `cpt-alternatives` now properly logs file swaps even when the original file
+ no longer exists.
+- Minor fixes
+
+
+[6.2.1] - 2021-09-20
+--------------------------------------------------------------------------------
+
+### Fixed
+- `cpt-fork` follows symbolic links when forking packages.
+- Fixed "crux-like" usage in `cpt-size`
+- Fixed documentation path in the manual page
+
+
+[6.2.0] - 2021-08-14
+--------------------------------------------------------------------------------
+
+### BLAKE3 checksums
+
+The package manager now uses `b3sum` for creating digests. The change is
+backwards compatible, which means that BLAKE3 will slowly replace the SHA256
+algorithm in packages. The `cpt` package in the repository will continue to use
+the sha256 until the end of 2021.
+
+The `checksums` files generated with BLAKE3 has the header `%BLAKE3` which is
+used to distinguish digest algorithms. If the file does not include such a
+header, it is assumed to be a file created using the SHA256 algorithm. This is
+especially handy for keeping the /etc checksums intact. If the package being
+built is already installed on the system `cpt` makes sure that the generated
+etcsums are also backwards compatible.
+
+
+### Description searching
+
+`cpt-search` utility has a new mode for searching through the package names and
+descriptions, which is enabled by the `-q` flag. The output is really similar to
+how the `apt search` command works, but the output is not meant for scripting.
+Descriptions are defined by the `description` keys in the meta file.
+
+Instead of wildcards, the passed argument is expected to be a POSIX Basic
+Regular Expression, and is interpreted by `grep`. `cpt-search` also accepts the
+`-F` flag for passing literal expressions.
+
+
+### Added
+- `cpt-checksum` now has the `-s` flag to generate checksums using the SHA256
+ digest algorithm.
+- Added `CPT_DOWNLOADER` variable to change the download program. Available
+ options are: `curl`, `wget`, `wget2`, `aria2c`, and `axel`.
+- `cpt-chroot` now has the flag `-m` to disable mounting/unmounting pseudo
+ filesystems.
+- This changelog is now installed by the `Makefile`.
+- `cpt-chbuild` now has `-r` flag to redownload the chroot.
+
+### Changed
+- `cpt-size` has been rewritten to support POSIX `du`, and to support packages
+ with a file count of over 50,000.
+- Installation now requires to run `./configure`.
+
+
+[6.1.1] - 2021-08-04
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed a rare bug during manifest generation that caused an empty line inside
+ the package manifest.
+
+
+[6.1.0] - 2021-07-22
+--------------------------------------------------------------------------------
+
+### IMPORTANT
+- The package manager now enforces the usage of `pax` instead of `tar`.
+
+### Repository Backend
+
+`cpt` now has a faster and modular repository backend. `fossil` is now supported
+by the package manager. During the repository fetch process, the repository
+backend is stored in the cache directory so that the update takes less time on
+the next pull. The usage of the repository cache can be disabled by setting
+`$CPT_REPO_CACHE` to 0.
+
+### Added
+- Added `-q, --quiet` flags to `cpt-list`.
+- Re-added `cpt-maintainer`. It now supports `meta` and repository backends
+ other than `git`.
+- The package manager now prints out `MOTD` files found on the repository root.
+- Added the `$CPT_VERBOSE` variable and the `--verbose` flags to some utilities.
+ With the addition of these, some parts of the package manager will be more
+ quiet unless verbosity is explicitly requested.
+
+### Changed
+- Reworked the package repository backend.
+
+
+[6.0.4] - 2021-05-12
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed the declaration place of the `$pid` variable
+
+
+[6.0.3] - 2021-05-10
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed interrupt behaviour when downloading package sources.
+- Fixed `cpt --help` output when inside a directory prefixed with `cpt-`
+
+
+[6.0.2] - 2021-04-05
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed `make dist` target.
+
+
+[6.0.1] - 2021-04-05
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed inconsistencies of the `Ctrl+C` interrupt behaviour
+
+
+[6.0.0] - 2021-04-03
+--------------------------------------------------------------------------------
+
+### Added
+- Added unit tests using `shellspec`.
+- Added support for `pax` for tarball extraction.
+- [ssu] support has been added for privilege escalation.
+- Added `-p` flag for specifying package when using `cpt-link`.
+- Added manual pages for all `cpt-contrib` scripts.
+- Added `lz` compression/decompression support to `$CPT_COMPRESS`.
+
+### Changed
+- Moved `cpt-lib` to `cpt-lib.in`.
+- All `src` scripts now exit with success after being called with `--help`.
+- Minor optimisations on `contrib` scripts.
+- Huge speed improvement on `cpt-export`.
+- Updated the `getoptions` library to version `2.5.0`.
+
+### Fixed
+- Fixed `cpt-cat` not using the `CPT_ROOT` value.
+- Fixed an error with the usage of `sbase grep` that resulted in exit when
+ removing packages.
+
+### Removed
+- Removed C binaries `cpt-readlink` and `cpt-stat` and instead replaced them
+ with `_readlink()` and `_stat()` library functions.
+
+
+[ssu]: https://github.com/illiliti/ssu
+
+[5.1.2] - 2021-01-04
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed the `Makefile` installing files other than `cpt-*` files.
+- Fixed `pkg_swap()` bug where swapping a prefix file would change the following
+ file locations on the manifest as well.
+
+
+[5.1.1] - 2020-12-20
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed an issue where the package build is continued even when it failed when
+ `$CPT_DEBUG` was set
+
+
+[5.1.0] - 2020-11-25
+--------------------------------------------------------------------------------
+
+### IMPORTANT
+- The `pkg_fixdeps()` function has been renamed to `pkg_fix_deps()`.
+- `cpt-lib` now parses options for you if `parser_definition()` is defined
+ before being called.
+
+### Changed
+- `cpt-fork` can now take full path for packages.
+- `cpt-size` can now display the total size of multiple packages.
+- Updated `getoptions()` parser to version `2.0.1`
+- Added `git` to the default `cpt-base`.
+- Temporary cache creation scheme is changed from `build-$pid/` to
+ `proc/$pid/build/`
+
+### Fixed
+- Moved option parsing to cpt-lib if `parser_definition` exists. This shouldn't
+ affect existing scripts where `cpt-lib` is called before the parser is
+ defined.
+
+
+[5.0.0] - 2020-10-06
+--------------------------------------------------------------------------------
+
+### IMPORTANT
+- `cpt-fetch` has been removed. `cpt-update -o` can be used instead.
+
+### Added
+- Added an `/etc/cpt-base` file to define a base. It can be used in order to
+ ship a default base, but to make it redefinable by the user. This file isn't
+ installed by default, it serves as a template.
+- Added `cpt-orphans` to view orphaned packages. This tool uses `/etc/cpt-base`
+ and doesn't output any packages in the defined base.
+- Added a `global_options()` function in order to add into the option parser.
+- Added `cpt-update -o` flag to replace the functionality of `cpt-fetch`.
+- Added `cpt-list -c` to use the current directory as the argument string.
+
+### Changed
+- `pkg_build()` now notifies the user if the build file was modified inside a
+ hook (the `pre-build` hook to be precise).
+- In git repository sources, `@` can now be used to specify tags.
+ E.g. `git+git://git.carbslinux.org/cpt@4.2.0`
+- `cpt-fork` now removes `manifest` and `etcsums` files.
+- `cpt-fork` can now be used to fork multiple packages.
+- `cpt-reset` now uses `/etc/cpt-base` when removing packages.
+- `cpt-build` now exports the `CPT_TEST` variable, so some tests that can't be
+ done in a `test` script can be done from the build itself.
+
+
+[4.1.1] - 2020-09-25
+--------------------------------------------------------------------------------
+
+### Changed
+- Git clones now fetch tags if commits are specified. This makes the operation
+ longer, but not as long as cloning the whole repository while building a
+ package.
+- `pkg_fixdeps()` now outputs to `stderr` instead of `/dev/tty`. You can now
+ have fully silent builds.
+
+### Fixed
+- Fixed the `as_root()` function when using `su`.
+
+
+[4.1.0] - 2020-09-11
+--------------------------------------------------------------------------------
+
+### Added
+- Added `bi` action to cpt for building and installing packages at the same time
+
+### Fixed
+- Fixed `as_root()` call on `cpt-chbuild`.
+
+
+[4.0.1] - 2020-09-10
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed flags starting with `--no-`
+
+
+[4.0.0] - 2020-09-09
+--------------------------------------------------------------------------------
+
+With this update, all the documentation was moved to the `docs` repository,
+which can be accessed from the following sources:
+
+- [Docs Repository](https://github.com/carbslinux/docs)
+- [Online User Manual](https://carbslinux.org/docs)
+- `carbs-docs` package
+
+### Added
+- Added the ability to test packages using a new executable file `test`.
+- Added `$CPT_TEST` variable for testing packages.
+- Added `--test|-t` option to build.
+- Added support for `mercurial` repositories.
+- Added options to install the tools "static" so they don't depend on cpt-lib.
+- Added basic unit tests. See `make test`.
+
+### Changed
+- Most contrib scripts now use the current directory as the package name.
+
+### Removed
+- Removed the `docs/` folder.
+
+### Fixed
+- Fixed `getoptions` parsers while declaring initial variables.
+- Fixed build `cpt-stat` on the Makefile.
+
+[3.3.1] - 2020-08-31
+--------------------------------------------------------------------------------
+
+### Changed
+- Reverted `sh256()` to the previous way.
+
+
+[3.3.0] - 2020-08-31
+--------------------------------------------------------------------------------
+
+### Added
+- Added `trap_set()` in order to manage traps.
+
+### Changed
+- Moved from `getopt` to a shell implementation of option parsing. This ensures
+ portability, and doesn't depend on a C program with GNU extensions. That was
+ a mistake. The new implementation is taken from the public domain library,
+ `getoptions`.
+- `warn()` function was modified to use `log "$1" "$2" "${3:-WARNING}"` instead.
+- Made `cpt` checksum method compatible with the KISS Community repository.
+
+
+[3.2.0] - 2020-08-22
+--------------------------------------------------------------------------------
+
+### Added
+- A `.build.cpt` file can be edited during the pre-build hook, so that a build
+ script can be modified. If the build is modified, a diff file will be
+ generated to the package database.
+- Some of the tools now use getopt. Since getopt isn't a POSIX utility,
+ util-linux implementation has been added to the `getopt-ul` directory. It
+ consists only of files required for the tool to be built.
+- Added `pre-chroot` hook for the `cpt-chbuild` utility.
+
+### Changed
+- `cpt-chbuild` now uses library functions such `sh256()`, and `as_root()`.
+- `cpt` programs no longer exit if `$CPT_PATH` is unset.
+
+
+[3.1.1] - 2020-08-11
+--------------------------------------------------------------------------------
+
+### Changed
+- `as_root()` now sets package manager variables with env.
+
+
+[3.1.0] - 2020-08-07
+--------------------------------------------------------------------------------
+
+### Changed
+- `cpt-lib` no longer creates temporary directories. This will need manual
+ adjustments for scripts that make use of the cache directories. Those
+ directories can now be created by calling the `create_cache()` function.
+- Dropping libtool's `*.la` library files from packages.
+
+
+[3.0.0] - 2020-07-24
+--------------------------------------------------------------------------------
+
+This is the 3.0.0 release. This will make `kiss` (now renamed as `cpt`) a
+toolchain for package management rather than a single script program. The main
+functionality is moved into a `lib.sh` file which the tools will source. This
+comes with nice benefits such as:
+
+- Easier option parsing for each tool.
+- Easier to extend the package manager as it is only a library. It no longer
+ requires dirty hacks to source the package manager functions and variables.
+- Clearer usage information is outputted, so the user doesn't have to delve into
+ documents to see the syntax/options of a tool.
+
+### Added
+- `$CPT_CACHE` to change the cache directory.
+- Added a bunch of flags, here is a table:
+
+| Flag | Function | Added tool |
+|------------|-------------------------------------------|------------------------|
+| --force | Force removal/installation | cpt-remove/cpt-install |
+| --root | Specify root directory | lots of tools |
+| --download | Only download packages | cpt-update |
+| --no-fetch | Do not fetch repositories before update | cpt-update |
+| --single | Only show the first instance of a package | cpt-search |
+
+
+### Changed
+
+- Renamed all variables from `KISS-*` to `CPT-*`
+- Moved database to `/var/db/cpt`
+- Changed the code style and did some minor nitpicks for the C programs.
+
+### Removed
+- Removed the ability to control color output (for now).
+- Removed `kiss-outdated` and `kiss-which`.
+
+
+[2.3.0] - 2020-07-16
+--------------------------------------------------------------------------------
+
+### Added
+- Added `KISS_FETCH` to optionally disable repository fetches while performing
+ a system update. You can now run `KISS_FETCH=0 kiss u` in order to update
+ your system without syncing repositories.
+
+### Changed
+- Changed usage outputs for kiss and contrib utilities.
+- `rsync` repositories are now synced based on checksums rather than timestamps.
+- `kiss-chroot` now uses system flags if available.
+- `kiss-chbuild` now installs extra packages if specified.
+- hooks now default to `null` if no arguments are given
+- `*-pull` hooks have been renamed to `*-fetch` and is run only once instead of
+ for every single git repository.
+
+### Fixed
+- Fixed an issue where using `su` to install packages resulted in a wrong
+ package ownership.
+
+
+[2.2.1] - 2020-06-11
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed directory checking on package removal
+
+
+[2.2.0] - 2020-06-10
+--------------------------------------------------------------------------------
+
+### Added
+- Makefile configurations were moved to config.mk.
+
+### Changed
+- `kiss` no longer ignores musl and gcc on `fixdeps()`. This will result in an
+ influx of musl dependencies. But you will be needing the C library to be
+ installed anyway if you want your programs to work. If your program links
+ to `libgcc`, you will need the gcc package for that given program to function.
+- Makefile now properly accepts `LIBS`, `LDFLAGS`, and `CFLAGS`.
+- Updated documentation.
+
+### Fixed
+- `C89` compatibility on C programs.
+- Fixed an alternatives issue where a file containing special regular expression
+ characters (such as `/usr/bin/[`) would result in a manifest deletion.
+
+
+[2.1.2] - 2020-06-03
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed a segmentation fault on `kiss-stat` when a file didn't have on owner on
+ the `passwd` database.
+
+
+[2.1.1] - 2020-06-03
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed 'No message in queue' message being outputted for every single package.
+- Fixed CFLAGS for x86_64 on `kiss-chroot`.
+- Fixed setting binary packages as dependencies.
+
+
+[2.1.0] - 2020-05-29
+--------------------------------------------------------------------------------
+
+### Added
+- Added '$2' '$3' for build scripts which specifies version and architecture
+ information.
+
+### Changed
+- `kiss-chroot` now sets architecture based on the system
+- Updated documentation
+
+### Removed
+- Removed strip messages
+
+
+[2.0.0] - 2020-05-28
+--------------------------------------------------------------------------------
+
+### Added
+- Rsync repository support.
+- pre/post hooks for package removal (pre-remove, post-remove).
+- pre/post hooks for git pulls (pre-pull, post-pull).
+
+### Changed
+- `kiss` no longer removes empty directories if they are defined on a different
+ package.
+- `$KISS_NOPROMPT` has been renamed to `$KISS_PROMPT` and must be set to 0 in
+ order to disable prompts.
+- `kiss-chbuild` now checks tarball digest.
+- `kiss-chbuild` now downloads tarballs according to arch (x86_64 or i686
+ currently).
+- Submodule repository fetching has been modified to match compatibility.
+
+### Removed
+- Removed `kiss-maintainer` and moved it to [kiss-extra]
+
+[kiss-extra]: https://github.com/carbslinux/kiss-extra
+
+
+[1.22.4] - 2020-05-26
+--------------------------------------------------------------------------------
+
+**NOTE:** `1.22.x` is the last minor version before `2.0.0`, meaning I will not
+be doing any releases except for patches and fixes. My attention is now on
+implementing binary repositories. I will be doing some 'release candidates'
+before release, as binary repositories will need user feedback.
+
+### Added
+- Added new documents.
+- Added `post-package` hook.
+
+### Changed
+- Renamed the `hashcheck` function to `sh256` for compatibility.
+- Enabled the usage of glob characters for `kiss-bin`.
+
+
+[1.22.3] - 2020-05-18
+--------------------------------------------------------------------------------
+
+### SECURITY
+- Fixed a bug regarding privilege escalation using `$KISS_HOOK`. `kiss` will now
+ use `$KISS_ROOT/etc/kiss-hook` on installation operations (which are run by
+ root) so that the hooks are defined by the system administrator rather than the
+ user. See [related proof-of-concept]
+
+[related proof-of-concept]: https://github.com/kisslinux/kiss/pull/157#issuecomment-629880775
+
+
+[1.22.2] - 2020-05-16
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed an issue where `pkg_conflicts` would abort if `kiss-readlink` failed due
+ to missing components. It now fallbacks to the original directory name.
+
+
+
+[1.22.1] - 2020-05-15
+--------------------------------------------------------------------------------
+
+### REMOVED
+- Removed some contrib scripts and moved them to [kiss-extra]
+- `kiss-cargo-urlgen`
+- `kiss-cargolock-urlgen`
+- `kiss-changelog`
+- `kiss-depends-finder`
+- `kiss-exec`
+- `kiss-message`
+- `kiss-orphans`
+- `kiss-reporevdepends`
+
+
+### Fixed
+- Fixed a `kiss-owns` typo that caused it to fail.
+- Fixed a `kiss-readlink` bug where it would fail if the last component wouldn't
+ exist.
+- Fixed an error on tarball extraction where a file name containing spaces would
+ be parsed as two files.
+
+
+[kiss-extra]: https://github.com/carbslinux/kiss-extra
+
+
+[1.22.0] - 2020-05-14
+--------------------------------------------------------------------------------
+
+### Added
+- Added `kiss-exec`, a tool to execute commands inside the alternatives system.
+
+### Changed
+- Replaced `KISS_COLOUR` with `KISS_COLOR` to match upstream.
+- Renamed `colour` variable to `color` for consistency.
+- The package manager no longer needs root privileges if the `KISS_ROOT` is
+ writable by the user.
+- `kiss` now uses the host cache regardless of `KISS_ROOT`.
+
+### Fixed
+- Fixed an issue where `kiss-owns` would output the wrong package because of
+ symbolic links. The script now reads the link of the directory instead of the
+ full file.
+
+
+[1.21.1] - 2020-05-14
+--------------------------------------------------------------------------------
+
+### Changed
+- All contrib messages now output usage information when called with `--help`
+ and `-h`.
+- `hashcheck` function now uses `$1` instead of `${file#\*}`.
+
+### Fixed
+- Fixed a non-POSIX `find` call. Thanks to @illiliti.
+
+
+[1.21.0] - 2020-05-12
+--------------------------------------------------------------------------------
+
+### Added
+- Added a `d|download` option to acquire the sources of given packages. If no
+ packages are given, it acquires the sources of outdated packages. This can be
+ used to acquire a package's sources to build it later, or periodically
+ downloading outdated package sources, so the user doesn't wait for the download
+ when updating the system.
+- kiss now understands `.txz` tarballs. (BSD `src.txz` wink wink)
+- `KISS_TMPDIR` can now be used to specify a temporary build directory. This
+ will be useful for those of you who would want to build on ram or a different
+ file system.
+
+### Changed
+- Simplified tarball extraction method.
+- Removed the 'esc' function inside kiss.
+- Added a 'warn' function to standardise warnings inside kiss
+
+### Fixed
+- Removed the `sys_db` usage on `pkg_find()` where directories could clash with
+ external utilities.
+
+
+[1.20.3] - 2020-05-09
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed an alternatives bug caused by the previous patch, where the package
+ moving to `/var/db/kiss/choices` would take the name of the preferred package.
+
+
+[1.20.2] - 2020-05-09
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed an issue regarding manifest format when using pkg_swap (alternatives).
+
+
+[1.20.1] - 2020-05-08
+--------------------------------------------------------------------------------
+
+### Changed
+- Faster conflict resolution by using a conflict cache file.
+- Standardised `kiss-readlink` usage output.
+
+
+[1.20.0] - 2020-05-07
+--------------------------------------------------------------------------------
+
+### Added
+- `KISS_NOPROMPT` can be specified in order to skip prompts.
+
+
+[1.19.1] - 2020-05-07
+--------------------------------------------------------------------------------
+
+### Added
+- Added `e|extension` to `kiss` which can be used to output kiss-extensions.
+
+### Changed
+- `kiss` no longer outputs the extensions when called with `kiss help`. The
+ output was too large for an average terminal, and a user had to scroll up
+ for actual package manager options. These can now be retrieved with `kiss e`.
+- When called from a subshell, `kiss` disables colour escape sequences. This
+ behaviour can be overridden by setting `KISS_COLOUR` environment variable.
+ If set to 1, it will be enabled globally, if set to 0 it will be disabled
+ globally.
+
+
+[1.19.0] - 2020-05-06
+--------------------------------------------------------------------------------
+
+### Added
+- Added `kiss-reporevdepends` for finding all the packages on the repository
+ that depends on the specified package.
+
+### Changed
+- Removed the `-p` flag from tar while installing packages. busybox ignores it
+ and we don't need it.
+- Replaced tar flags with keys for historical compatibility.
+- `kiss` now decompresses a tarball once and uses the decompressed tarball for
+ listing and extraction.
+
+### Fixed
+- Fixed the output of doc-strings in contrib scripts.
+- `kiss` now ignores the binary programs in the repository for
+ `kiss extensions`.
+
+
+[1.18.0] - 2020-05-04
+--------------------------------------------------------------------------------
+
+### Added
+- Added editorconfig file since we now have 4 languages (roff, Makefile, sh, C)
+ in the repository.
+- Added `kiss-readlink` as a `readlink -f` replacement.
+- Added `kiss-message` for checking package messages.
+- Added this CHANGELOG
+
+### Changed
+- Made tar calls portable. `kiss` is no longer limited to busybox, bsdtar, or
+ gnu tar!
+
+### Removed
+- Dropped the usage of `readlink` in `kiss`.
+
+
+[1.17.0] - 2020-05-03
+--------------------------------------------------------------------------------
+
+### Added
+- Added `kiss-stat`, a simple C program for getting the owner name of a
+ file/directory.
+
+### Removed
+- Removed the usage of `stat` calls, as they are not standardised.
+
+### Changed
+- `kiss` now doesn't report `Generating etcsums` if there isn't an `/etc`
+ directory in the package
+
+### Fixed
+- `kiss` now uses `sys_db` instead of `pkg_db` when removing packages from the
+ system.
+- `kiss` now explicitly exits if prompt returns with a status of 1. This is for
+ `ksh` compatibility.
+
+
+[1.16.3] - 2020-05-03
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed etcsum location.
+
+
+[1.16.2] - 2020-05-03
+--------------------------------------------------------------------------------
+
+### Added
+- Added fallbacks for sha256sum. `kiss` now fallbacks to `sha256`, and `openssl`
+ for hash checking, respectively.
+- Added `kiss-changelog` and `kiss-which` entries to the `kiss-contrib.1` manual
+ page.
+
+### Fixed
+- Fixed `kiss` not using the preferred `tar` program on decompression.
+- Fixed `pkg_conflicts()` getting stuck when you reinstall the same single
+ package on a system.
+- Fixed `pkg_conflicts()` giving an error if no packages are installed on a
+ system.
+
+
+[1.16.1] - 2020-05-01
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed `ksh` Ctrl+C interrupt signals.
+
+
+[1.16.0] - 2020-05-01
+--------------------------------------------------------------------------------
+
+### Added
+- New message queue system implementation. If a package includes a file named
+ `message` it will output its contents in a pretty way.
+- Added `kiss-which`, a tool like `which` but for `kiss` packages.
+- Added `kiss-changelog`, a tool for outputting the git log of a given package.
+
+### Fixed
+- Fixed colour outputting on `OpenBSD ksh`.
+- Made compatibility fixes on the Makefile
+- Fixed an installation issue where `kiss` would look for the manifest with the
+ `$KISS_ROOT` variable
+
+
+[1.15.0] - 2020-04-30
+--------------------------------------------------------------------------------
+
+I have decided to revert to rsync installation method as it is faster and safer.
+Now, rsync is not a huge dependency. Saving 500Kb is not worth it when you look
+at the trade-off.
+
+### REMOVED
+- Removed the new installation method.
+
+### Changed
+- Reverted to `rsync` for installation.
+- We are now forcing decompression to standard output while using `decompress()`
+- `kiss` now accepts decompressed tar archives for package installation as well.
+
+
+[1.14.2/1.14.3] - 2020-04-27
+--------------------------------------------------------------------------------
+
+### Fixed
+- The new installation method now complies to the `$KISS_ROOT` value.
+
+
+[1.14.1] - 2020-04-27
+--------------------------------------------------------------------------------
+
+### Removed
+- Removed the unnecessary `[ -d ]` from the path query.
+
+### Fixed
+- Fixed directory permissions in the new installation method.
+- Added support for `$KISS_ROOT` to the new installation method.
+- Added a check for symlinks that could overwrite a directory during
+ installation.
+- Whitespace cleanup.
+
+
+[1.14.0] - 2020-04-25
+--------------------------------------------------------------------------------
+
+This release removes `rsync` from `kiss` and implements its own installation
+method.
+
+### Added
+- `kiss` now implements user scripts available in the `$PATH`. This can be used
+ to call `kiss manifest` from `kiss` itself.
+- `kiss` now displays a warning if the user has a `$KISS_ROOT` that ends with
+ a `/`.
+- `kiss` now uses its own new package installation method.
+
+### Removed
+- usage of rsync as an installation method.
+- usage of `old_ifs`
+
+
+[1.13.1] - 2020-04-19
+--------------------------------------------------------------------------------
+
+### Removed
+- Reverted and removed `kiss ss` changes.
+
+
+[1.13.0] - 2020-04-19
+--------------------------------------------------------------------------------
+
+### Added
+- `kiss ss` for outputting a single location for scripting.
+
+### Changed
+- `kiss` now elevates permissions during checksum if the file isn't owned by us.
+- Hide read error messages when `version` file cannot be found.
+- Made the `pkg_fixdeps()` usage of `diff` portable.
+
+### Fixed
+- Fixed a shellcheck error.
+
+
+[1.12.3] - 2020-04-17
+--------------------------------------------------------------------------------
+
+### Changed
+- Changed indentation style on decompression.
+
+### Fixed
+- `kiss-export` fallbacks to gzip if the compression method is unknown.
+- `kiss-repodepends` now outputs the proper depends file.
+
+
+[1.12.2] - 2020-04-15
+--------------------------------------------------------------------------------
+
+### Added
+- `kiss` can now decompress zip files.
+
+### Changed
+- `checksum`, `build`, `install`, and `remove` operations can now be done on the
+ current package directory without arguments. So you can `cd` into a package an
+ type `kiss b` to build that package.
+
+### Fixed
+- `kiss-export` now honours your `KISS_COMPRESS` value
+
+
+[1.12.1] - 2020-04-12
+--------------------------------------------------------------------------------
+
+### Fixed
+- Fixed printing empty arguments in `kiss-outdated`.
+
+
+[1.12.0] - 2020-04-05
+--------------------------------------------------------------------------------
+
+### Added
+- `kiss-cargolock-urlgen`: a tool that can read a Cargo.lock file to generate a
+ list of urls.
+- `kiss-cat`: a tool to concatenate package build files.
+- Manual page for `kiss-contrib`.
+
+### Changed
+- `kiss-owns` now gives an error on directories.
+- `kiss-link` can now take multiple file names and will create symbolic links
+ of them all.
+- Simplified `kiss-link`
+
+### Fixed
+- `kiss-cargo-urlgen`: Fixed an issue where if a package version contained a '-'
+ it could lead to wrong url generation.
+
+
+[1.9.0 - 1.11.2] - 2020-04-04
+--------------------------------------------------------------------------------
+
+### Added
+- `kiss f` to fetch repositories without an update prompt.
+- Support for submodules in the repository.
+- Added a Makefile to standardise the installation.
+- Zstd compression method.
+
+### Changed
+- Modified `kiss-chbuild` to fit Carbs Linux.
+- Changed README to notify about forking status.
+- `pkg_find()` now also checks for symlinks instead of just directories.
+- `pkg_find()` now uses a `for` loop instead of `find`.
+- Force C locale for faster grepping.
+- Easily readable manual page.
+
+### Fixed
+- Compression method now fallbacks to gzip if unknown.
diff --git a/LICENSE b/LICENSE
index faf1233..ea3666c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2020-2021 Cem Keylan
+Copyright (c) 2020-2023 Cem Keylan
Copyright (c) 2019-2020 Dylan Araps
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/Makefile b/Makefile
index eceb18d..f30181c 100644
--- a/Makefile
+++ b/Makefile
@@ -5,20 +5,29 @@ INSTALL_SH = ./tools/install.sh
CONTRIB = `find contrib -name 'cpt*' ! -name '*.*'`
SRC = `find src -name 'cpt*' ! -name '*.*'`
BIN = ${SRC} ${CONTRIB}
-LIB = src/cpt-lib
-LIB_IN = ${LIB:=.in}
all: src/cpt-lib
- test "${DOCS}" != yes || ${MAKE} -C docs all
+ @test "${DOCS}" != yes || ${MAKE} -C docs all
src/cpt-lib: src/cpt-lib.in
- sed -e "s|@VERSION@|${VERSION}|g" \
- -e "s|@DOCSTRING@|Call functions from the library|g" < 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 $@
-test: all tests/etc/cpt-hook
+shellspec: all tests/etc/cpt-hook
shellspec
- cd src; find . ../contrib -name 'cpt*' ! -name '*.*' -exec shellcheck -e 2119 -x -f gcc {} +
+
+shellcheck: all
+ @cd src; find . ../contrib -name 'cpt*' ! -name '*.*' | while read -r file; do \
+ echo SHELLCHECK "$$file"; \
+ shellcheck -e 2119 -x -f gcc "$$file"; \
+ done
+
+test: shellspec shellcheck
tests/etc/cpt-hook:
ln -s ../hook-file $@
@@ -28,6 +37,11 @@ dist: docs/cpt.info
install: all
test "${DOCS}" != yes || ${MAKE} -C docs install
+ [ -f docs/cpt.info ] && \
+ ${INSTALL_SH} -Dm644 docs/cpt.info ${DESTDIR}${INFODIR}/cpt.info ||:
+ [ -f docs/cpt.txt ] && \
+ ${INSTALL_SH} -Dm644 docs/cpt.txt ${DESTDIR}${DOCDIR}/cpt.txt ||:
+ ${INSTALL_SH} -Dm644 CHANGELOG.md ${DESTDIR}${DOCDIR}/CHANGELOG
${INSTALL_SH} -Dm755 -t ${DESTDIR}${BINDIR} ${BIN}
${INSTALL_SH} -Dm644 -t ${DESTDIR}${MAN1} man/*.1
for man in ${CONTRIB}; do \
@@ -36,15 +50,19 @@ install: all
done
uninstall:
- test "${DOCS}" != yes || ${MAKE} -C docs uninstall
for bin in ${BIN}; do \
rm -f ${DESTDIR}${BINDIR}/$${bin##*/}; done
for man in man/*.1; do rm -f ${DESTDIR}${MAN1}/$${man##*/}; done
for man in ${CONTRIB}; do rm -f ${DESTDIR}${MAN1}/$${man##*/}.1; done
+ rm -rf ${DESTDIR}${DOCDIR}
+ rm -f ${DESTDIR}${INFODIR}/cpt.info
clean:
- test "${DOCS}" != yes || ${MAKE} -C docs clean
+ ${MAKE} -C docs clean
rm -rf src/cpt-lib "cpt-${VERSION}.tar.xz" coverage report
rm -f tests/etc/cpt-hook
-.PHONY: all dist clean install uninstall
+allclean: clean
+ rm -f config.mk
+
+.PHONY: all dist allclean clean install uninstall shellspec shellcheck test
diff --git a/README b/README.md
index 9ea2dc3..e5a5580 100644
--- a/README
+++ b/README.md
@@ -1,8 +1,15 @@
Carbs Packaging Tools
=====================
-Package management toolset for Carbs Linux. Forked from KISS[1]. All usage
-information can be obtained from the manual page. Refer to the ChangeLog[2] to
+ ##### #### #####
+ # # # # #
+ # #### #
+ # # # #
+ ##### # #
+
+
+Package management toolset for Carbs Linux. Forked from [KISS]. All usage
+information can be obtained from the manual page. Refer to the [ChangeLog] to
learn what's new.
@@ -14,7 +21,7 @@ To build and use cpt, you need the following software:
- rsync
- curl
- POSIX base utilities [coreutils, busybox, sbase, etc.]
-- pax or tar [GNU tar, busybox, toybox, libarchive, etc.]
+- pax
- Common compression utilities such as `gzip`, `bzip2`, `xz`, etc.
@@ -36,10 +43,11 @@ either passing `DOCS=no` to `make` or editing `config.mk` to disable it.
Installation
------------
-In order to install CPT, you can run the following with `make`:
+In order to install CPT, you can run the following:
+ ./configure
make
- make PREFIX=/usr install
+ make install
Documentation
@@ -47,12 +55,12 @@ Documentation
The documentation for each tool along with some examples can be found on
manpages installed with the package manager. User manual of CPT can be found
-online[3], or installed as both plain-text and as info pages. Without any
+[online], or installed as both plain-text and as info pages. Without any
changes to the Makefile configuration those files can be found at:
- /usr/local/share/docs/cpt/cpt.txt
- /usr/local/share/info/cpt.info
-[1]: https://github.com/kisslinux/kiss
-[2]: https://fossil.carbslinux.org/cpt/log
-[3]: https://carbslinux.org/docs/cpt
+[KISS]: https://github.com/kisslinux/kiss
+[ChangeLog]: https://fossil.carbslinux.org/cpt/doc/trunk/CHANGELOG.md
+[online]: https://carbslinux.org/docs/cpt
diff --git a/config.mk b/config.mk
deleted file mode 100644
index 1bc27fe..0000000
--- a/config.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-# Carbs Packaging Tools
-VERSION = dev
-
-# Installation paths
-PREFIX = /usr/local
-BINDIR = ${PREFIX}/bin
-SHAREDIR = ${PREFIX}/share
-INFODIR = ${SHAREDIR}/info
-DOCDIR = ${SHAREDIR}/doc
-CPTDOC = ${DOCDIR}/cpt
-MANPREFIX = ${SHAREDIR}/man
-MAN1 = ${MANPREFIX}/man1
-
-EMACS = emacs
-MAKEINFO = makeinfo
-
-# Comment or change if you don't want to build/install the documentation
-DOCS = yes
diff --git a/configure b/configure
new file mode 100755
index 0000000..6268da7
--- /dev/null
+++ b/configure
@@ -0,0 +1,121 @@
+#!/bin/sh -e
+
+version=Fossil
+
+die() {
+ printf '%s: %s\n' "${0##*/}" "$*" >&2
+ exit 1
+}
+
+out() { printf '%s\n' "$@" ;}
+
+_check() {
+ for arg; do
+ printf 'checking for %s... ' "$arg"
+ command -v "$arg" || { out no; die "'$arg' not found" ;}
+ done
+}
+
+_check_multi() {
+ c=$1; shift
+ printf 'checking for %s... ' "$c"
+ for arg; do command -v "$arg" && return 0; done
+ out no; die "no $c was found"
+}
+
+usage() {
+ out "usage: $0 [options]" \
+ "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]" \
+ " --docdir=dir Documentation directory [DATAROOTDIR/doc/cpt]" \
+ " --with-docs=opt Whether to build the texinfo documentation [auto]" "" \
+ " MAKEINFO Name of the 'makeinfo' executable" \
+ " EMACS Name of the 'emacs' executable" "" \
+ "Use these variables to override the behaviour of '$0'."
+ exit 1
+}
+
+prefix=/usr/local
+# We don't want expansion
+# shellcheck disable=2016
+{
+sysconfdir='$(PREFIX)/etc'
+bindir='$(PREFIX)/bin'
+datarootdir='$(PREFIX)/share'
+mandir='$(DATAROOTDIR)/man'
+infodir='$(DATAROOTDIR)/info'
+docdir='$(DATAROOTDIR)/doc/cpt'
+}
+docs=auto
+
+for arg; do
+ case $arg in
+ -h|--help) usage ;;
+ --prefix=*) prefix=${arg#*=} ;;
+ --bindir=*) bindir=${arg#*=} ;;
+ --sysconfdir=*) sysconfdir=${arg#*=} ;;
+ --mandir=*) mandir=${arg#*=} ;;
+ --infodir=*) infodir=${arg#*=} ;;
+ --docdir=*) docdir=${arg#*=} ;;
+ --without-docs) docs=no ;;
+ --with-docs) docs=yes ;;
+ --with-docs=*) docs=${arg#*=} ;;
+ *-*) die "Unknown option: '$arg'" ;;
+ *=*) export "${arg:?}" ;;
+ *) die "Unknown argument: '$arg'"
+ 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
+
+: "${EMACS:=emacs}" "${MAKEINFO:=makeinfo}"
+
+out "starting configuration..."
+
+cat <<EOF > config.mk
+PREFIX = $prefix
+BINDIR = $bindir
+SYSCONFDIR = $sysconfdir
+DATAROOTDIR = $datarootdir
+MANDIR = $mandir
+INFODIR = $infodir
+DOCDIR = $docdir
+MAN1 = \$(MANDIR)/man1
+
+VERSION = $version
+EMACS = $EMACS
+EOF
+
+case $docs in
+ auto|yes)
+ printf 'checking for makeinfo... '
+ if makeinfo=$(command -v "$MAKEINFO"); then
+ out "$makeinfo"
+ docs=yes
+ out "MAKEINFO = $makeinfo" >>config.mk
+ else
+ out no
+ [ "$docs" = yes ] && die "'$MAKEINFO' not found"
+ docs=no
+ fi
+esac
+[ "$docs" = no ] && out "not building documentation"
+out "DOCS = $docs" >>config.mk
+
+out "checking runtime dependencies"
+_check pax rsync sed awk grep b3sum
+_check_multi "sha256 provider" sha256sum sha256 openssl
+_check_multi "download utility" curl wget wget2 aria2c axel
+
+trap - EXIT INT
+out "written config.mk" "Run 'make' to build cpt"
diff --git a/contrib/cpt-cat b/contrib/cpt-cat
index bfc9d66..45e0dd9 100755
--- a/contrib/cpt-cat
+++ b/contrib/cpt-cat
@@ -28,23 +28,29 @@
## .Em version
## files.
-case "$1" in
- --help|-h)
- printf 'usage: %s [pkg] [file...]\n' "${0##*/}"
- exit 0
- ;;
- '')
- [ "$#" -gt 1 ] && shift
- set -- "${PWD##*/}" "$@"
-esac
+parser_definition() {
+ setup REST help:usage -- "usage: ${0##*/} [pkg] [file...]"
+ global_options silent
+}
+
+# shellcheck disable=1091
+. cpt-lib
+
+[ "$1" ] || {
+ # Usage such as `cpt-cat '' build` is also valid.
+ [ "$#" -gt 1 ] && shift
+ set -- "${PWD##*/}" "$@"
+}
pkg=$1; shift
-cpt-list "$pkg" >/dev/null
+pkg_list "$pkg" >/dev/null
[ "$1" ] || set -- build depends sources version
+# $sys_db and color variables are defined by cpt-lib
+# shellcheck disable=2154
for file; do
- [ -f "$CPT_ROOT/var/db/cpt/installed/$pkg/$file" ] || continue
- printf '\033[1m%s:\033[m\n' "$file" >&2
- cat "$CPT_ROOT/var/db/cpt/installed/$pkg/$file"
+ [ -f "$sys_db/$pkg/$file" ] || continue
+ printf '%b%s:%b\n' "$colbold" "$file" "$colre" >&2
+ cat "$sys_db/$pkg/$file"
done
diff --git a/contrib/cpt-chbuild b/contrib/cpt-chbuild
index e53d903..7a71c33 100755
--- a/contrib/cpt-chbuild
+++ b/contrib/cpt-chbuild
@@ -3,6 +3,7 @@
## SYNOPSIS:
## .Nm
+## .Op Fl r
## .Op Ar pkg...
## DESCRIPTION:
@@ -13,13 +14,19 @@
## exist in the user's cache directory, it will download it from the Carbs Linux
## website. If any packages are given as arguments,
## .Nm
-## will install those packages to this temporary chroot.
+## will install those packages to this temporary chroot. If the
+## .Fl r
+## flag is given,
+## .Nm
+## will remove the rootfs tarball and directory to download it again.
-case "$1" in
- --help|-h) printf '\033[1;33m-> \033[m%s\n' "usage: ${0##*/} [pkg...]"; exit 0
-esac
+parser_definition() {
+ setup REST help:usage -- "usage: ${0##*/} [-r] [pkg...]"
+ flag redownload -r hidden:1
+ global_options silent
+}
-# shellcheck disable=1091
+# shellcheck source=../src/cpt-lib
. cpt-lib
die() {
@@ -34,34 +41,46 @@ die() {
case "$(uname -m)" in i*86) arch=i686; esac
url="https://dl.carbslinux.org/releases/${arch:-$(uname -m)}/carbs-rootfs.tar.xz"
-cd "$cac_dir"
+cd "${cac_dir:?}"
+
+# Remove the existing tarball and the chroot directory, so that they can be
+# downloaded again.
+[ "$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"
- curl -fLO "$url"
+ pkg_download "$url"
}
[ -f carbs-rootfs.tar.xz.sum ] || {
log "Downloading checksums"
- curl -fLo- "${url%/*}/sha256sums.txt" |
- grep ' carbs-rootfs.tar.xz$' > carbs-rootfs.tar.xz.sum
+ 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; tar xf ../carbs-rootfs.tar.xz )
+ (cd carbs-chroot; xz -cd ../carbs-rootfs.tar.xz | pax -r)
}
-create_cache empty
+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"
@@ -71,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-chroot b/contrib/cpt-chroot
index 2f7eee7..a2ea151 100755
--- a/contrib/cpt-chroot
+++ b/contrib/cpt-chroot
@@ -1,22 +1,88 @@
#!/bin/sh -e
# Enter a chroot
+# shellcheck disable=2004
## SYNOPSIS:
## .Nm cpt-chroot
+## .Op Fl m
## .Op Ar dir
## DESCRIPTION:
## .Nm
## is a wrapper script to chroot inside other root filesystems. It automatically
## mounts important filesystems in to the chroot directory, and unmounts them
-## when the user exits the chroot and cleans up leftover host files.
+## when the user exits the chroot and cleans up leftover host files. If the flag
+## .Fl m
+## is given,
+## .Nm
+## does not try to mount or unmount any filesystems.
+
+# We generate the parser into the script, because we don't want this script to
+# depend on cpt-lib.
+nomount=''
+REST=''
+parse() {
+ OPTIND=$(($#+1))
+ while OPTARG= && [ $# -gt 0 ]; do
+ case $1 in
+ --?*=*) OPTARG=$1; shift
+ eval 'set -- "${OPTARG%%\=*}" "${OPTARG#*\=}"' ${1+'"$@"'}
+ ;;
+ --no-*) unset OPTARG ;;
+ -[mh]?*) OPTARG=$1; shift
+ eval 'set -- "${OPTARG%"${OPTARG#??}"}" -"${OPTARG#??}"' ${1+'"$@"'}
+ OPTARG= ;;
+ esac
+ case $1 in
+ '-m')
+ [ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
+ eval '[ ${OPTARG+x} ] &&:' && OPTARG='1' || OPTARG=''
+ nomount="$OPTARG"
+ ;;
+ '-h'|'--help')
+ usage
+ exit 0 ;;
+ --)
+ shift
+ while [ $# -gt 0 ]; do
+ REST="${REST} \"\${$(($OPTIND-$#))}\""
+ shift
+ done
+ break ;;
+ [-]?*)
+ set "unknown" "$1"; break ;;
+ *)
+ REST="${REST} \"\${$(($OPTIND-$#))}\""
+ esac
+ shift
+ done
+ [ $# -eq 0 ] && { OPTIND=1; unset OPTARG; return 0; }
+ case $1 in
+ unknown) set "Unrecognized option: $2" "$@" ;;
+ noarg) set "Does not allow an argument: $2" "$@" ;;
+ required) set "Requires an argument: $2" "$@" ;;
+ pattern:*) set "Does not match the pattern (${1#*:}): $2" "$@" ;;
+ notcmd) set "Not a command: $2" "$@" ;;
+ *) set "Validation error ($1): $2" "$@"
+ esac
+ echo "$1" >&2
+ exit 1
+}
+usage() { printf '%s\n' "usage: ${0##*/} [-m] [dir]" "" "Options:" \
+ " -m Don't mount or unmount directories"
+}
+
+parser_definition() {
+ setup REST help:usage -- "usage: ${0##*/} [-m] [dir]"
+ msg -- '' 'Options:'
+ flag nomount -m -- "Don't mount or unmount directories"
+ disp :usage -h --help hidden:1
+}
log() {
printf '\033[32m->\033[m %s.\n' "$*"
}
-usage() { printf '%s [dir]\n' "${0##*/}"; exit 0;}
-
die() {
log "$*" >&2
exit 1
@@ -35,7 +101,7 @@ clean() {
}
main() {
- case "$1" in ''|--help|-h) usage; esac
+ parse "$@" && eval set -- "$REST"
[ -d "$1" ] || die Given path does not exist
[ "$(id -u)" = 0 ] || die Script needs to be run as root
@@ -48,17 +114,19 @@ main() {
esac
}
- trap 'clean "$1"' EXIT INT
+ [ -z "$nomount" ] && {
+ trap 'clean "$1"' EXIT INT
- log Mounting /dev, /proc and /sys from host; {
- mountpoint -q "$1/dev" || mount -o bind /dev "$1/dev"
- mountpoint -q "$1/proc" || mount -t proc proc "$1/proc"
- mountpoint -q "$1/sys" || mount -t sysfs sys "$1/sys"
+ log Mounting /dev, /proc and /sys from host; {
+ mountpoint -q "$1/dev" || mount -o bind /dev "$1/dev"
+ mountpoint -q "$1/proc" || mount -t proc proc "$1/proc"
+ mountpoint -q "$1/sys" || mount -t sysfs sys "$1/sys"
- }
+ }
- log Copying /etc/resolv.conf from host; {
- [ -f "$1/etc/resolv.conf" ] || cp /etc/resolv.conf "$1/etc"
+ log Copying /etc/resolv.conf from host; {
+ [ -f "$1/etc/resolv.conf" ] || cp /etc/resolv.conf "$1/etc"
+ }
}
log Entering chroot; {
diff --git a/contrib/cpt-export b/contrib/cpt-export
index 300c7c4..478ae27 100755
--- a/contrib/cpt-export
+++ b/contrib/cpt-export
@@ -12,47 +12,29 @@
## .Nm
## will use the name of the current directory as the package.
-case "$1" in
- --help|-h)
- printf 'usage: %s [pkg]\n' "${0##*/}"
- exit 0
- ;;
- '') set -- "${PWD##*/}"
-esac
-
-cpt-list "${1:-null}" >/dev/null
-
-# Grab the package's version..
-read -r ver rel 2>/dev/null < \
- "$CPT_ROOT/var/db/cpt/installed/$1/version"
-
### Environment variables:
### The compression method can be changed while creating a tarball, using the
### .Ev CPT_COMPRESS
### environment variable.
-# Fallback to gzip if there is a typo
-case "$CPT_COMPRESS" in bz2|gz|xz|zst|lz) ;; *) CPT_COMPRESS=gz; esac
+parser_definition() {
+ setup REST help:usage -- "usage: ${0##*/} [pkg]"
+ global_options silent
+}
-# Reset the argument list.
-pkg=$1
-tarball="$PWD/$1#$ver-$rel.tar.$CPT_COMPRESS"
-set --
+# shellcheck disable=1091
+. cpt-lib
-# Construct the argument list using each file.
-eval set -- "$(sed '/\/$/d;s|^|".|;s|$|"|' \
- "$CPT_ROOT/var/db/cpt/installed/$pkg/manifest" | tr '\n' ' ')"
+[ "$1" ] || set -- "${PWD##*/}"
-# Turn the list of files back into a package.
-cd "$CPT_ROOT/"
-tar cf - -- "$@" |
+(pkg_list "$1" >/dev/null)
+
+# Grab the package's version..
+read -r ver rel 2>/dev/null < "$sys_db/$1/version"
-case "$CPT_COMPRESS" in
- bz2) bzip2 -z ;;
- gz) gzip -6 ;;
- xz) xz -zT 0 ;;
- zst) zstd -3 ;;
- lz) lzip -6 ;;
-esac > "$tarball"
+tarball="$PWD/$1#$ver-$rel.tar.$CPT_COMPRESS"
-printf 'tarball created in %s\n' "$tarball"
+# Turn the list of files back into a package.
+cd "$CPT_ROOT/"
+sed 's/^/./' "$sys_db/$1/manifest" | pax -wd | compress > "$tarball"
+out "tarball created in $tarball"
diff --git a/contrib/cpt-fork b/contrib/cpt-fork
index 21e1618..733c942 100755
--- a/contrib/cpt-fork
+++ b/contrib/cpt-fork
@@ -31,12 +31,12 @@ for pkg; do
case "$pkg" in
*/*)
[ -d "$pkg" ] || die "$pkg is not a directory"
- cp -r "$pkg" .
+ cp -Hr "$pkg" .
pkg=${pkg##*/}
;;
*)
cpt-search "$pkg" >/dev/null
- cp -r "$(cpt-search --single "$pkg")" .
+ cp -Hr "$(cpt-search --single "$pkg")" .
esac
# Sometimes forked packages are from the database and not from a repository.
diff --git a/contrib/cpt-maintainer b/contrib/cpt-maintainer
new file mode 100755
index 0000000..34f212f
--- /dev/null
+++ b/contrib/cpt-maintainer
@@ -0,0 +1,49 @@
+#!/bin/sh -e
+# Find the maintainer of a package
+
+## SYNOPSIS:
+## .Nm
+## .Op Ar pkg...
+
+## DESCRIPTION:
+## .Nm
+## finds the maintainer of the given pacage. If no package name is given,
+## .Nm
+## will use the name of the current directory as the package.
+
+# shellcheck disable=1091
+. cpt-lib
+
+usage() {
+ out "usage: ${0##*/} [pkg...]"
+ exit
+}
+
+case $1 in
+ --help|-h) usage ;;
+ '') set -- "${PWD##*/}"
+esac
+
+for pkgname; do
+ cpt-search -d "$pkgname" | while read -r pkg; do
+ # Default to the 'meta' file of the package instead of jumping through
+ # VCS hoops to find out.
+ log "$pkg" " "
+ pkg_query_meta "$pkg" maintainer && continue
+
+ cd "$pkg"
+ # Use pkg_vcs_info to find out the repository type, but don't save
+ # repository information to the repository cache file.
+ repo_type=$(CPT_REPO_CACHE=0 pkg_vcs_info)
+ repo_type=${repo_type##*:}
+
+ # We use the latest author who made a change to the version file to
+ # identify the maintainer of a package.
+ case $repo_type in
+ git) git log -1 --format='%an <%ae>' version ;;
+ fossil) fossil time par cur -n 1 -p version -F "%a" | sed \$d ;;
+ hg) hg log -l1 -T '{user}\n' -- version ;;
+ *) out "Maintainer information not available"
+ esac
+ done
+done
diff --git a/contrib/cpt-manifest-tree b/contrib/cpt-manifest-tree
index 599c0bd..bc38bc2 100755
--- a/contrib/cpt-manifest-tree
+++ b/contrib/cpt-manifest-tree
@@ -21,4 +21,4 @@ case "$1" in
esac
cpt-list "$1" >/dev/null
printf '%s\n' "[$1]:"
-tree -C --fromfile "$CPT_ROOT/var/db/cpt/installed/$1/manifest" | sed 1,2d
+tree -C --fromfile "$CPT_ROOT/var/db/cpt/installed/$1/manifest" | sed 1d
diff --git a/contrib/cpt-owns b/contrib/cpt-owns
index 9bc7d77..1f362d7 100755
--- a/contrib/cpt-owns
+++ b/contrib/cpt-owns
@@ -40,7 +40,7 @@ case "$1" in
esac
# Strip 'CPT_ROOT' from the file path if passed and follow symlinks.
-file="${1#$CPT_ROOT}"
+file="${1#"$CPT_ROOT"}"
dirname=$(_readlinkf "$CPT_ROOT/${file%/*}")
file="$dirname/${file##*/}"
diff --git a/contrib/cpt-reset b/contrib/cpt-reset
index 2a1b66e..a2336e3 100755
--- a/contrib/cpt-reset
+++ b/contrib/cpt-reset
@@ -3,6 +3,7 @@
#
# Disable word-splittng warnings as they're safe here.
# shellcheck disable=SC2046
+# shellcheck source=../src/cpt-lib
## SYNOPSIS:
## .Nm
@@ -11,10 +12,10 @@
## removes all packages from the system that is not defined as a base package in
## .Pa /etc/cpt-base .
-[ "$1" ] && {
- printf 'usage: %s\n\nRemove all packages not defined in the base.\n' \
- "${0##*/}"
- exit 0
+parser_definition() {
+ setup REST help:usage -- "usage: ${0##*/}"
+ global_options compact
+ msg -- '' "Remove all packages outside of base definition"
}
. cpt-lib
@@ -27,9 +28,14 @@ set +f; for pkg in *; do
contains "$base" "$pkg" || set -- "$pkg" "$@"
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 'Continue? [Enter/Ctrl+C]\n'
- read -r _ && CPT_FORCE=1 cpt-remove "$@"
+[ -z "$1" ] && {
+ log "No package outside of the base definition could be found, not continuing."
+ exit 0
}
+
+warn "" "This is a potentially harmful operation, do NOT continue unless"
+warn "" "you know exactly what you are doing. Continuing will remove $#"
+warn "" "packages that are not listed in the base definition or that the"
+warn "" "base packages don't depend on. See the CPT BASE section on the"
+warn "" "user manual to learn more."
+prompt && cpt-remove "$@"
diff --git a/contrib/cpt-revdepends b/contrib/cpt-revdepends
index 833dea2..3529a53 100755
--- a/contrib/cpt-revdepends
+++ b/contrib/cpt-revdepends
@@ -22,7 +22,7 @@
## .El
parser_definition() {
- setup REST help:usage -- "usage: ${0##*/} [options...] [pkg...]"
+ setup REST help:usage -- "usage: ${0##*/} [options...] [pkg]"
flag tree -t --tree -- "Also print indirect reverse dependencies"
flag make -m --make -- "Include make dependencies"
global_options
@@ -41,11 +41,11 @@ parser_definition() {
cd "$sys_db"
get_revdep() {
- query="^$1\$"
+ pkg=$1; set -- "^$pkg\$"
# Defined by parser.
# shellcheck disable=2154
- [ "$make" ] && query="$query\\|^$1 *make\$"
- grep "$query" -- */depends | while read -r pkg _; do
+ [ "$make" ] && set -- -e "$1" -e "^$pkg "
+ grep "$@" -- */depends | while read -r pkg _; do
printf '%s\n' "${pkg%%/*}"
done
}
@@ -53,7 +53,7 @@ get_revdep() {
# Defined by parser.
# shellcheck disable=2154
if [ "$tree" ]; then
- create_cache nobuild
+ mkdir -p "$tmp_dir"
:> "$tmp_dir/processed"
get_revdep "$1" > "$tmp_dir/dep"
while ! diff -q "$tmp_dir/dep" "$tmp_dir/processed" >/dev/null 2>&1; do
diff --git a/contrib/cpt-size b/contrib/cpt-size
index 2812d56..22a77b7 100755
--- a/contrib/cpt-size
+++ b/contrib/cpt-size
@@ -3,6 +3,7 @@
## SYNOPSIS:
## .Nm
+## .Op Fl st
## .Op Ar pkg...
## DESCRIPTION:
@@ -10,41 +11,68 @@
## calculates the sizes of given
## .Ar packages
## using the files from the package manifest and outputs a total size of the
-## packages along with all the files associated with them.
-
-## CAVEATS:
+## packages along with all the files associated with them. If no arguments have
+## been given,
## .Nm
-## uses the non-POSIX
-## .Fl h
-## and
-## .Fl c
-## flags for
-## .Xr du 1 ,
-## which will not work with
-## .Em sbase ,
-## but it is a major performance improvement compared to calculating
-## total and human-readable sizes by hand.
-
-case "$1" in
- --help|-h)
- printf '%s\n' "usage: ${0##*/} [pkg...]"
- exit 0
- ;;
- '') set -- "${PWD##*/}"
-esac
-
-for pkg; do cpt-list "$pkg" >/dev/null; done
-
-files=
-for pkg; do
- while read -r file; do
- # Filter directories from manifest and leave only files.
- # Directories in the manifest end in a trailing '/'.
- case $file in */) continue; esac
- files="$files '$file'"
- done < "$CPT_ROOT/var/db/cpt/installed/$pkg/manifest"
-done
-eval "set -- $files"
-
-# Send the file list to 'du'.
-du -shc -- "$@" 2>/dev/null
+## will use the name of the current directory as an argument.
+## .Pp
+## The options are as follows:
+## .Bl -tag -width 13n
+## .It Fl s
+## Sort the output by size.
+## .It Fl t
+## Output only the size of given packages and not individual files.
+parser_definition() {
+ setup REST help:usage -- "usage: ${0##*/} [-st] [pkg...]"
+ flag sort -s hidden:1
+ flag total -t hidden:1
+ disp :usage -h --help hidden:1
+}
+
+# shellcheck source=../src/cpt-lib
+# shellcheck disable=1091
+. cpt-lib
+
+# Use the current directory if no arguments have been given.
+[ "$1" ] || set -- "${PWD##*/}"
+
+# Ensure that all the packages given as arguments are installed.
+pkg_list "$@" >/dev/null
+
+mkdir -p "$tmp_dir"
+
+# We don't immediately pipe into awk as we want to exit in an error.
+if [ "$total" ]; then
+ for pkg; do
+ sed '/\/$/d;s/./\\&/g' "$sys_db/$pkg/manifest" |
+ xargs du -k |
+ awk -v name="$pkg" '{size+=$1}END{printf("%s %s\n", size, name)}' >> "$tmp_dir/size"
+ done
+else
+ for pkg; do sed '/\/$/d;s/./\\&/g' "$sys_db/$pkg/manifest"; done |
+ xargs du -k > "$tmp_dir/size"
+fi
+
+# Do a numerical sort on the file if requested.
+[ "$sort" ] && sort -no "$tmp_dir/size" "$tmp_dir/size"
+
+# This awk function formats the `du` output similar to the '-hc' flags. We
+# could have used a shell `while read` loop to do the exact same thing, but that
+# would be much much slower.
+awk 'function fmtsize(s) {
+ if (s==0) f=""
+ else if (s<1024) f="K"
+ else if (s<(1048576)){f="M";s=s/1024;}
+ else if (s<(1073741824)){f="G";s=s/1048576;}
+ else f=""
+ return int(s) f
+ }
+ {
+ sc = $1
+ size += $1
+ sub(sprintf("^%s\s*", $1), "")
+ printf("%-6s %s\n", fmtsize(sc), $0)
+ }
+ END {
+ printf("%-6s total\n", fmtsize(size))
+ }' "$tmp_dir/size"
diff --git a/docs/Makefile b/docs/Makefile
index 344bd70..7c5a431 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -1,9 +1,16 @@
# Carbs Packaging Tools Documentation
-include ../config.mk
+-include ../config.mk
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,14 +27,6 @@ clean:
rm -f cpt.info
all-clean: clean
- rm -f cpt.texi cpt.txt
-
-install: all
- ${INSTALL_SH} -Dm644 cpt.txt ${DESTDIR}${CPTDOC}/cpt.txt
- ${INSTALL_SH} -Dm644 cpt.info ${DESTDIR}${INFODIR}/cpt.info
-
-uninstall:
- rm -rf ${DESTDIR}${CPTDOC}
- rm -f ${DESTDIR}${INFODIR}/cpt.info
+ 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 3949cea..b3fc97b 100644
--- a/docs/cpt.org
+++ b/docs/cpt.org
@@ -6,10 +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:
@@ -38,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
@@ -107,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
@@ -144,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
@@ -156,41 +184,105 @@ variables that alter the behaviour of =cpt=, some of them have separate sections
to provide detailed information.
- ~CPT_PATH~ ::
+
+ #+VINDEX: CPT_PATH
Set the locations of your repositories. It is similar to the ~PATH~ variable.
+
- ~CPT_CACHE~ ::
+
+ #+VINDEX: CPT_CACHE
The cache directory for =cpt=. Default: ~$XDG_CACHE_HOME/cpt~.
+
- ~CPT_CHOICE~ ::
+
+ #+VINDEX: CPT_CHOICE
If this is set to 0, a package installation will be aborted on conflicts.
+
- ~CPT_COLOR~ ::
+
+ #+VINDEX: CPT_COLOR
If this is set to 1, =cpt= tools will be forced to display coloured output. If
set to 0, they will be forced to display them without colours. Otherwise,
=cpt= will output colour as long as it is outputting to a terminal.
+
- ~CPT_DEBUG~ ::
+
+ #+VINDEX: CPT_DEBUG
If set to 1, temporary directories will not be removed after the operation.
+
+- ~CPT_DOWNLOADER~ ::
+
+ The tool to be used to download package sources. One of =curl=, =wget=,
+ =wget2=, =axel=, =aria2c=. Defaults to the first one found in that order.
+
- ~CPT_FETCH~ ::
+
+ #+VINDEX: CPT_FETCH
If set to 0, ~cpt-update~ will not fetch repositories.
+
- ~CPT_FORCE~ ::
+
+ #+VINDEX: CPT_FORCE
If set to 1, =cpt= tools will force operation.
+
- ~CPT_HOOK~ ::
+
+ #+VINDEX: CPT_HOOK
Absolute path to the package manager hook file.
+
- ~CPT_KEEPLOG~ ::
+
+ #+VINDEX: CPT_KEEPLOG
If set to 1, =cpt= will keep logs regardless of operation success.
+
+- ~CPT_NOSTRIP~ ::
+
+ #+VINDEX: CPT_NOSTRIP
+ If set to 1, =cpt= will not strip debug information from the binaries. Keep in
+ mind that your compiler already strips most debug information during
+ compilation, so you also need to add ~-g~ flag to your ~$C{XX}FLAGS~
+
- ~CPT_PID~ ::
+
+ #+VINDEX: CPT_PID
Set the temporary build directory name.
+
- ~CPT_PROMPT~ ::
+
+ #+VINDEX: CPT_PROMPT
If set to 0, =cpt= will not prompt you for anything.
+
+- ~CPT_REPO_CACHE~ ::
+
+ #+VINDEX: CPT_REPO_CACHE
+ If set to 0, =cpt= will not use or write repository information cache.
+
- ~CPT_ROOT~ ::
+
+ #+VINDEX: CPT_ROOT
If this variable is set, =cpt= will assume the given path as the system root.
+
- ~CPT_TEST~ ::
+
+ #+VINDEX: CPT_TEST
If set to 1, ~cpt-build~ will run tests whenever available.
+
- ~CPT_TMPDIR~ ::
+
+ #+VINDEX: CPT_TMPDIR
The directory to create the temporary directories.
+- ~CPT_VERBOSE~ ::
+
+ #+VINDEX: CPT_VERBOSE
+ If this variable is set to 1, the package manager will print more information.
+
*** =CPT_PATH=
:PROPERTIES:
:DESCRIPTION: Set the locations of your repositories
:END:
+#+CINDEX: Setting up repositories
Similar to the =PATH= variable, =cpt= find repositories from the =CPT_PATH=
variable. Here is an example:
@@ -213,6 +305,7 @@ This example brings us to the next section of this document.
:DESCRIPTION: Prioritise package repositories
:END:
+#+CINDEX: package conflicts
When you are using multiple repositories from multiple vendors, you will find
out that some repositories have the same packages. =cpt= doesn't care about
conflicting packages. If you want to build a package that exists on multiple
@@ -310,8 +403,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
@@ -369,8 +464,8 @@ EOF
:DESCRIPTION: More detail on creating packages
:END:
-A package is formed of several files, from these files, only ~build~,
-~checksums~, and ~version~ files are mandatory.
+A package is a directory formed of several files, from these files, only
+~build~, ~checksums~, and ~version~ files are mandatory.
This section talks about files that are interpreted specially by the package
manager. Any other file can be added to the package directory at the discretion
@@ -378,6 +473,21 @@ of the package maintainer. Everything in the package directory will also be
added to the package database that is located on =/var/db/cpt/installed=. These
can be patches, configuration files, etc.
+Below is a table that provides a small summary for each file, see the relevant
+section to learn detailed information on each of them.
+
+| File | Language | Executable | Mandatory |
+|--------------+------------------------------------+------------+-----------|
+| build | any | yes | yes |
+| checksums | generated by =cpt-checksum= | no | no |
+| meta | key-value pairs as in RFC822[fn:1] | no | no[fn:2] |
+| depends | custom format | no | no |
+| sources | custom format | no | no |
+| version | custom format | no | yes |
+| message | plaintext | no | no |
+| post-install | any | yes | no |
+| test | any | yes | no |
+
** build
:PROPERTIES:
:DESCRIPTION: The build script
@@ -451,7 +561,7 @@ the sha256 algorithm.
** version
:PROPERTIES:
-:DESCRIPTION: The file containing the version and the release numbers of a package
+:DESCRIPTION: The file containing version information for a package
:END:
The version file includes the version of the software and the release number of
@@ -498,6 +608,9 @@ license: MIT
maintainer: Linux User <linux-user@example.com>
#+end_example
+Even though =meta= is not mandatory by the packaging system, it is a mandatory
+file for submitting packages to Carbs Linux repositories.
+
** post-install
:PROPERTIES:
:DESCRIPTION: The post-installation script
@@ -520,12 +633,30 @@ installed.
:DESCRIPTION: The test script for a package
:END:
+#+VINDEX: CPT_TEST
Test files are mainly for the repository maintainer to test the packages, and
will only run if the user has the =CPT_TEST= variable set, or the build is
run with the =-t= or =--test= options. This script is run on the
build directory. It is run right after the build script is finished.
-* Rsync Repositories
+* Package Repositories
+:PROPERTIES:
+:DESCRIPTION: Ways of distributing packages
+:END:
+
+*cpt* has backends to support the use of a variety of distribution methods. You
+can currently use Git, Mercurial, Fossil, and Rsync to distribute a package
+repository. That, however, does not mean that you need to setup either of those,
+if you are simply going for a local repository on your system.
+
+#+CINDEX: Setting up repositories
+In the broad sense, a package repository is any directory that contains packages
+that were described in [[Packaging System]]. This means that as long as you can
+serve them, there is not much needed to do in order to distribute a repository.
+The following subsections aim to detail the notes and the caveats of certain
+distribution methods.
+
+** Rsync Repositories
:PROPERTIES:
:DESCRIPTION: Information on using or creating rsync repositories
:END:
@@ -572,7 +703,7 @@ repository and will sync the entire repository instead of each individual reposi
If the upper directory doesn't have this =.rsync= file, this means that this
is an individual repository, and the package manager will fetch accordingly.
-** Setting up an Rsync repository
+*** Setting up an Rsync repository
:PROPERTIES:
:DESCRIPTION: Set up a repository for distribution
:END:
@@ -626,6 +757,37 @@ Create a service file at =/etc/sv/rsync/run= (runit):
exec rsync --daemon --no-detach
#+END_SRC
+** Fossil repositories
+:PROPERTIES:
+:DESCRIPTION: Advantages and disadvantages of Fossil
+:END:
+
+Setting up a Fossil repository is no different than setting up any other
+repository. There are certainly many advantages of using Fossil as a means of
+distributing packages. You can create a Linux distribution and have your
+website, forum, documentation, and your package repository entirely contained
+inside a single Fossil repository. Fossil's built-in wiki and forum features
+make it the ultimate single-tool distribution software.
+
+However, the biggest caveat of Fossil is that it doesn't allow symlinks by
+default unless it's manually set by the user, and this feature cannot even be
+set globally. Symbolic links aren't quite common within distribution
+repositories, but they come in handy where there are two packages that use the
+same source files (=emacs= and =emacs-nox=, or =libelf= and =libdw= from
+elfutils). If symbolic links are too big of a deal for your repository, this can
+be a huge issue for you.
+
+** Message of the Day
+:PROPERTIES:
+:DESCRIPTION: Communicate with the users using your repository
+:END:
+
+If a file named =MOTD= (all uppercase) is found on the root directory of the
+package repository, its contents will be printed to the standard output when the
+users are updating their repositories. This method can be used to communicate
+messages to the users, such as package removals or otherwise important
+information.
+
* Comparison Between CPT and KISS
Lots of things have changed since ~cpt~ was forked from ~kiss~ in terms of
@@ -649,12 +811,13 @@ this is the ~cpt~ documentation, so it may be biased regardless.
- Package Repositories ::
- In addition to git repositories, ~cpt~ also makes use of [[Rsync Repositories][rsync repositories]].
+ In addition to git repositories, ~cpt~ also supports Rsync, Fossil, and
+ Mercurial repositories.
- Package Sources ::
- In addition to git repositories for sources, ~cpt~ also supports mercurial
- repositories.
+ In addition to git repositories for sources, ~cpt~ also supports Mercurial and
+ Fossil repositories.
- Post-Installation Messages ::
@@ -697,6 +860,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
@@ -743,13 +952,21 @@ inside. Here is the proper way of doing it.
The =global_options()= function is a simple convenience call to include flags
that can be used inside most =cpt= tools. It defines the following flags:
-| Flag | Long Option | Calls |
-|------+---------------+--------------|
-| ~-f~ | ~--force~ | =CPT_FORCE= |
-| ~-y~ | ~--no-prompt~ | =CPT_PROMPT= |
-| | ~--root~ | =CPT_ROOT= |
-| ~-h~ | ~--help~ | =usage()= |
-| ~-v~ | ~--version~ | =version()= |
+| Flag | Long Option | Calls |
+|------+---------------+---------------|
+| ~-f~ | ~--force~ | =CPT_FORCE= |
+| ~-y~ | ~--no-prompt~ | =CPT_PROMPT= |
+| | ~--root~ | =CPT_ROOT= |
+| ~-h~ | ~--help~ | =usage()= |
+| ~-v~ | ~--version~ | =version()= |
+| | ~--verbose~ | =CPT_VERBOSE= |
+
+This function can take two arguments:
+
+- =silent= :: If this argument is specified, the function does not print the usage
+ information defined by its flags.
+- =compact= :: If this argument is specified, the function only prints the help
+ output of the ~--help~ and ~--version~ flags.
** Message functions
:PROPERTIES:
@@ -1058,7 +1275,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.
@@ -1110,12 +1327,24 @@ rsync curl zlib ca-certificates bearssl
This function is used to query the [[meta][meta file]] inside package directories. It can
be used to retrieve information on a package that is otherwise irrelevant to the
-package manager itself. It takes two arguments, first being the package and the
-second being the key to be retrieved. If the package does not have a =meta=
-file or the file does not contain the requested key, the function will return
-with 1.
+package manager itself. It takes two arguments, first being the package (or the
+full path to a package directory) and the second being the key to be retrieved.
+If the package does not have a =meta= file or the file does not contain the
+requested key, the function will return with 1.
#+begin_src sh
$ pkg_query_meta cpt description
Carbs Packaging Tools
+
+$ pkg_query_meta /path/to/cpt license
+MIT
#+end_src
+
+* {{{index(Concept, cp)}}}
+* {{{index(Variable,vr)}}}
+
+* Footnotes
+
+[fn:1] https://datatracker.ietf.org/doc/html/rfc822#section-3.2
+[fn:2] Not mandatory for the packaging system, but mandatory for inclusion in
+the repositories
diff --git a/docs/cpt.texi b/docs/cpt.texi
index c39b393..e6b331c 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
@@ -49,20 +50,27 @@ manual for @strong{Carbs Packaging Tools}. For development logs see @uref{https:
* Usage:: Basic usage of Carbs Packaging Tools
* Configuration:: Configuring the package manager
* Packaging System:: More detail on creating packages
-* Rsync Repositories:: Information on using or creating rsync repositories
+* Package Repositories:: Ways of distributing packages
* Comparison Between CPT and KISS::
* CPT Library:: Documentation of the Library
+* Concept Index:: Concepts mentioned in this manual
+* Variable Index:: Variables mentioned in this manual
@detailmenu
--- The Detailed Node Listing ---
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
@@ -75,13 +83,19 @@ Packaging System
* build:: The build script
* sources:: The file containing package sources
* checksums:: The file containing sha256sum of the sources
-* version:: The file containing the version and the release numbers of a package
+* version:: The file containing version information for a package
* depends:: The file containing the dependencies of a package
* meta:: File containing more information on packages
* post-install:: The post-installation script
* message:: The post-installation message to be displayed
* test:: The test script for a package
+Package Repositories
+
+* Rsync Repositories:: Information on using or creating rsync repositories
+* Fossil repositories:: Advantages and disadvantages of Fossil
+* Message of the Day:: Communicate with the users using your repository
+
Rsync Repositories
* Setting up an Rsync repository:: Set up a repository for distribution
@@ -89,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
@@ -152,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
@@ -218,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
@@ -259,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
@@ -270,35 +316,80 @@ to provide detailed information.
@table @asis
@item @code{CPT_PATH}
+@vindex CPT_PATH
Set the locations of your repositories. It is similar to the @code{PATH} variable.
+
@item @code{CPT_CACHE}
+@vindex CPT_CACHE
The cache directory for @samp{cpt}. Default: @code{$XDG_CACHE_HOME/cpt}.
+
@item @code{CPT_CHOICE}
+@vindex CPT_CHOICE
If this is set to 0, a package installation will be aborted on conflicts.
+
@item @code{CPT_COLOR}
+@vindex CPT_COLOR
If this is set to 1, @samp{cpt} tools will be forced to display coloured output. If
set to 0, they will be forced to display them without colours. Otherwise,
@samp{cpt} will output colour as long as it is outputting to a terminal.
+
@item @code{CPT_DEBUG}
+@vindex CPT_DEBUG
If set to 1, temporary directories will not be removed after the operation.
+
+@item @code{CPT_DOWNLOADER}
+The tool to be used to download package sources. One of @samp{curl}, @samp{wget},
+@samp{wget2}, @samp{axel}, @samp{aria2c}. Defaults to the first one found in that order.
+
@item @code{CPT_FETCH}
+@vindex CPT_FETCH
If set to 0, @code{cpt-update} will not fetch repositories.
+
@item @code{CPT_FORCE}
+@vindex CPT_FORCE
If set to 1, @samp{cpt} tools will force operation.
+
@item @code{CPT_HOOK}
+@vindex CPT_HOOK
Absolute path to the package manager hook file.
+
@item @code{CPT_KEEPLOG}
+@vindex CPT_KEEPLOG
If set to 1, @samp{cpt} will keep logs regardless of operation success.
+
+@item @code{CPT_NOSTRIP}
+@vindex CPT_NOSTRIP
+If set to 1, @samp{cpt} will not strip debug information from the binaries. Keep in
+mind that your compiler already strips most debug information during
+compilation, so you also need to add @code{-g} flag to your @code{$C@{XX@}FLAGS}
+
@item @code{CPT_PID}
+@vindex CPT_PID
Set the temporary build directory name.
+
@item @code{CPT_PROMPT}
+@vindex CPT_PROMPT
If set to 0, @samp{cpt} will not prompt you for anything.
+
+@item @code{CPT_REPO_CACHE}
+@vindex CPT_REPO_CACHE
+If set to 0, @samp{cpt} will not use or write repository information cache.
+
@item @code{CPT_ROOT}
+@vindex CPT_ROOT
If this variable is set, @samp{cpt} will assume the given path as the system root.
+
@item @code{CPT_TEST}
+@vindex CPT_TEST
If set to 1, @code{cpt-build} will run tests whenever available.
+
@item @code{CPT_TMPDIR}
+@vindex CPT_TMPDIR
The directory to create the temporary directories.
+
+@item @code{CPT_VERBOSE}
+@vindex CPT_VERBOSE
+If this variable is set to 1, the package manager will print more information.
@end table
@menu
@@ -311,6 +402,7 @@ The directory to create the temporary directories.
@node @samp{CPT_PATH}
@subsection @samp{CPT_PATH}
+@cindex Setting up repositories
Similar to the @samp{PATH} variable, @samp{cpt} find repositories from the @samp{CPT_PATH}
variable. Here is an example:
@@ -330,9 +422,10 @@ This example brings us to the next section of this document.
@enumerate
@item
-Repository preferences
+@anchor{Repository preferences}Repository preferences
+@cindex package conflicts
When you are using multiple repositories from multiple vendors, you will find
out that some repositories have the same packages. @samp{cpt} doesn't care about
conflicting packages. If you want to build a package that exists on multiple
@@ -347,7 +440,7 @@ CPT_PATH=$HOME/repos/personal:$HOME/repos/carbs/extra
@end example
@item
-Setting the @samp{CPT_PATH}
+@anchor{Setting the @samp{CPT_PATH}}Setting the @samp{CPT_PATH}
You can set the @samp{CPT_PATH} variable on your shell configuration or your
@@ -442,10 +535,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
@@ -505,8 +602,8 @@ EOF
@node Packaging System
@chapter Packaging System
-A package is formed of several files, from these files, only @code{build},
-@code{checksums}, and @code{version} files are mandatory.
+A package is a directory formed of several files, from these files, only
+@code{build}, @code{checksums}, and @code{version} files are mandatory.
This section talks about files that are interpreted specially by the package
manager. Any other file can be added to the package directory at the discretion
@@ -514,11 +611,58 @@ of the package maintainer. Everything in the package directory will also be
added to the package database that is located on @samp{/var/db/cpt/installed}. These
can be patches, configuration files, etc.
+Below is a table that provides a small summary for each file, see the relevant
+section to learn detailed information on each of them.
+
+@multitable {aaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaa} {aaaaaaaaa}
+@headitem File
+@tab Language
+@tab Executable
+@tab Mandatory
+@item build
+@tab any
+@tab yes
+@tab yes
+@item checksums
+@tab generated by @samp{cpt-checksum}
+@tab no
+@tab no
+@item meta
+@tab key-value pairs as in RFC822@footnote{@uref{https://datatracker.ietf.org/doc/html/rfc822#section-3.2}}
+@tab no
+@tab no@footnote{Not mandatory for the packaging system, but mandatory for inclusion in
+the repositories}
+@item depends
+@tab custom format
+@tab no
+@tab no
+@item sources
+@tab custom format
+@tab no
+@tab no
+@item version
+@tab custom format
+@tab no
+@tab yes
+@item message
+@tab plaintext
+@tab no
+@tab no
+@item post-install
+@tab any
+@tab yes
+@tab no
+@item test
+@tab any
+@tab yes
+@tab no
+@end multitable
+
@menu
* build:: The build script
* sources:: The file containing package sources
* checksums:: The file containing sha256sum of the sources
-* version:: The file containing the version and the release numbers of a package
+* version:: The file containing version information for a package
* depends:: The file containing the dependencies of a package
* meta:: File containing more information on packages
* post-install:: The post-installation script
@@ -644,6 +788,9 @@ license: MIT
maintainer: Linux User <linux-user@@example.com>
@end example
+Even though @samp{meta} is not mandatory by the packaging system, it is a mandatory
+file for submitting packages to Carbs Linux repositories.
+
@node post-install
@section post-install
@@ -660,13 +807,35 @@ installed.
@node test
@section test
+@vindex CPT_TEST
Test files are mainly for the repository maintainer to test the packages, and
will only run if the user has the @samp{CPT_TEST} variable set, or the build is
run with the @samp{-t} or @samp{--test} options. This script is run on the
build directory. It is run right after the build script is finished.
+@node Package Repositories
+@chapter Package Repositories
+
+@strong{cpt} has backends to support the use of a variety of distribution methods. You
+can currently use Git, Mercurial, Fossil, and Rsync to distribute a package
+repository. That, however, does not mean that you need to setup either of those,
+if you are simply going for a local repository on your system.
+
+@cindex Setting up repositories
+In the broad sense, a package repository is any directory that contains packages
+that were described in @ref{Packaging System}. This means that as long as you can
+serve them, there is not much needed to do in order to distribute a repository.
+The following subsections aim to detail the notes and the caveats of certain
+distribution methods.
+
+@menu
+* Rsync Repositories:: Information on using or creating rsync repositories
+* Fossil repositories:: Advantages and disadvantages of Fossil
+* Message of the Day:: Communicate with the users using your repository
+@end menu
+
@node Rsync Repositories
-@chapter Rsync Repositories
+@section Rsync Repositories
Rsync repositories are simple to serve and simple to use. In the repository
directory, there needs to be a @samp{.rsync} file that points to the remote of the
@@ -715,7 +884,7 @@ is an individual repository, and the package manager will fetch accordingly.
@end menu
@node Setting up an Rsync repository
-@section Setting up an Rsync repository
+@subsection Setting up an Rsync repository
Carbs Linux repositories automatically sync from the git repostitories and serve
it through the rsync daemon. Here is a sample shell script that I use in order to
@@ -766,6 +935,33 @@ Create a service file at @samp{/etc/sv/rsync/run} (runit):
exec rsync --daemon --no-detach
@end example
+@node Fossil repositories
+@section Fossil repositories
+
+Setting up a Fossil repository is no different than setting up any other
+repository. There are certainly many advantages of using Fossil as a means of
+distributing packages. You can create a Linux distribution and have your
+website, forum, documentation, and your package repository entirely contained
+inside a single Fossil repository. Fossil's built-in wiki and forum features
+make it the ultimate single-tool distribution software.
+
+However, the biggest caveat of Fossil is that it doesn't allow symlinks by
+default unless it's manually set by the user, and this feature cannot even be
+set globally. Symbolic links aren't quite common within distribution
+repositories, but they come in handy where there are two packages that use the
+same source files (@samp{emacs} and @samp{emacs-nox}, or @samp{libelf} and @samp{libdw} from
+elfutils). If symbolic links are too big of a deal for your repository, this can
+be a huge issue for you.
+
+@node Message of the Day
+@section Message of the Day
+
+If a file named @samp{MOTD} (all uppercase) is found on the root directory of the
+package repository, its contents will be printed to the standard output when the
+users are updating their repositories. This method can be used to communicate
+messages to the users, such as package removals or otherwise important
+information.
+
@node Comparison Between CPT and KISS
@chapter Comparison Between CPT and KISS
@@ -788,11 +984,12 @@ through environment variables. Additionally, all @code{cpt} tools can receive fl
that alter their functionality. @code{kiss} does not accept flags.
@item Package Repositories
-In addition to git repositories, @code{cpt} also makes use of @ref{Rsync Repositories, , rsync repositories}.
+In addition to git repositories, @code{cpt} also supports Rsync, Fossil, and
+Mercurial repositories.
@item Package Sources
-In addition to git repositories for sources, @code{cpt} also supports mercurial
-repositories.
+In addition to git repositories for sources, @code{cpt} also supports Mercurial and
+Fossil repositories.
@item Post-Installation Messages
@code{kiss} and @code{cpt} interact with @samp{post-install} messages differently. @code{kiss}
@@ -818,6 +1015,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
@@ -840,6 +1038,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
@@ -885,7 +1142,7 @@ parser_definition() @{
The @samp{global_options()} function is a simple convenience call to include flags
that can be used inside most @samp{cpt} tools. It defines the following flags:
-@multitable {aaaa} {aaaaaaaaaaaaa} {aaaaaaaaaaaa}
+@multitable {aaaa} {aaaaaaaaaaaaa} {aaaaaaaaaaaaa}
@headitem Flag
@tab Long Option
@tab Calls
@@ -904,8 +1161,22 @@ that can be used inside most @samp{cpt} tools. It defines the following flags:
@item @code{-v}
@tab @code{--version}
@tab @samp{version()}
+@item
+@tab @code{--verbose}
+@tab @samp{CPT_VERBOSE}
@end multitable
+This function can take two arguments:
+
+@table @asis
+@item @samp{silent}
+If this argument is specified, the function does not print the usage
+information defined by its flags.
+@item @samp{compact}
+If this argument is specified, the function only prints the help
+output of the @code{--help} and @code{--version} flags.
+@end table
+
@node Message functions
@section Message functions
@@ -1224,7 +1495,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.
@@ -1250,7 +1521,7 @@ Print all packages in a single line instead of a package per line.
@enumerate
@item
-Examples
+@anchor{Examples}Examples
This example uses the @samp{cpt} package for Carbs Linux. The package itself is
@@ -1282,14 +1553,27 @@ rsync curl zlib ca-certificates bearssl
This function is used to query the @ref{meta, , meta file} inside package directories. It can
be used to retrieve information on a package that is otherwise irrelevant to the
-package manager itself. It takes two arguments, first being the package and the
-second being the key to be retrieved. If the package does not have a @samp{meta}
-file or the file does not contain the requested key, the function will return
-with 1.
+package manager itself. It takes two arguments, first being the package (or the
+full path to a package directory) and the second being the key to be retrieved.
+If the package does not have a @samp{meta} file or the file does not contain the
+requested key, the function will return with 1.
@example
$ pkg_query_meta cpt description
Carbs Packaging Tools
+
+$ pkg_query_meta /path/to/cpt license
+MIT
@end example
+@node Concept Index
+@chapter Concept Index
+
+@printindex cp
+
+@node Variable Index
+@chapter Variable Index
+
+@printindex vr
+
@bye \ No newline at end of file
diff --git a/docs/cpt.txt b/docs/cpt.txt
index c04a52f..08433e9 100644
--- a/docs/cpt.txt
+++ b/docs/cpt.txt
@@ -1,10 +1,10 @@
- _______________________
+ _______________________
- CARBS PACKAGING TOOLS
- User Manual
+ CARBS PACKAGING TOOLS
+ User Manual
- Cem Keylan
- _______________________
+ Cem Keylan
+ _______________________
Table of Contents
@@ -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'
@@ -32,32 +34,36 @@ _________________
.. 7. post-install
.. 8. message
.. 9. test
-6. Rsync Repositories
-.. 1. Setting up an Rsync repository
+6. Package Repositories
+.. 1. Rsync Repositories
+..... 1. Setting up an Rsync repository
+.. 2. Fossil repositories
+.. 3. Message of the Day
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()'
@@ -71,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
@@ -103,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
=======
@@ -175,17 +187,31 @@ development manual for *Carbs Packaging Tools*. For development logs see
package manager.
-4.1 CPT Base
-~~~~~~~~~~~~
+4.1 Configuration directory
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 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'.
+ 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
+--------------
+
+ 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
@@ -211,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
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -223,40 +259,72 @@ development manual for *Carbs Packaging Tools*. For development logs see
`CPT_PATH'
Set the locations of your repositories. It is similar to the
`PATH' variable.
+
`CPT_CACHE'
The cache directory for `cpt'. Default: `$XDG_CACHE_HOME/cpt'.
+
`CPT_CHOICE'
If this is set to 0, a package installation will be aborted on
conflicts.
+
`CPT_COLOR'
If this is set to 1, `cpt' tools will be forced to display
coloured output. If set to 0, they will be forced to display
them without colours. Otherwise, `cpt' will output colour as
long as it is outputting to a terminal.
+
`CPT_DEBUG'
If set to 1, temporary directories will not be removed after the
operation.
+
+ `CPT_DOWNLOADER'
+ The tool to be used to download package sources. One of `curl',
+ `wget', `wget2', `axel', `aria2c'. Defaults to the first one
+ found in that order.
+
`CPT_FETCH'
If set to 0, `cpt-update' will not fetch repositories.
+
`CPT_FORCE'
If set to 1, `cpt' tools will force operation.
+
`CPT_HOOK'
Absolute path to the package manager hook file.
+
`CPT_KEEPLOG'
If set to 1, `cpt' will keep logs regardless of operation
success.
+
+ `CPT_NOSTRIP'
+ If set to 1, `cpt' will not strip debug information from the
+ binaries. Keep in mind that your compiler already strips most
+ debug information during compilation, so you also need to add
+ `-g' flag to your `$C{XX}FLAGS'
+
`CPT_PID'
Set the temporary build directory name.
+
`CPT_PROMPT'
If set to 0, `cpt' will not prompt you for anything.
+
+ `CPT_REPO_CACHE'
+ If set to 0, `cpt' will not use or write repository information
+ cache.
+
`CPT_ROOT'
If this variable is set, `cpt' will assume the given path as the
system root.
+
`CPT_TEST'
If set to 1, `cpt-build' will run tests whenever available.
+
`CPT_TMPDIR'
The directory to create the temporary directories.
+ `CPT_VERBOSE'
+ If this variable is set to 1, the package manager will print
+ more information.
+
4.2.1 `CPT_PATH'
----------------
@@ -383,10 +451,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
@@ -446,8 +518,8 @@ development manual for *Carbs Packaging Tools*. For development logs see
5 Packaging System
==================
- A package is formed of several files, from these files, only `build',
- `checksums', and `version' files are mandatory.
+ A package is a directory formed of several files, from these files,
+ only `build', `checksums', and `version' files are mandatory.
This section talks about files that are interpreted specially by the
package manager. Any other file can be added to the package directory
@@ -456,6 +528,21 @@ development manual for *Carbs Packaging Tools*. For development logs see
on `/var/db/cpt/installed'. These can be patches, configuration files,
etc.
+ Below is a table that provides a small summary for each file, see the
+ relevant section to learn detailed information on each of them.
+
+ File Language Executable Mandatory
+ ----------------------------------------------------------------------
+ build any yes yes
+ checksums generated by `cpt-checksum' no no
+ meta key-value pairs as in RFC822[1] no no[2]
+ depends custom format no no
+ sources custom format no no
+ version custom format no yes
+ message plaintext no no
+ post-install any yes no
+ test any yes no
+
5.1 build
~~~~~~~~~
@@ -579,8 +666,11 @@ development manual for *Carbs Packaging Tools*. For development logs see
| maintainer: Linux User <linux-user@example.com>
`----
+ Even though `meta' is not mandatory by the packaging system, it is a
+ 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
@@ -608,8 +698,24 @@ development manual for *Carbs Packaging Tools*. For development logs see
script is finished.
-6 Rsync Repositories
-====================
+6 Package Repositories
+======================
+
+ *cpt* has backends to support the use of a variety of distribution
+ methods. You can currently use Git, Mercurial, Fossil, and Rsync to
+ distribute a package repository. That, however, does not mean that you
+ need to setup either of those, if you are simply going for a local
+ repository on your system.
+
+ In the broad sense, a package repository is any directory that
+ contains packages that were described in 5. This means that as long as
+ you can serve them, there is not much needed to do in order to
+ distribute a repository. The following subsections aim to detail the
+ notes and the caveats of certain distribution methods.
+
+
+6.1 Rsync Repositories
+~~~~~~~~~~~~~~~~~~~~~~
Rsync repositories are simple to serve and simple to use. In the
repository directory, there needs to be a `.rsync' file that points to
@@ -658,8 +764,8 @@ development manual for *Carbs Packaging Tools*. For development logs see
fetch accordingly.
-6.1 Setting up an Rsync repository
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+6.1.1 Setting up an Rsync repository
+------------------------------------
Carbs Linux repositories automatically sync from the git repostitories
and serve it through the rsync daemon. Here is a sample shell script
@@ -712,6 +818,37 @@ development manual for *Carbs Packaging Tools*. For development logs see
`----
+6.2 Fossil repositories
+~~~~~~~~~~~~~~~~~~~~~~~
+
+ Setting up a Fossil repository is no different than setting up any
+ other repository. There are certainly many advantages of using Fossil
+ as a means of distributing packages. You can create a Linux
+ distribution and have your website, forum, documentation, and your
+ package repository entirely contained inside a single Fossil
+ repository. Fossil's built-in wiki and forum features make it the
+ ultimate single-tool distribution software.
+
+ However, the biggest caveat of Fossil is that it doesn't allow
+ symlinks by default unless it's manually set by the user, and this
+ feature cannot even be set globally. Symbolic links aren't quite
+ common within distribution repositories, but they come in handy where
+ there are two packages that use the same source files (`emacs' and
+ `emacs-nox', or `libelf' and `libdw' from elfutils). If symbolic links
+ are too big of a deal for your repository, this can be a huge issue
+ for you.
+
+
+6.3 Message of the Day
+~~~~~~~~~~~~~~~~~~~~~~
+
+ If a file named `MOTD' (all uppercase) is found on the root directory
+ of the package repository, its contents will be printed to the
+ standard output when the users are updating their repositories. This
+ method can be used to communicate messages to the users, such as
+ package removals or otherwise important information.
+
+
7 Comparison Between CPT and KISS
=================================
@@ -736,12 +873,12 @@ development manual for *Carbs Packaging Tools*. For development logs see
functionality. `kiss' does not accept flags.
Package Repositories
- In addition to git repositories, `cpt' also makes use of [rsync
- repositories].
+ In addition to git repositories, `cpt' also supports Rsync,
+ Fossil, and Mercurial repositories.
Package Sources
In addition to git repositories for sources, `cpt' also supports
- mercurial repositories.
+ Mercurial and Fossil repositories.
Post-Installation Messages
`kiss' and `cpt' interact with `post-install' messages
@@ -761,9 +898,6 @@ development manual for *Carbs Packaging Tools*. For development logs see
favour of portability.
-[rsync repositories] See section 6
-
-
8 CPT Library
=============
@@ -787,7 +921,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
@@ -799,7 +978,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
@@ -826,29 +1005,39 @@ 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
include flags that can be used inside most `cpt' tools. It defines the
following flags:
- Flag Long Option Calls
- -----------------------------------
- `-f' `--force' `CPT_FORCE'
- `-y' `--no-prompt' `CPT_PROMPT'
- `--root' `CPT_ROOT'
- `-h' `--help' `usage()'
- `-v' `--version' `version()'
+ Flag Long Option Calls
+ ------------------------------------
+ `-f' `--force' `CPT_FORCE'
+ `-y' `--no-prompt' `CPT_PROMPT'
+ `--root' `CPT_ROOT'
+ `-h' `--help' `usage()'
+ `-v' `--version' `version()'
+ `--verbose' `CPT_VERBOSE'
+
+ This function can take two arguments:
+
+ `silent'
+ If this argument is specified, the function does not print the
+ usage information defined by its flags.
+ `compact'
+ If this argument is specified, the function only prints the help
+ 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
@@ -863,7 +1052,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
@@ -881,7 +1070,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
@@ -889,14 +1078,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
@@ -906,14 +1095,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
@@ -929,7 +1118,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
@@ -941,7 +1130,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
@@ -955,7 +1144,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
@@ -975,7 +1164,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
@@ -983,7 +1172,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
@@ -997,7 +1186,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
@@ -1005,7 +1194,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
@@ -1017,10 +1206,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
@@ -1037,7 +1226,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
@@ -1045,7 +1234,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
@@ -1063,7 +1252,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,
@@ -1072,17 +1261,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
@@ -1103,7 +1292,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
@@ -1111,7 +1300,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
@@ -1119,7 +1308,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
@@ -1152,17 +1341,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
@@ -1182,7 +1371,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
@@ -1208,20 +1397,34 @@ 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
directories. It can be used to retrieve information on a package that
is otherwise irrelevant to the package manager itself. It takes two
- arguments, first being the package and the second being the key to be
- retrieved. If the package does not have a `meta' file or the file does
- not contain the requested key, the function will return with 1.
+ arguments, first being the package (or the full path to a package
+ directory) and the second being the key to be retrieved. If the
+ package does not have a `meta' file or the file does not contain the
+ requested key, the function will return with 1.
,----
| $ pkg_query_meta cpt description
| Carbs Packaging Tools
+ |
+ | $ pkg_query_meta /path/to/cpt license
+ | MIT
`----
[meta file] See section 5.6
+
+
+
+Footnotes
+_________
+
+[1] <https://datatracker.ietf.org/doc/html/rfc822#section-3.2>
+
+[2] Not mandatory for the packaging system, but mandatory for
+inclusion in the repositories
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/man/cpt-build.1 b/man/cpt-build.1
index 79b24c6..ec65eeb 100644
--- a/man/cpt-build.1
+++ b/man/cpt-build.1
@@ -5,7 +5,7 @@
.Nd build given packages
.Sh SYNOPSIS
.Nm cpt-build
-.Op Fl tfy
+.Op Fl dfSty
.Op Fl -root Ar ROOT
.Op Fl hv
.Op Ar package...
@@ -21,18 +21,36 @@ package.
.Pp
The options are as follows:
.Bl -tag -width 13n
+.It Fl d , -debug
+Keep the build directories after operation
.It Fl t , -test
Run tests (if they exist)
+.It Fl S , -nostrip
+Don't strip debug information from the binaries
+.Po
+might want to add
+.Fl g
+to your
+.Ev $CFLAGS
+.Pc
.It Fl f , -force
Force operation
.It Fl y , -no-prompt
Do not prompt for confirmation
+.It Fl -color Ar CPT_COLOR
+Enable/disable output color
+.Bo
+.Sy auto ,
+always, never, 1, 0
+.Bc
.It Fl -root Ar CPT_ROOT
Use an alternate root directory
.It Fl h , -help
Show help message
.It Fl v , -version
Print version information
+.It Fl -verbose
+Be more verbose
.El
.Sh AUTHOR
.An Cem Keylan Aq Mt cem@ckyln.com
diff --git a/man/cpt-checksum.1 b/man/cpt-checksum.1
index 4c637eb..bfced46 100644
--- a/man/cpt-checksum.1
+++ b/man/cpt-checksum.1
@@ -5,15 +5,27 @@
.Nd generate checksums
.Sh SYNOPSIS
.Nm
+.Op Fl s
.Op Ar package...
.Sh DESCRIPTION
.Nm
-lints a package, downloads the sources, and creates a checksum file
-including the SHA256 digests of the sources. If no
+lints a package, downloads the sources, and creates a file named
+.Sq checksums
+which includes the
+.Em BLAKE3
+digests of the sources. If no
.Ar package
is specified,
.Nm
will generate checksums assuming the working directory as the package.
+.Pp
+If the
+.Fl s
+flag is given,
+.Nm
+will generate checksums using the
+.Em SHA256
+algorithm.
.Sh AUTHOR
.An Cem Keylan Aq Mt cem@ckyln.com
.Sh LICENSE
diff --git a/man/cpt-install.1 b/man/cpt-install.1
index 65069f3..dfd483c 100644
--- a/man/cpt-install.1
+++ b/man/cpt-install.1
@@ -23,12 +23,20 @@ The options are as follows:
Force installation
.It Fl y , -no-prompt
Do not prompt for confirmation
+.It Fl -color Ar CPT_COLOR
+Enable/disable output color
+.Bo
+.Sy auto ,
+always, never, 1, 0
+.Bc
.It Fl -root Ar CPT_ROOT
Use an alternate root directory
.It Fl h , -help
Show help message
.It Fl v , -version
Print version information
+.It Fl -verbose
+Be more verbose
.El
.Sh AUTHOR
.An Cem Keylan Aq Mt cem@ckyln.com
diff --git a/man/cpt-list.1 b/man/cpt-list.1
index 292ba13..778a57d 100644
--- a/man/cpt-list.1
+++ b/man/cpt-list.1
@@ -5,7 +5,7 @@
.Nd list packages
.Sh SYNOPSIS
.Nm
-.Op Fl c
+.Op Fl cq
.Ar pkg...
.Nm
.Fl C
@@ -20,7 +20,7 @@ list the given packages. If any of the given packages are not installed on the
system,
.Nm
will exit with an error. However,
-.Fl c
+.Fl C
and
.Fl -check
flags can be used in order to change the behaviour of the utility:
@@ -28,6 +28,8 @@ flags can be used in order to change the behaviour of the utility:
.It Fl c , -current
Assumes that the current directory is a package and will use it instead of
arguments.
+.It Fl q , -quiet
+Make the operation quiet, only reporting exit status.
.It Fl C , -check Ar package true_statement false_statement
Checks whether the
.Em package
diff --git a/man/cpt-remove.1 b/man/cpt-remove.1
index f4bb6fb..6ebc415 100644
--- a/man/cpt-remove.1
+++ b/man/cpt-remove.1
@@ -21,12 +21,20 @@ The options are as follows:
Force removal
.It Fl y , -no-prompt
Do not prompt for confirmation
+.It Fl -color Ar CPT_COLOR
+Enable/disable output color
+.Bo
+.Sy auto ,
+always, never, 1, 0
+.Bc
.It Fl -root Ar CPT_ROOT
Use an alternate root directory
.It Fl h , -help
Show help message
.It Fl v , -version
Print version information
+.It Fl -verbose
+Be more verbose
.El
.Sh AUTHOR
.An Cem Keylan Aq Mt cem@ckyln.com
diff --git a/man/cpt-search.1 b/man/cpt-search.1
index 05452bd..6e96954 100644
--- a/man/cpt-search.1
+++ b/man/cpt-search.1
@@ -5,8 +5,15 @@
.Nd search for cpt packages
.Sh SYNOPSIS
.Nm
-.Op Fl dso
-.Op Ar query
+.Op Fl ds
+.Ar package...
+.Nm
+.Fl o
+.Op Fl ds
+.Nm
+.Fl q
+.Op Fl Fds
+.Ar query
.Sh DESCRIPTION
.Nm
can be used to search packages. Glob characters can also be used in the search.
@@ -17,14 +24,50 @@ The options are as follows:
Do not search the installed package database.
.It Fl s , -single
Only show the first instance of a package.
+.It Fl q , -query
+Search packages making use of package descriptions.
+.It Fl F , -fixed
+Run query mode interpreting the given pattern as a fixed string
.It Fl o , -others
Use the current directory as the package and show other instances of that
package.
+.It Fl -color Ar CPT_COLOR
+Enable/disable output color
+.Bo
+.Sy auto ,
+always, never, 1, 0
+.Bc
.It Fl h , -help
Show help message
.It Fl v , -version
Print version information
+.It Fl -verbose
+Be more verbose
.El
+.Pp
+The program has three modes of operations. The default operation is to search
+for the packages given as positional arguments.
+.Pp
+If the
+.Fl o
+flag is specified,
+.Nm
+will use the name of the current directory to search for instances of other
+packages with the same name.
+.Pp
+If the
+.Fl q
+flag is specified,
+.Nm
+will search through the name and description of packages using the given
+.Ar query ,
+and run a case-insensitive search through
+.Xr grep 1 .
+If additionally the
+.Fl F
+flag is given, the given
+.Ar query
+will be considered a fixed string.
.Sh EXAMPLES
Below are usage examples for
.Nm ,
diff --git a/man/cpt-update.1 b/man/cpt-update.1
index 3af1205..bc63ea7 100644
--- a/man/cpt-update.1
+++ b/man/cpt-update.1
@@ -30,6 +30,8 @@ Use an alternate root directory
Show help message
.It Fl v , -version
Print version information
+.It Fl -verbose
+Be more verbose
.El
.Sh AUTHOR
.An Cem Keylan Aq Mt cem@ckyln.com
diff --git a/man/cpt.1 b/man/cpt.1
index 54d0e0d..b9eece1 100644
--- a/man/cpt.1
+++ b/man/cpt.1
@@ -21,7 +21,7 @@ program or through the web from
.Lk https://carbslinux.org/docs.html .
It can also be read plaintext by running
.Pp
-.Dl less Pa /usr/share/doc/cpt.txt
+.Dl less Pa /usr/share/doc/cpt/cpt.txt
.Sh AUTHOR
.An Cem Keylan Aq Mt cem@ckyln.com
.Sh LICENSE
diff --git a/spec/01_lib_spec.sh b/spec/01_lib_spec.sh
index 581ba70..b7d83f3 100644
--- a/spec/01_lib_spec.sh
+++ b/spec/01_lib_spec.sh
@@ -1,4 +1,5 @@
# shellcheck disable=2091,2034
+CPT_VERBOSE=1
Describe 'CPT Library'
export CPT_COLOR=0
@@ -13,7 +14,7 @@ Describe 'CPT Library'
VERSION=$(sed -n '/VERSION/s/.* //gp' config.mk)
It 'prints version information'
When run script src/cpt-lib version
- The stderr should eq "-> Carbs Packaging Tools $VERSION"
+ The line 1 of stdout should eq "Carbs Packaging Tools, version $VERSION"
End
End
Describe 'text functions'
@@ -111,16 +112,16 @@ Describe 'CPT Library'
Describe '_readlinkf()'
mklink() { :> tests/testfile; ln -s testfile tests/testfile2 ;}
- rmlink() { rm -f tests/testfile tests/testfile2 ;}
+ rmlink() { rm tests/testfile tests/testfile2 ;}
RPWD=$(cd -P .||:; printf %s "$PWD")
- Before mklink
- After rmlink
+ BeforeEach mklink
+ AfterEach rmlink
Parameters
"#1" . "$RPWD"
- "#2" "$PWD/tests/testfile2" "$RPWD/tests/testfile"
+ "#2" "./tests/testfile2" "$RPWD/tests/testfile"
End
- It "outputs the real location of the given file ($1)"
- When call _readlinkf "$2"
+ It "outputs the real location of the given file [$1] ($2 -> $3)"
+ When run _readlinkf "$2"
The output should eq "$3"
End
End
@@ -150,6 +151,53 @@ Describe 'CPT Library'
End
End
+ Describe 'version control functions'
+ check_internet_connection() { ! curl -L git.carbslinux.org >/dev/null 2>&1 ;}
+ Skip if "no internet connection" check_internet_connection
+ Describe 'pkg_vcs_clone_git()'
+ tmpfos=$$
+ setup() { mkdir "/tmp/test_repository.$tmpfos" && cd "/tmp/test_repository.$tmpfos" || return ;}
+ cleanup() { cd /tmp && rm -rf "test_repository.$tmpfos" ;}
+ check_version() { [ "$1" = "$(sed -n '/^version=/s/.*=//p' configure)" ] ;}
+ BeforeEach setup
+ AfterEach cleanup
+ It "clones the given git repository to the current directory"
+ When call pkg_vcs_clone_git https://git.carbslinux.org/cpt
+ The output should not eq ""
+ The stderr should not eq ""
+ The status should be success
+ Assert [ ! -d test_repository ]
+ Assert [ -f README.md ]
+ Assert check_version Fossil
+ End
+ It "clones the given tag when asked for it"
+ When call pkg_vcs_clone_git https://git.carbslinux.org/cpt @6.2.4
+ The output should not eq ""
+ The stderr should not eq ""
+ The status should be success
+ Assert [ ! -d test_repository ]
+ Assert [ -f README.md ]
+ Assert check_version 6.2.4
+ End
+ End
+ Describe 'pkg_vcs_clone_fossil()'
+ tmpfos=$$
+ setup() { mkdir "/tmp/test_repository.$tmpfos" && cd "/tmp/test_repository.$tmpfos" || return ;}
+ cleanup() { cd /tmp && rm -rf "test_repository.$tmpfos" ;}
+ check_version() { [ "$1" = "$(sed -n '/^version=/s/.*=//p' configure)" ] ;}
+ BeforeEach setup
+ AfterEach cleanup
+ It "clones the given fossil repository to the current directory"
+ When call pkg_vcs_clone_fossil https://fossil.carbslinux.org/cpt
+ The output should not eq ""
+ The stderr should eq ""
+ The status should be success
+ Assert [ ! -d test_repository ]
+ Assert [ -f README.md ]
+ Assert check_version Fossil
+ End
+ End
+ End
Describe 'package functions'
Describe 'run_hook()'
CPT_HOOK=$PWD/tests/hook-file
@@ -161,15 +209,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 ""
+ 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
@@ -177,33 +219,42 @@ 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_cache()'
+ Describe 'create_tmp()'
After pkg_clean
It 'creates cache directories'
- When call create_cache
+ When call create_tmp
The variable mak_dir should be a directory
End
- It "doesn't create build directories if an argument is passed"
- When call create_cache nobuild
- The variable mak_dir should be undefined
- End
End
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 4685ec1..2c20849 100644
--- a/spec/02_src_spec.sh
+++ b/spec/02_src_spec.sh
@@ -1,7 +1,8 @@
Describe 'Main toolchain'
- export PATH=$PWD/src:$PATH
- export CPT_ROOT=$PWD/tests/02
- export CPT_PATH=$PWD/tests/repository
+ PATH=$PWD/src:$PATH
+ CPT_ROOT=$PWD/tests/02
+ CPT_PATH=$PWD/tests/repository
+ export PATH CPT_ROOT CPT_PATH
install_dummy() { CPT_HOOK='' ./src/cpt bi dummy-pkg >/dev/null 2>&1 ;}
remove_dummy() { rm -rf "${CPT_ROOT:?}/var" ;}
BeforeAll install_dummy
@@ -13,14 +14,14 @@ Describe 'Main toolchain'
VERSION=$(sed -n '/VERSION/s/.* //gp' config.mk)
It 'outputs cpt version'
When run script src/cpt --version
- The stderr should eq "-> Carbs Packaging Tools $VERSION"
+ The line 1 of stdout should eq "Carbs Packaging Tools, version $VERSION"
End
End
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
@@ -52,7 +53,7 @@ Describe 'Main toolchain'
It "expands the '$1' shortcut to '$2'"
When run script src/cpt "$1" --help
The status should be success
- The word 2 of line 1 should eq "cpt-${2%% *}"
+ The word 3 of line 1 should eq "$1"
End
End
End
diff --git a/spec/03_contrib_spec.sh b/spec/03_contrib_spec.sh
index 9c7589b..b3d6df4 100644
--- a/spec/03_contrib_spec.sh
+++ b/spec/03_contrib_spec.sh
@@ -1,8 +1,9 @@
Describe 'contrib scripts'
- export PATH=$PWD/src:$PWD/contrib:$PATH
- export CPT_ROOT=$PWD/tests/03
- export CPT_PATH=$PWD/tests/repository
- export CPT_COMPRESS=''
+ PATH=$PWD/src:$PWD/contrib:$PATH
+ CPT_ROOT=$PWD/tests/03
+ CPT_PATH=$PWD/tests/repository
+ CPT_COMPRESS=''
+ export PATH CPT_ROOT CPT_PATH CPT_COMPRESS
install_tmp() {
CPT_HOOK='' ./src/cpt b -y contrib-dummy-pkg >/dev/null 2>&1
CPT_HOOK='' ./src/cpt-install -y contrib-dummy-pkg >/dev/null 2>&1
@@ -17,13 +18,13 @@ Describe 'contrib scripts'
It 'outputs the file contents in the given package directory'
When run script ./contrib/cpt-cat "$firstpkg"
The stdout should not eq ""
- The line 1 of stderr should eq "$(printf '\033[1mbuild:\033[m\n')"
+ The line 1 of stderr should eq "build:"
End
It "uses the current directory for the package name if none is supplied (contrib-dummy-pkg)"
cd "$CPT_PATH/contrib-dummy-pkg" || return 1
When run script "$(command -v cpt-cat)"
The stdout should not eq ""
- The line 1 of stderr should eq "$(printf '\033[1mbuild:\033[m\n')"
+ The line 1 of stderr should eq "build:"
End
It "exits with error if the package isn't installed"
When run script ./contrib/cpt-cat somerandompackage
@@ -44,13 +45,13 @@ Describe 'contrib scripts'
It "outputs the given file contents in the given package directory ($1)"
When run script ./contrib/cpt-cat "$firstpkg" "$1"
The stdout should eq "$(cat "$CPT_ROOT/var/db/cpt/installed/$firstpkg/$1")"
- The stderr should eq "$(printf '\033[1m%s:\033[m\n' "$1")"
+ The stderr should eq "$1:"
End
It "outputs the given file contents for the name of the current directory (contrib-dummy-pkg - $1)"
cd "$CPT_PATH/contrib-dummy-pkg" || return 1
When run script "$(command -v cpt-cat)" "" "$1"
The stdout should eq "$(cat "$CPT_ROOT/var/db/cpt/installed/${PWD##*/}/$1")"
- The stderr should eq "$(printf '\033[1m%s:\033[m\n' "$1")"
+ The stderr should eq "$1:"
End
End
Describe 'cpt-depends'
@@ -94,6 +95,7 @@ Describe 'contrib scripts'
export CPT_COMPRESS=typo
When run script "$(command -v cpt-export)" contrib-dummy-pkg
The stdout should eq "tarball created in $CPT_ROOT/tmp/contrib-dummy-pkg#1-1.tar.gz"
+ The stderr should eq "WARNING 'typo' is not a valid CPT_COMPRESS value, falling back to 'gz' "
End
Parameters
bz2 bzip2
diff --git a/src/cpt b/src/cpt
index 4ddb4df..7905d9c 100755
--- a/src/cpt
+++ b/src/cpt
@@ -1,5 +1,52 @@
#!/bin/sh -ef
+bi() {
+ # Build and install function for cpt.
+ #
+ # shellcheck disable=2317
+ parser_definition() {
+ setup REST help:usage -- "usage: ${0##*/} bi [-dfSty] [--root ROOT] [pkg...]"
+ msg -- '' 'Options:'
+ flag CPT_TEST -t --test export:1 init:@export -- "Run tests (if they exist)"
+ flag CPT_DEBUG -d --debug export:1 init:@export -- "Keep the build directories after operation"
+ flag CPT_NOSTRIP -S --nostrip export:1 init:@export -- "Don't strip debug information from the binaries" \
+ "(might want to add '-g' to your '\$CFLAGS')"
+ global_options
+ }
+
+ eval "$(getoptions parser_definition parse "$0")"
+ parse "$@"
+ eval set -- "$REST"
+ cpt-build "$@"
+
+ # When building multiple packages, cpt will already ask to install
+ # the packages, so no need for this here.
+ [ "$2" ] || cpt-install "$@"
+}
+
+cbi() {
+ # Checksum, build and install.
+ #
+ # shellcheck disable=2317
+ parser_definition() {
+ setup REST help:usage -- "usage: ${0##*/} cbi [-dfSsty] [--root ROOT] [pkg...]"
+ msg -- '' 'Options:'
+ flag CPT_TEST -t --test export:1 init:@export -- "Run tests (if they exist)"
+ flag CPT_DEBUG -d --debug export:1 init:@export -- "Keep the build directories after operation"
+ flag CPT_NOSTRIP -S --nostrip export:1 init:@export -- "Don't strip debug information from the binaries" \
+ "(might want to add '-g' to your '\$CFLAGS')"
+ flag sha -s -- "Generate checksums using the depracated sha256 algorithm"
+ global_options
+ }
+
+ eval "$(getoptions parser_definition parse "$0")"
+ parse "$@"
+ eval set -- "$REST"
+
+ cpt-checksum "$@"; cpt-build "$@"
+ [ "$2" ] || cpt-install "$@"
+}
+
if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
# If none of the tools below are specified, we will reenable glob
@@ -11,7 +58,7 @@ case "$arg" in
log "Carbs Packaging Tool"
set --
for path in $(SEARCH_PATH=$PATH pkg_find cpt-* all -x); do
- set -- "${path#*/cpt-}" "$@"
+ set -- "${path##*/cpt-}" "$@"
max=$((${#1} > max ? ${#1} : max))
done
@@ -35,21 +82,7 @@ case "$arg" in
r|remove) arg=remove ;;
s|search) arg=search ;;
u|update) arg=update ;;
- bi)
- # Build and install function for cpt.
- cpt-build "$@"
-
- # When building multiple packages, cpt will already ask to install
- # the packages, so no need for this here.
- [ "$2" ] || cpt-install "$@"
- exit
- ;;
- cbi)
- # Checksum, build and install.
- cpt-checksum "$@"; cpt-build "$@"
- [ "$2" ] || cpt-install "$@"
- exit
- ;;
+ bi|cbi) "$arg" "$@"; exit "$?" ;;
*) glob=1 ;;
esac
diff --git a/src/cpt-alternatives b/src/cpt-alternatives
index c4c7726..87946f0 100755
--- a/src/cpt-alternatives
+++ b/src/cpt-alternatives
@@ -2,7 +2,11 @@
# List and swap to alternatives
parser_definition() {
- setup REST help:usage -- "usage: ${0##*/} [-] [package file]"
+ 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
}
@@ -10,23 +14,71 @@ 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-build b/src/cpt-build
index cb93949..eaf8849 100755
--- a/src/cpt-build
+++ b/src/cpt-build
@@ -2,15 +2,18 @@
# Build a package
parser_definition() {
- setup REST help:usage -- "usage: ${0##*/} [pkg...]"
+ setup REST help:usage -- "usage: ${0##*/} [-dfSty] [--root ROOT] [pkg...]"
msg -- '' 'Options:'
- flag CPT_TEST -t --test export:1 init:@export -- "Run tests (if they exist)"
+ flag CPT_DEBUG -d --debug export:1 init:@export -- "Keep the build directories after operation"
+ flag CPT_TEST -t --test export:1 init:@export -- "Run tests (if they exist)"
+ flag CPT_NOSTRIP -S --nostrip export:1 init:@export -- "Don't strip debug information from the binaries" \
+ "(might want to add '-g' to your '\$CFLAGS')"
global_options
}
if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
-[ "$1" ] || { set -- "${PWD##*/}"; export CPT_PATH=${PWD%/*}:$CPT_PATH ;}
+[ "$1" ] || { set -- "${PWD##*/}"; export CPT_PATH="${PWD%/*}:$CPT_PATH" ;}
create_cache
diff --git a/src/cpt-checksum b/src/cpt-checksum
index 5c6de52..488ab87 100755
--- a/src/cpt-checksum
+++ b/src/cpt-checksum
@@ -1,22 +1,32 @@
#!/bin/sh -ef
# Generate checksums
-if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
+parser_definition() {
+ setup REST help:usage -- "usage: ${0##*/} [-s] [pkg...]"
+ msg -- '' 'Options:'
+ flag sha -s -- "Generate checksums using the depracated sha256 algorithm"
+ global_options
+}
-case "$1" in
- --help|-h) out "usage: ${0##*/} [pkg...]"; exit 0 ;;
- --version|-v) version ;;
- '') set -- "${PWD##*/}"; export CPT_PATH=${PWD%/*}:$CPT_PATH ;;
-esac
+if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
+[ "$1" ] || { set -- "${PWD##*/}"; CPT_PATH=${PWD%/*}:$CPT_PATH ;}
create_cache
for pkg; do pkg_lint "$pkg" c; done
for pkg; do pkg_sources "$pkg" c; done
-
for pkg; do
- pkg_checksums "$pkg" | {
- repo_dir=$(pkg_find "$pkg")
+ # Do not generate checksums if the 'sources' file is empty or it doesn't
+ # exist.
+ repo_dir=$(pkg_find "$pkg")
+ [ -s "$repo_dir/sources" ] || {
+ log "$pkg" "No 'sources' file, skipping checksums"
+ continue
+ }
+
+ # $sha is defined by the parser.
+ # shellcheck disable=2154
+ pkg_checksums "$pkg" "${sha:+sh256}" | {
if [ -w "$repo_dir" ]; then
tee "$repo_dir/checksums"
diff --git a/src/cpt-download b/src/cpt-download
index d2c9aeb..231e4bb 100755
--- a/src/cpt-download
+++ b/src/cpt-download
@@ -9,7 +9,7 @@ case "$1" in
exit 0
;;
--version|-v) version ;;
- '') set -- "${PWD##*/}"; export CPT_PATH=${PWD%/*}:$CPT_PATH
+ '') set -- "${PWD##*/}"; export CPT_PATH="${PWD%/*}:$CPT_PATH"
esac
create_cache
diff --git a/src/cpt-install b/src/cpt-install
index aab70ea..8bafba6 100755
--- a/src/cpt-install
+++ b/src/cpt-install
@@ -10,7 +10,7 @@ parser_definition() {
if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
-[ "$1" ] || { set -- "${PWD##*/}"; export CPT_PATH=${PWD%/*}:$CPT_PATH ;}
+[ "$1" ] || { set -- "${PWD##*/}"; export CPT_PATH="${PWD%/*}:$CPT_PATH" ;}
[ -w "$CPT_ROOT/" ] || [ "$uid" = 0 ] || {
as_root "$0" "$@"
@@ -18,7 +18,6 @@ if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
}
pkg_order "$@"
-
create_cache
# shellcheck disable=2154
@@ -28,14 +27,21 @@ 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%#*}
+
[ -f "$sys_db/$pkg/message" ] && {
- printf '%s\n%s\n%s\n\n' \
- "=======================================" \
+ printf '\033[1m%s\n%s\n%s\033[m\n\n' \
+ "$(_multiply_char '=' 60)" \
"$pkg" \
- "======================================="
- cat "$sys_db/$pkg/message" >&2
+ "$(_multiply_char '=' 60)"
+ cat "$sys_db/$pkg/message"
msg=1
}
-done
+done >&2
[ "$msg" ] || log "No message in queue"
diff --git a/src/cpt-lib.in b/src/cpt-lib.in
index bf58fbe..1896920 100644
--- a/src/cpt-lib.in
+++ b/src/cpt-lib.in
@@ -9,7 +9,9 @@
# Currently maintained by Cem Keylan.
version() {
- log "Carbs Packaging Tools" @VERSION@
+ out "Carbs Packaging Tools, version $cpt_version" \
+ @LICENSE@
+
exit 0
}
@@ -23,11 +25,40 @@ 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() {
+ # Print a warning message
+ log "$1" "$2" "${3:-WARNING}"
+}
+
+outv() {
+ # Call `out()` when CPT_VERBOSE is set.
+ [ "$CPT_VERBOSE" = 1 ] || return 0
+ out "$@"
+}
+
+logv() {
+ # Call `log()` when CPT_VERBOSE is set.
+ [ "$CPT_VERBOSE" = 1 ] || return 0
+ log "$@"
+}
+
+warnv() {
+ # Call `warn()` when CPT_VERBOSE is set.
+ [ "$CPT_VERBOSE" = 1 ] || return 0
+ warn "$@"
+}
+
+execv() {
+ # Redirect the output to /dev/null unless CPT_VERBOSE is set.
+ if [ "$CPT_VERBOSE" = 1 ]; then "$@"; else "$@" >/dev/null 2>&1; fi
}
die() {
@@ -36,6 +67,124 @@ die() {
exit 1
}
+colors_enabled() {
+ case ${CPT_COLOR:=auto} in
+ auto) [ -t 1 ] ;;
+ 1|always) return 0 ;;
+ 0|never) return 1 ;;
+ *) die "Unknown color value: '$CPT_COLOR'"
+ 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.
+ #
+ # The script below was taken from <https://gist.github.com/apainintheneck/1803fb91dde3ba048ec51d44fa6065a4>
+ #
+ # The MIT License (MIT)
+ # Copyright (c) 2023 Kevin Robell
+ #
+ # Permission is hereby granted, free of charge, to any person obtaining a
+ # copy of this software and associated documentation files (the “Software”),
+ # to deal in the Software without restriction, including without limitation
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ # and/or sell copies of the Software, and to permit persons to whom the
+ # Software is furnished to do so, subject to the following conditions:
+ #
+ # The above copyright notice and this permission notice shall be included in
+ # all copies or substantial portions of the Software.
+ #
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ # DEALINGS IN THE SOFTWARE.
+ awk '{
+ for (i = 1; i <= NF; ++i) {
+ # Store each node.
+ nodes[$i] = 1
+ if (is_child) {
+ child = $i
+ # Skip nodes that point to themselves.
+ # This traditionally means that the node
+ # is disconnected from the rest of the graph.
+ if (parent != child) {
+ # Store from parent to child.
+ idx = ++child_count[parent]
+ child_graph[parent, idx] = child
+ # Store count from child to parent.
+ ++parent_count[child]
+ }
+ } else {
+ parent = $i
+ }
+ # Flip switch
+ is_child = !is_child
+ }
+ }
+ END {
+ # Print errors to the stderr
+ stderr = "/dev/stderr"
+
+ # Sanity Check
+ if (is_child) {
+ print("Error: odd number of input values: expected pairs of values") > stderr
+ exit(1)
+ }
+
+ #####
+ # Topological Sort
+ #####
+
+ # Remove unconnected nodes first.
+ for (node in nodes) {
+ if (parent_count[node] == 0 && child_count[node] == 0) {
+ delete nodes[node]
+ print(node)
+ }
+ }
+
+ # Remove the rest of the nodes starting with those without parents.
+ while (length(nodes) > 0) {
+ removed_node = 0
+ for (node in nodes) {
+ # Delete and print nodes without any remaining parents.
+ if (parent_count[node] == 0) {
+ delete nodes[node]
+ removed_node = 1
+ # Decrease child_count for each parent node.
+ for (i = child_count[node]; i > 0; --i) {
+ child = child_graph[node, i]
+ --parent_count[child]
+ }
+ print(node)
+ }
+ }
+
+ # If we havent removed any nodes, it means that there
+ # are no nodes without any remaining parents so we have
+ # a cycle.
+ if (!removed_node) {
+ print("Error: Cycle found") > stderr
+ exit(1)
+ }
+ }
+ }'
+}
+
trap_set() {
# Function to set the trap value.
case ${1:-cleanup} in
@@ -43,25 +192,30 @@ trap_set() {
trap pkg_clean EXIT
trap 'pkg_clean; exit 1' INT
;;
- block) trap '' INT ;;
- unset) trap - EXIT INT ;;
+ handle-int)
+ trap pkg_clean INT
+ ;;
+ block) trap '' INT ;;
+ unset) trap - EXIT INT ;;
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
+ # of $1.
+ printf %s "${2:?}" | grep -Eq "$1"
+}
_seq() (
# Pure shell counter meant to be used in 'for' loops.
@@ -72,13 +226,21 @@ _seq() (
printf '%s' "$buf"
)
+_multiply_char() (
+ buf=
+ for i in $(_seq "$2"); do
+ buf="$buf$1"
+ done
+ out "$buf"
+)
+
_stat() (
_user=; eval set -- "$(ls -ld "$1")"
id -u "${_user:=$3}" >/dev/null 2>&1 || _user=root
printf '%s' "$_user"
)
-_readlinkf() (
+_readlinkf() {
# Public domain POSIX sh readlink function by Koichi Nakashima
[ "${1:-}" ] || return 1
max_symlinks=40
@@ -112,13 +274,29 @@ _readlinkf() (
target=${link#*" $target -> "}
done
return 1
-)
+}
+
+_get_digest() {
+ # Get digest algorithm from the given file. It looks for a header on the
+ # file declaring the digest algorithm. Currently only BLAKE3 is supported.
+ # If the file does not include a header, the function will assume that it is
+ # using sha256 as a digest algorithm. If the given file doesn't exist it will
+ # return 1.
+ [ -r "$1" ] || return 1
+ read -r chk < "$1"
+ case $chk in
+ %BLAKE3) chk=b3sum ;;
+ %*) die "Unknown digest algorithm: '${chk#\%}'" ;;
+ *) chk=sh256
+ esac
+ out "$chk"
+}
# This is the public domain getoptions shell library. It also forms a usage
# function.
# URL: https://github.com/ko1nksm/getoptions (v2.5.0)
# License: Creative Commons Zero v1.0 Universal
-# shellcheck disable=2016,2086
+# shellcheck disable=2016,2086,2317
getoptions() {
_error='' _on=1 _off='' _export='' _plus='' _mode='' _alt='' _rest=''
_flags='' _nflags='' _opts='' _help='' _abbr='' _cmds='' _init=@empty IFS=' '
@@ -313,6 +491,7 @@ getoptions() {
}
# URL: https://github.com/ko1nksm/getoptions (v2.5.0)
# License: Creative Commons Zero v1.0 Universal
+# shellcheck disable=2317
getoptions_help() {
_width='30,12' _plus='' _leading=' '
@@ -357,18 +536,34 @@ getoptions_help() {
echo "}"
}
+# 2086:
+# The lack of quotes are intentional. We do this so `getoptions()` do not try
+# to parse the empty string.
+# 2120:
+# The library does not call this function with any positional arguments, but
+# that does not mean that other programs will not do it, so this can also be
+# safely ignored.
+# shellcheck disable=2086,2120
global_options() {
- msg -- '' 'Global Options:'
- flag CPT_FORCE -f --force init:@export -- "Force operation"
- flag CPT_PROMPT -y --no-prompt on:0 off:0 init:@export -- "Do not prompt for confirmation"
- param CPT_ROOT --root init:@export -- "Use an alternate root directory"
- disp :usage -h --help -- "Show this help message"
- disp :version -v --version -- "Print version information"
-}
-
-warn() {
- # Print a warning message
- log "$1" "$2" "${3:-WARNING}"
+ # These are options that are supported by most utilities. If the optional
+ # argument 'silent' is given, the usage will not print these options, but
+ # the arguments will still be accepted. Alternatively, if the 'compact'
+ # argument is given, the function only prints the '--help' and '--version'
+ # flags. Sometimes it doesn't make sense to pollute the screen with options
+ # that will be rarely ever used.
+ _h=hidden:1
+ case $1 in
+ silent) _c=$_h ;;
+ compact) _c='' ;;
+ *) msg -- '' 'Global Options:'; _c='' _h=''
+ esac
+ flag CPT_FORCE -f --force $_h init:@export -- "Force operation"
+ flag CPT_PROMPT -y --no-prompt on:0 off:0 $_h init:@export -- "Do not prompt for confirmation"
+ param CPT_ROOT --root $_h init:@export -- "Use an alternate root directory"
+ param CPT_COLOR --color $_h init:@export -- "Colorize the output [default:auto]"
+ disp :usage -h --help $_c -- "Show this help message"
+ disp :version -v --version $_c -- "Print version information"
+ flag CPT_VERBOSE --verbose $_h init:@export -- "Be more verbose"
}
contains() {
@@ -383,6 +578,22 @@ regesc() {
sed 's|\\|\\\\|g;s|\[|\\[|g;s|\$|\\$|g;s|\.|\\.|g;s|\*|\\*|g;s|\^|\\^|g'
}
+pkg_download() {
+ # $1: URL
+ # $2: Output (Optional)
+ set -- "$1" "$(_readlinkf "${2:-${1##*/}}")"
+ case ${dl_prog##*/} in
+ axel) set -- -o "$2" "$1" ;;
+ aria2c) set -- -d "${2%/*}" -o "${2##*/}" "$1" ;;
+ curl) set -- -fLo "$2" "$1" ;;
+ wget|wget2) set -- -O "$2" "$1" ;;
+ esac
+
+ "$dl_prog" "$@" || {
+ rm -f "$2"
+ return 1
+ }
+}
prompt() {
# If a CPT_NOPROMPT variable is set, continue.
@@ -407,6 +618,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" \
@@ -421,8 +635,10 @@ as_root() {
CPT_PATH="$CPT_PATH" \
CPT_PID="$CPT_PID" \
CPT_PROMPT="$CPT_PROMPT" \
+ CPT_REPO_CACHE="$CPT_REPO_CACHE" \
CPT_ROOT="$CPT_ROOT" \
CPT_TMPDIR="$CPT_TMPDIR" \
+ CPT_VERBOSE="$CPT_VERBOSE" \
"$@"
case ${su##*/} in
@@ -446,29 +662,48 @@ 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 ;}
+ # 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
- [ "$2" ] && log "$2" "Running $1 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
+}
- TYPE=${1:-null} PKG=${2:-null} DEST=${3:-null} . "$CPT_HOOK"
- CPT_HOOK=$oldCPT_HOOK
+# An optional argument could be provided to enforce a compression algorithm.
+# shellcheck disable=2120
+compress() {
+ case ${1:-$CPT_COMPRESS} in
+ bz2) bzip2 -z ;;
+ gz) gzip -6 ;;
+ xz) xz -zT 0 ;;
+ zst) zstd -3 ;;
+ lz) lzip -6 ;;
+ esac
}
decompress() {
case $1 in
- *.tar) cat ;;
- *.bz2) bzip2 -cd ;;
- *.lz) lzip -cd ;;
- *.xz|*.txz) xz -dcT 0 ;;
- *.tgz|*.gz) gzip -cd ;;
- *.zst) zstd -cd ;;
+ *.tar|*.cpio) cat ;;
+ *.bz2) bzip2 -cd ;;
+ *.lz) lzip -cd ;;
+ *.xz|*.txz) xz -dcT 0 ;;
+ *.tgz|*.gz) gzip -cd ;;
+ *.zst) zstd -cd ;;
esac < "$1"
}
@@ -486,69 +721,6 @@ sh256() {
while read -r hash _; do printf '%s %s\n' "$hash" "$1"; done
}
-tar_extract() {
- # Tarball extraction function that prefers pax(1) over tar(1). The reason we
- # are preferring pax is that we can strip components without relying on
- # ugly hacks such as the ones we are doing for 'tar'. Using 'tar' means that
- # we either have to sacrifice speed or portability, and we are choosing to
- # sacrifice speed. Fortunately, we don't have to make such a choice when
- # using pax.
- case "${extract##*/}" in
- pax) decompress "$1" | pax -r -s '/[^\/]*/./' ;;
- gtar|bsdtar) decompress "$1" | "$tar" xf - --strip-components 1 ;;
- tar) decompress "$1" > .ktar
-
- "$tar" xf .ktar || return
-
- # We now list the contents of the tarball so we can do our
- # version of 'strip-components'.
- "$tar" tf .ktar |
- while read -r file; do printf '%s\n' "${file%%/*}"; done |
-
- # Do not repeat files.
- uniq |
-
- # For every directory in the base we move each file
- # inside it to the upper directory.
- while read -r dir ; do
-
- # Skip if we are not dealing with a directory here.
- # This way we don't remove files on the upper directory
- # if a tar archive doesn't need directory stripping.
- [ -d "${dir#.}" ] || continue
-
- # Change into the directory in a subshell so we don't
- # need to cd back to the upper directory.
- (
- cd "$dir"
-
- # We use find because we want to move hidden files
- # as well.
- #
- # Skip the file if it has the same name as the directory.
- # We will deal with it later.
- #
- # Word splitting is intentional here.
- # shellcheck disable=2046
- find . \( ! -name . -prune \) ! -name "$dir" \
- -exec mv -f {} .. \;
-
- # If a file/directory with the same name as the directory
- # exists, append a '.cptbak' to it and move it to the
- # upper directory.
- ! [ -e "$dir" ] || mv "$dir" "../${dir}.cptbak"
- )
- rmdir "$dir"
-
- # If a backup file exists, move it into the original location.
- ! [ -e "${dir}.cptbak" ] || mv "${dir}.cptbak" "$dir"
- done
-
- # Clean up the temporary tarball.
- rm -f .ktar
- esac
-}
-
pkg_owner() {
set +f
@@ -562,6 +734,18 @@ pkg_owner() {
[ "$1" ] && printf '%s\n' "$1"
}
+pkg_owner_multi() {
+ set +f
+
+ [ "$3" ] || set -- "$1" "$2" "$sys_db"/*/manifest
+
+ grep "$@" | while read -r pkg_owner; do
+ pkg_owner=${pkg_owner%/*}
+ pkg_owner=${pkg_owner##*/}
+ printf '%s\n' "${pkg_owner##*/}"
+ done
+}
+
pkg_isbuilt() (
# Check if a package is built or not.
read -r ver rel < "$(pkg_find "$1")/version"
@@ -580,14 +764,20 @@ pkg_lint() {
repo_dir=$(pkg_find "$1")
cd "$repo_dir" || die "'$repo_dir' not accessible"
- [ -f sources ] || warn "$1" "Sources file not found"
+ [ -f sources ] || warnv "$1" "Sources file not found"
[ -x build ] || die "$1" "Build file not found or not executable"
[ -s version ] || die "$1" "Version file not found or empty"
read -r _ release 2>/dev/null < version || die "Version file not found"
[ "$release" ] || die "Release field not found in version file"
- [ "$2" ] || [ -f checksums ] || die "$pkg" "Checksums are missing"
+ # If we have a second argument, we are generating the checksums file,
+ # so we don't need to check whether there is one.
+ [ -z "$2" ] || return 0
+
+ # Check for a checksums file only if there is a sources file.
+ [ -f sources ] || return 0
+ [ -f checksums ] || die "$pkg" "Checksums are missing"
}
pkg_find() {
@@ -688,12 +878,8 @@ pkg_sources() {
repo_dir=$(pkg_find "$1")
while read -r src dest || [ "$src" ]; do
- # Remote git/hg repository or comment.
- if [ -z "${src##\#*}" ] ||
- [ -z "${src##git+*}" ] ||
- [ -z "${src##hg+*}" ]
-
- then :
+ # Remote repository or comment.
+ if _re "$re_vcs_or_com" "$src"; then :
# Remote source (cached).
elif [ -f "${src##*/}" ]; then
@@ -703,10 +889,15 @@ pkg_sources() {
elif [ -z "${src##*://*}" ]; then
log "$1" "Downloading $src"
- curl "$src" -fLo "${src##*/}" || {
- rm -f "${src##*/}"
- die "$1" "Failed to download $src"
- }
+ # We don't want our trap to exit immediately here if we receive an
+ # interrupt, we handle this ourselves.
+ trap_set handle-int
+
+ # Download the source
+ pkg_download "$src" || die "$1" "Failed to download $src"
+
+ # Restore original trap value.
+ trap_set cleanup
# Local source.
elif [ -f "$repo_dir/$src" ]; then
@@ -732,32 +923,17 @@ pkg_extract() {
mkdir -p "$mak_dir/$1/$dest" && cd "$mak_dir/$1/$dest"
case $src in
- # Git repository.
- git+*)
- # Split the source into URL + OBJECT (branch or commit).
- url=${src##git+} com=${url##*[@#]} com=${com#${url%[@#]*}}
-
- log "$1" "Cloning ${url%[@#]*}"; {
- git init
- git remote add origin "${url%[@#]*}"
- case "$url" in
- # Tags are specified via '@'
- *@*) git fetch -t --depth=1 origin "$com" || git fetch ;;
- *) git fetch --depth=1 origin "$com" || git fetch
- esac
- git checkout "${com:-FETCH_HEAD}"
- } || die "$1" "Failed to clone $src"
- ;;
- # Mercurial repository.
- hg+*)
- # Split the source into URL + OBJECT (branch or commit).
- url=${src##hg+} com=${url##*[@#]} com=${com#${url%[@#]*}}
+ # VCS Repository
+ git+*|hg+*|fossil+*)
+ backend=${src%%+*}
+ url=${src##"${backend}"+} com=${url##*[@#]} com=${com#"${url%[@#]*}"}
- # Unfortunately, there is no shallow cloning with Mercurial.
- log "$1" "Cloning ${url%[@#]*}"
- hg clone -u "${com:-tip}"
+ # Add back @ to com
+ case $url in *@*) com=@$com; esac
+ log "$1" "Cloning ${url%[#@]*}"
+ "pkg_vcs_clone_$backend" "${url%[#@]*}" "$com"
;;
# Comment or blank line.
@@ -766,11 +942,9 @@ pkg_extract() {
# Only 'tar', 'cpio', and 'zip' archives are currently supported for
# extraction. Other filetypes are simply copied to '$mak_dir'
# which allows for manual extraction.
- *://*.tar|*://*.tar.??|*://*.tar.???|*://*.tar.????|*://*.tgz|*://*.txz)
- tar_extract "$src_dir/$1/${src##*/}" ;;
-
- *://*.cpio|*://*.cpio.??|*://*.cpio.???|*://*.cpio.????)
- decompress "$src_dir/$1/${src##*/}" | pax -r ;;
+ *://*.tar|*://*.tar.??|*://*.tar.???|*://*.tar.????|*://*.tgz|\
+ *://*.txz|*://*.cpio|*://*.cpio.??|*://*.cpio.???|*://*.cpio.????)
+ decompress "$src_dir/$1/${src##*/}" | pax -rs '|[^/]*|.|' ;;
*://*.zip)
unzip "$src_dir/$1/${src##*/}" ||
@@ -799,12 +973,10 @@ 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
-
+ #
+ # shellcheck disable=2015
+ contains "$pkgs" "$1" && [ -z "$2" ] || {
+ [ "$2" = raw ] && _dep_append "$1" "$1"
while read -r dep type || [ "$dep" ]; do
# Skip comments and empty lines.
[ "${dep##\#*}" ] || continue
@@ -817,6 +989,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 "$dep" "$1"
+ fi
+
# Recurse through the dependencies of the child packages. Forward
# the 'tree' operation.
if [ "$2" = tree ]; then
@@ -826,12 +1008,15 @@ 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 "
+ pkgs="$pkgs $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
@@ -839,9 +1024,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
@@ -859,7 +1045,7 @@ pkg_strip() {
# system as well as on the tarballs we ship for installation.
# Package has stripping disabled, stop here.
- [ -f "$mak_dir/$pkg/nostrip" ] && return
+ [ "$CPT_NOSTRIP" ] || [ -f "$mak_dir/$pkg/nostrip" ] && return
log "$1" "Stripping binaries and libraries"
@@ -882,21 +1068,31 @@ pkg_strip() {
done 2>/dev/null ||:
}
+pkg_fix_deps_fullpath() {
+ # Return the canonical path of libraries extracted by readelf.
+ while read -r line _ rslv _; do
+ [ "$line" = "$1" ] || continue
+ case $rslv in
+ ldd) out "$line" ;;
+ *) out "$rslv" ;;
+ esac
+ done
+}
+
pkg_fix_deps() {
# Dynamically look for missing runtime dependencies by checking each binary
# and library with either 'ldd' or 'readelf'. This catches any extra
# libraries and or dependencies pulled in by the package's build suite.
- log "$1" "Checking for missing dependencies"
+ log "$1" "Checking for missing dependencies (using ${elf_prog##*/})"
# Go to the directory containing the built package to
# 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
@@ -905,40 +1101,72 @@ pkg_fix_deps() {
pkg_name=$1
set +f; set -f -- "$sys_db/"*/manifest
- # Get a list of binaries and libraries, false files
- # will be found, however it's faster to get 'ldd' to check
- # them anyway than to filter them out.
- find "$pkg_dir/$pkg_name/" -type f 2>/dev/null |
+ # We create two separate files for storing dependency information.
+ #
+ # 'lddfile' is where we will be storing the output of ldd, so that we can
+ # reference it later.
+ #
+ # 'dep_file_list' is where we will be listing the needed files which we will
+ # be passing to grep.
+ #
+ lddfile=$(_tmp_create lddfile) dep_file_list=$(_tmp_create dfl)
+
+ pkg_fix_deps_find() {
+ # We run the similar command twice, might as well be a function.
+ # Basically runs find on the package directory and executes the
+ # given command.
+ end=+; [ "$1" = ldd ] && end=';'
- while read -r file; do
- case ${elf_prog:-ldd} in
- *readelf) "$elf_prog" -d "$file" 2>/dev/null ;;
- *) ldd "$file" 2>/dev/null ;;
- esac |
- while read -r dep; do
- # Skip lines containing 'ldd'.
- [ "${dep##*ldd*}" ] || continue
- case $dep in *NEEDED*\[*\] | *'=>'*) ;; *) continue; esac
-
- # readelf output:
- # 0x0000 (NEEDED) Shared library: [libc.so]
- dep=${dep##*\[}
- dep=${dep%%\]*}
-
- # ldd output:
- # libc.so => /lib/ld-musl-x86_64.so.1
- dep=${dep#* => }
- dep=${dep% *}
-
- # Figure out which package owns the file. Skip file if it is owned
- # by the current package. This also handles cases where a '*-bin'
- # package exists on the system, so the package manager doesn't think
- # that the package we are building depends on the *-bin version of
- # itself, or any other renamed versions of the same software.
- pkg_owner -l "/${dep#/}\$" "$PWD/manifest" >/dev/null && continue
- pkg_owner -l "/${dep#/}\$" "$@" ||:
- done ||:
- done >> depends
+ # Get a list of binaries and libraries, false files will be found,
+ # however it's faster to get 'ldd' to check them anyway than to filter
+ # them out.
+ #
+ # We are terminating exec, so no worries.
+ # shellcheck disable=2067
+ find "$pkg_dir/$pkg_name/" -type f -exec "$@" {} "$end" 2>/dev/null |
+ sed 's/([^)]*) *$//' | sort -u
+ }
+
+ # Record all the dependencies in the 'lddfile'. This will include all
+ # dependencies, including non-direct ones. Unless the user prefers ldd,
+ # readelf will be used to filter the non-direct dependencies out.
+ pkg_fix_deps_find ldd -- > "$lddfile"
+
+ case "$elf_prog" in
+ *readelf) pkg_fix_deps_find "$elf_prog" -d ;;
+ *) cat "$lddfile"
+ esac | while read -r dep; do
+ # Skip lines containing 'ldd'.
+ [ "${dep##*ldd*}" ] || continue
+ case $dep in *NEEDED*\[*\] | *'=>'*) ;; *) continue; esac
+
+ # readelf output:
+ # 0x0000 (NEEDED) Shared library: [libc.so]
+ dep=${dep##*\[}
+ dep=${dep%%\]*}
+
+ # Retrieve the fullpath of the library from our ldd buffer.
+ case $elf_prog in
+ *readelf) dep=$(pkg_fix_deps_fullpath "$dep" < "$lddfile")
+ esac
+
+ # ldd output:
+ # libc.so => /lib/ld-musl-x86_64.so.1
+ dep=${dep#* => }
+ dep=${dep% *}
+
+ # Figure out which package owns the file. Skip file if it is owned
+ # by the current package. This also handles cases where a '*-bin'
+ # package exists on the system, so the package manager doesn't think
+ # that the package we are building depends on the *-bin version of
+ # itself, or any other renamed versions of the same software.
+ pkg_owner -l "/${dep#/}\$" "$PWD/manifest" >/dev/null && continue
+ out "/${dep#/}\$"
+ done >> "$dep_file_list"
+
+ # We write all the files into 'dep_file_list' so that we don't need to call
+ # grep on our entire database manifest hundreds of times.
+ pkg_owner_multi -lf "$dep_file_list" "$@" >> depends
# Remove duplicate entries from the new depends file.
# This removes duplicate lines looking *only* at the
@@ -946,7 +1174,7 @@ pkg_fix_deps() {
sort -uk1,1 -o depends depends 2>/dev/null ||:
# Display a diff of the new dependencies against the old ones.
- diff -U 3 "$dep_file" depends 2>/dev/null ||:
+ execv diff -U 3 "$dep_file" depends 2>/dev/null ||:
# Remove the depends file if it is empty.
[ -s depends ] || rm -f depends
@@ -968,7 +1196,7 @@ pkg_manifest() (
# sed: Remove the first character in each line (./dir -> /dir) and
# remove all lines which only contain '.'.
find . -type d -exec printf '%s/\n' {} + -o -print |
- sort -r | sed '/^\.\/$/d;ss.ss' > "${2:-$pkg_dir}/$1/$pkg_db/$1/manifest"
+ sort -r | sed '/^\.\/*$/d;ss.ss' > "${2:-$pkg_dir}/$1/$pkg_db/$1/manifest"
)
pkg_etcsums() (
@@ -980,10 +1208,16 @@ pkg_etcsums() (
# /etc/ directory for use in "smart" handling of these files.
log "$1" "Generating etcsums"
+ # Try to get the digest algorithm from the installed etcsums file. This
+ # makes sure that old packages continue to have the same digest algorithm
+ # and not a bunch of '.new' files are installed. It's not foolproof at all,
+ # but at least it keeps the /etc directory as clean as possible.
+ digest=$(_get_digest "$sys_db/$1/etcsums") || digest=b3sum
+ case $digest in b3sum) out "%BLAKE3"; esac > "$pkg_dir/$1/$pkg_db/$1/etcsums"
find etc -type f | while read -r file; do
- sh256 "$file"
- done > "$pkg_dir/$1/$pkg_db/$1/etcsums"
+ "$digest" "$file"
+ done >> "$pkg_dir/$1/$pkg_db/$1/etcsums"
)
pkg_tar() {
@@ -992,22 +1226,12 @@ pkg_tar() {
log "$1" "Creating tarball"
# Read the version information to name the package.
- read -r version release < "$(pkg_find "$1")/version"
+ read -r version release < "$pkg_dir/$1/$pkg_db/$1/version"
# Create a tarball from the contents of the built package.
- "$tar" cf - -C "$pkg_dir/$1" . |
- case $CPT_COMPRESS in
- bz2) bzip2 -z ;;
- xz) xz -zT 0 ;;
- gz) gzip -6 ;;
- zst) zstd -3 ;;
- lz) lzip -6 ;;
- *) gzip -6 ;; # Fallback to gzip
- esac \
- > "$bin_dir/$1#$version-$release.tar.$CPT_COMPRESS"
-
+ cd "$pkg_dir/$1"
+ pax -w . | compress > "$bin_dir/$1#$version-$release.tar.$CPT_COMPRESS"
log "$1" "Successfully created tarball"
-
run_hook post-package "$1" "$bin_dir/$1#$version-$release.tar.$CPT_COMPRESS"
}
@@ -1026,6 +1250,7 @@ pkg_build() {
# separately from those detected as dependencies.
explicit="$explicit $pkg "
} done
+ pkg_depends_commit
[ "$pkg_update" ] || explicit_build=$explicit
@@ -1203,10 +1428,12 @@ pkg_checksums() {
[ -f "$repo_dir/sources" ] || return 0
+ case ${2:-b3sum} in b3sum) out "%BLAKE3"; esac
+
while read -r src _ || [ "$src" ]; do
- # Comment.
- if [ -z "${src##\#*}" ]; then
- continue
+
+ # Skip checksums if it's a comment, or a VCS repository.
+ if _re "$re_vcs_or_com" "$src"; then continue
# File is local to the package.
elif [ -f "$repo_dir/$src" ]; then
@@ -1216,17 +1443,14 @@ pkg_checksums() {
elif [ -f "$src_dir/$1/${src##*/}" ]; then
src_path=$src_dir/$1
- # File is a git repository.
- elif [ -z "${src##git+*}" ]; then continue
-
# Die here if source for some reason, doesn't exist.
else
die "$1" "Couldn't find source '$src'"
fi
- # An easy way to get 'sha256sum' to print with the 'basename'
+ # An easy way to get 'b3sum' to print with the 'basename'
# of files is to 'cd' to the file's directory beforehand.
- (cd "$src_path" && sh256 "${src##*/}") ||
+ (cd "$src_path" && "${2:-b3sum}" "${src##*/}") ||
die "$1" "Failed to generate checksums"
done < "$repo_dir/sources"
}
@@ -1234,13 +1458,18 @@ pkg_checksums() {
pkg_verify() {
# Verify all package checksums. This is achieved by generating a new set of
# checksums and then comparing those with the old set.
- verify_cmd="NR==FNR{a[\$1];next}/^git .*/{next}!((\$1)in a){exit 1}"
+ vcmd="NR==FNR{a[\$1];next}/^git .*/{next}!((\$1)in a){exit 1}END{if(NR/2!=FNR)exit 1}"
for pkg; do
repo_dir=$(pkg_find "$pkg")
+
[ -f "$repo_dir/sources" ] || continue
- pkg_checksums "$pkg" | awk "$verify_cmd" - "$repo_dir/checksums" || {
+ # Determine the type of digest algorithm from the checksums file to do
+ # verification with.
+ digest="$(_get_digest "$repo_dir/checksums")"
+
+ pkg_checksums "$pkg" "$digest" | awk "$vcmd" - "$repo_dir/checksums" || {
log "$pkg" "Checksum mismatch"
# Instead of dying above, log it to the terminal. Also define a
@@ -1256,6 +1485,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).
@@ -1275,9 +1507,9 @@ pkg_conflicts() {
# Combine the dirname and file values, and print them into the
# temporary manifest to be parsed.
- printf '%s/%s\n' "${dirname#$CPT_ROOT}" "${file##*/}"
+ 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
@@ -1286,7 +1518,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
@@ -1302,13 +1534,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.
- "$grep" -Fxf "$CPT_TMPDIR/$pid/manifest" -- "$@" > "$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
@@ -1337,7 +1568,7 @@ pkg_conflicts() {
# this work.
#
# Pretty nifty huh?
- while IFS=: read -r _ con; do
+ while read -r con; do
printf '%s\n' "Found conflict $con"
# Create the "choices" directory inside of the tarball.
@@ -1359,13 +1590,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."
@@ -1398,15 +1629,22 @@ pkg_swap() {
# its manifest file to reflect this. We then resort this file
# so no issues arise when removing packages.
cp -Pf "$CPT_ROOT/$2" "$pkg_owns>${alt#*>}"
- sed "s#^$(regesc "$2")\$#${PWD#$CPT_ROOT}/$pkg_owns>${alt#*>}#" \
+ sed "s#^$(regesc "$2")\$#${PWD#"$CPT_ROOT"}/$pkg_owns>${alt#*>}#" \
"../installed/$pkg_owns/manifest" |
sort -r -o "../installed/$pkg_owns/manifest"
+ else
+ # If the file doesn't exist, we assume that there was a previous owner,
+ # but the package was then removed. We want the message to be short
+ # and clear, I thought of writing "Swapping [...] from 'null' to '$1'",
+ # but that would probably sound more like a package manager bug. Instead
+ # we are printing the message below which should be informative enough.
+ log "Installing '$2' from '$1'"
fi
# Convert the desired alternative to a real file and rewrite
# the manifest file to reflect this. The reverse of above.
mv -f "$alt" "$CPT_ROOT/$2"
- sed "s#^${PWD#$CPT_ROOT}/$(regesc "$alt")\$#$2#" "../installed/$1/manifest" |
+ sed "s#^${PWD#"$CPT_ROOT"}/$(regesc "$alt")\$#$2#" "../installed/$1/manifest" |
sort -r -o "../installed/$1/manifest"
}
@@ -1420,23 +1658,25 @@ pkg_etc() {
mkdir -p "$CPT_ROOT/$dir"
done
+ 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=$(sh256 "$file")
- sum_sys=$(cd "$CPT_ROOT/"; sh256 "$file")
- sum_old=$("$grep" "$file$" "$mak_dir/c"); } 2>/dev/null ||:
+ { sum_new=$("$digest" "$file")
+ sum_sys=$(cd "$CPT_ROOT/"; "$digest" "$file")
+ sum_old=$("$grep" "$file$" "$_etcsums"); } 2>/dev/null ||:
- log "$pkg_name" "Doing 3-way handshake for $file"
- printf '%s\n' "Previous: ${sum_old:-null}"
- printf '%s\n' "System: ${sum_sys:-null}"
- printf '%s\n' "New: ${sum_new:-null}"
+ logv "$pkg_name" "Doing 3-way handshake for $file"
+ outv "Previous: ${sum_old:-null}"
+ outv "System: ${sum_sys:-null}"
+ outv "New: ${sum_new:-null}"
# Use a case statement to easily compare three strings at
# the same time. Pretty nifty.
case ${sum_old:-null}${sum_sys:-null}${sum_new} in
# old = Y, sys = X, new = Y
"${sum_new}${sum_sys}${sum_old}")
- log "Skipping $file"
+ logv "Skipping $file"
continue
;;
@@ -1446,7 +1686,7 @@ pkg_etc() {
"${sum_old}${sum_old}${sum_old}"|\
"${sum_old:-null}${sum_sys}${sum_sys}"|\
"${sum_sys}${sum_old}"*)
- log "Installing $file"
+ logv "Installing $file"
new=
;;
@@ -1489,10 +1729,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
@@ -1500,7 +1741,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"
@@ -1511,7 +1752,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"
}
@@ -1534,12 +1775,14 @@ pkg_install() {
fi
mkdir -p "$tar_dir/$pkg_name"
+ cd "$tar_dir/$pkg_name"
+
log "$pkg_name" "Extracting $tar_file"
# Extract the tarball to catch any errors before installation begins.
- decompress "$tar_file" | "$tar" xf - -C "$tar_dir/$pkg_name"
+ decompress "$tar_file" | pax -rpp
- [ -f "$tar_dir/$pkg_name/$pkg_db/$pkg_name/manifest" ] ||
+ [ -f "./$pkg_db/$pkg_name/manifest" ] ||
die "'${tar_file##*/}' is not a valid CPT package"
# Ensure that the tarball's manifest is correct by checking that
@@ -1547,13 +1790,13 @@ pkg_install() {
[ "$CPT_FORCE" != 1 ] && log "$pkg_name" "Checking package manifest" &&
while read -r line; do
# Skip symbolic links
- [ -h "$tar_dir/$pkg_name/$line" ] ||
- [ -e "$tar_dir/$pkg_name/$line" ] || {
- log "File $line missing from tarball but mentioned in manifest" "" "!>"
- TARBALL_FAIL=1
- }
- done < "$tar_dir/$pkg_name/$pkg_db/$pkg_name/manifest"
- [ "$TARBALL_FAIL" ] && {
+ [ -h "./$line" ] ||
+ [ -e "./$line" ] || {
+ log "File $line missing from tarball but mentioned in manifest" "" "!>"
+ tarball_fail=1
+ }
+ done < "$pkg_db/$pkg_name/manifest"
+ [ "$tarball_fail" ] && {
log "You can still install this package by setting CPT_FORCE variable"
die "$pkg_name" "Missing files in manifest"
}
@@ -1562,18 +1805,17 @@ pkg_install() {
# Make sure that all run-time dependencies are installed prior to
# installing the package.
- [ -f "$tar_dir/$pkg_name/$pkg_db/$pkg_name/depends" ] &&
+ [ -f "$pkg_db/$pkg_name/depends" ] &&
[ "$CPT_FORCE" != 1 ] &&
while read -r dep dep_type || [ "$dep" ]; do
[ "${dep##\#*}" ] || continue
[ "$dep_type" ] || pkg_list "$dep" >/dev/null ||
install_dep="$install_dep'$dep', "
- done < "$tar_dir/$pkg_name/$pkg_db/$pkg_name/depends"
+ done < "$pkg_db/$pkg_name/depends"
[ "$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"
@@ -1585,8 +1827,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() {
@@ -1601,7 +1843,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
@@ -1638,144 +1880,231 @@ 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"
}
-pkg_fetch() {
- log "Updating repositories"
+pkg_repository_update() {
+ # Function to update the given package repository.
+ cd "$1"
+ repo_type=$(pkg_vcs_info)
+ repo_root=${repo_type#"$PWD":}
+ repo_type=${repo_type##*:} repo_root=${repo_root%:*}
+ contains "$repos" "$repo_root" || {
+ repos="$repos $repo_root "
+ cd "$repo_root"
+
+ "pkg_vcs_pull_$repo_type"
+
+ # Repositories can contain a "Message of the Day" file in order to
+ # relay important information to their users.
+ ! [ -r "$repo_root/MOTD" ] || {
+ printf '%s\n%s\n%s\n\n' \
+ "$(_multiply_char '=' 60)" \
+ "Message of the Day [$PWD]" \
+ "$(_multiply_char '=' 60)"
+ cat "$repo_root/MOTD"
+ printf '\n%s\n' "$(_multiply_char '=' 60)"
+ }
+ }
+}
- run_hook pre-fetch
+pkg_vcs_clone_git() {
+ # $1: Clone URL
+ # $2: Branch or Commit Object
+ git init
+ git remote add origin "${1%[#@]*}"
+ case $2 in
+ @*) git fetch -t --depth=1 origin "${2#@}" || git fetch; set -- "$1" "${2#@}" ;;
+ *) git fetch --depth=1 origin "$2" || git fetch
+ esac
+ git checkout "${2:-FETCH_HEAD}"
+}
- # Create a list of all repositories.
- # See [1] at top of script.
- # shellcheck disable=2046,2086
- { IFS=:; set -- $CPT_PATH; IFS=$old_ifs ;}
+pkg_vcs_clone_hg() {
+ # $1: Clone URL
+ # $2: Branch or Commit Object
+ hg clone -u "${2:-tip}" "${1%[#@]*}" .
+}
- # Update each repository in '$CPT_PATH'. It is assumed that
- # each repository is 'git' tracked.
- for repo; do
- # Go to the root of the repository (if it exists).
- cd "$repo"
- cd "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null ||
- cd "$(hg root 2>/dev/null)" 2>/dev/null ||:
+pkg_vcs_clone_fossil() {
+ # $1: Clone URL
+ # $2: Branch or Commit Object
+ fossil open -f "${1%[#@]*}" "${2:-trunk}"
+}
- if [ -d .git ]; then
+pkg_vcs_pull_fossil() {
+ # Pull function for Fossil.
+ log "$PWD" " "
+ [ "$(fossil remote 2>/dev/null)" != off ] || {
+ out "No remote, skipping."
+ return 0
+ }
- [ "$(git remote 2>/dev/null)" ] || {
- log "$repo" " "
- printf '%s\n' "No remote, skipping."
- continue
- }
+ # Ensure we have proper permissions to do the pull operation.
+ if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
+ fossil pull
+ fossil update
+ else
+ pkg_vcs_as_root "fossil pull && fossil update"
+ fi
+}
- contains "$repos" "$PWD" || {
- repos="$repos $PWD "
+pkg_vcs_pull_git() {
+ # Pull function for Git.
+ if [ "$(git remote 2>/dev/null)" ]; then
+ # Display a message if signing is enabled for this repository.
+ case $(git config merge.verifySignatures) in
+ true) log "$PWD" "[signed] " ;;
+ *) log "$PWD" " " ;;
+ esac
- # Display a tick if signing is enabled for this
- # repository.
- case $(git config merge.verifySignatures) in
- true) log "$PWD" "[signed] " ;;
- *) log "$PWD" " " ;;
- esac
+ # Ensure we have proper permissions to do the pull operation.
+ if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
+ git fetch
+ git merge
+ git submodule update --remote --init -f
+ else
+ pkg_vcs_as_root \
+ "git fetch && git merge && git submodule update --remote --init -f"
+ fi
+ else
+ log "$PWD" " "
+ # Skip if there are no submodules
+ [ -f .gitmodules ] || {
+ out "No remote, skipping."
+ return 0
+ }
+ if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
+ git submodule update --remote --init -f
+ else
+ pkg_vcs_as_root "git submodule update --remote --init -f"
+ fi
+ fi
+}
- if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
- git fetch
- git merge
- git submodule update --remote --init -f
+pkg_vcs_pull_hg() {
+ # Pull function for Mercurial.
+ log "$PWD" " "
+ [ "$(hg showconfig paths 2>/dev/null)" ] || {
+ out "No remote, skipping."
+ return 0
+ }
- else
- [ "$uid" = 0 ] || log "$PWD" "Need root to update"
-
- # Find out the owner of the repository and spawn
- # git as this user below.
- #
- # This prevents 'git' from changing the original
- # ownership of files and directories in the rare
- # case that the repository is owned by a 3rd user.
- (
- user=$(_stat "$PWD")
-
- [ "$user" = root ] ||
- log "Dropping permissions to $user for pull"
-
- git_cmd="git fetch && git merge && git submodule update --remote --init -f"
- case $su in *su) git_cmd="'$git_cmd'"; esac
-
- # Spawn a subshell to run multiple commands as
- # root at once. This makes things easier on users
- # who aren't using persist/timestamps for auth
- # caching.
- user=$user as_root sh -c "$git_cmd"
- )
- fi
- }
- elif [ -d .hg ]; then
+ if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
+ hg pull
+ hg update
+ else
+ pkg_vcs_as_root "hg pull && hg update"
+ fi
+}
- [ "$(hg showconfig paths 2>/dev/null)" ] || {
- log "$repo" " "
- printf '%s\n' "No remote, skipping."
- continue
- }
+pkg_vcs_pull_rsync() {
+ # Pull function for rsync repositories. The details of our rsync
+ # repositories are explained in the user manual.
+ log "$PWD" " "
- contains "$repos $PWD" || {
- repos="$repos $PWD"
+ # Read remote repository address from the '.rsync' file.
+ read -r remote < .rsync
+ if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
+ rsync -acvzzC --include=core --delete "$remote/" "$PWD"
+ else
+ pkg_vcs_as_root "rsync -acvzzC --include=core --delete \"$remote/\" \"$PWD\""
+ fi
+}
- if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
- hg pull
- hg update
- else
- [ "$uid" ] || log "$PWD" "Need root to update"
+pkg_vcs_pull_local() {
+ # Local repository. We don't do a "pull" here, we just notify the user that
+ # this is the case.
+ log "$PWD" " "
+ out "Not a remote repository, skipping."
+}
- # We are going to do the same operation as above, to
- # find the owner of the repository.
- (
- user=$(_stat "$PWD")
+pkg_vcs_as_root() (
+ # Helper function for pkg_vcs_pull* functions used for proper
+ # privilege escalation.
+ [ "$uid" = 0 ] || log "$PWD" "Need root to update"
- [ "$user" = root ] ||
- log "Dropping permissions to $user for pull"
+ # Find out the owner of the repository and spawn the operation as the user
+ # below.
+ #
+ # This prevents the VCS from changing the original ownership of files and
+ # directories in the rare case that the repository is owned by a third user.
+ user=$(_stat "$PWD")
- hg_cmd="hg pull && hg update"
+ [ "$user" = root ] || log "Dropping permissions to $user for pull"
+ case ${su##*/} in su) set -- "'$1'"; esac
- case $su in *su) hg_cmd="'$hg_cmd'"; esac
- user=$user as_root sh -c "$hg_cmd"
- )
- fi
- }
- elif [ -f .rsync ]; then
- # If an .rsync_root file exists, we check that the repository root
- # exists. If it does, we change to that directory to do the fetch.
- # This way, we allow for partial repositories while making sure that
- # we can fetch the repository in a single operation.
- [ -f .rsync_root ] && {
- read -r rsync_root < .rsync_root
- [ -f "$rsync_root/.rsync" ] && cd "$rsync_root"
- }
- contains "$repos" "$PWD" || {
- repos="$repos $PWD"
- read -r remote < .rsync
- if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
- rsync -acvzzC --include=core --delete "$remote/" "$PWD"
- else
- [ "$uid" = 0 ] || log "$PWD" "Need root to update"
+ # Spawn a subhsell to run multiple commands as root at once. This makes
+ # things easier on users who aren't using persist/timestamps for auth
+ # caching.
+ as_root sh -c "$@"
+)
- # Similar to the git update, we find the owner of
- # the repository and spawn rsync as that user.
- (
- user=$(_stat "$PWD")
+pkg_vcs_info() {
+ # Finds and returns repository information for the current directory. It
+ # will return current directory, repository root, and the type of repository
+ # in a colon separated format.
- [ "$user" = root ] ||
- log "Dropping permissions to $user for pull"
+ : "${repo_file:=$cac_dir/repository-cache}"
+ set --
- user=$user as_root rsync -acvzzC --include=core --delete "$remote/" "$PWD"
- )
- fi
- }
- else
- log "$repo" " "
- printf '%s\n' "Not a remote repository, skipping."
- fi
- done
+ if [ "$CPT_REPO_CACHE" != 0 ] && information=$(grep "^$PWD:" "$repo_file" 2>/dev/null); then
+ # Repository information is already cached.
+ printf '%s\n' "$information" | sed 1q
+ return
+ elif rootdir=$(git rev-parse --show-toplevel 2>/dev/null); then
+ # Git repository
+ backend=git
+ elif rootdir=$(hg root 2>/dev/null); then
+ # Mercurial repository
+ backend=hg
+ elif rootdir=$(fossil info 2>/dev/null | grep ^local-root:); then
+ # Fossil repository
+ backend=fossil
+
+ # We want to remove the initial spacing before the root directory, and
+ # the leading dash on the root directory.
+ rootdir=${rootdir#local-root: *} rootdir=${rootdir%/}
+ elif [ -f .rsync ]; then
+ backend=rsync
+ rootdir=$PWD
+
+ # If an .rsync_root file exists, we check that the repository root
+ # exists. If it does, we change to that directory to do the fetch.
+ # This way, we allow for partial repositories while making sure that
+ # we can fetch the repository in a single operation.
+ [ -f .rsync_root ] && {
+ read -r rsync_root < .rsync_root
+ [ -f "$rsync_root/.rsync" ] && rootdir=$(_readlinkf "$rsync_root")
+ }
+ else
+ # Local repository
+ backend=local
+ rootdir=$PWD
+ fi
+
+ # We cache all these information, so that we don't have to spend much time
+ # looking these up the next time we are doing it. If CPT_REPO_CACHE is set
+ # to 0, we will not write this cache.
+ [ "$CPT_REPO_CACHE" = 0 ] || set -- "$repo_file"
+ printf '%s:%s:%s\n' "$PWD" "$rootdir" "$backend" | tee -a "$@"
+}
+
+pkg_fetch() {
+ log "Updating repositories"
+
+ run_hook pre-fetch
+
+ # Create a list of all repositories.
+ # See [1] at top of script.
+ # shellcheck disable=2046,2086
+ { IFS=:; set -- $CPT_PATH; IFS=$old_ifs ;}
+
+ # Update each repository in '$CPT_PATH'. It is assumed that
+ # each repository is 'git' tracked.
+ for repo; do pkg_repository_update "$repo"; done
run_hook post-fetch
}
@@ -1786,7 +2115,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
@@ -1800,7 +2134,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
@@ -1821,6 +2155,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"
@@ -1831,18 +2172,17 @@ pkg_updates(){
cpt-install cpt
log "Updated the package manager"
- log "Re-run 'cpt update' to update your system"
-
- exit 0
- }
-
- [ "$outdated" ] || {
- log "Everything is up to date"
- return
+ 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
}
- log "Packages to update: ${outdated% }"
-
# Tell 'pkg_build' to always prompt before build.
pkg_update=1
@@ -1858,12 +2198,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.
@@ -1874,13 +2214,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
@@ -1905,6 +2252,7 @@ pkg_gentree() (
esac
done
pkg_depends "$1" tree "$make_deps"
+ pkg_depends_commit
# Unless 'f' is given, pop the package from the list so that we don't list
# the package (for example if it's part of the base package list). Normally
@@ -1916,7 +2264,9 @@ pkg_gentree() (
# shellcheck disable=2086
[ -z "${2##*f*}" ] || deps=$(pop "$1" from $deps)
- eval set -- "$deps"
+ # Word splitting is intentional.
+ # shellcheck disable=2086
+ set -- $deps
pkg_order "$@"
if [ "$reverse" ]; then eval set -- "$redro"; else eval set -- "$order"; fi
[ "$1" ] || return 0
@@ -1929,8 +2279,11 @@ pkg_gentree() (
pkg_query_meta() {
# Query the 'meta' file of the given meta package. If there is no meta file,
# or the key being queried is unavailable, the function will return with
- # error.
- repo_dir=$(pkg_find "$1")
+ # error. Full path can be specified instead of package names.
+ case $1 in
+ */*) repo_dir=$1 ;;
+ *) repo_dir=$(pkg_find "$1")
+ esac
[ -f "$repo_dir/meta" ] || return
while IFS=': ' read -r key val; do
case $key in
@@ -1952,29 +2305,51 @@ 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 -p "$1" "$_ret"
+ out "$_ret"
+}
+
+_tmp_create() {
+ # Create given file to the temporary directory and return its name
+ create_tmp
+ _ret=$(_tmp_name "$1")
+ :> "$_ret" || return 1
+ out "$_ret"
+}
+
+create_tmp() {
+ # Create the required temporary directories and set the variables which
+ # point to them.
+ 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() {
- # 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.
+ # DEPRECATED, use create_tmp() instead.
#
- # Create the required temporary directories and set the variables
- # which point to them.
- mkdir -p "${tmp_dir:=${CPT_TMPDIR:=$cac_dir/proc}/$pid}"
-
# If an argument is given, skip the creation of other cache directories.
- # This here makes shellcheck extremely angry, so I am globally disabling
- # SC2119.
- [ "$1" ] || mkdir -p "${mak_dir:=$tmp_dir/build}" \
- "${pkg_dir:=$tmp_dir/pkg}" \
- "${tar_dir:=$tmp_dir/export}"
-
+ [ "$1" ] || create_tmp
}
# main()
{
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 && {
@@ -1983,24 +2358,44 @@ create_cache() {
eval set -- "$REST"
}
- # 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.
- mkdir -p "${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}"
-
- # Set the location to the repository and package database.
- pkg_db=var/db/cpt/installed
-
# The PID of the current shell process is used to isolate directories
# to each specific CPT instance. This allows multiple package manager
# instances to be run at once. Store the value in another variable so
# that it doesn't change beneath us.
pid=${CPT_PID:-$$}
+ # 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 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
+
# Force the C locale to speed up things like 'grep' which disable unicode
# etc when this is set. We don't need unicode and a speed up is always
# welcome.
@@ -2015,17 +2410,6 @@ create_cache() {
# POSIX correctness (grep quoted to avoid shellcheck false-positive).
grep=$(command -v ggrep) || grep='grep'
- # Prefer libarchive tar or GNU tar if installed as they are much
- # much faster than busybox's implementation. Very much worth it if
- # you value performance.
- tar=$(command -v bsdtar || command -v gtar) || tar=tar
-
- # Prefer libarchive tar, GNU tar, or the POSIX defined pax for tarball
- # extraction, as they can strip components, which is much much faster than
- # our portability function. Our first preference is pax, because it is
- # actually slightly faster than bsdtar and GNU tar.
- extract=$(command -v pax || command -v "$tar")
-
# Figure out which 'sudo' command to use based on the user's choice or
# what is available on the system.
su=${CPT_SU:-$(command -v ssu ||
@@ -2045,6 +2429,15 @@ create_cache() {
command -v llvm-readelf ||
command -v eu-readelf)"} || elf_prog=ldd
+ # Use one of the following programs to download package sources. Downloads
+ # are made using the `pkg_download()` function.
+ dl_prog=${CPT_DOWNLOADER:="$(
+ command -v curl ||
+ command -v wget ||
+ command -v wget2 ||
+ command -v axel ||
+ command -v aria2c)"} || dl_prog=curl
+
# Make note of the user's current ID to do root checks later on.
# This is used enough to warrant a place here.
uid=$(id -u)
@@ -2054,10 +2447,7 @@ create_cache() {
# Make sure that the CPT_ROOT doesn't end with a '/'. This might
# break some operations.
- [ -z "$CPT_ROOT" ] || [ "${CPT_ROOT##*/}" ] || {
- warn "" "Your CPT_ROOT variable shouldn't end with '/'"
- CPT_ROOT=${CPT_ROOT%/}
- }
+ CPT_ROOT=${CPT_ROOT%"${CPT_ROOT##*[!/]}"}
# Define an optional sys_arch variable in order to provide
# information to build files with architectural information.
@@ -2067,20 +2457,32 @@ 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)\+)'
+
# This allows for automatic setup of a CPT chroot and will
# do nothing on a normal system.
mkdir -p "$CPT_ROOT/" 2>/dev/null ||:
- # Set a value for CPT_COMPRESS if it isn't set.
- : "${CPT_COMPRESS:=gz}"
-
- # Unless being piped or the user specifically doesn't want colors, set
- # colors. This can of course be overriden if the user specifically want
- # colors during piping.
- if { [ "$CPT_COLOR" != 0 ] && [ -t 1 ] ;} || [ "$CPT_COLOR" = 1 ]; then
- colory="\033[1;33m" colorb="\033[1;36m" colre="\033[m"
- fi
+ # Set the default compression to gzip, and warn the user if the value is
+ # invalid.
+ case ${CPT_COMPRESS:=gz} in
+ bz2|gz|xz|zst|lz) ;;
+ *) warn "'$CPT_COMPRESS' is not a valid CPT_COMPRESS value, falling back to 'gz'"
+ CPT_COMPRESS=gz
+ esac
+ # Set colors if they are to be enabled.
+ # shellcheck disable=2034
+ colors_enabled && colory="\033[1;33m" colorb="\033[1;34m" colre="\033[m" colbold="\033[1m"
}
# If the library is being called with its own name, run arguments.
diff --git a/src/cpt-list b/src/cpt-list
index 4eb7cf6..fcb1f49 100755
--- a/src/cpt-list
+++ b/src/cpt-list
@@ -3,10 +3,11 @@
parser_definition() {
setup REST help:usage -- \
- "usage: ${0##*/} [-c] pkg..." \
+ "usage: ${0##*/} [-cq] pkg..." \
"or: ${0##*/} -C pkg true-statement false-statement"
msg -- '' 'Options:'
flag CURRENT -c --current -- "Use the current directory as a package"
+ flag quiet -q --quiet -- "Make the operation quiet"
param PKG -C --check label:" -C,--check PKG TRUE FALSE" -- \
"Check if PKG exists and return the string of TRUE if"\
"it exists, and the string of FALSE if it doesn't." \
@@ -23,7 +24,7 @@ if [ "$PKG" ]; then
printf %s "$2"
fi
else
-[ "$CURRENT" ] && set -- "${PWD##*/}"
-
-pkg_list "$@"
+ [ "$CURRENT" ] && set -- "${PWD##*/}"
+ [ "$quiet" ] && exec >/dev/null 2>&1
+ pkg_list "$@"
fi
diff --git a/src/cpt-remove b/src/cpt-remove
index cce3739..f5a5abf 100755
--- a/src/cpt-remove
+++ b/src/cpt-remove
@@ -10,7 +10,7 @@ parser_definition() {
if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
-[ "$1" ] || { set -- "${PWD##*/}"; export CPT_PATH=${PWD%/*}:$CPT_PATH ;}
+[ "$1" ] || { set -- "${PWD##*/}"; export CPT_PATH="${PWD%/*}:$CPT_PATH" ;}
[ -w "$CPT_ROOT/" ] || [ "$uid" = 0 ] || {
as_root "$0" "$@"
@@ -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/src/cpt-search b/src/cpt-search
index fbe0b04..9eeac75 100755
--- a/src/cpt-search
+++ b/src/cpt-search
@@ -2,26 +2,64 @@
# Search for a package
parser_definition() {
- setup REST help:usage -- "usage: ${0##*/} [pkg...]"
+ setup REST help:usage -- "usage: ${0##*/} [-dFoqs] [pkg...]"
msg -- '' 'Options:'
flag SEARCH_PATH -d "on:$CPT_PATH" -- "Do not search the installed package database"
flag all -s --single init:=1 on:'' -- "Only show the first instance of a package"
- flag others -o --others -- "Use the current directory as the package" \
+ flag mode -q --query on:2 -- "Search packages making use of package descriptions"
+ flag fflag -F --fixed -- "Run query mode interpreting the given pattern as a" \
+ "fixed string"
+ flag mode -o --others on:1 -- "Use the current directory as the package" \
"and show other instances"
- global_options
+ global_options compact
}
if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
-# The 'all' variable is set by the option parser.
-# shellcheck disable=2154
-case $others in
- '') for pkg; do pkg_find "$pkg" "${all:+all}"; done ;;
- *) pkg_find "${PWD##*/}" all |
- while read -r pkg_dir; do case $pkg_dir in
- "$PWD") ;;
- *) printf '%s\n' "$pkg_dir"
- [ "$all" ] || exit 0
- esac
- done
+
+# The 'all' and 'mode' variables are set by the option parser, and are never
+# modified in the subshell.
+# shellcheck disable=2154,2030,2031
+case $mode in
+ '')
+ # Default mode of operation.
+ for pkg; do pkg_find "$pkg" "${all:+all}"; done
+ ;;
+ 1)
+ # Use the current directory as the package and show other instances.
+ pkg_find "${PWD##*/}" all |
+ while read -r pkg_dir; do
+ case $pkg_dir in
+ "$PWD") ;;
+ *) printf '%s\n' "$pkg_dir"
+ [ "$all" ] || exit 0
+ esac
+ done
+ ;;
+ 2)
+ # Make a partial string search using the name and the description of all
+ # packages. This is a "pretty information" mode, and its output is not
+ # meant to be used in scripting. There is a whole library meant for
+ # scripting.
+ pkg_find \* all |
+ while read -r pkg_dir; do
+ name=${pkg_dir##*/}
+ desc=$(pkg_query_meta "$pkg_dir" description ||:)
+
+ # We pipe the name and description to the given query and
+ # continue if it's not a match
+ printf '%s %s\n' "$name" "$desc" |
+ "$grep" "-iq${fflag:+F}" -- "$1" || continue
+
+ read -r ver rel < "$pkg_dir/version"
+ printf '%b%s%b@%s %s-%s\n %s\n\n' \
+ "$colorb" "$name" "$colre" \
+ "$pkg_dir" \
+ "$ver" "$rel" \
+ "$desc"
+
+ # I don't know why someone use the '-s' flag on this operation
+ # mode, but go ahead.
+ [ "$all" ] || exit 0
+ done
esac
diff --git a/src/cpt-update b/src/cpt-update
index a8f9616..7e7ee16 100755
--- a/src/cpt-update
+++ b/src/cpt-update
@@ -6,11 +6,15 @@ parser_definition() {
msg -- '' 'Options:'
flag download_only -d --download -- "Only download updatable packages"
flag CPT_FETCH -n --no-fetch on:0 off:0 init:@export -- "Do not refresh the repositories"
- disp :pkg_fetch -o --only-fetch -- "Only fetch repositories"
+ flag pkg_fetch -o --only-fetch -- "Only fetch repositories"
global_options
}
if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
-create_cache
-pkg_updates
+if [ "$pkg_fetch" ]; then
+ pkg_fetch
+else
+ create_cache
+ pkg_updates
+fi
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/tools/mkdist.sh b/tools/mkdist.sh
index c21e964..98f985c 100755
--- a/tools/mkdist.sh
+++ b/tools/mkdist.sh
@@ -25,6 +25,7 @@ fossil ls | while read -r file; do
cp "$file" "$basedir/$file"
done
-tar cf "$basedir.tar" "$basedir"
-xz -z "$basedir.tar"
+cp docs/cpt.info "$basedir/docs/cpt.info"
+
+pax -w "$basedir" | xz -zT 0 > "$basedir.tar.xz"
rm -rf -- "$basedir"
diff --git a/tools/tool2man.sh b/tools/tool2man.sh
index 38cdbf4..c4bbfb8 100755
--- a/tools/tool2man.sh
+++ b/tools/tool2man.sh
@@ -69,8 +69,8 @@ while read -r line; do
esac
done < "$file"
-out ".Sh AUTHOR" ".An Cem Keylan Aq Mt cem@ckyln.com"
-out ".Sh LICENSE" "See LICENSE for copyright information."
+out ".Sh AUTHOR" ".An Cem Keylan Aq Mt cem@carbslinux.org"
+out ".Sh COPYING" "See LICENSE for copyright information."
out ".Sh SEE ALSO" ".Xr cpt 1"
[ "$see" ] &&
for man in $see; do
@@ -79,6 +79,6 @@ out ".Sh SEE ALSO" ".Xr cpt 1"
out ".Pp"
out "The full documentation of cpt is available as an info page."
out "If either" ".Ic info" or ".Ic texinfo"
-out "package is installed on your system, you can run"
-out ".Bd -literal -offset indent" "info cpt" ".Ed"
-out .Pp "to learn more about the package manager."
+out "package is installed on your system, you can learn more about the package"
+out "manager by running"
+out ".Sq Sy info cpt ."
diff --git a/www/index.md b/www/index.md
index 99a1f13..e518540 100644
--- a/www/index.md
+++ b/www/index.md
@@ -1,5 +1,7 @@
# Home
+[![builds.sr.ht status](https://builds.sr.ht/~carbslinux/cpt.svg)](https://builds.sr.ht/~carbslinux/cpt?)
+
CPT is the package management toolset written for Carbs Linux. Its aim is to
provide a stable, powerful, and easily used library for package management that
complements the tools that come with it. It has the following features:
@@ -27,13 +29,13 @@ 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, 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.0.2 ([2021-04-05](/timeline?c=6.0.2))
+### Latest Release: 7.0.2 ([2023-02-05](/timeline?c=7.0.2))
- [Download](/uvlist?byage=1)
-- [Changelog](/wiki?name=Changelog)
+- [Changelog](/doc/trunk/CHANGELOG.md)
- [User Manual](https://carbslinux.org/docs/cpt)