Pacman-dev
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- 1 participants
- 7245 discussions
This removes support for autotools in favour of meson.
---
I'd still like support for including man pages (with --prefix=/usr) when
running "ninja dist". However, I am also happy taking the heavy handed approach of adding the built man pages to git if no solution is forthcoming.
There is probably some .gitignore cleanup that can be done in the translation
directories.
.gitignore | 21 --
.gitlab-ci.yml | 17 -
HACKING | 13 -
INSTALL | 370 ---------------------
Makefile.am | 78 -----
RELEASE | 9 +-
configure.ac | 594 ----------------------------------
doc/Makefile.am | 162 ----------
doc/index.asciidoc | 8 +-
etc/Makefile.am | 27 --
lib/libalpm/Makefile.am | 78 -----
scripts/Makefile.am | 287 ----------------
src/common/Makefile.am | 3 -
src/pacman/Makefile.am | 69 ----
src/util/Makefile.am | 27 --
test/pacman/Makefile.am | 22 --
test/pacman/tests/Makefile.am | 5 -
test/scripts/Makefile.am | 10 -
test/util/Makefile.am | 8 -
19 files changed, 8 insertions(+), 1800 deletions(-)
delete mode 100644 INSTALL
delete mode 100644 Makefile.am
delete mode 100644 configure.ac
delete mode 100644 doc/Makefile.am
delete mode 100644 etc/Makefile.am
delete mode 100644 lib/libalpm/Makefile.am
delete mode 100644 scripts/Makefile.am
delete mode 100644 src/common/Makefile.am
delete mode 100644 src/pacman/Makefile.am
delete mode 100644 src/util/Makefile.am
delete mode 100644 test/pacman/Makefile.am
delete mode 100644 test/pacman/tests/Makefile.am
delete mode 100644 test/scripts/Makefile.am
delete mode 100644 test/util/Makefile.am
diff --git a/.gitignore b/.gitignore
index 499d499b..01975fd2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,24 +1,3 @@
*~
*.o
-ABOUT-NLS
-aclocal.m4
-autom4te.cache
-config.h
-config.h.in
-config.log
-config.status
-config.status.lineno
-configure
-configure.lineno
-cov-int
-cscope.in.out
-cscope.out
-cscope.po.out
-intl
-libtool
-Makefile
-Makefile.in
pacman-*.tar.gz
-root
-stamp-h1
-tags
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a53d60cf..65b8c729 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -34,23 +34,6 @@ arch-docs:
- meson -Ddoc=enabled build
- ninja -C build
-arch-autoconf:
- extends: .arch-test
- script:
- - pacman -Syu --needed --noconfirm autoconf-archive
- - autoreconf -i
- - ./configure --enable-warningflags --disable-doc
- - make
- - fakechroot make check
-
-arch-distcheck:
- extends: .arch-test
- script:
- - pacman -Syu --needed --noconfirm autoconf-archive asciidoc
- - autoreconf -i
- - ./configure --enable-warningflags
- - fakechroot make distcheck
-
arch-clang:
extends: .arch-test
script:
diff --git a/HACKING b/HACKING
index 009a4682..334b7ac0 100644
--- a/HACKING
+++ b/HACKING
@@ -176,16 +176,3 @@ For pacman:
-------------------------------------------
Never directly include config.h. This will always be added via Makefiles.
-
-GDB and Valgrind Usage
-~~~~~~~~~~~~~~~~~~~~~~
-
-When using GDB or valgrind on pacman, you will want to run it on the actual
-binary rather than the shell script wrapper produced by libtool. The actual
-binary lives at `src/pacman/.libs/lt-pacman`, and will exist after running
-`./src/pacman/pacman` at least once.
-
-For example, to run valgrind:
-
- ./src/pacman/pacman
- valgrind --leak-check=full -- src/pacman/.libs/lt-pacman -Syu
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index 007e9396..00000000
--- a/INSTALL
+++ /dev/null
@@ -1,370 +0,0 @@
-Installation Instructions
-*************************
-
-Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
-Inc.
-
- Copying and distribution of this file, with or without modification,
-are permitted in any medium without royalty provided the copyright
-notice and this notice are preserved. This file is offered as-is,
-without warranty of any kind.
-
-Basic Installation
-==================
-
- Briefly, the shell commands `./configure; make; make install' should
-configure, build, and install this package. The following
-more-detailed instructions are generic; see the `README' file for
-instructions specific to this package. Some packages provide this
-`INSTALL' file but do not implement all of the features documented
-below. The lack of an optional feature in a given package is not
-necessarily a bug. More recommendations for GNU packages can be found
-in *note Makefile Conventions: (standards)Makefile Conventions.
-
- The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation. It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions. Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
- It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring. Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.
-
- If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release. If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
- The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'. You need `configure.ac' if
-you want to change it or regenerate `configure' using a newer version
-of `autoconf'.
-
- The simplest way to compile this package is:
-
- 1. `cd' to the directory containing the package's source code and type
- `./configure' to configure the package for your system.
-
- Running `configure' might take a while. While running, it prints
- some messages telling which features it is checking for.
-
- 2. Type `make' to compile the package.
-
- 3. Optionally, type `make check' to run any self-tests that come with
- the package, generally using the just-built uninstalled binaries.
-
- 4. Type `make install' to install the programs and any data files and
- documentation. When installing into a prefix owned by root, it is
- recommended that the package be configured and built as a regular
- user, and only the `make install' phase executed with root
- privileges.
-
- 5. Optionally, type `make installcheck' to repeat any self-tests, but
- this time using the binaries in their final installed location.
- This target does not install anything. Running this target as a
- regular user, particularly if the prior `make install' required
- root privileges, verifies that the installation completed
- correctly.
-
- 6. You can remove the program binaries and object files from the
- source code directory by typing `make clean'. To also remove the
- files that `configure' created (so you can compile the package for
- a different kind of computer), type `make distclean'. There is
- also a `make maintainer-clean' target, but that is intended mainly
- for the package's developers. If you use it, you may have to get
- all sorts of other programs in order to regenerate files that came
- with the distribution.
-
- 7. Often, you can also type `make uninstall' to remove the installed
- files again. In practice, not all packages have tested that
- uninstallation works correctly, even though it is required by the
- GNU Coding Standards.
-
- 8. Some packages, particularly those that use Automake, provide `make
- distcheck', which can by used by developers to test that all other
- targets like `make install' and `make uninstall' work correctly.
- This target is generally not run by end users.
-
-Compilers and Options
-=====================
-
- Some systems require unusual options for compilation or linking that
-the `configure' script does not know about. Run `./configure --help'
-for details on some of the pertinent environment variables.
-
- You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment. Here
-is an example:
-
- ./configure CC=c99 CFLAGS=-g LIBS=-lposix
-
- *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
- You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you can use GNU `make'. `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script. `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'. This
-is known as a "VPATH" build.
-
- With a non-GNU `make', it is safer to compile the package for one
-architecture at a time in the source code directory. After you have
-installed the package for one architecture, use `make distclean' before
-reconfiguring for another architecture.
-
- On MacOS X 10.5 and later systems, you can create libraries and
-executables that work on multiple system types--known as "fat" or
-"universal" binaries--by specifying multiple `-arch' options to the
-compiler but only a single `-arch' option to the preprocessor. Like
-this:
-
- ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
- CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
- CPP="gcc -E" CXXCPP="g++ -E"
-
- This is not guaranteed to produce working output in all cases, you
-may have to build one architecture at a time and combine the results
-using the `lipo' tool if you have problems.
-
-Installation Names
-==================
-
- By default, `make install' installs the package's commands under
-`/usr/local/bin', include files under `/usr/local/include', etc. You
-can specify an installation prefix other than `/usr/local' by giving
-`configure' the option `--prefix=PREFIX', where PREFIX must be an
-absolute file name.
-
- You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. If you
-pass the option `--exec-prefix=PREFIX' to `configure', the package uses
-PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files still use the regular prefix.
-
- In addition, if you use an unusual directory layout you can give
-options like `--bindir=DIR' to specify different values for particular
-kinds of files. Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them. In general, the
-default for these options is expressed in terms of `${prefix}', so that
-specifying just `--prefix' will affect all of the other directory
-specifications that were not explicitly provided.
-
- The most portable way to affect installation locations is to pass the
-correct locations to `configure'; however, many packages provide one or
-both of the following shortcuts of passing variable assignments to the
-`make install' command line to change installation locations without
-having to reconfigure or recompile.
-
- The first method involves providing an override variable for each
-affected directory. For example, `make install
-prefix=/alternate/directory' will choose an alternate location for all
-directory configuration variables that were expressed in terms of
-`${prefix}'. Any directories that were specified during `configure',
-but not in terms of `${prefix}', must each be overridden at install
-time for the entire installation to be relocated. The approach of
-makefile variable overrides for each directory variable is required by
-the GNU Coding Standards, and ideally causes no recompilation.
-However, some platforms have known limitations with the semantics of
-shared libraries that end up requiring recompilation when using this
-method, particularly noticeable in packages that use GNU Libtool.
-
- The second method involves providing the `DESTDIR' variable. For
-example, `make install DESTDIR=/alternate/directory' will prepend
-`/alternate/directory' before all installation names. The approach of
-`DESTDIR' overrides is not required by the GNU Coding Standards, and
-does not work on platforms that have drive letters. On the other hand,
-it does better at avoiding recompilation issues, and works well even
-when some directory options were not specified in terms of `${prefix}'
-at `configure' time.
-
-Optional Features
-=================
-
- If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
- Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System). The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
- For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
- Some packages offer the ability to configure how verbose the
-execution of `make' will be. For these packages, running `./configure
---enable-silent-rules' sets the default to minimal output, which can be
-overridden with `make V=1'; while running `./configure
---disable-silent-rules' sets the default to verbose, which can be
-overridden with `make V=0'.
-
-Particular systems
-==================
-
- On HP-UX, the default C compiler is not ANSI C compatible. If GNU
-CC is not installed, it is recommended to use the following options in
-order to use an ANSI C compiler:
-
- ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
-
-and if that doesn't work, install pre-built binaries of GCC for HP-UX.
-
- HP-UX `make' updates targets which have the same time stamps as
-their prerequisites, which makes it generally unusable when shipped
-generated files such as `configure' are involved. Use GNU `make'
-instead.
-
- On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
-parse its `<wchar.h>' header file. The option `-nodtk' can be used as
-a workaround. If GNU CC is not installed, it is therefore recommended
-to try
-
- ./configure CC="cc"
-
-and if that doesn't work, try
-
- ./configure CC="cc -nodtk"
-
- On Solaris, don't put `/usr/ucb' early in your `PATH'. This
-directory contains several dysfunctional programs; working variants of
-these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
-in your `PATH', put it _after_ `/usr/bin'.
-
- On Haiku, software installed for all users goes in `/boot/common',
-not `/usr/local'. It is recommended to use the following options:
-
- ./configure --prefix=/boot/common
-
-Specifying the System Type
-==========================
-
- There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on. Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
-`--build=TYPE' option. TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
- CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
- OS
- KERNEL-OS
-
- See the file `config.sub' for the possible values of each field. If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
- If you are _building_ compiler tools for cross-compiling, you should
-use the option `--target=TYPE' to select the type of system they will
-produce code for.
-
- If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
- If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists. Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
- Variables not defined in a site shell script can be set in the
-environment passed to `configure'. However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost. In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'. For example:
-
- ./configure CC=/usr/local2/bin/gcc
-
-causes the specified `gcc' to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-Unfortunately, this technique does not work for `CONFIG_SHELL' due to
-an Autoconf limitation. Until the limitation is lifted, you can use
-this workaround:
-
- CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
-
-`configure' Invocation
-======================
-
- `configure' recognizes the following options to control how it
-operates.
-
-`--help'
-`-h'
- Print a summary of all of the options to `configure', and exit.
-
-`--help=short'
-`--help=recursive'
- Print a summary of the options unique to this package's
- `configure', and exit. The `short' variant lists options used
- only in the top level, while the `recursive' variant lists options
- also present in any nested packages.
-
-`--version'
-`-V'
- Print the version of Autoconf used to generate the `configure'
- script, and exit.
-
-`--cache-file=FILE'
- Enable the cache: use and save the results of the tests in FILE,
- traditionally `config.cache'. FILE defaults to `/dev/null' to
- disable caching.
-
-`--config-cache'
-`-C'
- Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
- Do not print messages saying which checks are being made. To
- suppress all normal output, redirect it to `/dev/null' (any error
- messages will still be shown).
-
-`--srcdir=DIR'
- Look for the package's source code in directory DIR. Usually
- `configure' can determine that directory automatically.
-
-`--prefix=DIR'
- Use DIR as the installation prefix. *note Installation Names::
- for more details, including other options available for fine-tuning
- the installation locations.
-
-`--no-create'
-`-n'
- Run the configure checks, but stop before creating any output
- files.
-
-`configure' also accepts some other, not widely useful, options. Run
-`configure --help' for more details.
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index fbbc2559..00000000
--- a/Makefile.am
+++ /dev/null
@@ -1,78 +0,0 @@
-SUBDIRS = lib/libalpm src/util src/pacman scripts etc test/pacman test/util test/scripts
-if WANT_DOC
-SUBDIRS += doc
-endif
-
-DIST_SUBDIRS = $(SUBDIRS) src/common
-
-ACLOCAL_AMFLAGS = -I m4 --install
-AM_MAKEFLAGS = --no-print-directory
-
-# Make sure we test and build manpages when doing distcheck
-DISTCHECK_CONFIGURE_FLAGS = --enable-doc --disable-git-version \
- bashcompdir='$${prefix}/share/bash-completion/completions'
-
-# Some files automatically included, so they aren't specified below:
-# AUTHORS, COPYING, NEWS, README
-EXTRA_DIST = \
- HACKING test/tap.sh \
- meson.build meson_options.txt \
- build-aux/edit-script.sh.in \
- build-aux/meson-make-symlink.sh \
- build-aux/script-wrapper.sh.in
-
-
-# Sample makepkg prototype files
-pkgdatadir = ${datadir}/${PACKAGE}
-dist_pkgdata_DATA = \
- proto/PKGBUILD.proto \
- proto/PKGBUILD-split.proto \
- proto/PKGBUILD-vcs.proto \
- proto/proto.install
-
-$(top_srcdir)/test/pacman/tests/TESTS: $(wildcard test/pacman/tests/*.py)
- @printf "TESTS += %s\n" $^ | LC_ALL=C sort -u > "$@"
-
-TESTS = test/scripts/parseopts_test.sh \
- test/scripts/makepkg-template_test.sh \
- test/scripts/pacman-db-upgrade-v9.py \
- test/util/vercmptest.sh
-include $(top_srcdir)/test/pacman/tests/TESTS
-
-TEST_SUITE_LOG = test/test-suite.log
-TEST_EXTENSIONS = .py
-AM_TESTS_ENVIRONMENT = \
- PMTEST_UTIL_DIR=$(top_builddir)/src/util/; export PMTEST_UTIL_DIR; \
- PMTEST_SCRIPT_DIR=$(top_builddir)/scripts/; export PMTEST_SCRIPT_DIR; \
- PMTEST_SCRIPTLIB_DIR=$(top_srcdir)/scripts/library/; export PMTEST_SCRIPTLIB_DIR; \
- PMTEST_LIBMAKEPKG_DIR=$(top_builddir)/scripts/libmakepkg/; export PMTEST_LIBMAKEPKG_DIR;
-LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
- $(top_srcdir)/build-aux/tap-driver.sh
-PY_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
- $(top_srcdir)/build-aux/tap-driver.sh
-PY_LOG_COMPILER = $(PYTHON) $(top_srcdir)/test/pacman/pactest.py
-AM_PY_LOG_FLAGS = \
- --scriptlet-shell $(SCRIPTLET_SHELL) \
- --ldconfig $(LDCONFIG) \
- --bindir $(top_builddir)/src/pacman \
- --bindir $(top_builddir)/scripts
-if !HAVE_LIBGPGME
-AM_PY_LOG_FLAGS += --without-gpg
-endif
-if !HAVE_LIBCURL
-AM_PY_LOG_FLAGS += --without-curl
-endif
-
-# create the pacman DB, cache, makepkg-template and system hook directories upon install
-install-data-local:
- for dir in "$(DESTDIR)$(localstatedir)/lib/pacman" "$(DESTDIR)$(localstatedir)/cache/pacman/pkg" \
- "$(DESTDIR)$(datarootdir)/makepkg-template" "$(DESTDIR)$(datarootdir)/libalpm/hooks"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-
-update-po:
- $(MAKE) -C lib/libalpm/po update-po
- $(MAKE) -C scripts/po update-po
- $(MAKE) -C src/pacman/po update-po
-
-.PHONY: update-po
diff --git a/RELEASE b/RELEASE
index 7a9184b4..1ce462fd 100644
--- a/RELEASE
+++ b/RELEASE
@@ -1,22 +1,21 @@
The following checklist should be used for making a pacman release.
-- Ensure "make distcheck" succeeds
+- Ensure "ninja dist" succeeds
- Call a freeze to development.
- Send translation updates to Transifex at least two weeks before a major
release (see below). At this stage, strings can only be changed for a
major issue.
- Update NEWS and README files
- Pull translation updates from Transifex
-- Update version in configure.ac as described in file
+- Update version in meson.build as described in file
- Update doc/index.asciidoc
- Create a signed git tag (git tag -s vX.Y.Z -m "commit message")
-- Create and sign release tarballs (generate with "make distcheck")
- - In addition to the standard autotools toolchain, autoconf-archive is needed
+- Create and sign release tarballs (generate with "ninja dist")
- Update pacman website
Transifex updates are handled using the transifex client. The basic process is:
- Pull updates from transifex ("tx pull -a -f --minimum-perc 75")
-- Update po files ("make update-po")
+- Update po files ("./build-aux/update-po")
- Fix all translation errors found
- Add any new locales to the relevant LINGUAS file
- Optional: Make any manual changes needed (e.g. fixing spacing in a string)
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index 9db39232..00000000
--- a/configure.ac
+++ /dev/null
@@ -1,594 +0,0 @@
-# -*- Autoconf -*-
-# Process this file with autoconf to produce a configure script.
-# Minimum version of autoconf required
-AC_PREREQ(2.64)
-
-# UPDATING VERSION NUMBERS FOR RELEASES
-#
-# libalpm:
-# current
-# The most recent interface number that this library implements.
-# revision
-# The implementation number of the current interface.
-# age
-# The difference between the newest and oldest interfaces that this library
-# implements. In other words, the library implements all the interface
-# numbers in the range from number current - age to current.
-#
-# 1. Start with version information of `0:0:0' for each libtool library.
-# 2. Update the version information only immediately before a public release of
-# your software. More frequent updates are unnecessary, and only guarantee
-# that the current interface number gets larger faster.
-# 3. If the library source code has changed at all since the last update, then
-# increment revision (`c:r:a' becomes `c:r+1:a').
-# 4. If any interfaces have been added, removed, or changed since the last
-# update, increment current, and set revision to 0.
-# 5. If any interfaces have been added since the last public release, then
-# increment age.
-# 6. If any interfaces have been removed since the last public release, then
-# set age to 0.
-#
-# pacman:
-# Extreme huge major changes:
-# pacman_version_major += 1
-# pacman_version_minor = 0
-# pacman_version_micro = 0
-#
-# Real releases:
-# pacman_version_minor += 1
-# pacman_version_micro = 0
-#
-# Bugfix releases:
-# pacman_version_micro += 1
-
-m4_define([lib_current], [12])
-m4_define([lib_revision], [1])
-m4_define([lib_age], [0])
-
-m4_define([pacman_version_major], [5])
-m4_define([pacman_version_minor], [2])
-m4_define([pacman_version_micro], [1])
-m4_define([pacman_version],
- [pacman_version_major.pacman_version_minor.pacman_version_micro])
-
-# Autoconf initialization
-AC_INIT([pacman], [pacman_version], [pacman-dev(a)archlinux.org]
-AC_CONFIG_SRCDIR([config.h.in])
-AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_MACRO_DIR([m4])
-AC_CONFIG_AUX_DIR([build-aux])
-AC_REQUIRE_AUX_FILE([tap-driver.sh])
-
-AC_CANONICAL_HOST
-AM_INIT_AUTOMAKE([1.11 foreign])
-AM_SILENT_RULES([yes])
-
-LT_INIT
-LIB_VERSION=`expr lib_current - lib_age`.lib_age.lib_revision
-LIB_VERSION_INFO="lib_current:lib_revision:lib_age"
-
-# Respect empty CFLAGS during compiler tests
-if test "x$CFLAGS" = "x"; then
- CFLAGS=""
-fi
-
-# Set substitution values for version stuff in Makefiles and anywhere else,
-# and put LIB_VERSION in config.h
-AC_SUBST(LIB_VERSION)
-AC_SUBST(LIB_VERSION_INFO)
-AC_DEFINE_UNQUOTED([LIB_VERSION], ["$LIB_VERSION"], [libalpm version number])
-
-# Help line for root directory
-AC_ARG_WITH(root-dir,
- AS_HELP_STRING([--with-root-dir=path], [set the location of the root operating directory]),
- [ROOTDIR=$withval], [ROOTDIR=/])
-
-# Help line for package extension
-AC_ARG_WITH(pkg-ext,
- AS_HELP_STRING([--with-pkg-ext=ext], [set the file extension used by packages]),
- [PKGEXT=$withval], [PKGEXT=.pkg.tar.gz])
-
-# Help line for source package directory
-AC_ARG_WITH(src-ext,
- AS_HELP_STRING([--with-src-ext=ext], [set the file extension used by source packages]),
- [SRCEXT=$withval], [SRCEXT=.src.tar.gz])
-
-# Help line for buildscript filename
-AC_ARG_WITH(buildscript,
- AS_HELP_STRING([--with-buildscript=name], [set the build script name used by makepkg]),
- [BUILDSCRIPT=$withval], [BUILDSCRIPT=PKGBUILD])
-
-# Help line for buildscript filename
-AC_ARG_WITH(makepkg-template-dir,
- AS_HELP_STRING([--with-makepkg-template-dir=name], [set the template dir used by makepkg-template]),
- [TEMPLATE_DIR=$withval], [TEMPLATE_DIR=${datarootdir}/makepkg-template])
-
-# Help line for debug package suffix
-AC_ARG_WITH(debug-suffix,
- AS_HELP_STRING([--with-debug-suffix=name], [set the suffix for split debugging symbol packages used by makepkg]),
- [DEBUGSUFFIX=$withval], [DEBUGSUFFIX=debug])
-
-# Help line for changing shell used to run install scriptlets
-AC_ARG_WITH(scriptlet-shell,
- AS_HELP_STRING([--with-scriptlet-shell=shell],
- [set the full path to the shell used to run install scriptlets]),
- [SCRIPTLET_SHELL=$withval], [SCRIPTLET_SHELL=/bin/sh])
-
-# Help line for ldconfig path
-AC_ARG_WITH(ldconfig,
- AS_HELP_STRING([--with-ldconfig=path],
- [set the full path to ldconfig]),
- [LDCONFIG=$withval], [LDCONFIG=/sbin/ldconfig])
-
-# Help line for determining whether file is seccomp-enabled
-AC_ARG_WITH(file-seccomp,
- AS_HELP_STRING([--with-file-seccomp={yes|no|auto}],
- [determine whether file is seccomp-enabled @<:@default=auto@:>@]),
- [with_file_seccomp=$withval], [with_file_seccomp=auto])
-
-# Help line for selecting a crypto library
-AC_ARG_WITH(crypto,
- AS_HELP_STRING([--with-crypto={openssl|nettle}],
- [select crypto implementation @<:@default=openssl@:>@]),
- [with_crypto=$withval], [with_crypto=openssl])
-
-# Help line for using gpgme
-AC_ARG_WITH(gpgme,
- AS_HELP_STRING([--with-gpgme], [use GPGME for PGP signature verification]),
- [], [with_gpgme=check])
-
-# Help line for using libcurl
-AC_ARG_WITH(libcurl,
- AS_HELP_STRING([--with-libcurl], [use libcurl for the internal downloader]),
- [], [with_libcurl=check])
-
-# Help line for documentation
-AC_ARG_ENABLE(doc,
- AS_HELP_STRING([--disable-doc], [prevent make from looking at doc/ dir]),
- [wantdoc=$enableval], [wantdoc=yes])
-
-# Help line for doxygen
-AC_ARG_ENABLE(doxygen,
- AS_HELP_STRING([--enable-doxygen], [build your own API docs via Doxygen]),
- [wantdoxygen=$enableval], [wantdoxygen=no])
-
-# Help line for debug
-AC_ARG_ENABLE(debug,
- AS_HELP_STRING([--enable-debug], [enable debugging support]),
- [debug=$enableval], [debug=no])
-
-# Help line for compiler warning flags
-AC_ARG_ENABLE(warningflags,
- AS_HELP_STRING([--enable-warningflags], [enable extra compiler warning flags]),
- [warningflags=$enableval], [warningflags=no])
-
-# Help line for using git version in pacman version string
-AC_ARG_ENABLE(git-version,
- AS_HELP_STRING([--enable-git-version],
- [enable use of git version in version string if available]),
- [wantgitver=$enableval], [wantgitver=no])
-
-# Enable large file support if available (must be enabled before
-# testing compilation against gpgme).
-AC_SYS_LARGEFILE
-
-# Record large file flags in pkgconfig file
-if test "$enable_largefile" != no; then
- if test "$ac_cv_sys_file_offset_bits" != 'no'; then
- LFS_CFLAGS="-D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits"
- fi
-fi
-AC_SUBST(LFS_CFLAGS)
-
-
-# Checks for programs.
-AC_PROG_AWK
-AC_PROG_CC_C99
-AC_PROG_INSTALL
-AC_CHECK_PROGS([PYTHON], [python3 python], [false])
-AC_PATH_PROGS([BASH_SHELL], [bash bash4], [false])
-
-# check for perl 5.10.1 (needed by makepkg-template)
-AC_PATH_PROG([PERL],[perl])
-AC_DEFUN([AX_PROG_PERL_VERSION],
- [AC_CACHE_CHECK([for Perl version $1 or later], [ax_cv_prog_perl_version],
- [AS_IF(["$PERL" -e 'require v$1;' >/dev/null 2>&1],
- [ax_cv_prog_perl_version=yes],
- [ax_cv_prog_perl_version=no])])
- AS_IF([test x"$ax_cv_prog_perl_version" = xyes], [$2], [$3])])
-AX_PROG_PERL_VERSION([5.10.1], [], [AC_MSG_ERROR([perl is too old])])
-
-AS_IF([test "x$BASH_SHELL" = "xfalse"],
- AC_MSG_WARN([*** bash >= 4.4.0 is required for pacman scripts]),
- [bash_version_major=`$BASH_SHELL -c 'echo "${BASH_VERSINFO[[0]]}"'`
- bash_version_minor=`$BASH_SHELL -c 'echo "${BASH_VERSINFO[[1]]}"'`
- ok=yes
- if test "$bash_version_major" -lt 4; then
- ok=no
- fi
- if test "$bash_version_major" -eq 4 && test "$bash_version_minor" -lt 4; then
- ok=no
- fi
- if test "$ok" = "no"; then
- AC_MSG_ERROR([*** bash >= 4.4.0 is required for pacman scripts])
- fi
- unset bash_version_major bash_version_minor ok])
-
-# find installed gettext
-AM_GNU_GETTEXT([external], [need-ngettext])
-AM_GNU_GETTEXT_VERSION(0.13.1)
-
-AC_CHECK_LIB([m], [fabs], ,
- AC_MSG_ERROR([libm is needed to compile pacman!]))
-
-PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], ,
- bashcompdir="${datarootdir}/bash-completion/completions")
-
-# Check for libarchive
-PKG_CHECK_MODULES(LIBARCHIVE, [libarchive >= 3.0.0], ,
- AC_MSG_ERROR([*** libarchive >= 3.0.0 is needed to compile pacman!]))
-
-m4_pattern_forbid([^AX_COMPARE_VERSION$])
-# Check file for seccomp
-if test "x$with_file_seccomp" = "xauto"; then
- file_version="$(file --version| sed -n 's/^file-\(.*\)/\1/p')"
- AX_COMPARE_VERSION([$file_version], [ge], [5.38], [with_file_seccomp=yes])
-fi
-if test "x$with_file_seccomp" = "xyes"; then
- FILECMD="file -S"
-else
- FILECMD="file"
-fi
-AC_SUBST(FILECMD)
-
-# Check for OpenSSL
-have_openssl=no
-have_nettle=no
-if test "x$with_crypto" = "xnettle"; then
- AC_SUBST(pc_crypto, [nettle])
- PKG_CHECK_MODULES(NETTLE, [nettle],
- [AC_DEFINE(HAVE_LIBNETTLE, 1, [Define whether to use nettle]) have_nettle=yes], have_nettle=no)
- if test "x$have_nettle" = xno -a "x$with_crypto" = xnettle; then
- AC_MSG_ERROR([*** nettle support requested but libraries not found])
- fi
-else if test "x$with_crypto" = "xopenssl"; then
- AC_SUBST(pc_crypto, [libcrypto])
- PKG_CHECK_MODULES(LIBSSL, [libcrypto],
- [AC_DEFINE(HAVE_LIBSSL, 1, [Define if libcrypto is available]) have_openssl=yes], have_openssl=no)
- if test "x$have_openssl" = xno; then
- AC_MSG_ERROR([*** openssl support requested but libraries not found])
- fi
-else
- AC_MSG_ERROR([*** unknown crypto support library requested - $with_crypto])
-fi
-fi
-AM_CONDITIONAL(HAVE_LIBSSL, [test "$have_openssl" = "yes"])
-AM_CONDITIONAL(HAVE_LIBNETTLE, [test "$have_nettle" = "yes"])
-
-# Check for libcurl
-have_libcurl=no
-if test "x$with_libcurl" != "xno"; then
- PKG_CHECK_MODULES(LIBCURL, [libcurl >= 7.32.0],
- [AC_DEFINE(HAVE_LIBCURL, 1, [Define if libcurl is available]) have_libcurl=yes], have_libcurl=no)
- if test "x$have_libcurl" = xno -a "x$with_libcurl" = xyes; then
- AC_MSG_ERROR([*** libcurl >= 7.32.0 is required for internal downloader support])
- fi
-fi
-AM_CONDITIONAL(HAVE_LIBCURL, [test "$have_libcurl" = "yes"])
-# used to generate libalpm.pc
-if test "x$have_libcurl" = xyes; then
- AC_SUBST(pc_libcurl, [libcurl])
-fi
-
-# Check for gpgme
-AC_MSG_CHECKING(whether to link with libgpgme)
-AS_IF([test "x$with_gpgme" != "xno"],
- [AC_MSG_RESULT([yes])],
- [AC_MSG_RESULT([no])])
-
-have_gpgme=no
-if test "x$with_gpgme" != "xno"; then
- PKG_CHECK_MODULES(GPGME, [gpgme],
- [AC_DEFINE([HAVE_LIBGPGME], [1], [Define if gpgme should be used to provide GPG signature support.])
- AC_SUBST(pc_gpgme, [gpgme])
- have_gpgme=yes],
- [AM_PATH_GPGME([1.3.0],
- [LIBS_save="$LIBS"
- CPPFLAGS_save="$CPPFLAGS"
- CFLAGS_save="$CFLAGS"
-
- LIBS="$LIBS $GPGME_LIBS"
- CPPFLAGS="$CPPFLAGS $GPGME_CPPFLAGS"
- CFLAGS="$CFLAGS $GPGME_CFLAGS"
-
- AC_MSG_CHECKING([for sane gpgme])
- AC_LINK_IFELSE(
- [AC_LANG_PROGRAM(
- [[#include <gpgme.h>]],
- [[return gpgme_check_version("1.3.0");]])],
- [AC_MSG_RESULT([yes])
- have_gpgme=yes
- AC_DEFINE([HAVE_LIBGPGME], [1], [Define if gpgme should be used to provide GPG signature support.])
- AC_SUBST(pc_gpgme_libs, ["$GPGME_LIBS"])],
- [AC_MSG_RESULT([no])
- have_gpgme=no
- unset GPGME_LIBS
- unset GPGME_CFLAGS]
- AS_IF([test "x$with_gpgme" = "xyes"],
- [AC_MSG_FAILURE([*** gpgme >= 1.3.0 is needed for GPG signature support])])
- )
-
- LIBS="$LIBS_save"
- CPPFLAGS="$CPPFLAGS_save"
- CFLAGS="$CFLAGS_save"
- unset CPPFLAGS_save
- unset CFLAGS_save],)])
-fi
-
-AS_IF([test "x$have_gpgme" = xno -a "x$with_gpgme" = xyes],
- [AC_MSG_FAILURE([--with-gpgme was given, but gpgme was not found])])
-AM_CONDITIONAL([HAVE_LIBGPGME], [test "x$have_gpgme" = "xyes"])
-
-# Checks for header files.
-AC_CHECK_HEADERS([fcntl.h float.h glob.h langinfo.h libintl.h limits.h \
- locale.h mntent.h netinet/in.h netinet/tcp.h \
- stddef.h string.h sys/ioctl.h \
- sys/mnttab.h sys/mount.h \
- sys/param.h sys/statvfs.h sys/time.h sys/types.h \
- sys/ucred.h syslog.h termios.h wchar.h])
-
-# Checks for typedefs, structures, and compiler characteristics.
-AC_C_INLINE
-AC_TYPE_INT64_T
-AC_TYPE_MODE_T
-AC_TYPE_OFF_T
-AC_TYPE_PID_T
-AC_TYPE_SIZE_T
-AC_TYPE_SSIZE_T
-AC_STRUCT_TM
-AC_TYPE_UID_T
-AC_STRUCT_DIRENT_D_TYPE
-PATH_MAX_DEFINED
-
-# Checks for library functions.
-AC_FUNC_FORK
-AC_FUNC_GETMNTENT
-AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
-AC_CHECK_FUNCS([dup2 getcwd getmntinfo gettimeofday memmove memset \
- mkdir realpath regcomp rmdir setenv setlocale strcasecmp \
- strchr strcspn strdup strerror strndup strnlen strrchr \
- strsep strstr strtol swprintf tcflush wcwidth uname])
-AC_CHECK_MEMBERS([struct stat.st_blksize],,,[[#include <sys/stat.h>]])
-
-# For the diskspace code
-FS_STATS_TYPE
-AC_CHECK_MEMBERS([struct statvfs.f_flag],,,[[#include <sys/statvfs.h>]])
-AC_CHECK_MEMBERS([struct statfs.f_flags],,,[[#include <sys/param.h>
- #include <sys/mount.h>]])
-
-# Check if we can use symbol visibility support in GCC
-GCC_VISIBILITY_CC
-
-# Host-dependant definitions
-INODECMD="stat -c '%i %n'"
-STRIP_BINARIES="--strip-all"
-STRIP_SHARED="--strip-unneeded"
-STRIP_STATIC="--strip-debug"
-case "${host_os}" in
- *bsd*)
- INODECMD="stat -f '%i %N'"
- ;;
- darwin*)
- host_os_darwin=yes
- INODECMD="/usr/bin/stat -f '%i %N'"
- STRIP_BINARIES=""
- STRIP_SHARED="-S"
- STRIP_STATIC="-S"
- ;;
-esac
-AM_CONDITIONAL([DARWIN], test "x$host_os_darwin" = "xyes")
-AC_SUBST(INODECMD)
-AC_SUBST(STRIP_BINARIES)
-AC_SUBST(STRIP_SHARED)
-AC_SUBST(STRIP_STATIC)
-
-# Variables plugged into makepkg.conf
-CARCH="${host%%-*}"
-CHOST="${host}"
-AC_SUBST(CARCH)
-AC_SUBST(CHOST)
-
-# Check for documentation support and status
-AC_CHECK_PROGS([ASCIIDOC], [asciidoc])
-AC_MSG_CHECKING([for building documentation])
-if test "x$wantdoc" = "xyes" ; then
- if test $ASCIIDOC ; then
- AC_MSG_RESULT([yes, enabled by configure])
- else
- asciidoc="(warning : asciidoc not installed)"
- AC_MSG_RESULT([yes $asciidoc])
- fi
- wantdoc=yes
-else
- AC_MSG_RESULT([no, disabled by configure])
- wantdoc=no
-fi
-AM_CONDITIONAL(WANT_DOC, test "x$wantdoc" = "xyes")
-
-# Check for doxygen support and status
-AC_CHECK_PROGS([DOXYGEN], [doxygen])
-AC_MSG_CHECKING([for doxygen])
-if test "x$wantdoxygen" = "xyes" ; then
- if test $DOXYGEN ; then
- AC_MSG_RESULT([yes])
- usedoxygen=yes
- else
- AC_MSG_RESULT([no, doxygen missing])
- usedoxygen=no
- fi
-else
- AC_MSG_RESULT([no, disabled by configure])
- usedoxygen=no
-fi
-AM_CONDITIONAL(USE_DOXYGEN, test "x$usedoxygen" = "xyes")
-
-# Enable or disable debug code
-AC_MSG_CHECKING(for debug mode request)
-if test "x$debug" = "xyes" ; then
- AC_MSG_RESULT(yes)
- AC_DEFINE([PACMAN_DEBUG], , [Enable debug code])
- # Check for -fstack-protector availability
- GCC_STACK_PROTECT_LIB
- GCC_STACK_PROTECT_CC
- GCC_STACK_CLASH_PROTECTION
- GCC_FORTIFY_SOURCE_CC
- WARNING_CFLAGS="-g -Wall -Werror"
-else
- AC_MSG_RESULT(no)
- WARNING_CFLAGS="-Wall"
-fi
-
-# Enable or disable compiler warning flags
-AC_MSG_CHECKING(for excessive compiler warning flags)
-if test "x$warningflags" = "xyes" ; then
- AC_MSG_RESULT(yes)
- CFLAGS_ADD([-Wcast-align], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wclobbered], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wempty-body], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wfloat-equal], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wformat-nonliteral], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wformat-security], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wignored-qualifiers], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wimplicit-fallthrough], [WARNING_CFLAGS])
- CFLAGS_ADD([-Winit-self], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wlogical-op], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wmissing-declarations], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wmissing-field-initializers], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wmissing-parameter-type], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wmissing-prototypes], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wold-style-declaration], [WARNING_CFLAGS])
- CFLAGS_ADD([-Woverride-init], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wpointer-arith], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wredundant-decls], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wshadow], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wsign-compare], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wstrict-aliasing], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wstrict-overflow=5], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wstrict-prototypes], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wtype-limits], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wuninitialized], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wunused-but-set-parameter], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wunused-parameter], [WARNING_CFLAGS])
- CFLAGS_ADD([-Wwrite-strings], [WARNING_CFLAGS])
-else
- AC_MSG_RESULT(no)
-fi
-
-# Enable or disable use of git version in pacman version string
-AC_MSG_CHECKING(whether to use git version if available)
-if test "x$wantgitver" = "xyes" ; then
- AC_CHECK_PROGS([GIT], [git])
- AC_CHECK_FILE([.git/], hasgitdir=yes)
- usegitver=$ac_cv_file__git_
- if test $GIT -a "x$hasgitdir" = "xyes"; then
- AC_DEFINE([USE_GIT_VERSION], , [Use GIT version in version string])
- fi
-else
- AC_MSG_RESULT([no, disabled by configure])
- usegitver=no
-fi
-AM_CONDITIONAL(USE_GIT_VERSION, test "x$usegitver" = "xyes")
-
-# Set root directory
-AC_SUBST(ROOTDIR)
-AC_DEFINE_UNQUOTED([ROOTDIR], "$ROOTDIR", [The location of the root operating directory])
-# Set package file extension
-AC_SUBST(PKGEXT)
-AC_DEFINE_UNQUOTED([PKGEXT], "$PKGEXT", [The file extension used by pacman packages])
-# Set source package file extension
-AC_SUBST(SRCEXT)
-AC_DEFINE_UNQUOTED([SRCEXT], "$SRCEXT", [The file extension used by pacman source packages])
-# Set makepkg build script name
-AC_SUBST(BUILDSCRIPT)
-AC_DEFINE_UNQUOTED([BUILDSCRIPT], "$BUILDSCRIPT", [The build script name used by makepkg])
-# Set makepkg-template template directory
-AC_SUBST(TEMPLATE_DIR)
-AC_DEFINE_UNQUOTED([TEMPLATE_DIR], "$TEMPLATE_DIR", [The template directory used by makepkg-teplate])
-# Set makepkg split debugging symbol package suffix
-AC_SUBST(DEBUGSUFFIX)
-AC_DEFINE_UNQUOTED([DEBUGSUFFIX], "$DEBUGSUFFIX", [The suffix for debugging symbol packages used by makepkg])
-# Set shell used by install scriptlets
-AC_SUBST(SCRIPTLET_SHELL)
-AC_DEFINE_UNQUOTED([SCRIPTLET_SHELL], "$SCRIPTLET_SHELL", [The full path of the shell used to run install scriptlets])
-# Set ldconfig path
-AC_SUBST(LDCONFIG)
-AC_DEFINE_UNQUOTED([LDCONFIG], "$LDCONFIG", [The full path to ldconfig])
-
-
-# Configuration files
-AC_CONFIG_FILES([
-lib/libalpm/Makefile
-lib/libalpm/po/Makefile.in
-lib/libalpm/libalpm.pc
-src/common/Makefile
-src/pacman/Makefile
-src/pacman/po/Makefile.in
-src/util/Makefile
-scripts/Makefile
-scripts/po/Makefile.in
-doc/Makefile
-etc/Makefile
-test/pacman/Makefile
-test/pacman/tests/Makefile
-test/scripts/Makefile
-test/util/Makefile
-Makefile
-])
-AC_OUTPUT
-
-echo "
-${PACKAGE_NAME}:
-
- Build information:
- source code location : ${srcdir}
- prefix : ${prefix}
- sysconfdir : $(eval echo ${sysconfdir})
- conf file : $(eval echo ${sysconfdir})/pacman.conf
- localstatedir : $(eval echo ${localstatedir})
- database dir : $(eval echo ${localstatedir})/lib/pacman/
- cache dir : $(eval echo ${localstatedir})/cache/pacman/pkg/
-
- compiler : ${CC}
- preprocessor flags : ${CPPFLAGS}
- compiler flags : ${WARNING_CFLAGS} ${CFLAGS}
- library flags : ${LIBS} ${LIBSSL_LIBS} ${NETTLE_LIBS} ${LIBARCHIVE_LIBS} ${LIBCURL_LIBS} ${GPGME_LIBS}
- linker flags : ${LDFLAGS}
-
- Architecture : ${CARCH}
- Host Type : ${CHOST}
- File inode command : ${INODECMD}
- File seccomp command : ${FILECMD}
-
- libalpm version : ${LIB_VERSION}
- libalpm version info : ${LIB_VERSION_INFO}
- pacman version : ${PACKAGE_VERSION}
- using git version : ${usegitver}
-
- Directory and file information:
- root working directory : ${ROOTDIR}
- package extension : ${PKGEXT}
- source pkg extension : ${SRCEXT}
- build script name : ${BUILDSCRIPT}
- template directory : ${TEMPLATE_DIR}
-
- Compilation options:
- Use libcurl : ${have_libcurl}
- Use GPGME : ${have_gpgme}
- Use OpenSSL : ${have_openssl}
- Use nettle : ${have_nettle}
- Run make in doc/ dir : ${wantdoc} ${asciidoc}
- Doxygen support : ${usedoxygen}
- debug support : ${debug}
- extra warning flags : ${warningflags}
- use git version : ${wantgitver}
-"
diff --git a/doc/Makefile.am b/doc/Makefile.am
deleted file mode 100644
index 4de67566..00000000
--- a/doc/Makefile.am
+++ /dev/null
@@ -1,162 +0,0 @@
-# We have to do some funny stuff here with the manpages. In order to ensure
-# a dist tarball doesn't get put out there without manpages, we keep those
-# files listed in EXTRA_DIST no matter what. However, we only add them to
-# man_MANS if --enable-asciidoc and/or --enable-doxygen are used.
-
-MANPAGES = \
- alpm-hooks.5 \
- pacman.8 \
- makepkg.8 \
- makepkg-template.1 \
- repo-add.8 \
- vercmp.8 \
- pacman-key.8 \
- PKGBUILD.5 \
- makepkg.conf.5 \
- pacman.conf.5 \
- libalpm.3 \
- BUILDINFO.5 \
- pacman-conf.8
-
-DOXYGEN_MANS = $(wildcard man3/*.3)
-
-HTML_MANPAGES = $(addsuffix .html,$(MANPAGES))
-ASCIIDOC_MANPAGES = $(addsuffix .asciidoc,$(MANPAGES))
-
-HTML_OTHER = \
- index.html \
- submitting-patches.html \
- translation-help.html \
- HACKING.html
-
-HTML_DOCS = \
- $(HTML_MANPAGES) \
- $(HTML_OTHER)
-
-EXTRA_DIST = \
- meson.build \
- asciidoc.conf \
- asciidoc-override.css \
- PKGBUILD-example.txt \
- footer.asciidoc \
- index.asciidoc \
- submitting-patches.asciidoc \
- translation-help.asciidoc \
- $(ASCIIDOC_MANPAGES) \
- $(MANPAGES) \
- $(DOXYGEN_MANS)
-
-# Files that should be removed, but which Automake does not know.
-MOSTLYCLEANFILES = *.xml $(MANPAGES) $(HTML_DOCS) \
- pacman-hooks.5 repo-remove.8 website.tar.gz
-
-# Ensure manpages are fresh when building a dist tarball
-dist-hook:
- $(MAKE) $(AM_MAKEFLAGS) clean
- $(MAKE) $(AM_MAKEFLAGS) all
-
-if USE_GIT_VERSION
-GIT_VERSION := $(shell sh -c 'git describe --abbrev=4 --dirty | sed s/^v//')
-REAL_PACKAGE_VERSION = $(GIT_VERSION)
-else
-REAL_PACKAGE_VERSION = $(PACKAGE_VERSION)
-endif
-
-man_MANS =
-dist_man_MANS = $(MANPAGES)
-
-if USE_DOXYGEN
-man_MANS += $(DOXYGEN_MANS)
-
-all-local: doxygen.in
-
-Doxyfile: Doxyfile.in
- sed 's,@OUTPUT_DIRECTORY@,./,' Doxyfile.in >Doxyfile
-
-doxygen.in: Doxyfile
- $(DOXYGEN) $(srcdir)/Doxyfile
-endif
-
-man: $(MANPAGES)
-html: $(HTML_DOCS)
-
-website: website.tar.gz
-
-.PHONY: html website
-
-website.tar.gz: html
- $(AM_V_GEN)bsdtar czf $@ $(HTML_DOCS) \
- asciidoc-override.css \
- -C /etc/asciidoc/stylesheets/ \
- asciidoc.css \
- -C /etc/asciidoc/javascripts/ \
- asciidoc.js \
- -C /etc/asciidoc/ \
- images
-
-pkgdatadir = ${datadir}/${PACKAGE}
-
-ASCIIDOC_OPTS = \
- -f $(srcdir)/asciidoc.conf \
- -a pacman_version="$(REAL_PACKAGE_VERSION)" \
- -a pacman_date="`date +%Y-%m-%d`" \
- -a srcext="$(SRCEXT)" \
- -a pkgext="$(PKGEXT)" \
- -a pkgdatadir=$(pkgdatadir) \
- -a localstatedir=$(localstatedir) \
- -a sysconfdir=$(sysconfdir) \
- -a datarootdir=$(datarootdir) \
- -a rootdir=$(ROOTDIR)
-
-A2X_OPTS = \
- --no-xmllint \
- -d manpage \
- -f manpage \
- --xsltproc-opts='-param man.endnotes.list.enabled 0 -param man.endnotes.are.numbered 0'
-
-# Generate manpages
-%: %.asciidoc asciidoc.conf footer.asciidoc Makefile.am
- $(AM_V_GEN)a2x $(A2X_OPTS) --asciidoc-opts="$(ASCIIDOC_OPTS) --out-file=./$@.xml" $(srcdir)/$@.asciidoc
-
-# Generate HTML pages
-%.html: %.asciidoc asciidoc.conf footer.asciidoc Makefile.am
- $(AM_V_GEN)asciidoc $(ASCIIDOC_OPTS) -o - $*.asciidoc | \
- sed -e 's/\r$$//' > $@
-
-HACKING.html: ../HACKING
- $(AM_V_GEN)asciidoc $(ASCIIDOC_OPTS) -o - ../HACKING | \
- sed -e 's/\r$$//' > $@
-
-# Customizations for certain HTML docs
-%.html: ASCIIDOC_OPTS += -a linkcss -a toc -a icons -a max-width=960px -a stylesheet=asciidoc-override.css
-%.8.html: ASCIIDOC_OPTS += -d manpage
-%.5.html: ASCIIDOC_OPTS += -d manpage
-%.3.html: ASCIIDOC_OPTS += -d manpage
-
-# Custom dependency rules
-PKGBUILD.5 PKGBUILD.5.html: PKGBUILD.5.asciidoc PKGBUILD-example.txt
-
-# Manpages as symlinks
-repo-remove.8: repo-add.8
- $(RM) repo-remove.8
- $(LN_S) repo-add.8 repo-remove.8
-
-pacman-hooks.5: alpm-hooks.5
- $(RM) pacman-hooks.5
- $(LN_S) alpm-hooks.5 pacman-hooks.5
-
-install-data-hook:
- cd $(DESTDIR)$(mandir)/man8 && \
- $(RM) repo-remove.8 && \
- ( $(LN_S) repo-add.8 repo-remove.8 || \
- ln repo-add.8 repo-remove.8 || \
- cp repo-add.8 repo-remove.8 )
- cd $(DESTDIR)$(mandir)/man5 && \
- $(RM) pacman-hooks.5 && \
- ( $(LN_S) alpm-hooks.5 pacman-hooks.5 || \
- ln alpm-hooks.5 pacman-hooks.5 || \
- cp alpm-hooks.5 pacman-hooks.5 )
-
-uninstall-hook:
- $(RM) $(DESTDIR)$(mandir)/man8/repo-remove.8
- $(RM) $(DESTDIR)$(mandir)/man5/pacman-hooks.5
diff --git a/doc/index.asciidoc b/doc/index.asciidoc
index ebf02c20..716ceabf 100644
--- a/doc/index.asciidoc
+++ b/doc/index.asciidoc
@@ -193,11 +193,11 @@ link:https://sources.archlinux.org/other/pacman/[]. To install, download the new
available source tarball, unpack it in a directory, and run the three magic
commands:
- $ ./configure
- $ make
- # make install
+ $ meson build
+ $ ninja -C build
+ # ninja -C build install
-You may wish to read the options presented by `./configure --help` in order to
+You may wish to read the options presented by `meson` in order to
set appropriate paths and build options that are correct for your system.
Development
diff --git a/etc/Makefile.am b/etc/Makefile.am
deleted file mode 100644
index 0d4fbc07..00000000
--- a/etc/Makefile.am
+++ /dev/null
@@ -1,27 +0,0 @@
-dist_sysconf_DATA = makepkg.conf pacman.conf
-EXTRA_DIST = makepkg.conf.in pacman.conf.in
-
-# Files that should be removed, but which Automake does not know.
-MOSTLYCLEANFILES = $(dist_sysconf_DATA)
-
-SED_PROCESS = \
- $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
- $(SED) \
- -e 's|@sysconfdir[@]|$(sysconfdir)|g' \
- -e 's|@localstatedir[@]|$(localstatedir)|g' \
- -e 's|@prefix[@]|$(prefix)|g' \
- -e 's|@PACKAGE_VERSION[@]|$(PACKAGE_VERSION)|g' \
- -e 's|@PACKAGE_NAME[@]|$(PACKAGE_NAME)|g' \
- -e 's|@PKGEXT[@]|$(PKGEXT)|g' \
- -e 's|@SRCEXT[@]|$(SRCEXT)|g' \
- -e 's|@STRIP_BINARIES[@]|$(STRIP_BINARIES)|g' \
- -e 's|@STRIP_SHARED[@]|$(STRIP_SHARED)|g' \
- -e 's|@STRIP_STATIC[@]|$(STRIP_STATIC)|g' \
- -e 's|@CARCH[@]|$(CARCH)|g' \
- -e 's|@CHOST[@]|$(CHOST)|g' \
- -e 's|@ARCHSWITCH[@]|$(ARCHSWITCH)|g' \
- -e 's|@ROOTDIR[@]|$(ROOTDIR)|g' \
- < $< > $@
-
-%.conf: %.conf.in Makefile
- $(SED_PROCESS)
diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am
deleted file mode 100644
index e4f83223..00000000
--- a/lib/libalpm/Makefile.am
+++ /dev/null
@@ -1,78 +0,0 @@
-AUTOMAKE_OPTIONS = gnu
-
-SUBDIRS = po
-
-EXTRA_DIST = meson.build po/meson.build
-
-lib_LTLIBRARIES = libalpm.la
-include_HEADERS = alpm_list.h alpm.h
-
-AM_CPPFLAGS = \
- -imacros $(top_builddir)/config.h \
- -DSYSHOOKDIR=\"@datarootdir@/libalpm/hooks/\" \
- -DLOCALEDIR=\"@localedir@\"
-
-AM_CFLAGS = -pedantic -D_GNU_SOURCE $(WARNING_CFLAGS)
-
-if ENABLE_VISIBILITY_CC
-if DARWIN
-AM_CFLAGS += -fvisibility=hidden
-else
-AM_CFLAGS += -fvisibility=internal
-endif
-endif
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libalpm.pc
-
-libalpm_la_SOURCES = \
- add.h add.c \
- alpm.h alpm.c \
- alpm_list.h alpm_list.c \
- backup.h backup.c \
- base64.h base64.c \
- be_local.c \
- be_package.c \
- be_sync.c \
- conflict.h conflict.c \
- db.h db.c \
- deps.h deps.c \
- diskspace.h diskspace.c \
- dload.h dload.c \
- error.c \
- filelist.h filelist.c \
- graph.h graph.c \
- group.h group.c \
- handle.h handle.c \
- hook.h hook.c \
- ini.h ini.c \
- libarchive-compat.h \
- log.h log.c \
- package.h package.c \
- pkghash.h pkghash.c \
- rawstr.c \
- remove.h remove.c \
- signing.c signing.h \
- sync.h sync.c \
- trans.h trans.c \
- util.h util.c \
- util-common.h util-common.c \
- version.c
-
-libalpm_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_INFO)
-
-libalpm_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(GPGME_CFLAGS) \
- $(LIBARCHIVE_CFLAGS) \
- $(LIBCURL_CFLAGS) \
- $(LIBSSL_CFLAGS) \
- $(NETTLE_CFLAGS)
-
-libalpm_la_LIBADD = \
- $(LTLIBINTL) \
- $(GPGME_LIBS) \
- $(LIBARCHIVE_LIBS) \
- $(LIBCURL_LIBS) \
- $(LIBSSL_LIBS) \
- $(NETTLE_LIBS)
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
deleted file mode 100644
index 47455ed2..00000000
--- a/scripts/Makefile.am
+++ /dev/null
@@ -1,287 +0,0 @@
-# enforce that all scripts have a --help and --version option
-AUTOMAKE_OPTIONS = std-options
-AM_INSTALLCHECK_STD_OPTIONS_EXEMPT = \
- $(WRAPPER)
-
-SUBDIRS = po
-
-pkgconfigdir = $(datarootdir)/pkgconfig
-pkgconfig_DATA = libmakepkg.pc
-
-bin_SCRIPTS = \
- $(OURSCRIPTS) \
- makepkg-template \
- repo-remove \
- repo-elephant \
- $(WRAPPER)
-
-OURSCRIPTS = \
- makepkg \
- pacman-db-upgrade \
- pacman-key \
- repo-add
-
-EXTRA_DIST = \
- meson.build \
- libmakepkg.pc.in \
- makepkg.sh.in \
- makepkg-template.pl.in \
- pacman-db-upgrade.sh.in \
- pacman-key.sh.in \
- repo-add.sh.in \
- wrapper.sh.in \
- $(COMPLETION_DIST) \
- $(LIBMAKEPKG_DIST) \
- po/meson.build
-
-libmakepkgdir = $(datarootdir)/makepkg
-
-LIBMAKEPKGDIRS = \
- buildenv \
- executable \
- integrity \
- lint_config \
- lint_package \
- lint_pkgbuild \
- source \
- tidy \
- util
-
-LIBMAKEPKG_IN = \
- libmakepkg/executable.sh \
- libmakepkg/executable/ccache.sh \
- libmakepkg/executable/checksum.sh \
- libmakepkg/executable/distcc.sh \
- libmakepkg/executable/fakeroot.sh \
- libmakepkg/executable/gpg.sh \
- libmakepkg/executable/gzip.sh \
- libmakepkg/executable/pacman.sh \
- libmakepkg/executable/strip.sh \
- libmakepkg/executable/sudo.sh \
- libmakepkg/executable/vcs.sh \
- libmakepkg/buildenv.sh \
- libmakepkg/buildenv/buildflags.sh \
- libmakepkg/buildenv/compiler.sh \
- libmakepkg/buildenv/debugflags.sh \
- libmakepkg/buildenv/makeflags.sh \
- libmakepkg/integrity.sh \
- libmakepkg/integrity/generate_checksum.sh \
- libmakepkg/integrity/generate_signature.sh \
- libmakepkg/integrity/verify_checksum.sh \
- libmakepkg/integrity/verify_signature.sh \
- libmakepkg/lint_config.sh \
- libmakepkg/lint_config/ext.sh \
- libmakepkg/lint_config/paths.sh \
- libmakepkg/lint_config/source_date_epoch.sh \
- libmakepkg/lint_config/variable.sh \
- libmakepkg/lint_package.sh \
- libmakepkg/lint_package/build_references.sh \
- libmakepkg/lint_package/dotfiles.sh \
- libmakepkg/lint_package/file_names.sh \
- libmakepkg/lint_package/missing_backup.sh \
- libmakepkg/lint_pkgbuild.sh \
- libmakepkg/lint_pkgbuild/arch.sh \
- libmakepkg/lint_pkgbuild/arch_specific.sh \
- libmakepkg/lint_pkgbuild/backup.sh \
- libmakepkg/lint_pkgbuild/changelog.sh \
- libmakepkg/lint_pkgbuild/checkdepends.sh \
- libmakepkg/lint_pkgbuild/conflicts.sh \
- libmakepkg/lint_pkgbuild/depends.sh \
- libmakepkg/lint_pkgbuild/epoch.sh \
- libmakepkg/lint_pkgbuild/fullpkgver.sh \
- libmakepkg/lint_pkgbuild/install.sh \
- libmakepkg/lint_pkgbuild/makedepends.sh \
- libmakepkg/lint_pkgbuild/optdepends.sh \
- libmakepkg/lint_pkgbuild/options.sh \
- libmakepkg/lint_pkgbuild/package_function.sh \
- libmakepkg/lint_pkgbuild/package_function_variable.sh \
- libmakepkg/lint_pkgbuild/pkgbase.sh \
- libmakepkg/lint_pkgbuild/pkglist.sh \
- libmakepkg/lint_pkgbuild/pkgname.sh \
- libmakepkg/lint_pkgbuild/pkgrel.sh \
- libmakepkg/lint_pkgbuild/pkgver.sh \
- libmakepkg/lint_pkgbuild/provides.sh \
- libmakepkg/lint_pkgbuild/source.sh \
- libmakepkg/lint_pkgbuild/util.sh \
- libmakepkg/lint_pkgbuild/variable.sh \
- libmakepkg/source.sh \
- libmakepkg/source/bzr.sh \
- libmakepkg/source/file.sh \
- libmakepkg/source/git.sh \
- libmakepkg/source/hg.sh \
- libmakepkg/source/local.sh \
- libmakepkg/source/svn.sh \
- libmakepkg/srcinfo.sh \
- libmakepkg/tidy.sh \
- libmakepkg/tidy/docs.sh \
- libmakepkg/tidy/emptydirs.sh \
- libmakepkg/tidy/libtool.sh \
- libmakepkg/tidy/purge.sh \
- libmakepkg/tidy/staticlibs.sh \
- libmakepkg/tidy/strip.sh \
- libmakepkg/tidy/zipman.sh \
- libmakepkg/util.sh \
- libmakepkg/util/compress.sh \
- libmakepkg/util/config.sh \
- libmakepkg/util/dirsize.sh \
- libmakepkg/util/error.sh \
- libmakepkg/util/message.sh \
- libmakepkg/util/option.sh \
- libmakepkg/util/parseopts.sh \
- libmakepkg/util/pkgbuild.sh \
- libmakepkg/util/schema.sh \
- libmakepkg/util/source.sh \
- libmakepkg/util/util.sh
-
-LIBMAKEPKG_DIST = \
- libmakepkg/meson.build \
- $(addprefix libmakepkg/, $(addsuffix /meson.build, $(LIBMAKEPKGDIRS))) \
- $(addsuffix .in, $(LIBMAKEPKG_IN))
-
-WRAPPER = \
- makepkg-wrapper \
- pacman-db-upgrade-wrapper \
- pacman-key-wrapper \
- repo-add-wrapper
-
-COMPLETION_IN = \
- completion/bash_completion \
- completion/zsh_completion
-
-COMPLETION_DIST = \
- $(addsuffix .in, $(COMPLETION_IN))
-
-# Files that should be removed, but which Automake does not know.
-MOSTLYCLEANFILES = $(bin_SCRIPTS) $(LIBMAKEPKG_IN) $(COMPLETION_IN) libmakepkg.pc
-
-clean-local:
- $(AM_V_at)$(RM) -r .lib
-
-if USE_GIT_VERSION
-GIT_VERSION := $(shell sh -c 'git describe --abbrev=4 --dirty | sed s/^v//')
-REAL_PACKAGE_VERSION = $(GIT_VERSION)
-else
-REAL_PACKAGE_VERSION = $(PACKAGE_VERSION)
-endif
-
-#### Taken from the autoconf scripts Makefile.am ####
-edit = sed \
- -e 's|@rootdir[@]|$(ROOTDIR)|g' \
- -e 's|@localedir[@]|$(localedir)|g' \
- -e 's|@sysconfdir[@]|$(sysconfdir)|g' \
- -e 's|@localstatedir[@]|$(localstatedir)|g' \
- -e 's|@libmakepkgdir[@]|$(libmakepkgdir)|g' \
- -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' \
- -e 's|@prefix[@]|$(prefix)|g' \
- -e '1s|!/bin/bash|!$(BASH_SHELL)|g' \
- -e 's|@PACKAGE_VERSION[@]|$(REAL_PACKAGE_VERSION)|g' \
- -e 's|@PACKAGE_BUGREPORT[@]|$(PACKAGE_BUGREPORT)|g' \
- -e 's|@PACKAGE_NAME[@]|$(PACKAGE_NAME)|g' \
- -e 's|@BUILDSCRIPT[@]|$(BUILDSCRIPT)|g' \
- -e 's|@TEMPLATE_DIR[@]|$(TEMPLATE_DIR)|g' \
- -e 's|@DEBUGSUFFIX[@]|$(DEBUGSUFFIX)|g' \
- -e "s|@INODECMD[@]|$(INODECMD)|g" \
- -e "s|@FILECMD[@]|$(FILECMD)|g" \
- -e 's|@SCRIPTNAME[@]|$@|g'
-
-## All the scripts depend on Makefile so that they are rebuilt when the
-## prefix etc. changes. Use chmod -w to prevent people from editing the
-## wrong file by accident.
-$(OURSCRIPTS): %: %.sh.in wrapper.sh.in $(LIBMAKEPKG_IN) Makefile
- $(AM_V_at)$(RM) $@
- $(AM_V_GEN)test -f $(srcdir)/$@.sh.in && $(edit) $(srcdir)/$@.sh.in >$@
- $(AM_V_at)chmod +x,a-w $@
- @$(BASH_SHELL) -O extglob -n $@
-
-$(LIBMAKEPKG_IN): %: %.in Makefile
- $(AM_V_at)$(RM) $@
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)test -f $(srcdir)/$@.in && $(edit) $(srcdir)/$@.in >$@
- $(AM_V_at)chmod a-w $@
- @$(BASH_SHELL) -O extglob -n $@
-
-$(COMPLETION_IN) libmakepkg.pc: %: %.in Makefile
- $(AM_V_at)$(RM) $@
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)$(edit) $(srcdir)/$@.in >$@
- $(AM_V_at)chmod a-w $@
-
-all-am: $(COMPLETION_IN)
-
-makepkg-template: \
- $(srcdir)/makepkg-template.pl.in \
- Makefile
-
- $(AM_V_at)$(RM) -f makepkg-template
- $(AM_V_GEN)$(edit) $< > $@
- $(AM_V_at)chmod +x,a-w $@
-
-repo-remove repo-elephant: repo-add
- $(AM_V_at)$(RM) $@
- $(AM_V_at)$(LN_S) repo-add $@
-
-.SECONDEXPANSION:
-$(WRAPPER): \
- $(srcdir)/wrapper.sh.in \
- $$(subst -wrapper,,$$@)
-
- $(AM_V_at)$(MKDIR_P) .lib
- $(AM_V_at)mv -f $(subst -wrapper,,$@) .lib
- $(AM_V_at)$(RM) $@
- $(AM_V_GEN)sed \
- -e "s|@PWD[@]|$$(pwd)|" \
- -e "s|@PROGNAME[@]|$(subst -wrapper,,$@)|g" \
- -e '1s|!/bin/bash|!$(BASH_SHELL)|g' \
- $(srcdir)/wrapper.sh.in > $@
- $(AM_V_at)chmod +x,a-w $@
- $(AM_V_at)$(LN_S) $@ $(subst -wrapper,,$@)
-
-install-data-local:
- $(MKDIR_P) $(DESTDIR)$(bashcompdir)
- $(INSTALL_DATA) completion/bash_completion $(DESTDIR)/$(bashcompdir)/pacman
- for completion in makepkg pacman-key; do \
- $(LN_S) pacman $(DESTDIR)/$(bashcompdir)/$$completion; \
- done
- $(MKDIR_P) $(DESTDIR)$(datarootdir)/zsh/site-functions/
- $(INSTALL_DATA) completion/zsh_completion $(DESTDIR)$(datarootdir)/zsh/site-functions/_pacman
-
-uninstall-local:
- $(RM) $(DESTDIR)$(bashcompdir)/makepkg
- $(RM) $(DESTDIR)$(bashcompdir)/pacman
- $(RM) $(DESTDIR)$(bashcompdir)/pacman-key
- $(RM) $(DESTDIR)$(datarootdir)/zsh/site-functions/_pacman
-
-install-exec-hook:
- for wrapper in $(WRAPPER); do \
- $(RM) $(DESTDIR)$(bindir)/$${wrapper}; \
- $(INSTALL) .lib/$${wrapper%-wrapper} $(DESTDIR)$(bindir)/$${wrapper%-wrapper}; \
- done
- for dir in $(LIBMAKEPKGDIRS); do \
- $(MKDIR_P) $(DESTDIR)$(libmakepkgdir)/$$dir; \
- done
- for lib in $(LIBMAKEPKG); do \
- $(INSTALL) $(srcdir)/$$lib $(DESTDIR)$(libmakepkgdir)/$${lib#libmakepkg}; \
- done
- for lib in $(LIBMAKEPKG_IN); do \
- $(INSTALL) $$lib $(DESTDIR)$(libmakepkgdir)/$${lib#libmakepkg}; \
- done
- cd $(DESTDIR)$(bindir) && \
- $(RM) repo-elephant && \
- ( $(LN_S) repo-add repo-elephant || \
- ln repo-add repo-elephant || \
- cp repo-add repo-elephant )
- cd $(DESTDIR)$(bindir) && \
- $(RM) repo-remove && \
- ( $(LN_S) repo-add repo-remove || \
- ln repo-add repo-remove || \
- cp repo-add repo-remove )
-
-uninstall-hook:
- cd $(DESTDIR)$(bindir) && \
- $(RM) repo-remove repo-elephant
- for lib in $(LIBMAKEPKG) $(LIBMAKEPKG_IN); do \
- $(RM) $(DESTDIR)$(libmakepkgdir)/$${lib#libmakepkg}; \
- done
- for dir in $(LIBMAKEPKGDIRS); do \
- $(RM) -r $(DESTDIR)$(libmakepkgdir)/$$dir; \
- done
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
deleted file mode 100644
index 05378712..00000000
--- a/src/common/Makefile.am
+++ /dev/null
@@ -1,3 +0,0 @@
-EXTRA_DIST = \
- meson.build \
- ini.h ini.c util-common.h util-common.c
diff --git a/src/pacman/Makefile.am b/src/pacman/Makefile.am
deleted file mode 100644
index ac2f8e46..00000000
--- a/src/pacman/Makefile.am
+++ /dev/null
@@ -1,69 +0,0 @@
-SUBDIRS = po
-
-EXTRA_DIST = meson.build po/meson.build
-
-# paths set at make time
-conffile = ${sysconfdir}/pacman.conf
-dbpath = ${localstatedir}/lib/pacman/
-gpgdir = ${sysconfdir}/pacman.d/gnupg/
-hookdir = ${sysconfdir}/pacman.d/hooks/
-cachedir = ${localstatedir}/cache/pacman/pkg/
-logfile = ${localstatedir}/log/pacman.log
-
-bin_PROGRAMS = pacman pacman-conf
-
-AM_CPPFLAGS = \
- -imacros $(top_builddir)/config.h \
- -I$(top_srcdir)/lib/libalpm \
- -DLOCALEDIR=\"@localedir@\" \
- -DCONFFILE=\"$(conffile)\" \
- -DDBPATH=\"$(dbpath)\" \
- -DGPGDIR=\"$(gpgdir)\" \
- -DHOOKDIR=\"$(hookdir)\" \
- -DCACHEDIR=\"$(cachedir)\" \
- -DLOGFILE=\"$(logfile)\"
-
-AM_CFLAGS = -pedantic -D_GNU_SOURCE $(WARNING_CFLAGS) \
- $(LIBARCHIVE_CFLAGS)
-
-if USE_GIT_VERSION
-GIT_VERSION := $(shell sh -c 'git describe --abbrev=4 --dirty | sed s/^v//')
-AM_CPPFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
-endif
-
-pacman_SOURCES = \
- check.h check.c \
- conf.h conf.c \
- database.c \
- deptest.c \
- files.c \
- ini.h ini.c \
- package.h package.c \
- pacman.h pacman.c \
- query.c \
- remove.c \
- sighandler.h sighandler.c \
- sync.c \
- callback.h callback.c \
- upgrade.c \
- util.h util.c \
- util-common.h util-common.c
-
-pacman_LDADD = \
- $(LTLIBINTL) \
- $(top_builddir)/lib/libalpm/.libs/libalpm.la \
- $(LIBARCHIVE_LIBS)
-
-pacman_conf_SOURCES = pacman-conf.c \
- util.h \
- util.c \
- ini.h \
- ini.c \
- util-common.h \
- util-common.c \
- callback.h \
- callback.c \
- conf.h \
- conf.c
-
-pacman_conf_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
deleted file mode 100644
index a454f224..00000000
--- a/src/util/Makefile.am
+++ /dev/null
@@ -1,27 +0,0 @@
-EXTRA_DIST = meson.build
-
-# paths set at make time
-conffile = ${sysconfdir}/pacman.conf
-dbpath = ${localstatedir}/lib/pacman/
-gpgdir = ${sysconfdir}/pacman.d/gnupg/
-cachedir = ${localstatedir}/cache/pacman/pkg/
-
-bin_PROGRAMS = vercmp testpkg
-
-AM_CPPFLAGS = \
- -imacros $(top_builddir)/config.h \
- -I$(top_srcdir)/lib/libalpm \
- -DLOCALEDIR=\"@localedir@\" \
- -DCONFFILE=\"$(conffile)\" \
- -DDBPATH=\"$(dbpath)\" \
- -DGPGDIR=\"$(gpgdir)\" \
- -DCACHEDIR=\"$(cachedir)\"
-
-AM_CFLAGS = -pedantic -D_GNU_SOURCE $(WARNING_CFLAGS) \
- $(LIBARCHIVE_CFLAGS)
-
-testpkg_SOURCES = testpkg.c
-testpkg_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la
-
-vercmp_SOURCES = vercmp.c
-vercmp_LDADD = $(top_builddir)/lib/libalpm/libalpm_la-version.lo
diff --git a/test/pacman/Makefile.am b/test/pacman/Makefile.am
deleted file mode 100644
index d211215a..00000000
--- a/test/pacman/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-SUBDIRS = tests
-
-check_SCRIPTS = \
- pactest.py \
- pmdb.py \
- pmenv.py \
- pmfile.py \
- pmpkg.py \
- pmrule.py \
- pmtest.py \
- tap.py \
- util.py
-
-noinst_SCRIPTS = $(check_SCRIPTS)
-
-EXTRA_DIST = \
- meson.build \
- README \
- TODO \
- ChangeLog \
- ldconfig.stub \
- $(check_SCRIPTS)
diff --git a/test/pacman/tests/Makefile.am b/test/pacman/tests/Makefile.am
deleted file mode 100644
index ba3d0993..00000000
--- a/test/pacman/tests/Makefile.am
+++ /dev/null
@@ -1,5 +0,0 @@
-check_SCRIPTS = $(wildcard *.py)
-
-noinst_SCRIPTS = $(check_SCRIPTS)
-
-EXTRA_DIST = $(check_SCRIPTS)
diff --git a/test/scripts/Makefile.am b/test/scripts/Makefile.am
deleted file mode 100644
index 0100bffb..00000000
--- a/test/scripts/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-check_SCRIPTS = \
- parseopts_test.sh \
- pacman-db-upgrade-v9.py \
- makepkg-template_test.sh
-
-noinst_SCRIPTS = $(check_SCRIPTS)
-
-EXTRA_DIST = \
- meson.build \
- $(check_SCRIPTS)
diff --git a/test/util/Makefile.am b/test/util/Makefile.am
deleted file mode 100644
index a270079f..00000000
--- a/test/util/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
-check_SCRIPTS = \
- vercmptest.sh
-
-noinst_SCRIPTS = $(check_SCRIPTS)
-
-EXTRA_DIST = \
- meson.build \
- $(check_SCRIPTS)
--
2.26.2
2
1
[pacman-dev] [GIT] The official pacman repository branch, master, updated. v5.2.1-83-g8ce142a2
by Allan McRae 11 May '20
by Allan McRae 11 May '20
11 May '20
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The official pacman repository".
The branch, master has been updated
via 8ce142a2552418f64a74e773f659d92b065d6209 (commit)
via 8e769ddb8a59a9fbacf4614283d2fb519f022386 (commit)
via 7423b166047ff168ef337818958bf86ed1d42a0a (commit)
via 559590256c48fa5f995944de3802911e5a56ba7f (commit)
from 22a58f5420438f35effb991696d37529d7a31969 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 8ce142a2552418f64a74e773f659d92b065d6209
Author: Levente Polyak <anthraxx(a)archlinux.org>
Date: Mon May 11 00:45:49 2020 +0200
makepkg: deterministic PKGINFO libprovides for multiple library versions
While iterating over the provides array, the find call for locating a
shared library may result in listing multiple entries which by itself
does not produce a stable deterministic order and may vary depending on
the underlying filesystem.
To provide a stable listing and a reproducible .PKGINFO file the result
of find is piped to sort with a static LC_ALL=C localisation.
Signed-off-by: Levente Polyak <anthraxx(a)archlinux.org>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit 8e769ddb8a59a9fbacf4614283d2fb519f022386
Author: Eli Schwartz <eschwartz(a)archlinux.org>
Date: Sun May 10 00:32:39 2020 -0400
Log invalid conf settings as an error
This is not a warning, _parse_options() returns failure without even
parsing further lines and the attempted pacman/pacman-conf program
execution immediately aborts. Warnings are for when e.g. later on if we
don't recognize a setting at all, we skip over it and have enough
confidence in this to continue executing the program.
The current implementation results in pacman-conf aborting with:
warning: config file /etc/pacman.conf, line 60: invalid value for 'ParallelDownloads' : '2.5'
error parsing '/etc/pacman.conf'
or pacman -Syu aborting with the entirely more cryptic:
warning: config file /etc/pacman.conf, line 59: invalid value for 'ParallelDownloads' : '2.5'
and this isn't just a problem for the newly added ParallelDownloads
setting, either, you could get the same problem if you specified a
broken XferCommand, but that's harder as it's more accepting of input
and you probably don't hit this except with unbalanced quotes.
Signed-off-by: Eli Schwartz <eschwartz(a)archlinux.org>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit 7423b166047ff168ef337818958bf86ed1d42a0a
Author: Eli Schwartz <eschwartz(a)archlinux.org>
Date: Sun May 10 00:32:40 2020 -0400
pacman-conf: fix incomplete support for ILoveCandy
This was only partially implemented in the original implementation.
`pacman-conf | grep ILoveCandy` would tell you if it was set, but
querying directly by name would not.
Signed-off-by: Eli Schwartz <eschwartz(a)archlinux.org>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit 559590256c48fa5f995944de3802911e5a56ba7f
Author: Eli Schwartz <eschwartz(a)archlinux.org>
Date: Sun May 10 00:32:38 2020 -0400
pacman-conf: add support for new ParallelDownloads config option
This was forgotten in the initial implementation, so it was impossible
to figure out the value from a script, or correctly roundtrip the
config file.
Signed-off-by: Eli Schwartz <eschwartz(a)archlinux.org>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
-----------------------------------------------------------------------
Summary of changes:
scripts/makepkg.sh.in | 2 +-
src/pacman/conf.c | 8 ++++----
src/pacman/pacman-conf.c | 15 +++++++++++++++
3 files changed, 20 insertions(+), 5 deletions(-)
hooks/post-receive
--
The official pacman repository
1
0
[pacman-dev] [PATCH] makepkg: deterministic PKGINFO libprovides for multiple library versions
by anthraxxï¼ archlinux.org 11 May '20
by anthraxxï¼ archlinux.org 11 May '20
11 May '20
From: Levente Polyak <anthraxx(a)archlinux.org>
While iterating over the provides array, the find call for locating a
shared library may result in listing multiple entries which by itself
does not produce a stable deterministic order and may vary depending on
the underlying filesystem.
To provide a stable listing and a reproducible .PKGINFO file the result
of find is piped to sort with a static LC_ALL=C localisation.
Signed-off-by: Levente Polyak <anthraxx(a)archlinux.org>
---
scripts/makepkg.sh.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index d1416d15..b95a03af 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -521,7 +521,7 @@ find_libprovides() {
missing=0
case "$p" in
*.so)
- mapfile -t filename < <(find "$pkgdir" -type f -name $p\*)
+ mapfile -t filename < <(find "$pkgdir" -type f -name $p\* | LC_ALL=C sort)
if [[ $filename ]]; then
# packages may provide multiple versions of the same library
for fn in "${filename[@]}"; do
--
2.26.2
3
2
[pacman-dev] [PATCH 1/3] pacman-conf: add support for new ParallelDownloads config option
by Eli Schwartz 10 May '20
by Eli Schwartz 10 May '20
10 May '20
This was forgotten in the initial implementation, so it was impossible
to figure out the value from a script, or correctly roundtrip the
config file.
Signed-off-by: Eli Schwartz <eschwartz(a)archlinux.org>
---
src/pacman/pacman-conf.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/src/pacman/pacman-conf.c b/src/pacman/pacman-conf.c
index 60739bf6..d76c0985 100644
--- a/src/pacman/pacman-conf.c
+++ b/src/pacman/pacman-conf.c
@@ -142,6 +142,14 @@ static void show_str(const char *directive, const char *val)
printf("%s%c", val, sep);
}
+static void show_int(const char *directive, unsigned int val)
+{
+ if (verbose) {
+ printf("%s = ", directive);
+ }
+ printf("%u%c", val, sep);
+}
+
static void show_list_str(const char *directive, alpm_list_t *list)
{
alpm_list_t *i;
@@ -261,6 +269,8 @@ static void dump_config(void)
show_bool("ILoveCandy", config->chomp);
show_bool("NoProgressBar", config->noprogressbar);
+ show_int("ParallelDownloads", config->parallel_downloads);
+
show_cleanmethod("CleanMethod", config->cleanmethod);
show_siglevel("SigLevel", config->siglevel, 0);
@@ -372,6 +382,9 @@ static int list_directives(void)
} else if(strcasecmp(i->data, "NoProgressBar") == 0) {
show_bool("NoProgressBar", config->noprogressbar);
+ } else if(strcasecmp(i->data, "ParallelDownloads") == 0) {
+ show_int("ParallelDownloads", config->parallel_downloads);
+
} else if(strcasecmp(i->data, "CleanMethod") == 0) {
show_cleanmethod("CleanMethod", config->cleanmethod);
--
2.26.2
2
8
[pacman-dev] [GIT] The official pacman repository branch, master, updated. v5.2.1-79-g22a58f54
by Allan McRae 09 May '20
by Allan McRae 09 May '20
09 May '20
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The official pacman repository".
The branch, master has been updated
via 22a58f5420438f35effb991696d37529d7a31969 (commit)
via 557845bc971ff272c53da773baea277a2d2d47b8 (commit)
via 0346e0eef224ab8ba22b659026ffdf2bfe95f3ae (commit)
via b96e0df4dceaa2677baa1a3563211950708d3e63 (commit)
via c78eb48d915dc22146073162dda08ddf73c4a508 (commit)
via 64c4669f579dc5ad8d05329abffbd752ad0ed8f2 (commit)
via 6a331af27fe6dc7842725d067fd2fb4a1c60c139 (commit)
via 1d42a8f954eed3205e84cfb946b67ba889b04135 (commit)
via fa68c33fa821cd7ddc5ae32baf62af2a238e44dc (commit)
via dc98d0ea09f3632cd28a12099f3f09d466dcad1d (commit)
via a8a1a1bb3ec98a8471cb5cd13d096f39a267f789 (commit)
via fe8e13341bdeae4a59c0270a632c29e71ae9deda (commit)
via cffda331adca0aedd7c1fc17d739c27fc8041a20 (commit)
from 411b12d09ddb47722acf6d354c17ee9ee5228964 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 22a58f5420438f35effb991696d37529d7a31969
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Sat Apr 18 19:15:44 2020 -0700
Swap alpm_db_update() implementation to multiplexed version
Now when all callers of the old alpm_db_update() function are gone we can
remove this implementation. And then rename alpm_dbs_update() function to
alpm_db_update().
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit 557845bc971ff272c53da773baea277a2d2d47b8
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Sat Apr 18 19:05:13 2020 -0700
Convert downloading databases to the new multiplexed API
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit 0346e0eef224ab8ba22b659026ffdf2bfe95f3ae
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Sat Apr 18 19:00:49 2020 -0700
Convert download packages logic to multiplexed API
Create a list of dload_payloads and pass it to the new _alpm_multi_*
interface.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit b96e0df4dceaa2677baa1a3563211950708d3e63
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Fri Apr 17 10:36:38 2020 -0700
Implement multibar UI
Multiplexed download requires ability to draw UI for multiple active progress
bars. To implement it we use ANSI codes to move cursor up/down and then
redraw the required progress bar.
`pacman_multibar_ui.active_downloads` field represents the list of active
downloads that correspond to progress bars.
`struct pacman_progress_bar` is a data structure for a progress bar.
In some cases (e.g. database downloads) we want to keep progress bars in order.
In some other cases (package downloads) we want to move completed items to the
top of the screen. Function `multibar_move_completed_up` allows to configure
such behavior.
Per discussion in the maillist we do not want to show download progress for
signature files.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit c78eb48d915dc22146073162dda08ddf73c4a508
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Tue May 5 19:50:51 2020 -0700
Extend download callback interface with start/complete events
With the previous download interface the callback uses the first progress
event as 'download has started' signal. Unfortunately it does not work with
up-to-date files that never receive 'download progress' events.
Up-to-date database messages are currently handled in sync_syncdbs()
after the sequential download is completed and a result from ALPM is
received. But this is not going to work with multiplexed download
interface that returns the result only after all files are completed.
Another problem with 'first progress event is the beginning of the
download' is that such events time are unpredictable. Thus the UI progress
bar order might differ from what has been passed by client to
alpm_dbs_update() function. We actually want to keep the dbs progress bars
in a strict order.
To help to solve the given problems extend the download callback to
allow 2 more events - download started and completed. 'Download started'
events appear in the same order as in the list given by a client.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit 64c4669f579dc5ad8d05329abffbd752ad0ed8f2
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Tue May 5 18:28:49 2020 -0700
Introduce event types for start/end database list download
Multiplexed database/files downloads will use multiple progress bars.
The UI logic is quite complicated and printing error messages while
handling multiple progress bars is going to be challenging.
Instead we are going to save all ALPM error messages to a list and flush
it at the end of the download process. Use on_progress variable that
blocks error messages printing.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit 6a331af27fe6dc7842725d067fd2fb4a1c60c139
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Mon Apr 13 21:48:55 2020 -0700
Implement multiplexed download using mCURL
curl_multi_download_internal() is the main loop that creates up to
'ParallelDownloads' easy curl handles, adds them to mcurl and then
performs curl execution. This is when the paralled downloads happens.
Once any of the downloads complete the function checks its result.
In case if the download fails it initiates retry with the next server
from payload->servers list. At the download completion all the payload
resources are cleaned up.
curl_multi_check_finished_download() is essentially refactored version of
curl_download_internal() adopted for multi_curl. Once mcurl porting is
complete curl_download_internal() will be removed.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit 1d42a8f954eed3205e84cfb946b67ba889b04135
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Mon Apr 13 21:40:54 2020 -0700
Implement _alpm_multi_download
It is an equivalent of _alpm_download but accepts a list of payloads.
curl_multi_download_internal() is a stub at this moment and will be
implemented in the later commits of this patch series.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit fa68c33fa821cd7ddc5ae32baf62af2a238e44dc
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Mon Mar 9 15:36:48 2020 -0700
Inline dload_payload->curlerr field into a local variable
dload_payload->curlerr is a field that is used inside
curl_download_internal() function only. It can be converted to a local
variable.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit dc98d0ea09f3632cd28a12099f3f09d466dcad1d
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Mon Mar 9 15:23:12 2020 -0700
Add multi_curl handle to ALPM global context
To be able to run multiple download in parallel efficiently we need to
use curl_multi interface [1]. It introduces a set of APIs over new type
of handler 'CURLM'.
Create CURLM object at the application start and set it to global ALPM
context.
The 'single-download' CURL handle moves to payload struct. A new CURL
handle is created for each payload with intention to be processed by CURLM.
Note that curl_download_internal() is not ported to CURLM interface due
to the fact that the function will go away soon.
[1] https://curl.haxx.se/libcurl/c/libcurl-multi.html
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit a8a1a1bb3ec98a8471cb5cd13d096f39a267f789
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Thu Mar 26 13:19:59 2020 -0700
Introduce alpm_dbs_update() function for parallel db updates
This is an equivalent of alpm_db_update but for multiplexed (parallel)
download. The difference is that this function accepts list of
databases to update. And then ALPM internals download it in parallel if
possible.
Add a stub for _alpm_multi_download the function that will do parallel
payloads downloads in the future.
Introduce dload_payload->filepath field that contains url path to the
file we download. It is like fileurl field but does not contain
protocol/server part. The rationale for having this field is that with
the curl multidownload the server retry logic is going to move to a curl
callback. And the callback needs to be able to reconstruct the 'next'
fileurl. One will be able to do it by getting the next server url from
'servers' list and then concat with filepath. Once the 'parallel download'
refactoring is over 'fileurl' field will go away.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit fe8e13341bdeae4a59c0270a632c29e71ae9deda
Author: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Date: Sun Mar 8 13:33:32 2020 -0700
Add config option to specify amount of parallel download streams
It includes pacman.conf new 'ParallelDownloads' option that
specifies how many concurrent downloads cURL starts in parallel.
Add alpm_option_set_parallel_downloads() ALPM function that
allows to set this config option programmatically.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
commit cffda331adca0aedd7c1fc17d739c27fc8041a20
Author: Eli Schwartz <eschwartz(a)archlinux.org>
Date: Tue May 5 22:09:42 2020 -0400
doc: remove vim modelines from BUILDINFO(5)
We (thought we) removed all modelines from the project in commit
860e4c4943ad062bd0eff99f28e7d64804b3c08e, but apparently this one
sneaked in by virtue of this manpage being added to the project after
the "remove all the modelines" patch was submitted, but before it was
applied.
I must have failed to update the patch to remove it from this file also.
Signed-off-by: Eli Schwartz <eschwartz(a)archlinux.org>
Signed-off-by: Allan McRae <allan(a)archlinux.org>
-----------------------------------------------------------------------
Summary of changes:
README | 14 ++
doc/BUILDINFO.5.asciidoc | 3 -
doc/pacman.conf.5.asciidoc | 5 +
etc/pacman.conf.in | 1 +
lib/libalpm/alpm.c | 12 +-
lib/libalpm/alpm.h | 106 +++++----
lib/libalpm/be_sync.c | 195 ++++++++---------
lib/libalpm/dload.c | 521 +++++++++++++++++++++++++++++++++++++++++----
lib/libalpm/dload.h | 11 +-
lib/libalpm/handle.c | 20 +-
lib/libalpm/handle.h | 3 +-
lib/libalpm/sync.c | 75 +++----
src/pacman/callback.c | 408 +++++++++++++++++++++++------------
src/pacman/callback.h | 7 +-
src/pacman/conf.c | 58 ++++-
src/pacman/conf.h | 2 +
src/pacman/sync.c | 2 +
src/pacman/util.c | 45 ++--
src/pacman/util.h | 4 +
19 files changed, 1086 insertions(+), 406 deletions(-)
hooks/post-receive
--
The official pacman repository
1
0
[pacman-dev] [PATCH v3] Convert download packages logic to multiplexed API
by Anatol Pomozov 08 May '20
by Anatol Pomozov 08 May '20
08 May '20
Create a list of dload_payloads and pass it to the new _alpm_multi_*
interface.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
---
README | 11 +++++++
lib/libalpm/alpm.h | 9 ------
lib/libalpm/dload.c | 1 -
lib/libalpm/sync.c | 73 +++++++++++++++----------------------------
src/pacman/callback.c | 4 ---
5 files changed, 36 insertions(+), 62 deletions(-)
diff --git a/README b/README
index 6818ef70..f5bbaf02 100644
--- a/README
+++ b/README
@@ -655,3 +655,14 @@ API CHANGES BETWEEN 5.1 AND 5.2
- alpm_errno_t - added member ALPM_ERR_MISSING_CAPABILITY_SIGNATURES
- alpm_sync_newversion() replaced with alpm_sync_get_new_version() which
does not filter on any ALPM_DB_USAGE_*.
+
+
+API CHANGES BETWEEN 5.2 AND 6.0
+===============================
+
+[REMOVED]
+- ALPM_EVENT_PKGDOWNLOAD_START, ALPM_EVENT_PKGDOWNLOAD_DONE, ALPM_EVENT_PKGDOWNLOAD_FAILED
+
+[CHANGED]
+
+[ADDED]
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 534a8189..903e2fbc 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -414,15 +414,6 @@ typedef enum _alpm_event_type_t {
ALPM_EVENT_PKG_RETRIEVE_DONE,
/** Not all package files were successfully downloaded from a repository. */
ALPM_EVENT_PKG_RETRIEVE_FAILED,
- /** A file will be downloaded from a repository; See alpm_event_pkgdownload_t
- * for arguments */
- ALPM_EVENT_PKGDOWNLOAD_START,
- /** A file was downloaded from a repository; See alpm_event_pkgdownload_t
- * for arguments */
- ALPM_EVENT_PKGDOWNLOAD_DONE,
- /** A file failed to be downloaded from a repository; See
- * alpm_event_pkgdownload_t for arguments */
- ALPM_EVENT_PKGDOWNLOAD_FAILED,
/** Disk space usage will be computed for a package. */
ALPM_EVENT_DISKSPACE_START,
/** Disk space usage was computed for a package. */
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 9ab0e5c4..13aa4086 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -952,7 +952,6 @@ static int curl_multi_download_internal(alpm_handle_t *handle,
}
payloads = payloads->next;
- // TODO: report that download has started
} else {
// the payload failed to start, do not start any new downloads just wait until
// active one complete.
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 855ca69c..f329de10 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -726,47 +726,13 @@ static int find_dl_candidates(alpm_handle_t *handle, alpm_list_t **files)
return 0;
}
-static int download_single_file(alpm_handle_t *handle, struct dload_payload *payload,
- const char *cachedir)
-{
- alpm_event_pkgdownload_t event = {
- .type = ALPM_EVENT_PKGDOWNLOAD_START,
- .file = payload->remote_name
- };
- const alpm_list_t *server;
-
- payload->handle = handle;
- payload->allow_resume = 1;
-
- EVENT(handle, &event);
- for(server = payload->servers; server; server = server->next) {
- const char *server_url = server->data;
- size_t len;
-
- /* print server + filename into a buffer */
- len = strlen(server_url) + strlen(payload->remote_name) + 2;
- MALLOC(payload->fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
- snprintf(payload->fileurl, len, "%s/%s", server_url, payload->remote_name);
-
- if(_alpm_download(payload, cachedir, NULL, NULL) != -1) {
- event.type = ALPM_EVENT_PKGDOWNLOAD_DONE;
- EVENT(handle, &event);
- return 0;
- }
- _alpm_dload_payload_reset_for_retry(payload);
- }
-
- event.type = ALPM_EVENT_PKGDOWNLOAD_FAILED;
- EVENT(handle, &event);
- return -1;
-}
-
static int download_files(alpm_handle_t *handle)
{
const char *cachedir;
alpm_list_t *i, *files = NULL;
int errors = 0;
alpm_event_t event;
+ alpm_list_t *payloads = NULL;
cachedir = _alpm_filecache_setup(handle);
handle->trans->state = STATE_DOWNLOADING;
@@ -814,26 +780,37 @@ static int download_files(alpm_handle_t *handle)
event.type = ALPM_EVENT_PKG_RETRIEVE_START;
EVENT(handle, &event);
- event.type = ALPM_EVENT_PKG_RETRIEVE_DONE;
for(i = files; i; i = i->next) {
const alpm_pkg_t *pkg = i->data;
- struct dload_payload payload = {0};
-
- STRDUP(payload.remote_name, pkg->filename, GOTO_ERR(handle, ALPM_ERR_MEMORY, finish));
- payload.servers = pkg->origin_data.db->servers;
- payload.max_size = pkg->size;
-
- if(download_single_file(handle, &payload, cachedir) == -1) {
- errors++;
- event.type = ALPM_EVENT_PKG_RETRIEVE_FAILED;
- _alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files\n"));
- }
- _alpm_dload_payload_reset(&payload);
+ struct dload_payload *payload = NULL;
+
+ CALLOC(payload, 1, sizeof(*payload), GOTO_ERR(handle, ALPM_ERR_MEMORY, finish));
+ STRDUP(payload->remote_name, pkg->filename, FREE(payload); GOTO_ERR(handle, ALPM_ERR_MEMORY, finish));
+ STRDUP(payload->filepath, pkg->filename,
+ FREE(payload->remote_name); FREE(payload);
+ GOTO_ERR(handle, ALPM_ERR_MEMORY, finish));
+ payload->max_size = pkg->size;
+ payload->servers = pkg->origin_data.db->servers;
+ payload->handle = handle;
+ payload->allow_resume = 1;
+
+ payloads = alpm_list_add(payloads, payload);
+ }
+ event.type = ALPM_EVENT_PKG_RETRIEVE_DONE;
+ if(_alpm_multi_download(handle, payloads, cachedir) == -1) {
+ errors++;
+ event.type = ALPM_EVENT_PKG_RETRIEVE_FAILED;
+ _alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files\n"));
}
EVENT(handle, &event);
}
finish:
+ if(payloads) {
+ alpm_list_free_inner(payloads, (alpm_list_fn_free)_alpm_dload_payload_reset);
+ FREELIST(payloads);
+ }
+
if(files) {
alpm_list_free(files);
}
diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index c2e516ec..25909e02 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -405,10 +405,6 @@ void cb_event(alpm_event_t *event)
case ALPM_EVENT_DISKSPACE_DONE:
case ALPM_EVENT_HOOK_DONE:
case ALPM_EVENT_HOOK_RUN_DONE:
- /* we can safely ignore those as well */
- case ALPM_EVENT_PKGDOWNLOAD_START:
- case ALPM_EVENT_PKGDOWNLOAD_DONE:
- case ALPM_EVENT_PKGDOWNLOAD_FAILED:
/* nothing */
break;
}
--
2.26.2
1
0
Multiplexed download requires ability to draw UI for multiple active progress
bars. To implement it we use ANSI codes to move cursor up/down and then
redraw the required progress bar.
`pacman_multibar_ui.active_downloads` field represents the list of active
downloads that correspond to progress bars.
`struct pacman_progress_bar` is a data structure for a progress bar.
In some cases (e.g. database downloads) we want to keep progress bars in order.
In some other cases (package downloads) we want to move completed items to the
top of the screen. Function `multibar_move_completed_up` allows to configure
such behavior.
Per discussion in the maillist we do not want to show download progress for
signature files.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
---
lib/libalpm/be_sync.c | 1 +
lib/libalpm/dload.c | 61 +++----
lib/libalpm/dload.h | 2 +-
src/pacman/callback.c | 387 ++++++++++++++++++++++++++++--------------
src/pacman/callback.h | 4 +
src/pacman/sync.c | 2 +
src/pacman/util.c | 18 ++
src/pacman/util.h | 4 +
8 files changed, 320 insertions(+), 159 deletions(-)
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index add1a576..86015ab6 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -366,6 +366,7 @@ int SYMEXPORT alpm_dbs_update(alpm_handle_t *handle, alpm_list_t *dbs, int force
if(siglevel & ALPM_SIG_DATABASE) {
struct dload_payload *sig_payload;
CALLOC(sig_payload, 1, sizeof(*sig_payload), GOTO_ERR(handle, ALPM_ERR_MEMORY, cleanup));
+ sig_payload->signature = 1;
/* print filename into a buffer (leave space for separator and .sig) */
len = strlen(db->treename) + strlen(dbext) + 5;
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 2f360ab8..9ab0e5c4 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -90,6 +90,11 @@ static int dload_progress_cb(void *file, curl_off_t dltotal, curl_off_t dlnow,
off_t current_size, total_size;
alpm_download_event_progress_t cb_data = {0};
+ /* do not print signature files progress bar */
+ if(payload->signature) {
+ return 0;
+ }
+
/* avoid displaying progress bar for redirects with a body */
if(payload->respcode >= 300) {
return 0;
@@ -100,6 +105,11 @@ static int dload_progress_cb(void *file, curl_off_t dltotal, curl_off_t dlnow,
return 1;
}
+ if(dlnow < 0 || dltotal <= 0 || dlnow > dltotal) {
+ /* bogus values : stop here */
+ return 0;
+ }
+
current_size = payload->initial_size + dlnow;
/* is our filesize still under any set limit? */
@@ -115,34 +125,15 @@ static int dload_progress_cb(void *file, curl_off_t dltotal, curl_off_t dlnow,
total_size = payload->initial_size + dltotal;
- if(dltotal == 0 || payload->prevprogress == total_size) {
+ if(payload->prevprogress == total_size) {
return 0;
}
- /* initialize the progress bar here to avoid displaying it when
- * a repo is up to date and nothing gets downloaded.
- * payload->handle->dlcb will receive the remote_name
- * and the following arguments:
- * 0, -1: download initialized
- * 0, 0: non-download event
- * x {x>0}, x: download complete
- * x {x>0, x<y}, y {y > 0}: download progress, expected total is known */
- if(!payload->cb_initialized) {
- cb_data.downloaded = 0;
- cb_data.total = -1;
- payload->cb_initialized = 1;
- }
- if(payload->prevprogress == current_size) {
- cb_data.downloaded = 0;
- cb_data.total = 0;
- } else {
/* do NOT include initial_size since it wasn't part of the package's
* download_size (nor included in the total download size callback) */
- cb_data.downloaded = dlnow;
- cb_data.total = dltotal;
- }
+ cb_data.total = dltotal;
+ cb_data.downloaded = dlnow;
payload->handle->dlcb(payload->remote_name, ALPM_DOWNLOAD_PROGRESS, &cb_data);
-
payload->prevprogress = current_size;
return 0;
@@ -375,6 +366,8 @@ static int curl_download_internal(struct dload_payload *payload,
double remote_size, bytes_dl;
struct sigaction orig_sig_pipe, orig_sig_int;
CURLcode curlerr;
+ alpm_download_event_init_t init_cb_data = {0};
+ alpm_download_event_completed_t completed_cb_data = {0};
/* shortcut to our handle within the payload */
alpm_handle_t *handle = payload->handle;
CURL *curl = curl_easy_init();
@@ -444,6 +437,8 @@ static int curl_download_internal(struct dload_payload *payload,
dload_interrupted = 0;
mask_signal(SIGINT, &inthandler, &orig_sig_int);
+ handle->dlcb(payload->remote_name, ALPM_DOWNLOAD_INIT, &init_cb_data);
+
/* perform transfer */
curlerr = curl_easy_perform(curl);
_alpm_log(handle, ALPM_LOG_DEBUG, "curl returned error %d from transfer\n",
@@ -604,6 +599,10 @@ cleanup:
raise(SIGINT);
}
+ completed_cb_data.total = bytes_dl;
+ completed_cb_data.result = ret;
+ handle->dlcb(payload->remote_name, ALPM_DOWNLOAD_COMPLETED, &completed_cb_data);
+
return ret;
}
@@ -665,7 +664,6 @@ static int curl_multi_check_finished_download(CURLM *curlm, CURLMsg *msg,
long remote_time = -1;
struct stat st;
char hostname[HOSTNAME_SIZE];
- alpm_download_event_completed_t cb_data = {0};
int ret = -1;
curlerr = curl_easy_getinfo(curl, CURLINFO_PRIVATE, &payload);
@@ -825,9 +823,12 @@ cleanup:
unlink(payload->tempfile_name);
}
- cb_data.total = bytes_dl;
- cb_data.result = ret;
- handle->dlcb(payload->remote_name, ALPM_DOWNLOAD_COMPLETED, &cb_data);
+ if(!payload->signature) {
+ alpm_download_event_completed_t cb_data = {0};
+ cb_data.total = bytes_dl;
+ cb_data.result = ret;
+ handle->dlcb(payload->remote_name, ALPM_DOWNLOAD_COMPLETED, &cb_data);
+ }
curl_multi_remove_handle(curlm, curl);
curl_easy_cleanup(curl);
@@ -945,9 +946,11 @@ static int curl_multi_download_internal(alpm_handle_t *handle,
struct dload_payload *payload = payloads->data;
if(curl_multi_add_payload(handle, curlm, payload, localpath) == 0) {
- alpm_download_event_init_t cb_data = {.optional = payload->errors_ok};
+ if(!payload->signature) {
+ alpm_download_event_init_t cb_data = {.optional = payload->errors_ok};
+ handle->dlcb(payload->remote_name, ALPM_DOWNLOAD_INIT, &cb_data);
+ }
- handle->dlcb(payload->remote_name, ALPM_DOWNLOAD_INIT, &cb_data);
payloads = payloads->next;
// TODO: report that download has started
} else {
@@ -1129,6 +1132,7 @@ char SYMEXPORT *alpm_fetch_pkgurl(alpm_handle_t *handle, const char *url)
sig_filepath = filecache_find_url(handle, payload.fileurl);
if(sig_filepath == NULL) {
+ payload.signature = 1;
payload.handle = handle;
payload.trust_remote_name = 1;
payload.force = 1;
@@ -1184,5 +1188,4 @@ void _alpm_dload_payload_reset_for_retry(struct dload_payload *payload)
payload->initial_size += payload->prevprogress;
payload->prevprogress = 0;
payload->unlink_on_fail = 0;
- payload->cb_initialized = 0;
}
diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h
index 3f2fb9ea..8b52cdae 100644
--- a/lib/libalpm/dload.h
+++ b/lib/libalpm/dload.h
@@ -42,7 +42,7 @@ struct dload_payload {
int errors_ok;
int unlink_on_fail;
int trust_remote_name;
- int cb_initialized;
+ int signature; /* specifies if the payload is a signature file */
#ifdef HAVE_LIBCURL
CURL *curl;
char error_buffer[CURL_ERROR_SIZE];
diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index 613d59d4..c2e516ec 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -18,6 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <assert.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -52,6 +54,50 @@ static alpm_list_t *output = NULL;
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
#endif
+struct pacman_progress_bar {
+ const char *filename;
+ off_t xfered;
+ off_t total_size;
+ uint64_t init_time; /* Time when this download started doing any progress */
+ uint64_t sync_time; /* Last time we updated the bar info */
+ double rate;
+ unsigned int eta; /* ETA in seconds */
+ bool completed; /* transfer is completed */
+};
+
+/* This datastruct represents the state of multiline progressbar UI */
+struct pacman_multibar_ui {
+ /* List of active downloads handled by multibar UI.
+ * Once the first download in the list is completed it is removed
+ * from this list and we never redraw it anymore.
+ * If the download is in this list, then the UI can redraw the progress bar or change
+ * the order of the bars (e.g. moving completed bars to the top of the list)
+ */
+ alpm_list_t *active_downloads; /* List of type 'struct pacman_progress_bar' */
+
+ /* Number of active download bars that multibar UI handles. */
+ size_t active_downloads_num;
+
+ /* Specifies whether a completed progress bar need to be reordered and moved
+ * to the top of the list.
+ */
+ bool move_completed_up;
+
+ /* Cursor position relative to the first active progress bar,
+ * e.g. 0 means the first active progress bar, active_downloads_num-1 means the last bar,
+ * active_downloads_num - is the line below all progress bars.
+ */
+ int cursor_lineno;
+};
+
+struct pacman_multibar_ui multibar_ui = {0};
+
+static void cursor_goto_end(void);
+
+void multibar_move_completed_up(bool value) {
+ multibar_ui.move_completed_up = value;
+}
+
static int64_t get_time_ms(void)
{
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) && defined(CLOCK_MONOTONIC_COARSE)
@@ -152,11 +198,7 @@ static void fill_progress(const int bar_percent, const int disp_percent,
printf(" %3d%%", disp_percent);
}
- if(bar_percent == 100) {
- putchar('\n');
- } else {
- putchar('\r');
- }
+ putchar('\r');
fflush(stdout);
}
@@ -346,6 +388,7 @@ void cb_event(alpm_event_t *event)
case ALPM_EVENT_DB_RETRIEVE_FAILED:
case ALPM_EVENT_PKG_RETRIEVE_DONE:
case ALPM_EVENT_PKG_RETRIEVE_FAILED:
+ cursor_goto_end();
flush_output_list();
on_progress = 0;
break;
@@ -629,6 +672,7 @@ void cb_progress(alpm_progress_t event, const char *pkgname, int percent,
fill_progress(percent, percent, cols - infolen);
if(percent == 100) {
+ putchar('\n');
flush_output_list();
on_progress = 0;
} else {
@@ -647,149 +691,87 @@ void cb_dl_total(off_t total)
}
}
-/* callback to handle display of download progress */
-static void dload_progress_event(const char *filename, off_t file_xfered, off_t file_total)
+static int dload_progressbar_enabled(void)
+{
+ return !config->noprogressbar && (getcols() != 0);
+}
+
+/* Goto the line that corresponds to num-th active download */
+static void cursor_goto_bar(int num)
+{
+ if(num > multibar_ui.cursor_lineno) {
+ console_cursor_move_down(num - multibar_ui.cursor_lineno);
+ } else if(num < multibar_ui.cursor_lineno) {
+ console_cursor_move_up(multibar_ui.cursor_lineno - num);
+ }
+ multibar_ui.cursor_lineno = num;
+}
+
+/* Goto the line *after* the last active progress bar */
+static void cursor_goto_end(void)
+{
+ cursor_goto_bar(multibar_ui.active_downloads_num);
+}
+
+/* Returns true if element with the specified name is found, false otherwise */
+static bool find_bar_for_filename(const char *filename, int *index, struct pacman_progress_bar **bar)
+{
+ int i = 0;
+ alpm_list_t *listitem = multibar_ui.active_downloads;
+ for(; listitem; listitem = listitem->next, i++) {
+ struct pacman_progress_bar *b = listitem->data;
+ if (strcmp(b->filename, filename) == 0) {
+ /* we found a progress bar with the given name */
+ *index = i;
+ *bar = b;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void draw_pacman_progress_bar(struct pacman_progress_bar *bar)
{
- static double rate_last;
- static off_t xfered_last;
- static int64_t initial_time = 0;
int infolen;
int filenamelen;
char *fname, *p;
/* used for wide character width determination and printing */
int len, wclen, wcwid, padwid;
wchar_t *wcfname;
-
- int totaldownload = 0;
- off_t xfered, total;
- double rate = 0.0;
- unsigned int eta_h = 0, eta_m = 0, eta_s = 0;
+ unsigned int eta_h = 0, eta_m = 0, eta_s = bar->eta;
double rate_human, xfered_human;
const char *rate_label, *xfered_label;
- int file_percent = 0, total_percent = 0;
+ int file_percent = 0;
const unsigned short cols = getcols();
- /* Nothing has changed since last callback; stop here */
- if(file_xfered == 0 && file_total == 0) {
- return;
- }
-
- if(config->noprogressbar || cols == 0) {
- if(file_xfered == 0 && file_total == -1) {
- printf(_("downloading %s...\n"), filename);
- fflush(stdout);
- }
- return;
- }
-
- infolen = cols * 6 / 10;
- if(infolen < 50) {
- infolen = 50;
- }
- /* only use TotalDownload if enabled and we have a callback value */
- if(config->totaldownload && list_total) {
- /* sanity check */
- if(list_xfered + file_total <= list_total) {
- totaldownload = 1;
- } else {
- /* bogus values : don't enable totaldownload and reset */
- list_xfered = 0;
- list_total = 0;
- }
- }
-
- if(totaldownload) {
- xfered = list_xfered + file_xfered;
- total = list_total;
- } else {
- xfered = file_xfered;
- total = file_total;
- }
-
- /* this is basically a switch on xfered: 0, total, and
- * anything else */
- if(file_xfered == 0 && file_total == -1) {
- /* set default starting values, ensure we only call this once
- * if TotalDownload is enabled */
- if(!totaldownload || (totaldownload && list_xfered == 0)) {
- initial_time = get_time_ms();
- xfered_last = (off_t)0;
- rate_last = 0.0;
- get_update_timediff(1);
- }
- } else if(xfered > total || xfered < 0) {
- /* bogus values : stop here */
- return;
- } else if(file_xfered == file_total) {
- /* compute final values */
- int64_t timediff = get_time_ms() - initial_time;
- if(timediff > 0) {
- rate = (double)xfered / (timediff / 1000.0);
- /* round elapsed time (in ms) to the nearest second */
- eta_s = (unsigned int)(timediff + 500) / 1000;
- } else {
- eta_s = 0;
- }
- } else {
- /* compute current average values */
- int64_t timediff = get_update_timediff(0);
-
- if(timediff < UPDATE_SPEED_MS) {
- /* return if the calling interval was too short */
- return;
- }
- rate = (double)(xfered - xfered_last) / (timediff / 1000.0);
- /* average rate to reduce jumpiness */
- rate = (rate + 2 * rate_last) / 3;
- if(rate > 0.0) {
- eta_s = (total - xfered) / rate;
- } else {
- eta_s = UINT_MAX;
- }
- rate_last = rate;
- xfered_last = xfered;
- }
-
- if(file_total) {
- file_percent = (file_xfered * 100) / file_total;
+ if(bar->total_size) {
+ file_percent = (bar->xfered * 100) / bar->total_size;
} else {
file_percent = 100;
}
- if(totaldownload) {
- total_percent = ((list_xfered + file_xfered) * 100) /
- list_total;
-
- /* if we are at the end, add the completed file to list_xfered */
- if(file_xfered == file_total) {
- list_xfered += file_total;
- }
- }
-
/* fix up time for display */
eta_h = eta_s / 3600;
eta_s -= eta_h * 3600;
eta_m = eta_s / 60;
eta_s -= eta_m * 60;
- len = strlen(filename);
+ len = strlen(bar->filename);
fname = malloc(len + 1);
- memcpy(fname, filename, len + 1);
+ memcpy(fname, bar->filename, len + 1);
/* strip package or DB extension for cleaner look */
if((p = strstr(fname, ".pkg")) || (p = strstr(fname, ".db")) || (p = strstr(fname, ".files"))) {
- /* tack on a .sig suffix for signatures */
- if(memcmp(&filename[len - 4], ".sig", 4) == 0) {
- memcpy(p, ".sig", 4);
-
- /* adjust length for later calculations */
- len = p - fname + 4;
- } else {
- len = p - fname;
- }
+ len = p - fname;
fname[len] = '\0';
}
+ infolen = cols * 6 / 10;
+ if(infolen < 50) {
+ infolen = 50;
+ }
+
/* 1 space + filenamelen + 1 space + 6 for size + 1 space + 3 for label +
* + 2 spaces + 4 for rate + 1 space + 3 for label + 2 for /s + 1 space +
* 8 for eta, gives us the magic 33 */
@@ -824,8 +806,8 @@ static void dload_progress_event(const char *filename, off_t file_xfered, off_t
}
- rate_human = humanize_size((off_t)rate, '\0', -1, &rate_label);
- xfered_human = humanize_size(xfered, '\0', -1, &xfered_label);
+ rate_human = humanize_size((off_t)bar->rate, '\0', -1, &rate_label);
+ xfered_human = humanize_size(bar->xfered, '\0', -1, &xfered_label);
printf(" %ls%-*s ", wcfname, padwid, "");
/* We will show 1.62 MiB/s, 11.6 MiB/s, but 116 KiB/s and 1116 KiB/s */
@@ -850,19 +832,166 @@ static void dload_progress_event(const char *filename, off_t file_xfered, off_t
free(fname);
free(wcfname);
- if(totaldownload) {
- fill_progress(file_percent, total_percent, cols - infolen);
+ fill_progress(file_percent, file_percent, cols - infolen);
+ return;
+}
+
+static void dload_init_event(const char *filename, alpm_download_event_init_t *data)
+{
+ (void)data;
+
+ if(!dload_progressbar_enabled()) {
+ printf(_(" %s downloading...\n"), filename);
+ return;
+ }
+
+ struct pacman_progress_bar *bar = calloc(1, sizeof(struct pacman_progress_bar));
+ assert(bar);
+ bar->filename = filename;
+ bar->init_time = get_time_ms();
+ bar->rate = 0.0;
+ multibar_ui.active_downloads = alpm_list_add(multibar_ui.active_downloads, bar);
+
+ cursor_goto_end();
+ printf(_(" %s downloading...\n"), filename);
+ multibar_ui.cursor_lineno++;
+ multibar_ui.active_downloads_num++;
+}
+
+/* Draws download progress */
+static void dload_progress_event(const char *filename, alpm_download_event_progress_t *data)
+{
+ int index;
+ struct pacman_progress_bar *bar;
+ int64_t curr_time = get_time_ms();
+ double last_chunk_rate;
+ int64_t timediff;
+
+ if(!dload_progressbar_enabled()) {
+ return;
+ }
+
+ assert(find_bar_for_filename(filename, &index, &bar));
+
+ /* compute current average values */
+ timediff = curr_time - bar->sync_time;
+
+ if(timediff < UPDATE_SPEED_MS) {
+ /* return if the calling interval was too short */
+ return;
+ }
+ bar->sync_time = curr_time;
+
+ last_chunk_rate = (double)(data->downloaded - bar->xfered) / (timediff / 1000.0);
+ /* average rate to reduce jumpiness */
+ bar->rate = (last_chunk_rate + 2 * bar->rate) / 3;
+ if(bar->rate > 0.0) {
+ bar->eta = (data->total - data->downloaded) / bar->rate;
} else {
- fill_progress(file_percent, file_percent, cols - infolen);
+ bar->eta = UINT_MAX;
+ }
+
+ /* Total size is received after the download starts. */
+ bar->total_size = data->total;
+ bar->xfered = data->downloaded;
+
+ cursor_goto_bar(index);
+ draw_pacman_progress_bar(bar);
+ fflush(stdout);
+}
+
+/* download completed */
+static void dload_complete_event(const char *filename, alpm_download_event_completed_t *data)
+{
+ int index;
+ struct pacman_progress_bar *bar;
+ int64_t timediff;
+
+ if(!dload_progressbar_enabled()) {
+ return;
+ }
+
+ assert(find_bar_for_filename(filename, &index, &bar));
+ bar->completed = true;
+
+ /* This may not have been initialized if the download finished before
+ * an alpm_download_event_progress_t event happened */
+ bar->total_size = data->total;
+
+ if(data->result == 1) {
+ cursor_goto_bar(index);
+ printf(_(" %s is up to date"), bar->filename);
+ /* The line contains text from previous status. Erase these leftovers. */
+ console_erase_line();
+ } else if(data->result == 0) {
+ /* compute final values */
+ bar->xfered = bar->total_size;
+ timediff = get_time_ms() - bar->init_time;
+
+ /* if transfer was too fast, treat it as a 1ms transfer, for the sake
+ * of the rate calculation */
+ if(timediff < 1)
+ timediff = 1;
+
+ bar->rate = (double)bar->xfered / (timediff / 1000.0);
+ /* round elapsed time (in ms) to the nearest second */
+ bar->eta = (unsigned int)(timediff + 500) / 1000;
+
+ if(multibar_ui.move_completed_up && index != 0) {
+ /* If this item completed then move it to the top.
+ * Swap 0-th bar data with `index`-th one
+ */
+ struct pacman_progress_bar *former_topbar = multibar_ui.active_downloads->data;
+ alpm_list_t *baritem = alpm_list_nth(multibar_ui.active_downloads, index);
+ multibar_ui.active_downloads->data = bar;
+ baritem->data = former_topbar;
+
+ cursor_goto_bar(index);
+ draw_pacman_progress_bar(former_topbar);
+
+ index = 0;
+ }
+
+ cursor_goto_bar(index);
+ draw_pacman_progress_bar(bar);
+ } else {
+ cursor_goto_bar(index);
+ printf(_(" %s failed to download"), bar->filename);
+ console_erase_line();
+ }
+ fflush(stdout);
+
+ /* If the first bar is completed then there is no reason to keep it
+ * in the list as we are not going to redraw it anymore.
+ */
+ while(multibar_ui.active_downloads) {
+ alpm_list_t *head = multibar_ui.active_downloads;
+ struct pacman_progress_bar *j = head->data;
+ if(j->completed) {
+ multibar_ui.cursor_lineno--;
+ multibar_ui.active_downloads_num--;
+ multibar_ui.active_downloads = alpm_list_remove_item(
+ multibar_ui.active_downloads, head);
+ free(head);
+ free(j);
+ } else {
+ break;
+ }
}
- return;
}
+/* Callback to handle display of download progress */
void cb_download(const char *filename, alpm_download_event_type_t event, void *data)
{
- if(event == ALPM_DOWNLOAD_PROGRESS) {
- alpm_download_event_progress_t *progress = data;
- dload_progress_event(filename, progress->downloaded, progress->total);
+ if(event == ALPM_DOWNLOAD_INIT) {
+ dload_init_event(filename, data);
+ } else if(event == ALPM_DOWNLOAD_PROGRESS) {
+ dload_progress_event(filename, data);
+ } else if(event == ALPM_DOWNLOAD_COMPLETED) {
+ dload_complete_event(filename, data);
+ } else {
+ pm_printf(ALPM_LOG_ERROR, _("unknown callback event type %d for %s\n"),
+ event, filename);
}
}
diff --git a/src/pacman/callback.h b/src/pacman/callback.h
index 6d92e86b..09d544a6 100644
--- a/src/pacman/callback.h
+++ b/src/pacman/callback.h
@@ -20,6 +20,7 @@
#ifndef PM_CALLBACK_H
#define PM_CALLBACK_H
+#include <stdbool.h>
#include <sys/types.h> /* off_t */
#include <alpm.h>
@@ -44,4 +45,7 @@ void cb_download(const char *filename, alpm_download_event_type_t event,
__attribute__((format(printf, 2, 0)))
void cb_log(alpm_loglevel_t level, const char *fmt, va_list args);
+/* specify if multibar UI should move completed bars to the top of the screen */
+void multibar_move_completed_up(bool value);
+
#endif /* PM_CALLBACK_H */
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index f7dcb958..a05af5da 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -35,6 +35,7 @@
#include "pacman.h"
#include "util.h"
#include "package.h"
+#include "callback.h"
#include "conf.h"
static int unlink_verbose(const char *pathname, int ignore_missing)
@@ -824,6 +825,7 @@ int sync_prepare_execute(void)
goto cleanup;
}
+ multibar_move_completed_up(true);
if(alpm_trans_commit(config->handle, &data) == -1) {
alpm_errno_t err = alpm_errno(config->handle);
pm_printf(ALPM_LOG_ERROR, _("failed to commit transaction (%s)\n"),
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 97b8e06d..03035037 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -1837,3 +1837,21 @@ char *arg_to_string(int argc, char *argv[])
strcpy(p, argv[i]);
return cl_text;
}
+
+/* Moves console cursor `lines` up */
+void console_cursor_move_up(unsigned int lines)
+{
+ printf("\x1B[%dF", lines);
+}
+
+/* Moves console cursor `lines` down */
+void console_cursor_move_down(unsigned int lines)
+{
+ printf("\x1B[%dE", lines);
+}
+
+/* Erases line from the current cursor position till the end of the line */
+void console_erase_line(void)
+{
+ printf("\x1B[K");
+}
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 2b21f3d5..c97048fb 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -83,6 +83,10 @@ char *arg_to_string(int argc, char *argv[]);
char *safe_fgets_stdin(char *s, int size);
void console_cursor_hide(void);
void console_cursor_show(void);
+void console_cursor_move_up(unsigned int lines);
+void console_cursor_move_down(unsigned int lines);
+/* Erases line from the current cursor position till the end of the line */
+void console_erase_line(void);
int pm_printf(alpm_loglevel_t level, const char *format, ...) __attribute__((format(printf,2,3)));
int pm_asprintf(char **string, const char *format, ...) __attribute__((format(printf,2,3)));
--
2.26.2
1
1
The bash completion files were the only reason pacman was not able to
build as a non-root user. This patch adds the option to not install
these files. This was needed for my use case, hopefully upstream someone
else has a use for it as well.
Signed-off-by: Wouter Wijsman <wwijsman(a)live.nl>
---
meson_options.txt | 3 +++
scripts/meson.build | 44 +++++++++++++++++++++++---------------------
2 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/meson_options.txt b/meson_options.txt
index 4d8cc300..2927cd15 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -51,6 +51,9 @@ option('gpgme', type : 'feature', value : 'auto',
option('i18n', type : 'boolean', value : true,
description : 'enable localization of pacman, libalpm and scripts')
+option('bash-completion', type : 'boolean', value : true,
+ description : 'install bash-completion files')
+
# tools
option('file-seccomp', type: 'feature', value: 'auto',
description: 'determine whether file is seccomp-enabled')
diff --git a/scripts/meson.build b/scripts/meson.build
index d2466523..12262e98 100644
--- a/scripts/meson.build
+++ b/scripts/meson.build
@@ -68,25 +68,27 @@ configure_file(
output : '@BASENAME@',
install_dir : join_paths(DATAROOTDIR, 'pkgconfig'))
-custom_target(
- 'bash_completion',
- command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ],
- input : 'completion/bash_completion.in',
- output : 'pacman',
- install : true,
- install_dir : BASHCOMPDIR)
-
-foreach symlink : ['pacman-key', 'makepkg']
- meson.add_install_script(MESON_MAKE_SYMLINK,
- 'pacman',
- join_paths(BASHCOMPDIR, symlink))
-endforeach
+if get_option('bash-completion')
+ custom_target(
+ 'bash_completion',
+ command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ],
+ input : 'completion/bash_completion.in',
+ output : 'pacman',
+ install : true,
+ install_dir : BASHCOMPDIR)
-zsh_completion_dir = join_paths(DATAROOTDIR, 'zsh/site-functions')
-custom_target(
- 'zsh_completion',
- command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ],
- input : 'completion/zsh_completion.in',
- output : '_pacman',
- install : true,
- install_dir : zsh_completion_dir)
+ foreach symlink : ['pacman-key', 'makepkg']
+ meson.add_install_script(MESON_MAKE_SYMLINK,
+ 'pacman',
+ join_paths(BASHCOMPDIR, symlink))
+ endforeach
+
+ zsh_completion_dir = join_paths(DATAROOTDIR, 'zsh/site-functions')
+ custom_target(
+ 'zsh_completion',
+ command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ],
+ input : 'completion/zsh_completion.in',
+ output : '_pacman',
+ install : true,
+ install_dir : zsh_completion_dir)
+endif
--
2.20.1
4
3
Multiplexed download requires ability to draw UI for multiple active progress bars.
To implement it we use ANSI codes to move cursor up/down.
`active_dls` variable represents the list of active progress bars.
`struct dl_progress_bar` is a data structure for a progress bar.
In some cases we want to keep progress bars in order (e.g. db downloads).
In some other cases (package downloads) we want to move completed items to the
top of the screen. Global variable `multibar_move_completed_up` allows to
configure such behavior.
Signature file downloads are not shown at the UI.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
---
lib/libalpm/dload.c | 31 +---
lib/libalpm/dload.h | 1 -
src/pacman/callback.c | 402 ++++++++++++++++++++++++++++--------------
src/pacman/callback.h | 3 +
src/pacman/sync.c | 2 +
5 files changed, 286 insertions(+), 153 deletions(-)
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 2f360ab8..1556d72c 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -100,6 +100,11 @@ static int dload_progress_cb(void *file, curl_off_t dltotal, curl_off_t dlnow,
return 1;
}
+ if(dlnow < 0 || dltotal <= 0 || dlnow > dltotal) {
+ /* bogus values : stop here */
+ return 0;
+ }
+
current_size = payload->initial_size + dlnow;
/* is our filesize still under any set limit? */
@@ -115,34 +120,15 @@ static int dload_progress_cb(void *file, curl_off_t dltotal, curl_off_t dlnow,
total_size = payload->initial_size + dltotal;
- if(dltotal == 0 || payload->prevprogress == total_size) {
+ if(payload->prevprogress == total_size) {
return 0;
}
- /* initialize the progress bar here to avoid displaying it when
- * a repo is up to date and nothing gets downloaded.
- * payload->handle->dlcb will receive the remote_name
- * and the following arguments:
- * 0, -1: download initialized
- * 0, 0: non-download event
- * x {x>0}, x: download complete
- * x {x>0, x<y}, y {y > 0}: download progress, expected total is known */
- if(!payload->cb_initialized) {
- cb_data.downloaded = 0;
- cb_data.total = -1;
- payload->cb_initialized = 1;
- }
- if(payload->prevprogress == current_size) {
- cb_data.downloaded = 0;
- cb_data.total = 0;
- } else {
/* do NOT include initial_size since it wasn't part of the package's
* download_size (nor included in the total download size callback) */
- cb_data.downloaded = dlnow;
- cb_data.total = dltotal;
- }
+ cb_data.total = dltotal;
+ cb_data.downloaded = dlnow;
payload->handle->dlcb(payload->remote_name, ALPM_DOWNLOAD_PROGRESS, &cb_data);
-
payload->prevprogress = current_size;
return 0;
@@ -1184,5 +1170,4 @@ void _alpm_dload_payload_reset_for_retry(struct dload_payload *payload)
payload->initial_size += payload->prevprogress;
payload->prevprogress = 0;
payload->unlink_on_fail = 0;
- payload->cb_initialized = 0;
}
diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h
index 3f2fb9ea..c7fd40ee 100644
--- a/lib/libalpm/dload.h
+++ b/lib/libalpm/dload.h
@@ -42,7 +42,6 @@ struct dload_payload {
int errors_ok;
int unlink_on_fail;
int trust_remote_name;
- int cb_initialized;
#ifdef HAVE_LIBCURL
CURL *curl;
char error_buffer[CURL_ERROR_SIZE];
diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index 613d59d4..5d42a274 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -18,6 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <assert.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -45,6 +47,8 @@ static off_t list_total = 0.0;
static int on_progress = 0;
static alpm_list_t *output = NULL;
+static void cursor_goto_end(void);
+
/* update speed for the fill_progress based functions */
#define UPDATE_SPEED_MS 200
@@ -152,11 +156,7 @@ static void fill_progress(const int bar_percent, const int disp_percent,
printf(" %3d%%", disp_percent);
}
- if(bar_percent == 100) {
- putchar('\n');
- } else {
- putchar('\r');
- }
+ putchar('\r');
fflush(stdout);
}
@@ -346,6 +346,7 @@ void cb_event(alpm_event_t *event)
case ALPM_EVENT_DB_RETRIEVE_FAILED:
case ALPM_EVENT_PKG_RETRIEVE_DONE:
case ALPM_EVENT_PKG_RETRIEVE_FAILED:
+ cursor_goto_end();
flush_output_list();
on_progress = 0;
break;
@@ -629,6 +630,7 @@ void cb_progress(alpm_progress_t event, const char *pkgname, int percent,
fill_progress(percent, percent, cols - infolen);
if(percent == 100) {
+ putchar('\n');
flush_output_list();
on_progress = 0;
} else {
@@ -647,124 +649,119 @@ void cb_dl_total(off_t total)
}
}
-/* callback to handle display of download progress */
-static void dload_progress_event(const char *filename, off_t file_xfered, off_t file_total)
+static int dload_progressbar_enabled(void)
{
- static double rate_last;
- static off_t xfered_last;
- static int64_t initial_time = 0;
- int infolen;
- int filenamelen;
- char *fname, *p;
- /* used for wide character width determination and printing */
- int len, wclen, wcwid, padwid;
- wchar_t *wcfname;
+ return !config->noprogressbar && (getcols() != 0);
+}
- int totaldownload = 0;
- off_t xfered, total;
- double rate = 0.0;
- unsigned int eta_h = 0, eta_m = 0, eta_s = 0;
- double rate_human, xfered_human;
- const char *rate_label, *xfered_label;
- int file_percent = 0, total_percent = 0;
+struct dl_progress_bar {
+ const char *filename;
+ off_t xfered;
+ off_t total_size;
+ uint64_t init_time; /* Time when this download started doing any progress */
+ uint64_t sync_time; /* Last time we updated the bar info */
+ double rate;
+ unsigned int eta; /* ETA in seconds */
+ bool completed; /* transfer is completed */
+};
- const unsigned short cols = getcols();
+/* List of active downloads handled by multibar UI.
+ * Once the first download in the list is completed it is removed
+ * from this list and we never redraw it anymore.
+ * If the download is in this list, then the UI can redraw the progress bar or change
+ * the order of the bars (e.g. moving completed bars to the top of the list)
+ */
+alpm_list_t *pacman_active_downloads = NULL;
- /* Nothing has changed since last callback; stop here */
- if(file_xfered == 0 && file_total == 0) {
- return;
- }
+/* Number of active progress bars that multibar UI handles.
+ * Each progress bar has a corresponding active download.
+ * Note that some downloads might not have a bar, e.g. optional signature files
+ * do not have a corresponding bar.
+ */
+size_t pacman_active_downloads_num = 0;
- if(config->noprogressbar || cols == 0) {
- if(file_xfered == 0 && file_total == -1) {
- printf(_("downloading %s...\n"), filename);
- fflush(stdout);
- }
- return;
- }
+int multibar_move_completed_up = 0;
- infolen = cols * 6 / 10;
- if(infolen < 50) {
- infolen = 50;
- }
- /* only use TotalDownload if enabled and we have a callback value */
- if(config->totaldownload && list_total) {
- /* sanity check */
- if(list_xfered + file_total <= list_total) {
- totaldownload = 1;
- } else {
- /* bogus values : don't enable totaldownload and reset */
- list_xfered = 0;
- list_total = 0;
- }
+/* Cursor position relative to the first active progress bar,
+ * e.g. 0 means the first active progress bar, pacman_active_downloads_num-1 means the last bar,
+ * pacman_active_downloads_num - is the line below all progress bars.
+ */
+int cursor_lineno = 0;
+
+/* Move console cursor `lines` up */
+static void cursor_line_up(unsigned int lines)
+{
+ assert(lines > 0);
+ printf("\x1B[%dF", lines);
+}
+
+/* Move console cursor `lines` down */
+static void cursor_line_down(unsigned int lines)
+{
+ assert(lines > 0);
+ printf("\x1B[%dE", lines);
+}
+
+/* Erase line from the cursor position till the end of the line */
+static void console_erase_line(void)
+{
+ printf("\x1B[K");
+}
+
+/* Goto the line that corresponds to num-th active download */
+static void cursor_goto_bar(int num)
+{
+ if(num > cursor_lineno) {
+ cursor_line_down(num - cursor_lineno);
+ } else if(num < cursor_lineno) {
+ cursor_line_up(cursor_lineno - num);
}
+ cursor_lineno = num;
+}
- if(totaldownload) {
- xfered = list_xfered + file_xfered;
- total = list_total;
- } else {
- xfered = file_xfered;
- total = file_total;
- }
-
- /* this is basically a switch on xfered: 0, total, and
- * anything else */
- if(file_xfered == 0 && file_total == -1) {
- /* set default starting values, ensure we only call this once
- * if TotalDownload is enabled */
- if(!totaldownload || (totaldownload && list_xfered == 0)) {
- initial_time = get_time_ms();
- xfered_last = (off_t)0;
- rate_last = 0.0;
- get_update_timediff(1);
- }
- } else if(xfered > total || xfered < 0) {
- /* bogus values : stop here */
- return;
- } else if(file_xfered == file_total) {
- /* compute final values */
- int64_t timediff = get_time_ms() - initial_time;
- if(timediff > 0) {
- rate = (double)xfered / (timediff / 1000.0);
- /* round elapsed time (in ms) to the nearest second */
- eta_s = (unsigned int)(timediff + 500) / 1000;
- } else {
- eta_s = 0;
- }
- } else {
- /* compute current average values */
- int64_t timediff = get_update_timediff(0);
+/* Goto the line *after* the last active progress bar */
+static void cursor_goto_end(void)
+{
+ cursor_goto_bar(pacman_active_downloads_num);
+}
- if(timediff < UPDATE_SPEED_MS) {
- /* return if the calling interval was too short */
- return;
- }
- rate = (double)(xfered - xfered_last) / (timediff / 1000.0);
- /* average rate to reduce jumpiness */
- rate = (rate + 2 * rate_last) / 3;
- if(rate > 0.0) {
- eta_s = (total - xfered) / rate;
- } else {
- eta_s = UINT_MAX;
+/* Returns true if element with the specified name is found, false otherwise */
+static bool find_bar_for_filename(const char *filename, int *index, struct dl_progress_bar **bar)
+{
+ int i = 0;
+ alpm_list_t *listitem = pacman_active_downloads;
+ for(; listitem; listitem = listitem->next, i++) {
+ struct dl_progress_bar *b = listitem->data;
+ if (strcmp(b->filename, filename) == 0) {
+ /* we found a progress bar with the given name */
+ *index = i;
+ *bar = b;
+ return true;
}
- rate_last = rate;
- xfered_last = xfered;
}
- if(file_total) {
- file_percent = (file_xfered * 100) / file_total;
- } else {
- file_percent = 100;
- }
+ return false;
+}
+
+static void draw_dl_progress_bar(struct dl_progress_bar *bar)
+{
+ int infolen;
+ int filenamelen;
+ char *fname, *p;
+ /* used for wide character width determination and printing */
+ int len, wclen, wcwid, padwid;
+ wchar_t *wcfname;
+ unsigned int eta_h = 0, eta_m = 0, eta_s = bar->eta;
+ double rate_human, xfered_human;
+ const char *rate_label, *xfered_label;
+ int file_percent = 0;
- if(totaldownload) {
- total_percent = ((list_xfered + file_xfered) * 100) /
- list_total;
+ const unsigned short cols = getcols();
- /* if we are at the end, add the completed file to list_xfered */
- if(file_xfered == file_total) {
- list_xfered += file_total;
- }
+ if(bar->total_size) {
+ file_percent = (bar->xfered * 100) / bar->total_size;
+ } else {
+ file_percent = 100;
}
/* fix up time for display */
@@ -773,23 +770,20 @@ static void dload_progress_event(const char *filename, off_t file_xfered, off_t
eta_m = eta_s / 60;
eta_s -= eta_m * 60;
- len = strlen(filename);
+ len = strlen(bar->filename);
fname = malloc(len + 1);
- memcpy(fname, filename, len + 1);
+ memcpy(fname, bar->filename, len + 1);
/* strip package or DB extension for cleaner look */
if((p = strstr(fname, ".pkg")) || (p = strstr(fname, ".db")) || (p = strstr(fname, ".files"))) {
- /* tack on a .sig suffix for signatures */
- if(memcmp(&filename[len - 4], ".sig", 4) == 0) {
- memcpy(p, ".sig", 4);
-
- /* adjust length for later calculations */
- len = p - fname + 4;
- } else {
- len = p - fname;
- }
+ len = p - fname;
fname[len] = '\0';
}
+ infolen = cols * 6 / 10;
+ if(infolen < 50) {
+ infolen = 50;
+ }
+
/* 1 space + filenamelen + 1 space + 6 for size + 1 space + 3 for label +
* + 2 spaces + 4 for rate + 1 space + 3 for label + 2 for /s + 1 space +
* 8 for eta, gives us the magic 33 */
@@ -824,8 +818,8 @@ static void dload_progress_event(const char *filename, off_t file_xfered, off_t
}
- rate_human = humanize_size((off_t)rate, '\0', -1, &rate_label);
- xfered_human = humanize_size(xfered, '\0', -1, &xfered_label);
+ rate_human = humanize_size((off_t)bar->rate, '\0', -1, &rate_label);
+ xfered_human = humanize_size(bar->xfered, '\0', -1, &xfered_label);
printf(" %ls%-*s ", wcfname, padwid, "");
/* We will show 1.62 MiB/s, 11.6 MiB/s, but 116 KiB/s and 1116 KiB/s */
@@ -850,19 +844,169 @@ static void dload_progress_event(const char *filename, off_t file_xfered, off_t
free(fname);
free(wcfname);
- if(totaldownload) {
- fill_progress(file_percent, total_percent, cols - infolen);
+ fill_progress(file_percent, file_percent, cols - infolen);
+ return;
+}
+
+static void dload_init_event(const char *filename, alpm_download_event_init_t *data)
+{
+ (void)data;
+
+ if(!dload_progressbar_enabled()) {
+ printf(_(" %s downloading...\n"), filename);
+ return;
+ }
+
+ struct dl_progress_bar *bar = calloc(1, sizeof(struct dl_progress_bar));
+ assert(bar);
+ bar->filename = filename;
+ bar->init_time = get_time_ms();
+ bar->rate = 0.0;
+ pacman_active_downloads = alpm_list_add(pacman_active_downloads, bar);
+
+ cursor_goto_end();
+ printf(_(" %s downloading...\n"), filename);
+ cursor_lineno++;
+ pacman_active_downloads_num++;
+}
+
+/* Draws download progress */
+static void dload_progress_event(const char *filename, alpm_download_event_progress_t *data)
+{
+ int index;
+ struct dl_progress_bar *bar;
+ int64_t curr_time = get_time_ms();
+ double last_chunk_rate;
+ int64_t timediff;
+
+ if(!dload_progressbar_enabled()) {
+ return;
+ }
+
+ assert(find_bar_for_filename(filename, &index, &bar));
+
+ /* compute current average values */
+ timediff = curr_time - bar->sync_time;
+
+ if(timediff < UPDATE_SPEED_MS) {
+ /* return if the calling interval was too short */
+ return;
+ }
+ bar->sync_time = curr_time;
+
+ last_chunk_rate = (double)(data->downloaded - bar->xfered) / (timediff / 1000.0);
+ /* average rate to reduce jumpiness */
+ bar->rate = (last_chunk_rate + 2 * bar->rate) / 3;
+ if(bar->rate > 0.0) {
+ bar->eta = (data->total - data->downloaded) / bar->rate;
} else {
- fill_progress(file_percent, file_percent, cols - infolen);
+ bar->eta = UINT_MAX;
+ }
+
+ /* Total size is received after the download starts. */
+ bar->total_size = data->total;
+ bar->xfered = data->downloaded;
+
+ cursor_goto_bar(index);
+ draw_dl_progress_bar(bar);
+ fflush(stdout);
+}
+
+/* download completed */
+static void dload_complete_event(const char *filename, alpm_download_event_completed_t *data)
+{
+ int index;
+ struct dl_progress_bar *bar;
+ int64_t timediff;
+
+ if(!dload_progressbar_enabled()) {
+ return;
+ }
+
+ assert(find_bar_for_filename(filename, &index, &bar));
+ bar->completed = true;
+
+ /* This may not have been initialized if the download finished before
+ * an alpm_download_event_progress_t event happened */
+ bar->total_size = data->total;
+
+ if(data->result == 1) {
+ cursor_goto_bar(index);
+ printf(_(" %s is up to date"), bar->filename);
+ /* The line contains text from previous status. Erase these leftovers. */
+ console_erase_line();
+ } else if(data->result == 0) {
+ /* compute final values */
+ bar->xfered = bar->total_size;
+ timediff = get_time_ms() - bar->init_time;
+
+ /* if transfer was too fast, treat it as a 1ms transfer, for the sake
+ * of the rate calculation */
+ if(timediff < 1)
+ timediff = 1;
+
+ bar->rate = (double)bar->xfered / (timediff / 1000.0);
+ /* round elapsed time (in ms) to the nearest second */
+ bar->eta = (unsigned int)(timediff + 500) / 1000;
+
+ if(multibar_move_completed_up && index != 0) {
+ /* If this item completed then move it to the top.
+ * Swap 0-th bar data with `index`-th one
+ */
+ struct dl_progress_bar *former_topbar = pacman_active_downloads->data;
+ alpm_list_t *baritem = alpm_list_nth(pacman_active_downloads, index);
+ pacman_active_downloads->data = bar;
+ baritem->data = former_topbar;
+
+ cursor_goto_bar(index);
+ draw_dl_progress_bar(former_topbar);
+
+ index = 0;
+ }
+
+ cursor_goto_bar(index);
+ draw_dl_progress_bar(bar);
+ } else {
+ cursor_goto_bar(index);
+ printf(_(" %s failed to download"), bar->filename);
+ console_erase_line();
+ }
+ fflush(stdout);
+
+ /* If the first bar is completed then there is no reason to keep it
+ * in the list as we are not going to redraw it anymore.
+ */
+ while(pacman_active_downloads) {
+ alpm_list_t *head = pacman_active_downloads;
+ struct dl_progress_bar *j = head->data;
+ if(j->completed) {
+ cursor_lineno--;
+ pacman_active_downloads_num--;
+ pacman_active_downloads = alpm_list_remove_item(pacman_active_downloads, head);
+ free(head);
+ free(j);
+ } else {
+ break;
+ }
}
- return;
}
+/* Callback to handle display of download progress */
void cb_download(const char *filename, alpm_download_event_type_t event, void *data)
{
- if(event == ALPM_DOWNLOAD_PROGRESS) {
- alpm_download_event_progress_t *progress = data;
- dload_progress_event(filename, progress->downloaded, progress->total);
+ if(str_endswith(filename, ".sig")) {
+ return;
+ }
+
+ if(event == ALPM_DOWNLOAD_INIT) {
+ dload_init_event(filename, data);
+ } else if(event == ALPM_DOWNLOAD_PROGRESS) {
+ dload_progress_event(filename, data);
+ } else if(event == ALPM_DOWNLOAD_COMPLETED) {
+ dload_complete_event(filename, data);
+ } else {
+ pm_printf(ALPM_LOG_ERROR, _("unknown callback event type %d for %s\n"),
+ event, filename);
}
}
diff --git a/src/pacman/callback.h b/src/pacman/callback.h
index 6d92e86b..7d1f3f08 100644
--- a/src/pacman/callback.h
+++ b/src/pacman/callback.h
@@ -44,4 +44,7 @@ void cb_download(const char *filename, alpm_download_event_type_t event,
__attribute__((format(printf, 2, 0)))
void cb_log(alpm_loglevel_t level, const char *fmt, va_list args);
+/* specify if multibar should move complete bars to the top of the screen */
+int multibar_move_completed_up;
+
#endif /* PM_CALLBACK_H */
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index f7dcb958..c23b8385 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -35,6 +35,7 @@
#include "pacman.h"
#include "util.h"
#include "package.h"
+#include "callback.h"
#include "conf.h"
static int unlink_verbose(const char *pathname, int ignore_missing)
@@ -824,6 +825,7 @@ int sync_prepare_execute(void)
goto cleanup;
}
+ multibar_move_completed_up = 1;
if(alpm_trans_commit(config->handle, &data) == -1) {
alpm_errno_t err = alpm_errno(config->handle);
pm_printf(ALPM_LOG_ERROR, _("failed to commit transaction (%s)\n"),
--
2.26.2
2
2
Multiplexed download requires ability to draw UI for multiple active progress bars.
To implement it we use ANSI codes to move cursor up/down.
`active_dls` variable represents the list of active progress bars.
`struct dl_progress_bar` is a data structure for a progress bar.
In some cases we want to keep progress bars in order (e.g. db downloads).
In some other cases (package downloads) we want to move completed items to the
top of the screen. Global variable `multibar_move_complete_top` allows to
configure such behavior.
Signature file downloads are not shown at the UI.
Signed-off-by: Anatol Pomozov <anatol.pomozov(a)gmail.com>
---
lib/libalpm/dload.c | 31 +---
lib/libalpm/dload.h | 1 -
src/pacman/callback.c | 393 +++++++++++++++++++++++++++++-------------
src/pacman/callback.h | 3 +
src/pacman/sync.c | 2 +
5 files changed, 285 insertions(+), 145 deletions(-)
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index c09abde4..cf467ff0 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -100,6 +100,11 @@ static int dload_progress_cb(void *file, curl_off_t dltotal, curl_off_t dlnow,
return 1;
}
+ if(dlnow < 0 || dltotal <= 0 || dlnow > dltotal) {
+ /* bogus values : stop here */
+ return 0;
+ }
+
current_size = payload->initial_size + dlnow;
/* is our filesize still under any set limit? */
@@ -115,34 +120,15 @@ static int dload_progress_cb(void *file, curl_off_t dltotal, curl_off_t dlnow,
total_size = payload->initial_size + dltotal;
- if(dltotal == 0 || payload->prevprogress == total_size) {
+ if(payload->prevprogress == total_size) {
return 0;
}
- /* initialize the progress bar here to avoid displaying it when
- * a repo is up to date and nothing gets downloaded.
- * payload->handle->dlcb will receive the remote_name
- * and the following arguments:
- * 0, -1: download initialized
- * 0, 0: non-download event
- * x {x>0}, x: download complete
- * x {x>0, x<y}, y {y > 0}: download progress, expected total is known */
- if(!payload->cb_initialized) {
- cb_data.downloaded = 0;
- cb_data.total = -1;
- payload->cb_initialized = 1;
- }
- if(payload->prevprogress == current_size) {
- cb_data.downloaded = 0;
- cb_data.total = 0;
- } else {
/* do NOT include initial_size since it wasn't part of the package's
* download_size (nor included in the total download size callback) */
- cb_data.downloaded = dlnow;
- cb_data.total = dltotal;
- }
+ cb_data.total = dltotal;
+ cb_data.downloaded = dlnow;
payload->handle->dlcb(payload->remote_name, ALPM_DOWNLOAD_PROGRESS, &cb_data);
-
payload->prevprogress = current_size;
return 0;
@@ -1160,5 +1146,4 @@ void _alpm_dload_payload_reset_for_retry(struct dload_payload *payload)
payload->initial_size += payload->prevprogress;
payload->prevprogress = 0;
payload->unlink_on_fail = 0;
- payload->cb_initialized = 0;
}
diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h
index a40b51b7..142568e8 100644
--- a/lib/libalpm/dload.h
+++ b/lib/libalpm/dload.h
@@ -42,7 +42,6 @@ struct dload_payload {
int errors_ok;
int unlink_on_fail;
int trust_remote_name;
- int cb_initialized;
#ifdef HAVE_LIBCURL
CURL *curl;
char error_buffer[CURL_ERROR_SIZE];
diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index 387319b6..6133a036 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -18,6 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <assert.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -45,6 +47,8 @@ static off_t list_total = 0.0;
static int on_progress = 0;
static alpm_list_t *output = NULL;
+static void cursor_goto_end(void);
+
/* update speed for the fill_progress based functions */
#define UPDATE_SPEED_MS 200
@@ -152,11 +156,7 @@ static void fill_progress(const int bar_percent, const int disp_percent,
printf(" %3d%%", disp_percent);
}
- if(bar_percent == 100) {
- putchar('\n');
- } else {
- putchar('\r');
- }
+ putchar('\r');
fflush(stdout);
}
@@ -346,6 +346,7 @@ void cb_event(alpm_event_t *event)
case ALPM_EVENT_DB_RETRIEVE_FAILED:
case ALPM_EVENT_RETRIEVE_DONE:
case ALPM_EVENT_RETRIEVE_FAILED:
+ cursor_goto_end();
flush_output_list();
on_progress = 0;
break;
@@ -629,6 +630,7 @@ void cb_progress(alpm_progress_t event, const char *pkgname, int percent,
fill_progress(percent, percent, cols - infolen);
if(percent == 100) {
+ putchar('\n');
flush_output_list();
on_progress = 0;
} else {
@@ -647,124 +649,118 @@ void cb_dl_total(off_t total)
}
}
-/* callback to handle display of download progress */
-static void dload_progress_event(const char *filename, off_t file_xfered, off_t file_total)
+static int dload_progressbar_enabled(void)
{
- static double rate_last;
- static off_t xfered_last;
- static int64_t initial_time = 0;
- int infolen;
- int filenamelen;
- char *fname, *p;
- /* used for wide character width determination and printing */
- int len, wclen, wcwid, padwid;
- wchar_t *wcfname;
+ return !config->noprogressbar && getcols() != 0;
+}
- int totaldownload = 0;
- off_t xfered, total;
- double rate = 0.0;
- unsigned int eta_h = 0, eta_m = 0, eta_s = 0;
- double rate_human, xfered_human;
- const char *rate_label, *xfered_label;
- int file_percent = 0, total_percent = 0;
+struct dl_progress_bar {
+ const char *filename;
+ off_t xfered;
+ off_t total_size;
+ uint64_t init_time; /* Time when this download started doing any progress */
+ uint64_t sync_time; /* Last time we updated the bar info */
+ double rate;
+ unsigned int eta; /* ETA in seconds */
+ bool completed; /* transfer is completed */
+};
- const unsigned short cols = getcols();
+/* List of active downloads handled by multibar UI.
+ * Once the first download in the list is completed it is removed
+ * from this list and we never redraw it anymore.
+ * If the download in this list then UI can redraw the progress bar or change
+ * the order of the bars (e.g. completed bar is moved to the top of the list)
+ */
+alpm_list_t *active_dls = NULL;
- /* Nothing has changed since last callback; stop here */
- if(file_xfered == 0 && file_total == 0) {
- return;
- }
+/* Number of active progress bars that multibar UI handles.
+ * Each progress bar has a corresponding active download.
+ * Note that some downloads might not have a bar, e.g. optional signature files
+ * do not have a corresponding bar.
+ */
+size_t active_bars_no = 0;
- if(config->noprogressbar || cols == 0) {
- if(file_xfered == 0 && file_total == -1) {
- printf(_("downloading %s...\n"), filename);
- fflush(stdout);
- }
- return;
- }
+int multibar_move_complete_top = 0;
- infolen = cols * 6 / 10;
- if(infolen < 50) {
- infolen = 50;
- }
- /* only use TotalDownload if enabled and we have a callback value */
- if(config->totaldownload && list_total) {
- /* sanity check */
- if(list_xfered + file_total <= list_total) {
- totaldownload = 1;
- } else {
- /* bogus values : don't enable totaldownload and reset */
- list_xfered = 0;
- list_total = 0;
- }
+/* Cursor position relative to the first active progress bar,
+ * e.g. 0 means the first active progress bar, active_bars_no-1 means the last bar,
+ * active_bars_no - is the line below all progress bars.
+ */
+int cursor_lineno = 0;
+
+/* Move console cursor `lines` up */
+static void cursor_line_up(unsigned int lines)
+{
+ assert(lines > 0);
+ printf("\x1B[%dF", lines);
+}
+
+/* Move console cursor `lines` down */
+static void cursor_line_down(unsigned int lines)
+{
+ assert(lines > 0);
+ printf("\x1B[%dE", lines);
+}
+
+/* Erase line from the cursor position till the end of the line */
+static void console_erase_line(void)
+{
+ printf("\x1B[K");
+}
+
+/* Goto the line that corresponds to num-th active download */
+static void cursor_goto_bar(int num)
+{
+ if(num > cursor_lineno) {
+ cursor_line_down(num - cursor_lineno);
+ } else if(num < cursor_lineno) {
+ cursor_line_up(cursor_lineno - num);
}
+ cursor_lineno = num;
+}
- if(totaldownload) {
- xfered = list_xfered + file_xfered;
- total = list_total;
- } else {
- xfered = file_xfered;
- total = file_total;
- }
-
- /* this is basically a switch on xfered: 0, total, and
- * anything else */
- if(file_xfered == 0 && file_total == -1) {
- /* set default starting values, ensure we only call this once
- * if TotalDownload is enabled */
- if(!totaldownload || (totaldownload && list_xfered == 0)) {
- initial_time = get_time_ms();
- xfered_last = (off_t)0;
- rate_last = 0.0;
- get_update_timediff(1);
- }
- } else if(xfered > total || xfered < 0) {
- /* bogus values : stop here */
- return;
- } else if(file_xfered == file_total) {
- /* compute final values */
- int64_t timediff = get_time_ms() - initial_time;
- if(timediff > 0) {
- rate = (double)xfered / (timediff / 1000.0);
- /* round elapsed time (in ms) to the nearest second */
- eta_s = (unsigned int)(timediff + 500) / 1000;
- } else {
- eta_s = 0;
- }
- } else {
- /* compute current average values */
- int64_t timediff = get_update_timediff(0);
+/* Goto the line *after* the last active progress bar */
+static void cursor_goto_end(void)
+{
+ cursor_goto_bar(active_bars_no);
+}
- if(timediff < UPDATE_SPEED_MS) {
- /* return if the calling interval was too short */
- return;
- }
- rate = (double)(xfered - xfered_last) / (timediff / 1000.0);
- /* average rate to reduce jumpiness */
- rate = (rate + 2 * rate_last) / 3;
- if(rate > 0.0) {
- eta_s = (total - xfered) / rate;
- } else {
- eta_s = UINT_MAX;
+/* Returns true if element with the specified name is found, false otherwise */
+static bool find_bar_for_filename(const char *filename, int *index, struct dl_progress_bar **bar)
+{
+ int i = 0;
+ alpm_list_t *listitem = active_dls;
+ for(; listitem; listitem = listitem->next, i++) {
+ struct dl_progress_bar *b = listitem->data;
+ if (b->filename == filename /* or strcmp() ? */) {
+ *index = i;
+ *bar = b;
+ return true;
}
- rate_last = rate;
- xfered_last = xfered;
}
- if(file_total) {
- file_percent = (file_xfered * 100) / file_total;
- } else {
- file_percent = 100;
- }
+ return false;
+}
- if(totaldownload) {
- total_percent = ((list_xfered + file_xfered) * 100) /
- list_total;
+static void draw_dl_progress_bar(struct dl_progress_bar *bar)
+{
+ int infolen;
+ int filenamelen;
+ char *fname, *p;
+ /* used for wide character width determination and printing */
+ int len, wclen, wcwid, padwid;
+ wchar_t *wcfname;
+ unsigned int eta_h = 0, eta_m = 0, eta_s = bar->eta;
+ double rate_human, xfered_human;
+ const char *rate_label, *xfered_label;
+ int file_percent = 0;
- /* if we are at the end, add the completed file to list_xfered */
- if(file_xfered == file_total) {
- list_xfered += file_total;
- }
+ const unsigned short cols = getcols();
+
+ if(bar->total_size) {
+ file_percent = (bar->xfered * 100) / bar->total_size;
+ } else {
+ file_percent = 100;
}
/* fix up time for display */
@@ -773,13 +769,13 @@ static void dload_progress_event(const char *filename, off_t file_xfered, off_t
eta_m = eta_s / 60;
eta_s -= eta_m * 60;
- len = strlen(filename);
+ len = strlen(bar->filename);
fname = malloc(len + 1);
- memcpy(fname, filename, len + 1);
+ memcpy(fname, bar->filename, len + 1);
/* strip package or DB extension for cleaner look */
if((p = strstr(fname, ".pkg")) || (p = strstr(fname, ".db")) || (p = strstr(fname, ".files"))) {
/* tack on a .sig suffix for signatures */
- if(memcmp(&filename[len - 4], ".sig", 4) == 0) {
+ if(memcmp(&bar->filename[len - 4], ".sig", 4) == 0) {
memcpy(p, ".sig", 4);
/* adjust length for later calculations */
@@ -790,6 +786,11 @@ static void dload_progress_event(const char *filename, off_t file_xfered, off_t
fname[len] = '\0';
}
+ infolen = cols * 6 / 10;
+ if(infolen < 50) {
+ infolen = 50;
+ }
+
/* 1 space + filenamelen + 1 space + 6 for size + 1 space + 3 for label +
* + 2 spaces + 4 for rate + 1 space + 3 for label + 2 for /s + 1 space +
* 8 for eta, gives us the magic 33 */
@@ -824,8 +825,8 @@ static void dload_progress_event(const char *filename, off_t file_xfered, off_t
}
- rate_human = humanize_size((off_t)rate, '\0', -1, &rate_label);
- xfered_human = humanize_size(xfered, '\0', -1, &xfered_label);
+ rate_human = humanize_size((off_t)bar->rate, '\0', -1, &rate_label);
+ xfered_human = humanize_size(bar->xfered, '\0', -1, &xfered_label);
printf(" %ls%-*s ", wcfname, padwid, "");
/* We will show 1.62 MiB/s, 11.6 MiB/s, but 116 KiB/s and 1116 KiB/s */
@@ -850,19 +851,169 @@ static void dload_progress_event(const char *filename, off_t file_xfered, off_t
free(fname);
free(wcfname);
- if(totaldownload) {
- fill_progress(file_percent, total_percent, cols - infolen);
+ fill_progress(file_percent, file_percent, cols - infolen);
+ return;
+}
+
+static void dload_init_event(const char *filename, alpm_download_event_init_t *data)
+{
+ (void)data;
+
+ if(!dload_progressbar_enabled()) {
+ printf(_(" %s downloading...\n"), filename);
+ return;
+ }
+
+ struct dl_progress_bar *bar = calloc(1, sizeof(struct dl_progress_bar));
+ assert(bar);
+ bar->filename = filename;
+ bar->init_time = get_time_ms();
+ bar->rate = 0.0;
+ active_dls = alpm_list_add(active_dls, bar);
+
+ cursor_goto_end();
+ printf(_(" %s downloading...\n"), filename);
+ cursor_lineno++;
+ active_bars_no++;
+}
+
+/* Draws download progress */
+static void dload_progress_event(const char *filename, alpm_download_event_progress_t *data)
+{
+ int index;
+ struct dl_progress_bar *bar;
+ int64_t curr_time = get_time_ms();
+ double last_chunk_rate;
+ int64_t timediff;
+
+ if(!dload_progressbar_enabled()) {
+ return;
+ }
+
+ assert(find_bar_for_filename(filename, &index, &bar));
+
+ /* compute current average values */
+ timediff = curr_time - bar->sync_time;
+
+ if(timediff < UPDATE_SPEED_MS) {
+ /* return if the calling interval was too short */
+ return;
+ }
+ bar->sync_time = curr_time;
+
+ last_chunk_rate = (double)(data->downloaded - bar->xfered) / (timediff / 1000.0);
+ /* average rate to reduce jumpiness */
+ bar->rate = (last_chunk_rate + 2 * bar->rate) / 3;
+ if(bar->rate > 0.0) {
+ bar->eta = (data->total - data->downloaded) / bar->rate;
} else {
- fill_progress(file_percent, file_percent, cols - infolen);
+ bar->eta = UINT_MAX;
}
- return;
+
+ /* Total size is received after the download starts. */
+ bar->total_size = data->total;
+ bar->xfered = data->downloaded;
+
+ cursor_goto_bar(index);
+ draw_dl_progress_bar(bar);
+ fflush(stdout);
}
+/* download completed */
+static void dload_complete_event(const char *filename, alpm_download_event_completed_t *data)
+{
+ int index;
+ struct dl_progress_bar *bar;
+ int64_t timediff;
+
+ if(!dload_progressbar_enabled()) {
+ return;
+ }
+
+ assert(find_bar_for_filename(filename, &index, &bar));
+ bar->completed = true;
+
+ /* This may not have been initialized if the download finished before
+ * an alpm_download_event_progress_t event happened */
+ bar->total_size = data->total;
+
+ if(data->result == 1) {
+ cursor_goto_bar(index);
+ printf(_(" %s is up to date"), bar->filename);
+ /* The line contains text from previous status. Erase these leftovers. */
+ console_erase_line();
+ } else if(data->result == 0) {
+ /* compute final values */
+ bar->xfered = bar->total_size;
+ timediff = get_time_ms() - bar->init_time;
+
+ /* if transfer was too fast, treat it as a 1ms transfer, for the sake
+ * of the rate calculation */
+ if(timediff < 1)
+ timediff = 1;
+
+ bar->rate = (double)bar->xfered / (timediff / 1000.0);
+ /* round elapsed time (in ms) to the nearest second */
+ bar->eta = (unsigned int)(timediff + 500) / 1000;
+
+ if(multibar_move_complete_top && index != 0) {
+ /* If this item completed then move it to the top.
+ * Swap 0-th bar data with `index`-th one
+ */
+ struct dl_progress_bar *former_topbar = active_dls->data;
+ alpm_list_t *baritem = alpm_list_nth(active_dls, index);
+ active_dls->data = bar;
+ baritem->data = former_topbar;
+
+ cursor_goto_bar(index);
+ draw_dl_progress_bar(former_topbar);
+
+ index = 0;
+ }
+
+ cursor_goto_bar(index);
+ draw_dl_progress_bar(bar);
+ } else {
+ cursor_goto_bar(index);
+ printf(_(" %s failed to download"), bar->filename);
+ console_erase_line();
+ }
+ fflush(stdout);
+
+ /* If the first bar is completed then there is no reason to keep it
+ * in the list as we are not going to redraw it anymore.
+ */
+ while(active_dls) {
+ alpm_list_t *head = active_dls;
+ struct dl_progress_bar *j = head->data;
+ if(j->completed) {
+ cursor_lineno--;
+ active_bars_no--;
+ active_dls = alpm_list_remove_item(active_dls, head);
+ free(head);
+ free(j);
+ } else {
+ break;
+ }
+ }
+}
+
+/* Callback to handle display of download progress */
void cb_download(const char *filename, alpm_download_event_type_t event, void *data)
{
- if(event == ALPM_DOWNLOAD_PROGRESS) {
- alpm_download_event_progress_t *progress = data;
- dload_progress_event(filename, progress->downloaded, progress->total);
+ if(str_endswith(filename, ".sig")) {
+ return;
+ }
+
+ if(event == ALPM_DOWNLOAD_INIT) {
+ dload_init_event(filename, data);
+ } else if(event == ALPM_DOWNLOAD_PROGRESS) {
+ dload_progress_event(filename, data);
+ } else if(event == ALPM_DOWNLOAD_COMPLETED) {
+ dload_complete_event(filename, data);
+ } else {
+ pm_printf(ALPM_LOG_ERROR, _("unknown callback event type %d for %s\n"),
+ event, filename);
}
}
diff --git a/src/pacman/callback.h b/src/pacman/callback.h
index 6d92e86b..916b9dad 100644
--- a/src/pacman/callback.h
+++ b/src/pacman/callback.h
@@ -44,4 +44,7 @@ void cb_download(const char *filename, alpm_download_event_type_t event,
__attribute__((format(printf, 2, 0)))
void cb_log(alpm_loglevel_t level, const char *fmt, va_list args);
+/* specify if multibar should move complete bars to the top of the screen */
+int multibar_move_complete_top;
+
#endif /* PM_CALLBACK_H */
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index f7dcb958..d5886f13 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -35,6 +35,7 @@
#include "pacman.h"
#include "util.h"
#include "package.h"
+#include "callback.h"
#include "conf.h"
static int unlink_verbose(const char *pathname, int ignore_missing)
@@ -824,6 +825,7 @@ int sync_prepare_execute(void)
goto cleanup;
}
+ multibar_move_complete_top = 1;
if(alpm_trans_commit(config->handle, &data) == -1) {
alpm_errno_t err = alpm_errno(config->handle);
pm_printf(ALPM_LOG_ERROR, _("failed to commit transaction (%s)\n"),
--
2.26.2
2
5