Pacman-dev
Threads by month
- ----- 2024 -----
- 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
April 2017
- 10 participants
- 34 discussions
[pacman-dev] [PATCH] Check for all return values of _alpm_key_in_keychain
by David Phillips 24 Jan '19
by David Phillips 24 Jan '19
24 Jan '19
This fixes a bug I encountered with a GPG keyring where the
key id used to locate a key in the keyring was ambiguous within
my keychain.
This commit ensures that all valid return values are checked to
catch this and related error cases rather than incorrectly taking
an error case to mean the key was found, since this is rarely going
to be the case.
---
lib/libalpm/be_package.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index 7e8b7920..1891fa5a 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -754,10 +754,21 @@ int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int ful
alpm_list_t *k;
for(k = keys; k; k = k->next) {
char *key = k->data;
- if(_alpm_key_in_keychain(handle, key) == 0) {
- if(_alpm_key_import(handle, key) == -1) {
+ switch(_alpm_key_in_keychain(handle, key)) {
+ case 1:
+ /* key is known; proceed */
+ break;
+ case 0:
+ /* key is unknown; attempt to import */
+ if(_alpm_key_import(handle, key) == -1) {
+ fail = 1;
+ }
+ break;
+ case -1:
+ /* error finding key in keychain */
+ default:
fail = 1;
- }
+ break;
}
}
FREELIST(keys);
--
2.12.2
3
3
The long-awaited makepkg test suite is finally here, or at least the start of
it. The tests can be run via `make check` or they can also be run directly.
Included so far are a few tests for package generation and a single libmakepkg
test for some of the util/pkgbuild functions. I made some small changes to the
lib in order to make it easier to use and to allow stricter error checking in
the test suite (set -u).
Andrew Gregory (4):
util/pkgbuild: guard against unset variable
util/pkgbuild: manually set extglob
util/pkgbuild: fix broken indentation
add basic makepkg test
Makefile.am | 6 +-
configure.ac | 2 +
scripts/libmakepkg/util/pkgbuild.sh.in | 23 +++---
test/makepkg/Makefile.am | 9 +++
test/makepkg/README | 15 ++++
test/makepkg/test_functions.sh | 143 +++++++++++++++++++++++++++++++++
test/makepkg/tests/Makefile.am | 7 ++
test/makepkg/tests/TESTS | 4 +
test/makepkg/tests/dbfiles.sh | 35 ++++++++
test/makepkg/tests/dotfiles.sh | 33 ++++++++
test/makepkg/tests/pkgbuild.sh | 53 ++++++++++++
test/makepkg/tests/util-pkgbuild.sh | 35 ++++++++
12 files changed, 355 insertions(+), 10 deletions(-)
create mode 100644 test/makepkg/Makefile.am
create mode 100644 test/makepkg/README
create mode 100644 test/makepkg/test_functions.sh
create mode 100644 test/makepkg/tests/Makefile.am
create mode 100644 test/makepkg/tests/TESTS
create mode 100755 test/makepkg/tests/dbfiles.sh
create mode 100755 test/makepkg/tests/dotfiles.sh
create mode 100755 test/makepkg/tests/pkgbuild.sh
create mode 100755 test/makepkg/tests/util-pkgbuild.sh
--
2.11.1
5
13
This conforms with the rest of the pacman codebase.
The modelines appear to have been mistakenly dropped when libmakepkg was
separated out into separate files from the original monolithic makepkg
script.
Signed-off-by: Eli Schwartz <eschwartz93(a)gmail.com>
---
scripts/libmakepkg/integrity.sh.in | 2 ++
scripts/libmakepkg/integrity/generate_checksum.sh.in | 2 ++
scripts/libmakepkg/integrity/generate_signature.sh.in | 2 ++
scripts/libmakepkg/integrity/verify_checksum.sh.in | 2 ++
scripts/libmakepkg/integrity/verify_signature.sh.in | 2 ++
scripts/libmakepkg/lint_package.sh.in | 2 ++
scripts/libmakepkg/lint_package/build_references.sh.in | 2 ++
scripts/libmakepkg/lint_package/dotfiles.sh.in | 2 ++
scripts/libmakepkg/lint_package/file_names.sh.in | 2 ++
scripts/libmakepkg/lint_package/missing_backup.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/arch.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/backup.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/changelog.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/epoch.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/install.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/optdepends.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/options.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/package_function.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/pkglist.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/pkgname.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/pkgrel.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/pkgver.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/provides.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/source.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/util.sh.in | 2 ++
scripts/libmakepkg/lint_pkgbuild/variable.sh.in | 2 ++
scripts/libmakepkg/source.sh.in | 2 ++
scripts/libmakepkg/source/bzr.sh.in | 2 ++
scripts/libmakepkg/source/file.sh.in | 2 ++
scripts/libmakepkg/source/git.sh.in | 2 ++
scripts/libmakepkg/source/hg.sh.in | 2 ++
scripts/libmakepkg/source/local.sh.in | 2 ++
scripts/libmakepkg/source/svn.sh.in | 2 ++
scripts/libmakepkg/srcinfo.sh.in | 2 ++
scripts/libmakepkg/tidy.sh.in | 2 ++
scripts/libmakepkg/tidy/docs.sh.in | 2 ++
scripts/libmakepkg/tidy/emptydirs.sh.in | 2 ++
scripts/libmakepkg/tidy/libtool.sh.in | 2 ++
scripts/libmakepkg/tidy/purge.sh.in | 2 ++
scripts/libmakepkg/tidy/staticlibs.sh.in | 2 ++
scripts/libmakepkg/tidy/strip.sh.in | 2 ++
scripts/libmakepkg/tidy/zipman.sh.in | 2 ++
scripts/libmakepkg/util.sh.in | 2 ++
scripts/libmakepkg/util/message.sh.in | 2 ++
scripts/libmakepkg/util/option.sh.in | 2 ++
scripts/libmakepkg/util/parseopts.sh.in | 2 ++
scripts/libmakepkg/util/pkgbuild.sh.in | 2 ++
scripts/libmakepkg/util/source.sh.in | 2 ++
scripts/libmakepkg/util/util.sh.in | 2 ++
51 files changed, 102 insertions(+)
diff --git a/scripts/libmakepkg/integrity.sh.in b/scripts/libmakepkg/integrity.sh.in
index 3a77ef16..68177884 100644
--- a/scripts/libmakepkg/integrity.sh.in
+++ b/scripts/libmakepkg/integrity.sh.in
@@ -43,3 +43,5 @@ check_source_integrity() {
check_pgpsigs "$@"
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/integrity/generate_checksum.sh.in b/scripts/libmakepkg/integrity/generate_checksum.sh.in
index 902a989e..35dbb7cc 100644
--- a/scripts/libmakepkg/integrity/generate_checksum.sh.in
+++ b/scripts/libmakepkg/integrity/generate_checksum.sh.in
@@ -100,3 +100,5 @@ generate_checksums() {
done
done
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/integrity/generate_signature.sh.in b/scripts/libmakepkg/integrity/generate_signature.sh.in
index 060ae344..732df131 100644
--- a/scripts/libmakepkg/integrity/generate_signature.sh.in
+++ b/scripts/libmakepkg/integrity/generate_signature.sh.in
@@ -47,3 +47,5 @@ create_signature() {
warning "$(gettext "Failed to sign package file.")"
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/integrity/verify_checksum.sh.in b/scripts/libmakepkg/integrity/verify_checksum.sh.in
index 1a11a082..b194b9fe 100644
--- a/scripts/libmakepkg/integrity/verify_checksum.sh.in
+++ b/scripts/libmakepkg/integrity/verify_checksum.sh.in
@@ -128,3 +128,5 @@ verify_integrity_sums() {
return 1
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/integrity/verify_signature.sh.in b/scripts/libmakepkg/integrity/verify_signature.sh.in
index b5577523..2f02b337 100644
--- a/scripts/libmakepkg/integrity/verify_signature.sh.in
+++ b/scripts/libmakepkg/integrity/verify_signature.sh.in
@@ -267,3 +267,5 @@ source_has_signatures() {
done
return 1
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_package.sh.in b/scripts/libmakepkg/lint_package.sh.in
index ff0894ec..5043dc24 100644
--- a/scripts/libmakepkg/lint_package.sh.in
+++ b/scripts/libmakepkg/lint_package.sh.in
@@ -46,3 +46,5 @@ lint_package() {
done
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_package/build_references.sh.in b/scripts/libmakepkg/lint_package/build_references.sh.in
index 9183fce9..29347d2e 100644
--- a/scripts/libmakepkg/lint_package/build_references.sh.in
+++ b/scripts/libmakepkg/lint_package/build_references.sh.in
@@ -39,3 +39,5 @@ warn_build_references() {
done
return 0
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_package/dotfiles.sh.in b/scripts/libmakepkg/lint_package/dotfiles.sh.in
index 9842028c..cf6ef749 100644
--- a/scripts/libmakepkg/lint_package/dotfiles.sh.in
+++ b/scripts/libmakepkg/lint_package/dotfiles.sh.in
@@ -36,3 +36,5 @@ check_dotfiles() {
done
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_package/file_names.sh.in b/scripts/libmakepkg/lint_package/file_names.sh.in
index 0b8e7a03..657489bd 100644
--- a/scripts/libmakepkg/lint_package/file_names.sh.in
+++ b/scripts/libmakepkg/lint_package/file_names.sh.in
@@ -40,3 +40,5 @@ lint_file_names() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_package/missing_backup.sh.in b/scripts/libmakepkg/lint_package/missing_backup.sh.in
index 934dd12f..bb2f3f3e 100644
--- a/scripts/libmakepkg/lint_package/missing_backup.sh.in
+++ b/scripts/libmakepkg/lint_package/missing_backup.sh.in
@@ -37,3 +37,5 @@ warn_missing_backup() {
done
return 0
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild.sh.in b/scripts/libmakepkg/lint_pkgbuild.sh.in
index d3a1a083..c126c662 100644
--- a/scripts/libmakepkg/lint_pkgbuild.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild.sh.in
@@ -44,3 +44,5 @@ lint_pkgbuild() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/arch.sh.in b/scripts/libmakepkg/lint_pkgbuild/arch.sh.in
index ddc2f29e..79377f36 100644
--- a/scripts/libmakepkg/lint_pkgbuild/arch.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/arch.sh.in
@@ -62,3 +62,5 @@ lint_arch() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/backup.sh.in b/scripts/libmakepkg/lint_pkgbuild/backup.sh.in
index 5b37b4e9..9ead0a8d 100644
--- a/scripts/libmakepkg/lint_pkgbuild/backup.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/backup.sh.in
@@ -49,3 +49,5 @@ lint_backup() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/changelog.sh.in b/scripts/libmakepkg/lint_pkgbuild/changelog.sh.in
index 264ea105..d7c5f1ca 100644
--- a/scripts/libmakepkg/lint_pkgbuild/changelog.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/changelog.sh.in
@@ -45,3 +45,5 @@ lint_changelog() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/epoch.sh.in b/scripts/libmakepkg/lint_pkgbuild/epoch.sh.in
index cc11d975..7c56b77b 100644
--- a/scripts/libmakepkg/lint_pkgbuild/epoch.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/epoch.sh.in
@@ -35,3 +35,5 @@ lint_epoch() {
return 1
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/install.sh.in b/scripts/libmakepkg/lint_pkgbuild/install.sh.in
index 3e268923..1435ec95 100644
--- a/scripts/libmakepkg/lint_pkgbuild/install.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/install.sh.in
@@ -44,3 +44,5 @@ lint_install() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/optdepends.sh.in b/scripts/libmakepkg/lint_pkgbuild/optdepends.sh.in
index f5fdbb90..7fc2d98e 100644
--- a/scripts/libmakepkg/lint_pkgbuild/optdepends.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/optdepends.sh.in
@@ -62,3 +62,5 @@ lint_optdepends() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/options.sh.in b/scripts/libmakepkg/lint_pkgbuild/options.sh.in
index ffcd19e3..d5b0bd48 100644
--- a/scripts/libmakepkg/lint_pkgbuild/options.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/options.sh.in
@@ -55,3 +55,5 @@ lint_options() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/package_function.sh.in b/scripts/libmakepkg/lint_pkgbuild/package_function.sh.in
index 14398217..f1c97279 100644
--- a/scripts/libmakepkg/lint_pkgbuild/package_function.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/package_function.sh.in
@@ -49,3 +49,5 @@ lint_package_function() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in b/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in
index 911e1128..e697d813 100644
--- a/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/pkgbase.sh.in
@@ -48,3 +48,5 @@ lint_pkgbase() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/pkglist.sh.in b/scripts/libmakepkg/lint_pkgbuild/pkglist.sh.in
index 8c09ad5b..64d76d92 100644
--- a/scripts/libmakepkg/lint_pkgbuild/pkglist.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/pkglist.sh.in
@@ -42,3 +42,5 @@ lint_pkglist() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/pkgname.sh.in b/scripts/libmakepkg/lint_pkgbuild/pkgname.sh.in
index b66eda68..bb749f37 100644
--- a/scripts/libmakepkg/lint_pkgbuild/pkgname.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/pkgname.sh.in
@@ -60,3 +60,5 @@ lint_pkgname() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/pkgrel.sh.in b/scripts/libmakepkg/lint_pkgbuild/pkgrel.sh.in
index b5cdfcf1..8c7a9bdd 100644
--- a/scripts/libmakepkg/lint_pkgbuild/pkgrel.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/pkgrel.sh.in
@@ -40,3 +40,5 @@ lint_pkgrel() {
return 1
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/pkgver.sh.in b/scripts/libmakepkg/lint_pkgbuild/pkgver.sh.in
index 0ec6584c..727f054c 100644
--- a/scripts/libmakepkg/lint_pkgbuild/pkgver.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/pkgver.sh.in
@@ -49,3 +49,5 @@ lint_pkgver() {
check_pkgver $pkgver
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/provides.sh.in b/scripts/libmakepkg/lint_pkgbuild/provides.sh.in
index f521d0f5..ab3cd9b0 100644
--- a/scripts/libmakepkg/lint_pkgbuild/provides.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/provides.sh.in
@@ -60,3 +60,5 @@ lint_provides() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/source.sh.in b/scripts/libmakepkg/lint_pkgbuild/source.sh.in
index 052b9d54..c9cbe9f3 100644
--- a/scripts/libmakepkg/lint_pkgbuild/source.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/source.sh.in
@@ -37,3 +37,5 @@ lint_source() {
return 1
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/util.sh.in b/scripts/libmakepkg/lint_pkgbuild/util.sh.in
index e8a35933..1eb1eb74 100644
--- a/scripts/libmakepkg/lint_pkgbuild/util.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/util.sh.in
@@ -39,3 +39,5 @@ check_files_exist() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/lint_pkgbuild/variable.sh.in b/scripts/libmakepkg/lint_pkgbuild/variable.sh.in
index 1e749638..78df84a5 100644
--- a/scripts/libmakepkg/lint_pkgbuild/variable.sh.in
+++ b/scripts/libmakepkg/lint_pkgbuild/variable.sh.in
@@ -105,3 +105,5 @@ lint_variable() {
return $ret
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/source.sh.in b/scripts/libmakepkg/source.sh.in
index 234e35e4..42e70d67 100644
--- a/scripts/libmakepkg/source.sh.in
+++ b/scripts/libmakepkg/source.sh.in
@@ -111,3 +111,5 @@ extract_sources() {
esac
done
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/source/bzr.sh.in b/scripts/libmakepkg/source/bzr.sh.in
index 97206714..69529f4b 100644
--- a/scripts/libmakepkg/source/bzr.sh.in
+++ b/scripts/libmakepkg/source/bzr.sh.in
@@ -104,3 +104,5 @@ extract_bzr() {
popd &>/dev/null
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/source/file.sh.in b/scripts/libmakepkg/source/file.sh.in
index 1d85ea9b..5e724249 100644
--- a/scripts/libmakepkg/source/file.sh.in
+++ b/scripts/libmakepkg/source/file.sh.in
@@ -145,3 +145,5 @@ extract_file() {
chown -R 0:0 "$srcdir"
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/source/git.sh.in b/scripts/libmakepkg/source/git.sh.in
index 6d7e0a67..8129a717 100644
--- a/scripts/libmakepkg/source/git.sh.in
+++ b/scripts/libmakepkg/source/git.sh.in
@@ -120,3 +120,5 @@ extract_git() {
popd &>/dev/null
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/source/hg.sh.in b/scripts/libmakepkg/source/hg.sh.in
index 4e6ebad9..6a3e863d 100644
--- a/scripts/libmakepkg/source/hg.sh.in
+++ b/scripts/libmakepkg/source/hg.sh.in
@@ -102,3 +102,5 @@ extract_hg() {
popd &>/dev/null
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/source/local.sh.in b/scripts/libmakepkg/source/local.sh.in
index 8104141a..bfb93f8e 100644
--- a/scripts/libmakepkg/source/local.sh.in
+++ b/scripts/libmakepkg/source/local.sh.in
@@ -40,3 +40,5 @@ download_local() {
exit 1 # $E_MISSING_FILE
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/source/svn.sh.in b/scripts/libmakepkg/source/svn.sh.in
index 6cb78235..2fafadfe 100644
--- a/scripts/libmakepkg/source/svn.sh.in
+++ b/scripts/libmakepkg/source/svn.sh.in
@@ -91,3 +91,5 @@ extract_svn() {
cp -au "$dir" "$srcdir"
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/srcinfo.sh.in b/scripts/libmakepkg/srcinfo.sh.in
index 99f5628a..f627f88d 100644
--- a/scripts/libmakepkg/srcinfo.sh.in
+++ b/scripts/libmakepkg/srcinfo.sh.in
@@ -125,3 +125,5 @@ write_srcinfo() {
write_srcinfo_header
write_srcinfo_content
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/tidy.sh.in b/scripts/libmakepkg/tidy.sh.in
index 856f2394..ce7d879d 100644
--- a/scripts/libmakepkg/tidy.sh.in
+++ b/scripts/libmakepkg/tidy.sh.in
@@ -50,3 +50,5 @@ tidy_install() {
$func
done
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/tidy/docs.sh.in b/scripts/libmakepkg/tidy/docs.sh.in
index 0919f201..31617c81 100644
--- a/scripts/libmakepkg/tidy/docs.sh.in
+++ b/scripts/libmakepkg/tidy/docs.sh.in
@@ -35,3 +35,5 @@ tidy_docs() {
rm -rf -- ${DOC_DIRS[@]}
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/tidy/emptydirs.sh.in b/scripts/libmakepkg/tidy/emptydirs.sh.in
index 2b16afdf..9acf7f0f 100644
--- a/scripts/libmakepkg/tidy/emptydirs.sh.in
+++ b/scripts/libmakepkg/tidy/emptydirs.sh.in
@@ -37,3 +37,5 @@ tidy_emptydirs() {
find . -depth -type d -exec rmdir '{}' \; 2>/dev/null
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/tidy/libtool.sh.in b/scripts/libmakepkg/tidy/libtool.sh.in
index b844c792..3690e7bc 100644
--- a/scripts/libmakepkg/tidy/libtool.sh.in
+++ b/scripts/libmakepkg/tidy/libtool.sh.in
@@ -36,3 +36,5 @@ tidy_libtool() {
find . ! -type d -name "*.la" -exec rm -f -- '{}' +
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/tidy/purge.sh.in b/scripts/libmakepkg/tidy/purge.sh.in
index 5d37ded5..9c32e34d 100644
--- a/scripts/libmakepkg/tidy/purge.sh.in
+++ b/scripts/libmakepkg/tidy/purge.sh.in
@@ -43,3 +43,5 @@ tidy_purge() {
done
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/tidy/staticlibs.sh.in b/scripts/libmakepkg/tidy/staticlibs.sh.in
index 643932dd..df0bb4ed 100644
--- a/scripts/libmakepkg/tidy/staticlibs.sh.in
+++ b/scripts/libmakepkg/tidy/staticlibs.sh.in
@@ -41,3 +41,5 @@ tidy_staticlibs() {
done < <(find . ! -type d -name "*.a" -print0)
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/tidy/strip.sh.in b/scripts/libmakepkg/tidy/strip.sh.in
index 76562808..29218c4d 100644
--- a/scripts/libmakepkg/tidy/strip.sh.in
+++ b/scripts/libmakepkg/tidy/strip.sh.in
@@ -134,3 +134,5 @@ tidy_strip() {
done
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/tidy/zipman.sh.in b/scripts/libmakepkg/tidy/zipman.sh.in
index ff82d43c..ca30118a 100644
--- a/scripts/libmakepkg/tidy/zipman.sh.in
+++ b/scripts/libmakepkg/tidy/zipman.sh.in
@@ -59,3 +59,5 @@ tidy_zipman() {
-exec @INODECMD@ '{}' + 2>/dev/null)
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/util.sh.in b/scripts/libmakepkg/util.sh.in
index b7b56d34..7c8f9c98 100644
--- a/scripts/libmakepkg/util.sh.in
+++ b/scripts/libmakepkg/util.sh.in
@@ -26,3 +26,5 @@ LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
for lib in "$LIBRARY/util/"*.sh; do
source "$lib"
done
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/util/message.sh.in b/scripts/libmakepkg/util/message.sh.in
index 33808de7..49ce025d 100644
--- a/scripts/libmakepkg/util/message.sh.in
+++ b/scripts/libmakepkg/util/message.sh.in
@@ -67,3 +67,5 @@ error() {
local mesg=$1; shift
printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/util/option.sh.in b/scripts/libmakepkg/util/option.sh.in
index 8cf0039b..2892cdfb 100644
--- a/scripts/libmakepkg/util/option.sh.in
+++ b/scripts/libmakepkg/util/option.sh.in
@@ -140,3 +140,5 @@ check_buildoption() {
# not found
return 127
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/util/parseopts.sh.in b/scripts/libmakepkg/util/parseopts.sh.in
index a7638cf1..bd018cc8 100644
--- a/scripts/libmakepkg/util/parseopts.sh.in
+++ b/scripts/libmakepkg/util/parseopts.sh.in
@@ -171,3 +171,5 @@ parseopts() {
return 0
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in
index 2a4bd3af..7f431394 100644
--- a/scripts/libmakepkg/util/pkgbuild.sh.in
+++ b/scripts/libmakepkg/util/pkgbuild.sh.in
@@ -218,3 +218,5 @@ get_integlist() {
printf "%s\n" "${INTEGRITY_CHECK[@]}"
fi
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/util/source.sh.in b/scripts/libmakepkg/util/source.sh.in
index 238d1f58..aeeca00a 100644
--- a/scripts/libmakepkg/util/source.sh.in
+++ b/scripts/libmakepkg/util/source.sh.in
@@ -169,3 +169,5 @@ get_downloadclient() {
printf "%s\n" "$agent"
}
+
+# vim: set noet:
diff --git a/scripts/libmakepkg/util/util.sh.in b/scripts/libmakepkg/util/util.sh.in
index d676249d..45070bea 100644
--- a/scripts/libmakepkg/util/util.sh.in
+++ b/scripts/libmakepkg/util/util.sh.in
@@ -83,3 +83,5 @@ cd_safe() {
exit 1
fi
}
+
+# vim: set noet:
--
2.11.0
4
8
[pacman-dev] [PATCH] hooks: warn if reassignment overwrites previous setting
by Stefan Klinger 14 Mar '18
by Stefan Klinger 14 Mar '18
14 Mar '18
In hook definition files, repeated assignment to Description, Exec,
Type, and When silently overwrote previous settings. This yields a
warning now.
Signed-off-by: Stefan Klinger <git(a)stefan-klinger.de>
---
lib/libalpm/hook.c | 15 ++++++++++++++-
test/pacman/tests/TESTS | 4 ++++
test/pacman/tests/hook-description-reused.py | 23 +++++++++++++++++++++++
test/pacman/tests/hook-exec-reused.py | 22 ++++++++++++++++++++++
test/pacman/tests/hook-type-reused.py | 22 ++++++++++++++++++++++
test/pacman/tests/hook-when-reused.py | 22 ++++++++++++++++++++++
6 files changed, 107 insertions(+), 1 deletion(-)
create mode 100644 test/pacman/tests/hook-description-reused.py
create mode 100644 test/pacman/tests/hook-exec-reused.py
create mode 100644 test/pacman/tests/hook-type-reused.py
create mode 100644 test/pacman/tests/hook-when-reused.py
diff --git a/lib/libalpm/hook.c b/lib/libalpm/hook.c
index ccde225e..51e74484 100644
--- a/lib/libalpm/hook.c
+++ b/lib/libalpm/hook.c
@@ -267,6 +267,7 @@ static int _alpm_hook_parse_cb(const char *file, int line,
struct _alpm_hook_t *hook = ctx->hook;
#define error(...) _alpm_log(handle, ALPM_LOG_ERROR, __VA_ARGS__); return 1;
+#define warning(...) _alpm_log(handle, ALPM_LOG_WARNING, __VA_ARGS__);
if(!section && !key) {
error(_("error while reading hook %s: %s\n"), file, strerror(errno));
@@ -296,6 +297,9 @@ static int _alpm_hook_parse_cb(const char *file, int line,
error(_("hook %s line %d: invalid value %s\n"), file, line, value);
}
} else if(strcmp(key, "Type") == 0) {
+ if(t->type != 0) {
+ warning(_("hook %s line %d: overwriting previous definition of Type\n"), file, line);
+ }
if(strcmp(value, "Package") == 0) {
t->type = ALPM_HOOK_TYPE_PACKAGE;
} else if(strcmp(value, "File") == 0) {
@@ -312,6 +316,9 @@ static int _alpm_hook_parse_cb(const char *file, int line,
}
} else if(strcmp(section, "Action") == 0) {
if(strcmp(key, "When") == 0) {
+ if(hook->when != 0) {
+ warning(_("hook %s line %d: overwriting previous definition of When\n"), file, line);
+ }
if(strcmp(value, "PreTransaction") == 0) {
hook->when = ALPM_HOOK_PRE_TRANSACTION;
} else if(strcmp(value, "PostTransaction") == 0) {
@@ -320,6 +327,9 @@ static int _alpm_hook_parse_cb(const char *file, int line,
error(_("hook %s line %d: invalid value %s\n"), file, line, value);
}
} else if(strcmp(key, "Description") == 0) {
+ if(hook->desc != NULL) {
+ warning(_("hook %s line %d: overwriting previous definition of Description\n"), file, line);
+ }
STRDUP(hook->desc, value, return 1);
} else if(strcmp(key, "Depends") == 0) {
char *val;
@@ -330,7 +340,10 @@ static int _alpm_hook_parse_cb(const char *file, int line,
} else if(strcmp(key, "NeedsTargets") == 0) {
hook->needs_targets = 1;
} else if(strcmp(key, "Exec") == 0) {
- if((hook->cmd = _alpm_wordsplit(value)) == NULL) {
+ if(hook->cmd != NULL) {
+ warning(_("hook %s line %d: overwriting previous definition of Exec\n"), file, line);
+ }
+ if((hook->cmd = _alpm_wordsplit(value)) == NULL) {
if(errno == EINVAL) {
error(_("hook %s line %d: invalid value %s\n"), file, line, value);
} else {
diff --git a/test/pacman/tests/TESTS b/test/pacman/tests/TESTS
index 2d877962..4329ca90 100644
--- a/test/pacman/tests/TESTS
+++ b/test/pacman/tests/TESTS
@@ -53,6 +53,8 @@ TESTS += test/pacman/tests/fileconflict030.py
TESTS += test/pacman/tests/fileconflict031.py
TESTS += test/pacman/tests/fileconflict032.py
TESTS += test/pacman/tests/hook-abortonfail.py
+TESTS += test/pacman/tests/hook-description-reused.py
+TESTS += test/pacman/tests/hook-exec-reused.py
TESTS += test/pacman/tests/hook-exec-with-arguments.py
TESTS += test/pacman/tests/hook-file-change-packages.py
TESTS += test/pacman/tests/hook-file-remove-trigger-match.py
@@ -63,7 +65,9 @@ TESTS += test/pacman/tests/hook-pkg-postinstall-trigger-match.py
TESTS += test/pacman/tests/hook-pkg-remove-trigger-match.py
TESTS += test/pacman/tests/hook-pkg-upgrade-trigger-match.py
TESTS += test/pacman/tests/hook-target-list.py
+TESTS += test/pacman/tests/hook-type-reused.py
TESTS += test/pacman/tests/hook-upgrade-trigger-no-match.py
+TESTS += test/pacman/tests/hook-when-reused.py
TESTS += test/pacman/tests/ignore001.py
TESTS += test/pacman/tests/ignore002.py
TESTS += test/pacman/tests/ignore003.py
diff --git a/test/pacman/tests/hook-description-reused.py b/test/pacman/tests/hook-description-reused.py
new file mode 100644
index 00000000..5826a30e
--- /dev/null
+++ b/test/pacman/tests/hook-description-reused.py
@@ -0,0 +1,23 @@
+self.description = "Hook using multiple Description's"
+
+self.add_hook("hook",
+ """
+ [Trigger]
+ Type = Package
+ Operation = Install
+ Target = foo
+
+ [Action]
+ Description = lala
+ Description = foobar
+ When = PreTransaction
+ Exec = /bin/date
+ """);
+
+sp = pmpkg("foo")
+self.addpkg2db("sync", sp)
+
+self.args = "-S foo"
+
+self.addrule("PACMAN_RETCODE=0")
+self.addrule("PACMAN_OUTPUT=warning.*overwriting previous definition of Description")
diff --git a/test/pacman/tests/hook-exec-reused.py b/test/pacman/tests/hook-exec-reused.py
new file mode 100644
index 00000000..6fe53151
--- /dev/null
+++ b/test/pacman/tests/hook-exec-reused.py
@@ -0,0 +1,22 @@
+self.description = "Hook using multiple Exec's"
+
+self.add_hook("hook",
+ """
+ [Trigger]
+ Type = Package
+ Operation = Install
+ Target = foo
+
+ [Action]
+ When = PostTransaction
+ Exec = /bin/date
+ Exec = /bin/date
+ """);
+
+sp = pmpkg("foo")
+self.addpkg2db("sync", sp)
+
+self.args = "-S foo"
+
+self.addrule("PACMAN_RETCODE=0")
+self.addrule("PACMAN_OUTPUT=warning.*overwriting previous definition of Exec")
diff --git a/test/pacman/tests/hook-type-reused.py b/test/pacman/tests/hook-type-reused.py
new file mode 100644
index 00000000..8c4dfd0f
--- /dev/null
+++ b/test/pacman/tests/hook-type-reused.py
@@ -0,0 +1,22 @@
+self.description = "Hook using multiple Type's"
+
+self.add_hook("hook",
+ """
+ [Trigger]
+ Type = Package
+ Type = File
+ Operation = Install
+ Target = foo
+
+ [Action]
+ When = PostTransaction
+ Exec = /bin/date
+ """);
+
+sp = pmpkg("foo")
+self.addpkg2db("sync", sp)
+
+self.args = "-S foo"
+
+self.addrule("PACMAN_RETCODE=0")
+self.addrule("PACMAN_OUTPUT=warning.*overwriting previous definition of Type")
diff --git a/test/pacman/tests/hook-when-reused.py b/test/pacman/tests/hook-when-reused.py
new file mode 100644
index 00000000..07c3bc5e
--- /dev/null
+++ b/test/pacman/tests/hook-when-reused.py
@@ -0,0 +1,22 @@
+self.description = "Hook using multiple When's"
+
+self.add_hook("hook",
+ """
+ [Trigger]
+ Type = Package
+ Operation = Install
+ Target = foo
+
+ [Action]
+ When = PreTransaction
+ Exec = /bin/date
+ When = PostTransaction
+ """);
+
+sp = pmpkg("foo")
+self.addpkg2db("sync", sp)
+
+self.args = "-S foo"
+
+self.addrule("PACMAN_RETCODE=0")
+self.addrule("PACMAN_OUTPUT=warning.*overwriting previous definition of When")
--
2.11.0
7
20
20 May '17
Signed-off-by: Olivier Brunel <jjk(a)jjacky.com>
---
doc/pacman.8.txt | 5 +++++
doc/pacman.conf.5.txt | 6 ++++++
lib/libalpm/alpm.h | 3 +++
lib/libalpm/dload.c | 1 +
lib/libalpm/handle.c | 26 ++++++++++++++++++++++++++
lib/libalpm/handle.h | 1 +
src/pacman/conf.c | 11 +++++++++++
src/pacman/conf.h | 4 +++-
src/pacman/pacman.c | 11 +++++++++++
src/pacman/util.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
src/pacman/util.h | 2 ++
11 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt
index 231e0bc..1890cd9 100644
--- a/doc/pacman.8.txt
+++ b/doc/pacman.8.txt
@@ -266,6 +266,11 @@ Upgrade Options (apply to '-S' and '-U')[[UO]]
*\--needed*::
Do not reinstall the targets that are already up-to-date.
+*\--maxdlspeed* <speed>::
+ Sets the maximum download speed to the specified speed in bytes/s, unless a
+ suffix is appended. Suffix 'k' or 'K' will count as KiB/s, 'm' or 'M' as
+ MiB/s, and 'g' or 'G' as GiB/s.
+
Query Options (apply to '-Q')[[QO]]
-----------------------------------
diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index c665870..49ce63b 100644
--- a/doc/pacman.conf.5.txt
+++ b/doc/pacman.conf.5.txt
@@ -201,6 +201,12 @@ Options
bar is still based solely on the current file download.
This option won't work if XferCommand is used.
+*MaxDlSpeed*::
+ Sets the maximum download speed to the specified speed in bytes/s, unless a
+ suffix is appended. Suffix 'k' or 'K' will count as KiB/s, 'm' or 'M' as
+ MiB/s, and 'g' or 'G' as GiB/s.
+ This option won't work if XferCommand is used.
+
*CheckSpace*::
Performs an approximate check for adequate available disk space before
installing packages.
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 168d71b..7e4e9da 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -925,6 +925,9 @@ int alpm_option_set_local_file_siglevel(alpm_handle_t *handle, alpm_siglevel_t l
alpm_siglevel_t alpm_option_get_remote_file_siglevel(alpm_handle_t *handle);
int alpm_option_set_remote_file_siglevel(alpm_handle_t *handle, alpm_siglevel_t level);
+off_t alpm_option_get_maxdlspeed(alpm_handle_t *handle);
+int alpm_option_set_maxdlspeed(alpm_handle_t *handle, off_t speed);
+
/** @} */
/** @addtogroup alpm_api_databases Database Functions
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 31ae82c..8c6d6af 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -295,6 +295,7 @@ static void curl_set_handle_opts(struct dload_payload *payload,
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, dload_progress_cb);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, (void *)payload);
+ curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, handle->maxdlspeed);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1L);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 10L);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, dload_parseheader_cb);
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index e9439a0..9cab5da 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -844,4 +844,30 @@ alpm_siglevel_t SYMEXPORT alpm_option_get_remote_file_siglevel(alpm_handle_t *ha
}
}
+off_t SYMEXPORT alpm_option_get_maxdlspeed(alpm_handle_t *handle)
+{
+ CHECK_HANDLE(handle, return -1);
+#ifdef HAVE_LIBCURL
+ return (off_t) handle->maxdlspeed;
+#else
+ return 0;
+#endif
+}
+
+int SYMEXPORT alpm_option_set_maxdlspeed(alpm_handle_t *handle, off_t speed)
+{
+ CHECK_HANDLE(handle, return -1);
+#ifdef HAVE_LIBCURL
+ if(speed >= 0) {
+ handle->maxdlspeed = (curl_off_t) speed;
+ return 0;
+ } else
+#else
+ if(speed == 0)
+ return 0;
+ else
+#endif
+ RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
+}
+
/* vim: set noet: */
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index a1d0f9a..f55b6ed 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -60,6 +60,7 @@ struct __alpm_handle_t {
#ifdef HAVE_LIBCURL
/* libcurl handle */
CURL *curl; /* reusable curl_easy handle */
+ curl_off_t maxdlspeed; /* maximum download speed (B/s) */
#endif
#ifdef HAVE_LIBGPGME
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 25de7af..39cc15c 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -544,6 +544,16 @@ static int _parse_options(const char *key, char *value,
}
config->deltaratio = ratio;
pm_printf(ALPM_LOG_DEBUG, "config: usedelta = %f\n", ratio);
+ } else if(strcmp(key, "MaxDlSpeed") == 0) {
+ off_t speed = parsesize(value);
+ if(speed < 0) {
+ pm_printf(ALPM_LOG_ERROR,
+ _("config file %s, line %d: invalid value for '%s' : '%s'\n"),
+ file, linenum, "MaxDlSpeed", value);
+ return 1;
+ }
+ config->maxdlspeed = speed;
+ pm_printf(ALPM_LOG_DEBUG, "config: maxdlspeed = %jd\n", (intmax_t) speed);
} else if(strcmp(key, "DBPath") == 0) {
/* don't overwrite a path specified on the command line */
if(!config->dbpath) {
@@ -810,6 +820,7 @@ static int setup_libalpm(void)
alpm_option_set_checkspace(handle, config->checkspace);
alpm_option_set_usesyslog(handle, config->usesyslog);
alpm_option_set_deltaratio(handle, config->deltaratio);
+ alpm_option_set_maxdlspeed(handle, config->maxdlspeed);
alpm_option_set_ignorepkgs(handle, config->ignorepkg);
alpm_option_set_ignoregroups(handle, config->ignoregrp);
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 2aba8bf..77353a2 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -56,6 +56,7 @@ typedef struct __config_t {
unsigned short usesyslog;
unsigned short color;
double deltaratio;
+ off_t maxdlspeed;
char *arch;
char *print_format;
/* unfortunately, we have to keep track of paths both here and in the library
@@ -201,7 +202,8 @@ enum {
OP_VERBOSE,
OP_DOWNLOADONLY,
OP_REFRESH,
- OP_ASSUMEINSTALLED
+ OP_ASSUMEINSTALLED,
+ OP_MAXDLSPEED
};
/* clean method */
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index be52d1b..91f8500 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -194,6 +194,8 @@ static void usage(int op, const char * const myname)
addlist(_(" --ignore <pkg> ignore a package upgrade (can be used more than once)\n"));
addlist(_(" --ignoregroup <grp>\n"
" ignore a group upgrade (can be used more than once)\n"));
+ addlist(_(" --maxdlspeed <speed>\n"
+ " set the maximum download speed\n"));
/* pass through */
case PM_OP_REMOVE:
addlist(_(" -d, --nodeps skip dependency version checks (-dd to skip all checks)\n"));
@@ -713,6 +715,14 @@ static int parsearg_upgrade(int opt)
case OP_IGNOREGROUP:
parsearg_util_addlist(&(config->ignoregrp));
break;
+ case OP_MAXDLSPEED:
+ {
+ off_t speed = parsesize(optarg);
+ if(speed < 0)
+ return 1;
+ config->maxdlspeed = speed;
+ break;
+ }
default: return 1;
}
return 0;
@@ -929,6 +939,7 @@ static int parseargs(int argc, char *argv[])
{"ignoregroup", required_argument, 0, OP_IGNOREGROUP},
{"needed", no_argument, 0, OP_NEEDED},
{"asexplicit", no_argument, 0, OP_ASEXPLICIT},
+ {"maxdlspeed", required_argument, 0, OP_MAXDLSPEED},
{"arch", required_argument, 0, OP_ARCH},
{"print-format", required_argument, 0, OP_PRINTFORMAT},
{"gpgdir", required_argument, 0, OP_GPGDIR},
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 81780f7..35b4f23 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -1763,4 +1763,49 @@ int pm_vfprintf(FILE *stream, alpm_loglevel_t level, const char *format, va_list
return ret;
}
+off_t parsesize(const char *str)
+{
+ long size;
+ char *endptr;
+
+ size = strtol(str, &endptr, 10);
+ if((size == LONG_MIN || size == LONG_MAX) && errno == ERANGE) {
+ return -1;
+ }
+ if(*endptr != '\0') {
+ if(endptr[1] != '\0') {
+ return -1;
+ }
+ switch(*endptr) {
+ case 'g':
+ case 'G':
+ if(size > LONG_MAX / 1024) {
+ return -1;
+ }
+ size *= 1024;
+ /* fallthrough */
+ case 'm':
+ case 'M':
+ if(size > LONG_MAX / 1024) {
+ return -1;
+ }
+ size *= 1024;
+ /* fallthrough */
+ case 'k':
+ case 'K':
+ if(size > LONG_MAX / 1024) {
+ return -1;
+ }
+ size *= 1024;
+ break;
+ default:
+ return -1;
+ }
+ }
+ if(size < 0) {
+ return -1;
+ }
+ return (off_t) size;
+}
+
/* vim: set noet: */
diff --git a/src/pacman/util.h b/src/pacman/util.h
index f5e37c8..7d0a897 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -82,6 +82,8 @@ int pm_vfprintf(FILE *stream, alpm_loglevel_t level, const char *format, va_list
int pm_sprintf(char **string, alpm_loglevel_t level, const char *format, ...) __attribute__((format(printf,3,4)));
int pm_vasprintf(char **string, alpm_loglevel_t level, const char *format, va_list args) __attribute__((format(printf,3,0)));
+off_t parsesize(const char *str);
+
#endif /* _PM_UTIL_H */
/* vim: set noet: */
--
2.9.3
3
2
Re: [pacman-dev] [PATCH 3/4] makepkg: unify source file times for improved build reproducibility
by Allan McRae 02 May '17
by Allan McRae 02 May '17
02 May '17
On 21/04/17 13:36, Eli Schwartz wrote:
> On 04/20/2017 11:01 PM, Allan McRae wrote:
>> I am probably moving this to after source extraction/prepare() running,
>> so it can be skipped with --noextract.
>
> But --noextract depends on your having at some point previously run
> --nobuild, in order to pull updated sources, re-patch any patches, etc.
> which I still don't want to do manually outside of makepkg... I don't
> see why makepkg should start breaking things for me.
>
> How about instead we guard it with
> BUILDENV+=(fix_everyone_elses_SOURCE_DATE_EPOCH_stuff)
>
> Or better yet, just file bugs against whatever upstream build
> system/programming language/source code is determined to sneakily embed
> source code modification times into generated files, and call it a day?
>
Adding list back - any further off-list replies will be completely ignored.
The reproducible builds people will provide details, but it appears
pyo/pyc do this.
A
3
3
On 23/04/17 09:36, Dustin Falgout wrote:
> I would like a way to include custom attributes from the PKGBUILD in the output of the --printsrcinfo option. So basically, this...
>
> pkgbase = pacman
> pkgdesc = A library-based package manager with dependency support
> pkgver = 5.0.1
> pkgrel = 4
> url = http://www.archlinux.org/pacman/
> arch = i686
> arch = x86_64
> ...
> _custom_attribute1 = some value
> _custom_attribute2 = some value
> _custom_attribute3 = some value
> ...
>
> pkgname = pacman
>
Bringing the mailing list back into this (seems our reply field is
broken...)
Can you give an example of what a custom attribute would be? Your
example is still to vague to judge whether this would be something we
wish to support.
Thanks,
Allan
2
3
---
For alpm tests, we use compiled tests using pactest.c to setup package/db files
and temporary working environments, ptserve.c to run an http server for sync
packages, and tap.c to generate the test output. Everything is already
working, but I would appreciate feedback on the following in particular:
1. autotools - I have no idea if I got all of the autotools nonsense correct.
2. pactest.c API - Being C programs these are always going to be more verbose
and have more boilerplate than our python test suite, but any suggestions
for how to improve the pactest.c API to make writing tests easier are
welcome.
3. git submodules - tap.c, pactest.c, and ptserve.c are projects that I'm
managing externally, just like tap.sh. This patch just includes static
copies of them; should we use git submodules instead?
Makefile.am | 7 +-
configure.ac | 2 +
test/alpm/Makefile.am | 11 +
test/alpm/README | 108 ++++++
test/alpm/alpmtest.h | 14 +
test/alpm/pactest.c | 458 +++++++++++++++++++++++++
test/alpm/ptrun | 58 ++++
test/alpm/ptserve.c | 403 ++++++++++++++++++++++
test/alpm/tap.c | 305 ++++++++++++++++
test/alpm/tests/.gitignore | 3 +
test/alpm/tests/Makefile.am | 21 ++
test/alpm/tests/TESTS | 3 +
test/alpm/tests/add_remove.c | 56 +++
test/alpm/tests/cached_part_file.c | 65 ++++
test/alpm/tests/part_file_in_secondary_cache.c | 102 ++++++
15 files changed, 1615 insertions(+), 1 deletion(-)
create mode 100644 test/alpm/Makefile.am
create mode 100644 test/alpm/README
create mode 100644 test/alpm/alpmtest.h
create mode 100644 test/alpm/pactest.c
create mode 100755 test/alpm/ptrun
create mode 100644 test/alpm/ptserve.c
create mode 100644 test/alpm/tap.c
create mode 100644 test/alpm/tests/.gitignore
create mode 100644 test/alpm/tests/Makefile.am
create mode 100644 test/alpm/tests/TESTS
create mode 100644 test/alpm/tests/add_remove.c
create mode 100644 test/alpm/tests/cached_part_file.c
create mode 100644 test/alpm/tests/part_file_in_secondary_cache.c
diff --git a/Makefile.am b/Makefile.am
index 67ffc6b4..20544242 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = lib/libalpm src/util src/pacman scripts etc test/pacman test/util test/scripts
+SUBDIRS = lib/libalpm src/util src/pacman scripts etc test/pacman test/util test/scripts test/alpm
if WANT_DOC
SUBDIRS += doc
endif
@@ -32,6 +32,7 @@ TESTS = test/scripts/parseopts_test.sh \
test/scripts/pacman-db-upgrade-v9.py \
test/util/vercmptest.sh
include $(top_srcdir)/test/pacman/tests/TESTS
+include $(top_srcdir)/test/alpm/tests/TESTS
TEST_SUITE_LOG = test/test-suite.log
TEST_EXTENSIONS = .py
@@ -50,6 +51,10 @@ AM_PY_LOG_FLAGS = \
--ldconfig $(LDCONFIG) \
--bindir $(top_builddir)/src/pacman \
--bindir $(top_builddir)/scripts
+T_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
+ $(top_srcdir)/build-aux/tap-driver.sh
+T_LOG_COMPILER = $(top_srcdir)/test/alpm/ptrun
+AM_T_LOG_FLAGS = -rc
# create the pacman DB, cache, makepkg-template and system hook directories upon install
install-data-local:
diff --git a/configure.ac b/configure.ac
index 57f068d3..514a8dd6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -526,6 +526,8 @@ scripts/Makefile
scripts/po/Makefile.in
doc/Makefile
etc/Makefile
+test/alpm/Makefile
+test/alpm/tests/Makefile
test/pacman/Makefile
test/pacman/tests/Makefile
test/scripts/Makefile
diff --git a/test/alpm/Makefile.am b/test/alpm/Makefile.am
new file mode 100644
index 00000000..7f0a4ca0
--- /dev/null
+++ b/test/alpm/Makefile.am
@@ -0,0 +1,11 @@
+SUBDIRS = tests
+
+check_SCRIPTS = ptrun
+
+noinst_SCRIPTS = $(check_SCRIPTS)
+
+EXTRA_DIST = \
+ README \
+ $(check_SCRIPTS)
+
+# vim:set noet:
diff --git a/test/alpm/README b/test/alpm/README
new file mode 100644
index 00000000..3762545d
--- /dev/null
+++ b/test/alpm/README
@@ -0,0 +1,108 @@
+Running Tests
+=============
+
+Tests are normally run using `make check` from the project root. Individual
+tests are located under 'tests/' and can be run directly. `ptrun` is a wrapper
+script provided as a convenience for modifying how tests are run (using
+fakeroot, fakechroot, valgrind, etc.).
+
+Requirements
+------------
+
+All requirements are optional unless otherwise noted. Tests that depend on any
+missing requirements will be skipped.
+
+* pthreads
+* fakechroot
+* fakeroot
+
+Writing Tests
+=============
+
+Libraries
+---------
+
+Tests should `#include "../alpmtest.h"`. This will bring in libalpm,
+pactest.c, ptserve.c, tap.c, and stdio libraries.
+
+Test Naming
+-----------
+
+Tests designed to check a particular function or data type under multiple
+conditions should be named after the function or data type being tested (e.g.
+`alpm_filelist.c`). Otherwise, tests should be named according to the
+particular condition being tested, avoiding an `alpm` prefix if possible (e.g.
+`cached_part_file.c`).
+
+Test Initialization
+-------------------
+
+Any functions called during test setup that could fail should be wrapped in
+`ASSERT`.
+
+Any calls that could fail should be wrapped in either an `ASSERT` or
+a `tap_*` function.
+
+Do not rely on pactest.c default settings. If a test requires a particular
+option, set it manually in the test.
+
+If a test program is being run in an environment where it is impossible for the
+tests to properly run (e.g. due to insufficient permissions or missing
+features) the test should be skipped using `tap_skip_all` and return 0. Tests
+which should be able to run but fail to should bail out and return 99. In
+particular, tests which rely on install scriptlets or ldconfig should check for
+`chroot` permissions with the `CAN_CHROOT` macro and tests which rely on
+setting file ownership should check `CAN_CHOWN` before running.
+
+Test Cleanup
+------------
+
+Tests should ensure that all memory is freed after a successful run. Memory
+leaks are acceptable if the test fails, but any `pt_env_t` or `pt_serve_t`
+resources must be freed regardless of test failure. The easiest way to
+accomplish this is to register a `cleanup` function using `atexit`.
+
+Return Values
+-------------
+
+ 0 - success or test skipped (returned by `tap_finish`)
+ 1 - failed test(s) or bad/missing test plan (returned by `tap_finish`)
+ 77 - reserved*
+ 99 - hard error** (set by `ASSERT`)
+ 123 - valgrind error (set by ptrun)
+
+* Automake uses an exit status of 77 for simple tests to indicate that a test
+ was skipped. For TAP-based tests an exit status of 77 counts as failure, so
+ skipped tests should call `tap_skip_all` and return 0. Avoiding 77 as an
+ exit status prevents confusion between a failed or skipped test if a test is
+ accidentally run as a simple test.
+
+** For compatibility with Automake's simple test runner.
+
+Template
+--------
+
+.. code:: c
+
+ #include "../alpmtest.h"
+
+ /* <describe what is being tested> */
+
+ pt_env_t *pt = NULL;
+
+ void cleanup(void) {
+ pt_cleanup(pt);
+ }
+
+ int main(void) {
+ ASSERT(atexit(cleanup) == 0);
+
+ <setup test>
+
+ tap_plan(<number of tests>);
+ <perform test>
+
+ return tap_finish();
+ }
+
+.. vim: set ft=rst:
diff --git a/test/alpm/alpmtest.h b/test/alpm/alpmtest.h
new file mode 100644
index 00000000..3df772ab
--- /dev/null
+++ b/test/alpm/alpmtest.h
@@ -0,0 +1,14 @@
+#include "pactest.c"
+#include "ptserve.c"
+#include "tap.c"
+#include <alpm.h>
+#include <stdio.h>
+
+#define ASSERT(x) \
+ if(!(x)) { \
+ tap_bail("ASSERT FAILED %s line %d: '%s'", __FILE__, __LINE__, #x); \
+ exit(1); \
+ }
+
+#define CAN_CHROOT chroot("/") == 0
+#define CAN_CHOWN geteuid() == 0
diff --git a/test/alpm/pactest.c b/test/alpm/pactest.c
new file mode 100644
index 00000000..28fdb14e
--- /dev/null
+++ b/test/alpm/pactest.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright 2015 Andrew Gregory <andrew.gregory.8(a)gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Project URL: http://github.com/andrewgregory/pactest.c
+ */
+
+#ifndef PACTEST_C
+#define PACTEST_C
+
+#define PACTEST_C_VERSION "0.1"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <alpm.h>
+#include <archive.h>
+#include <archive_entry.h>
+
+typedef struct pt_pkg_t {
+ alpm_list_t *backup;
+ alpm_list_t *conflicts;
+ alpm_list_t *depends;
+ alpm_list_t *groups;
+ alpm_list_t *licenses;
+ alpm_list_t *optdepends;
+ alpm_list_t *makedepends;
+ alpm_list_t *checkdepends;
+ alpm_list_t *provides;
+ alpm_list_t *replaces;
+ char *arch;
+ char *base;
+ char *builddate;
+ char *desc;
+ char *csize;
+ char *isize;
+ char *name;
+ char *packager;
+ char *url;
+ char *version;
+ char *filename;
+} pt_pkg_t;
+
+typedef struct pt_db_t {
+ char *name;
+ alpm_list_t *pkgs;
+} pt_db_t;
+
+typedef struct pt_env_t {
+ char *root;
+ char *dbpath;
+ int rootfd;
+ int dbpathfd;
+ alpm_list_t *pkgs;
+ alpm_list_t *dbs;
+} pt_env_t;
+
+/************************************
+ * utility functions
+ ************************************/
+
+char *pt_path(pt_env_t *pt, const char *path) {
+ static char abspath[PATH_MAX];
+ if(snprintf(abspath, PATH_MAX, "%s/%s", pt->root, path) >= PATH_MAX) {
+ return NULL;
+ } else {
+ return abspath;
+ }
+}
+
+static int _pt_rmrfat(int dd, const char *path) {
+ struct stat sbuf;
+ if(fstatat(dd, path, &sbuf, AT_SYMLINK_NOFOLLOW) != 0) {
+ return errno == ENOENT ? 0 : -1;
+ } else if(S_ISDIR(sbuf.st_mode)) {
+ int fd;
+ DIR *d;
+ struct dirent ent, *ctx;
+
+ if((fd = openat(dd, path, O_DIRECTORY)) < 0) { return -1; }
+ if((d = fdopendir(fd)) == NULL) { close(fd); return -1; }
+
+ while(readdir_r(d, &ent, &ctx) == 0 && ctx != NULL) {
+ if(strcmp(ent.d_name, ".") == 0) { continue; }
+ if(strcmp(ent.d_name, "..") == 0) { continue; }
+ if(_pt_rmrfat(fd, ent.d_name) != 0) { break; }
+ }
+ closedir(d);
+ return ctx == NULL ? unlinkat(dd, path, AT_REMOVEDIR) : -1;
+ } else {
+ return unlinkat(dd, path, 0);
+ }
+}
+
+static int _pt_mkpdirat(int dd, const char *path, mode_t mode) {
+ char *c, *pcopy = strdup(path);
+ if(pcopy == NULL) { return -1; }
+ for(c = pcopy; *c == '/'; c++); /* skip leading '/' */
+ while((c = strchr(c, '/'))) {
+ *c = '\0';
+ if(mkdirat(dd, pcopy, mode) != 0 && errno != EEXIST) {
+ free(pcopy);
+ return -1;
+ }
+ for(*(c++) = '/'; *c == '/'; c++); /* restore and skip '/' */
+ }
+ free(pcopy);
+ return 0;
+}
+
+int pt_mkdirat(int dd, const char *path, mode_t mode) {
+ if(_pt_mkpdirat(dd, path, mode) != 0) { return -1; }
+ return mkdirat(dd, path, mode);
+}
+
+/************************************
+ * package functions
+ ************************************/
+
+void pt_pkg_free(pt_pkg_t *pkg) {
+ if(pkg == NULL) { return; }
+ FREELIST(pkg->backup);
+ FREELIST(pkg->conflicts);
+ FREELIST(pkg->depends);
+ FREELIST(pkg->groups);
+ FREELIST(pkg->licenses);
+ FREELIST(pkg->optdepends);
+ FREELIST(pkg->provides);
+ FREELIST(pkg->replaces);
+ free(pkg->arch);
+ free(pkg->base);
+ free(pkg->builddate);
+ free(pkg->desc);
+ free(pkg->csize);
+ free(pkg->isize);
+ free(pkg->name);
+ free(pkg->packager);
+ free(pkg->url);
+ free(pkg->version);
+ free(pkg->filename);
+ free(pkg);
+}
+
+pt_pkg_t *pt_pkg_new(pt_env_t *pt, const char *pkgname, const char *pkgver) {
+ pt_pkg_t *pkg = NULL;
+#define _PT_ASSERT(x) if(!(x)) { pt_pkg_free(pkg); return NULL; }
+ _PT_ASSERT(pkg = calloc(sizeof(pt_pkg_t), 1));
+ _PT_ASSERT(pkg->name = strdup(pkgname));
+ _PT_ASSERT(pkg->version = strdup(pkgver));
+ _PT_ASSERT(pt == NULL || alpm_list_append(&pt->pkgs, pkg));
+#undef _PT_ASSERT
+ return pkg;
+}
+
+static int _pt_fwrite_pkgentry(FILE *f, const char *section, const char *value) {
+ if(value && fprintf(f, "%s = %s\n", section, value) < 0) { return -1; }
+ return 0;
+}
+
+static int _pt_fwrite_pkglist(FILE *f, const char *section, alpm_list_t *values) {
+ while(values) {
+ if(_pt_fwrite_pkgentry(f, section, values->data) < 0) { return -1; }
+ values = values->next;
+ }
+ return 0;
+}
+
+
+int _pt_pkg_write_archive(pt_pkg_t *pkg, struct archive *a) {
+ FILE *contents;
+ struct archive_entry *e;
+ char *buf = NULL;
+ size_t buflen = 0;
+
+ if((contents = open_memstream(&buf, &buflen)) == NULL) { return -1; }
+
+#define _PT_ASSERT(x) if(!(x)) { fclose(contents); free(buf); return -1; }
+ _PT_ASSERT( _pt_fwrite_pkgentry(contents, "pkgname", pkg->name) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkgentry(contents, "pkgver", pkg->version) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkgentry(contents, "pkgdesc", pkg->desc) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkgentry(contents, "url", pkg->url) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkgentry(contents, "builddate", pkg->builddate) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkgentry(contents, "packager", pkg->packager) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkgentry(contents, "arch", pkg->arch) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkgentry(contents, "size", pkg->isize) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkglist(contents, "group", pkg->groups) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkglist(contents, "license", pkg->licenses) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkglist(contents, "depend", pkg->depends) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkglist(contents, "optdepend", pkg->optdepends) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkglist(contents, "conflict", pkg->conflicts) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkglist(contents, "replaces", pkg->replaces) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkglist(contents, "provides", pkg->provides) == 0 );
+ _PT_ASSERT( _pt_fwrite_pkglist(contents, "backup", pkg->backup) == 0 );
+ _PT_ASSERT( fclose(contents) == 0 );
+#undef _PT_ASSERT
+
+#define _PT_ASSERT(x) if(!(x)) { free(buf); archive_entry_free(e); return -1; }
+ _PT_ASSERT( e = archive_entry_new() );
+
+ archive_entry_set_pathname(e, ".PKGINFO");
+ archive_entry_set_perm(e, 0644);
+ archive_entry_set_filetype(e, AE_IFREG);
+ archive_entry_set_size(e, buflen);
+
+ _PT_ASSERT( archive_write_header(a, e) == ARCHIVE_OK );
+ _PT_ASSERT( archive_write_data(a, buf, buflen) != -1 );
+#undef _PT_ASSERT
+
+ free(buf);
+ archive_entry_free(e);
+
+ return 0;
+}
+
+int pt_pkg_writeat(int dd, const char *path, pt_pkg_t *pkg) {
+ struct archive *a;
+ char *c;
+ int fd;
+
+ if(_pt_mkpdirat(dd, path, 0700) != 0) { return -1; }
+ if((fd = openat(dd, path, O_CREAT | O_WRONLY, 0644)) < 0) { return -1; }
+
+ if((a = archive_write_new()) == NULL) { close(fd); return -1; }
+
+#define _PT_ASSERT(x) if(!(x)) { close(fd); archive_write_free(a); return -1; }
+
+ if((c = strrchr(path, '.'))) {
+ if(strcmp(c, ".bz2") == 0) {
+ _PT_ASSERT( archive_write_add_filter_bzip2(a) == ARCHIVE_OK );
+ } else if(strcmp(c, ".gz") == 0) {
+ _PT_ASSERT( archive_write_add_filter_gzip(a) == ARCHIVE_OK );
+ } else if(strcmp(c, ".xz") == 0) {
+ _PT_ASSERT( archive_write_add_filter_xz(a) == ARCHIVE_OK );
+ } else if(strcmp(c, ".lz") == 0) {
+ _PT_ASSERT( archive_write_add_filter_lzip(a) == ARCHIVE_OK );
+ } else if(strcmp(c, ".Z") == 0) {
+ _PT_ASSERT( archive_write_add_filter_compress(a) == ARCHIVE_OK );
+ }
+ }
+
+ _PT_ASSERT( archive_write_set_format_ustar(a) == ARCHIVE_OK );
+ _PT_ASSERT( archive_write_open_fd(a, fd) == ARCHIVE_OK );
+ _PT_ASSERT( _pt_pkg_write_archive(pkg, a) == 0 );
+
+#undef _PT_ASSERT
+
+ archive_write_free(a);
+ close(fd);
+ return 0;
+}
+
+/************************************
+ * database functions
+ ************************************/
+
+void pt_db_free(pt_db_t *db) {
+ if(db == NULL) { return; }
+ alpm_list_free(db->pkgs);
+ free(db->name);
+ free(db);
+}
+
+pt_db_t *pt_db_new(pt_env_t *pt, const char *dbname) {
+ pt_db_t *db = NULL;
+#define _PT_ASSERT(x) if(!(x)) { pt_db_free(db); return NULL; }
+ _PT_ASSERT(db = calloc(sizeof(pt_db_t), 1));
+ _PT_ASSERT(db->name = strdup(dbname));
+ _PT_ASSERT(pt == NULL || alpm_list_append(&pt->dbs, db));
+#undef _PT_ASSERT
+ return db;
+}
+
+int pt_db_add_pkg(pt_db_t *db, pt_pkg_t *pkg) {
+ return alpm_list_append(&db->pkgs, pkg) ? 1 : 0;
+}
+
+int _pt_fwrite_dbheader(FILE *f, const char *header) {
+ return fprintf(f, "%%" "%s" "%%" "\n", header);
+}
+
+void _pt_fwrite_dbentry(FILE *f, const char *section, const char *value) {
+ if(value == NULL) { return; }
+ _pt_fwrite_dbheader(f, section);
+ fprintf(f, "%s\n\n", value);
+}
+
+void _pt_fwrite_dblist(FILE *f, const char *section, alpm_list_t *values) {
+ _pt_fwrite_dbheader(f, section);
+ while(values) {
+ fprintf(f, "%s\n", (char *) values->data);
+ values = values->next;
+ }
+ fputc('\n', f);
+}
+
+int pt_db_writeat(int dd, const char *path, pt_db_t *db) {
+ alpm_list_t *i;
+ struct archive *a = archive_write_new();
+ struct archive_entry *e = archive_entry_new();
+ int fd = openat(dd, path, O_CREAT | O_WRONLY, 0644);
+
+ archive_write_set_format_ustar(a);
+ archive_write_open_fd(a, fd);
+ for(i = db->pkgs; i; i = i->next) {
+ pt_pkg_t *pkg = i->data;
+ size_t buflen = 0;
+ char *buf, ppath[PATH_MAX];
+ FILE *f;
+
+ sprintf(ppath, "%s-%s/", pkg->name, pkg->version);
+ archive_entry_clear(e);
+ archive_entry_set_pathname(e, ppath);
+ archive_entry_set_filetype(e, AE_IFDIR);
+ archive_entry_set_perm(e, 0755);
+ archive_write_header(a, e);
+
+ f = open_memstream(&buf, &buflen);
+ _pt_fwrite_dblist(f, "DEPENDS", pkg->depends);
+ _pt_fwrite_dblist(f, "CONFLICTS", pkg->conflicts);
+ _pt_fwrite_dblist(f, "PROVIDES", pkg->provides);
+ _pt_fwrite_dblist(f, "OPTDEPENDS", pkg->optdepends);
+ _pt_fwrite_dblist(f, "MAKEDEPENDS", pkg->makedepends);
+ _pt_fwrite_dblist(f, "CHECKDEPENDS", pkg->checkdepends);
+ fclose(f);
+
+ sprintf(ppath, "%s-%s/depends", pkg->name, pkg->version);
+ archive_entry_clear(e);
+ archive_entry_set_pathname(e, ppath);
+ archive_entry_set_filetype(e, AE_IFREG);
+ archive_entry_set_perm(e, 0644);
+ archive_entry_set_size(e, buflen);
+ archive_write_header(a, e);
+ archive_write_data(a, buf, buflen);
+ free(buf);
+
+ f = open_memstream(&buf, &buflen);
+ _pt_fwrite_dbentry(f, "FILENAME", pkg->filename);
+ _pt_fwrite_dbentry(f, "NAME", pkg->name);
+ _pt_fwrite_dbentry(f, "ARCH", pkg->arch);
+ _pt_fwrite_dbentry(f, "BASE", pkg->base);
+ _pt_fwrite_dbentry(f, "VERSION", pkg->version);
+ _pt_fwrite_dbentry(f, "DESC", pkg->desc);
+ _pt_fwrite_dbentry(f, "CSIZE", pkg->csize);
+ _pt_fwrite_dbentry(f, "ISIZE", pkg->isize);
+ _pt_fwrite_dblist(f, "GROUPS", pkg->groups);
+ fclose(f);
+
+ sprintf(ppath, "%s-%s/desc", pkg->name, pkg->version);
+ archive_entry_clear(e);
+ archive_entry_set_pathname(e, ppath);
+ archive_entry_set_filetype(e, AE_IFREG);
+ archive_entry_set_perm(e, 0644);
+ archive_entry_set_size(e, buflen);
+ archive_write_header(a, e);
+ archive_write_data(a, buf, buflen);
+ free(buf);
+ }
+
+ archive_entry_free(e);
+ archive_write_free(a);
+ close(fd);
+ return 0;
+}
+
+/************************************
+ * pactest functions
+ ************************************/
+
+void pt_cleanup(pt_env_t *pt) {
+ if(pt == NULL) { return; }
+
+ alpm_list_free_inner(pt->pkgs, (alpm_list_fn_free) pt_pkg_free);
+ alpm_list_free(pt->pkgs);
+ alpm_list_free_inner(pt->dbs, (alpm_list_fn_free) pt_db_free);
+ alpm_list_free(pt->dbs);
+
+ close(pt->rootfd);
+ close(pt->dbpathfd);
+
+ _pt_rmrfat(AT_FDCWD, pt->root);
+
+ free(pt->root);
+ free(pt->dbpath);
+ free(pt);
+}
+
+pt_env_t *pt_init(const char *dbpath) {
+ pt_env_t *pt = NULL;
+ char *tmpdir = getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp";
+ char *template = "pactest-XXXXXX";
+ size_t rootlen = strlen(tmpdir) + strlen("/") + strlen(template);
+ if(dbpath == NULL) { dbpath = "var/lib/pacman"; }
+#define _PT_ASSERT(x) if(!(x)) { pt_cleanup(pt); return NULL; }
+ _PT_ASSERT(pt = calloc(sizeof(pt_env_t), 1));
+ _PT_ASSERT(pt->root = malloc(rootlen + 1));
+ _PT_ASSERT(sprintf(pt->root, "%s/%s", tmpdir, template) > 0);
+ _PT_ASSERT(mkdtemp(pt->root) != NULL);
+ _PT_ASSERT((pt->rootfd = open(pt->root, O_DIRECTORY)) >= 0);
+ _PT_ASSERT(pt->dbpath = strdup(pt_path(pt, dbpath)));
+ _PT_ASSERT(pt_mkdirat(pt->rootfd, dbpath, 0700) == 0);
+ _PT_ASSERT((pt->dbpathfd = open(pt->dbpath, O_DIRECTORY)) >= 0);
+#undef _PT_ASSERT
+ return pt;
+}
+
+int pt_install_db(pt_env_t *pt, pt_db_t *db) {
+ char path[PATH_MAX];
+ pt_mkdirat(pt->dbpathfd, "sync", 0755);
+ sprintf(path, "sync/%s.db", db->name);
+ return pt_db_writeat(pt->dbpathfd, path, db);
+}
+
+char *pt_vasprintf(const char *fmt, va_list args) {
+ va_list arg_cp;
+ size_t len;
+ char *ret;
+ va_copy(arg_cp, args);
+ len = vsnprintf(NULL, 0, fmt, arg_cp);
+ va_end(arg_cp);
+ if((ret = malloc(len + 2)) != NULL) { vsprintf(ret, fmt, args); }
+ return ret;
+}
+
+char *pt_asprintf(const char *fmt, ...) {
+ va_list args;
+ char *ret;
+ va_start(args, fmt);
+ ret = pt_vasprintf(fmt, args);
+ va_end(args);
+ return ret;
+}
+
+#endif /* PACTEST_C */
diff --git a/test/alpm/ptrun b/test/alpm/ptrun
new file mode 100755
index 00000000..dcdc9e55
--- /dev/null
+++ b/test/alpm/ptrun
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+fakechroot=0
+fakeroot=0
+gdb=0
+libtool=0
+valgrind=0
+cmd=()
+
+extend() {
+ if which "$1" &>/dev/null; then
+ cmd+=("$@")
+ else
+ # bailing out would be counted as a failure by test harnesses,
+ # ignore missing programs so that tests can be gracefully skipped
+ printf "warning: command '$1' not found\n" >&2
+ fi
+}
+
+usage() {
+ printf "ptrun - run an executable pacman test\n"
+ printf "usage: ptrun [options] <testfile> [test-options]\n"
+ printf "\n"
+ printf "Options:\n"
+ printf " -c fakechroot\n"
+ printf " -d enable alpm debug log\n"
+ printf " -r fakeroot\n"
+ printf " -g gdb (implies -l)\n"
+ printf " -h display help\n"
+ printf " -l libtool execute\n"
+ printf " -s preserve test environment\n"
+ printf " -v valgrind (implies -l)\n"
+}
+
+while getopts cdghlrsv name; do
+ case $name in
+ c) fakechroot=1;;
+ d) export PT_DEBUG=1;;
+ g) libtool=1; gdb=1;;
+ h) usage; exit;;
+ l) libtool=1;;
+ r) fakeroot=1;;
+ s) export PT_KEEP_ROOT=1;;
+ v) libtool=1; valgrind=1;;
+ esac
+done
+
+[ $fakechroot -eq 1 ] && extend fakechroot
+[ $fakeroot -eq 1 ] && extend fakeroot
+[ $libtool -eq 1 ] && extend libtool execute
+[ $gdb -eq 1 ] && extend gdb
+[ $valgrind -eq 1 ] && extend valgrind --quiet --leak-check=full \
+ --gen-suppressions=yes --error-exitcode=123 \
+ --suppressions="$(dirname "$0")/../../valgrind.supp"
+
+while (( --OPTIND > 0 )); do shift; done # remove our options from the stack
+
+"${cmd[@]}" "$@"
diff --git a/test/alpm/ptserve.c b/test/alpm/ptserve.c
new file mode 100644
index 00000000..049abda0
--- /dev/null
+++ b/test/alpm/ptserve.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright 2015 Andrew Gregory <andrew.gregory.8(a)gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Project URL: http://github.com/andrewgregory/pactest.c
+ */
+
+#ifndef PTSERVE_C
+#define PTSERVE_C
+
+#define PTSERVE_C_VERSION 0.1
+
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/wait.h>
+
+#include <alpm.h>
+
+typedef struct ptserve_message_t {
+ struct ptserve_t *ptserve;
+ char *method;
+ char *path;
+ char *protocol;
+ alpm_list_t *headers;
+ int socket_fd;
+} ptserve_message_t;
+
+typedef void (ptserve_response_cb_t)(ptserve_message_t *request);
+
+typedef struct ptserve_t {
+ ptserve_response_cb_t *response_cb;
+ uint16_t port;
+ char *url;
+ void *data;
+ int rootfd;
+ int sd_server;
+ pid_t _pid;
+ pthread_t _tid;
+} ptserve_t;
+
+/*****************************************************************************
+ * utilities
+ ****************************************************************************/
+
+static int _vasprintf(char **strp, const char *fmt, va_list args) {
+ va_list arg_cp;
+ size_t len;
+ va_copy(arg_cp, args);
+ len = vsnprintf(NULL, 0, fmt, arg_cp);
+ va_end(arg_cp);
+ if((*strp = malloc(len + 2)) != NULL) { return vsprintf(*strp, fmt, args); }
+ else { return -1; }
+}
+
+static int _asprintf(char **strp, const char *fmt, ...) {
+ va_list args;
+ int ret;
+ va_start(args, fmt);
+ ret = _vasprintf(strp, fmt, args);
+ va_end(args);
+ return ret;
+}
+
+static ssize_t _send(int socket, const void *buf, size_t len) {
+ return send(socket, buf, len, MSG_NOSIGNAL);
+}
+
+static ssize_t _sendf(int socket, const char *fmt, ...) {
+ ssize_t ret;
+ char *buf = NULL;
+ int blen = 0;
+ va_list args;
+ va_start(args, fmt);
+ blen = _vasprintf(&buf, fmt, args);
+ va_end(args);
+ ret = _send(socket, buf, blen);
+ free(buf);
+ return ret;
+}
+
+static ssize_t _dgetdelim(int fd, char *buf, ssize_t bufsiz, char *delim) {
+ char *d = delim, *b = buf;
+ while(1) {
+ ssize_t ret = read(fd, b, 1);
+ if(ret == 0) { *b = '\0'; return b - buf; }
+ if(ret == -1) { return -1; }
+ if(*d && *b == *d) {
+ if(*(++d) == '\0') {
+ b -= strlen(delim) - 1;
+ *b = '\0';
+ return b - buf;
+ }
+ } else {
+ d = delim;
+ }
+ if(++b - buf >= bufsiz - 1) { return -1; }
+ }
+}
+
+/*****************************************************************************
+ * http message
+ ****************************************************************************/
+
+#define PTSERVE_HDR_MAX 1024
+ptserve_message_t *ptserve_message_new(ptserve_t *server, int socket_fd) {
+ ptserve_message_t *msg = calloc(sizeof(ptserve_message_t), 1);
+ char line[PTSERVE_HDR_MAX];
+
+ _dgetdelim(socket_fd, line, PTSERVE_HDR_MAX, " ");
+ msg->method = strdup(line);
+ _dgetdelim(socket_fd, line, PTSERVE_HDR_MAX, " ");
+ msg->path = strdup(line);
+ _dgetdelim(socket_fd, line, PTSERVE_HDR_MAX, "\r\n");
+ msg->protocol = strdup(line);
+
+ while(_dgetdelim(socket_fd, line, PTSERVE_HDR_MAX, "\r\n") > 0) {
+ msg->headers = alpm_list_add(msg->headers, strdup(line));
+ }
+
+ msg->ptserve = server;
+ msg->socket_fd = socket_fd;
+
+ return msg;
+}
+
+void ptserve_message_free(ptserve_message_t *msg) {
+ if(msg == NULL) { return; }
+ free(msg->method);
+ free(msg->path);
+ free(msg->protocol);
+ FREELIST(msg->headers);
+ if(msg->socket_fd >= 0) { close(msg->socket_fd); }
+ free(msg);
+}
+
+const char *ptserve_message_get_header(ptserve_message_t *msg, const char *hdr) {
+ alpm_list_t *i;
+ size_t hlen = strlen(hdr);
+ for(i = msg->headers; i; i = alpm_list_next(i)) {
+ const char *mhdr = i->data;
+ if(strncasecmp(mhdr, hdr, hlen) == 0 && strncmp(mhdr + hlen, ": ", 2) == 0) {
+ return mhdr + hlen + 2;
+ }
+ }
+ return NULL;
+}
+
+void ptserve_message_rm_header(ptserve_message_t *msg, const char *hdr) {
+ alpm_list_t *i;
+ size_t hlen = strlen(hdr);
+ for(i = msg->headers; i; i = i->next) {
+ char *oldheader = i->data;
+ if(strncasecmp(i->data, hdr, hlen) == 0 && oldheader[hlen] == ':') {
+ msg->headers = alpm_list_remove_item(msg->headers, i);
+ free(i->data);
+ free(i);
+ return;
+ }
+ }
+}
+
+int ptserve_message_set_header(ptserve_message_t *message,
+ const char *header, const char *value) {
+ alpm_list_t *i;
+ char *newheader;
+ size_t hlen = strlen(header);
+
+ if(_asprintf(&newheader, "%s: %s", header, value) == -1) { return 0; }
+
+ /* look for an existing header */
+ for(i = message->headers; i; i = i->next) {
+ char *oldheader = i->data;
+ if(strncasecmp(i->data, header, hlen) == 0 && oldheader[hlen] == ':') {
+ free(i->data);
+ i->data = newheader;
+ return 1;
+ }
+ }
+
+ message->headers = alpm_list_add(message->headers, newheader);
+ return 1;
+}
+
+/*****************************************************************************
+ * ptserve
+ ****************************************************************************/
+
+ptserve_t *ptserve_new() {
+ ptserve_t *ptserve = calloc(sizeof(ptserve_t), 1);
+ if(ptserve == NULL) { return NULL; }
+ ptserve->rootfd = AT_FDCWD;
+ ptserve->sd_server = -1;
+ ptserve->_tid = -1;
+ return ptserve;
+}
+
+void ptserve_free(ptserve_t *ptserve) {
+ if(ptserve == NULL) { return; }
+ if(ptserve->_pid > 0) {
+ kill(ptserve->_pid, SIGTERM);
+ waitpid(ptserve->_pid, NULL, 0);
+ } else if(ptserve->_tid != -1) {
+ pthread_cancel(ptserve->_tid);
+ /* pthread_kill(ptserve->_tid, SIGINT); */
+ /* pthread_join(ptserve->_tid, NULL); */
+ }
+ free(ptserve->url);
+ free(ptserve);
+}
+
+void ptserve_listen(ptserve_t *ptserve) {
+ struct sockaddr_in sin;
+ socklen_t addrlen = sizeof(sin);
+
+ if(ptserve->sd_server >= 0) { return; } /* already listening */
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ sin.sin_port = htons(0);
+
+ ptserve->sd_server = socket(PF_INET, SOCK_STREAM, 0);
+ bind(ptserve->sd_server, (struct sockaddr*) &sin, sizeof(sin));
+ getsockname(ptserve->sd_server, (struct sockaddr*) &sin, &addrlen);
+
+ listen(ptserve->sd_server, SOMAXCONN);
+
+ ptserve->port = ntohs(sin.sin_port);
+ _asprintf(&(ptserve->url), "http://127.0.0.1:%d", ptserve->port);
+}
+
+int ptserve_accept(ptserve_t *ptserve) {
+ return accept(ptserve->sd_server, 0, 0);
+}
+
+void *ptserve_serve(ptserve_t *ptserve) {
+ int session_fd;
+ ptserve_listen(ptserve);
+ while((session_fd = ptserve_accept(ptserve)) >= 0) {
+ ptserve_message_t *msg = ptserve_message_new(ptserve, session_fd);
+ ptserve->response_cb(msg);
+ ptserve_message_free(msg);
+ }
+ return NULL;
+}
+
+/*****************************************************************************
+ * ptserve helpers
+ ****************************************************************************/
+
+void ptserve_send_file(int socket, int rootfd, const char *path) {
+ struct stat sbuf;
+ ssize_t nread;
+ char buf[128];
+ int fd = openat(rootfd, path, O_RDONLY);
+ fstat(fd, &sbuf);
+ _sendf(socket, "HTTP/1.1 200 OK\r\n");
+ _sendf(socket, "Content-Length: %zd\r\n", sbuf.st_size);
+ _sendf(socket, "\r\n");
+ while((nread = read(fd, buf, 128)) > 0 && _send(socket, buf, nread));
+ close(fd);
+}
+
+void ptserve_send_range(int socket, int rootfd, const char *path, off_t start, off_t len) {
+ struct stat sbuf;
+ ssize_t nread;
+ char buf[128];
+ int fd = openat(rootfd, path, O_RDONLY);
+ lseek(fd, start, SEEK_SET);
+ fstat(fd, &sbuf);
+ if(len > sbuf.st_size - start) { len = sbuf.st_size - start; }
+ _sendf(socket, "HTTP/1.1 200 OK\r\n");
+ _sendf(socket, "Content-Length: %zd\r\n", len);
+ _sendf(socket, "Content-Range: bytes %zd-%zd/%zd\r\n",
+ start, start + len, sbuf.st_size);
+ _sendf(socket, "\r\n");
+ while((nread = read(fd, buf, 128)) > 0 && _send(socket, buf, nread));
+ close(fd);
+}
+
+void ptserve_send_str(int socket, const char *body) {
+ size_t blen = strlen(body);
+ _sendf(socket, "HTTP/1.1 200 OK\r\n");
+ _sendf(socket, "Content-Length: %zd\r\n", blen);
+ _sendf(socket, "\r\n");
+ _send(socket, body, blen);
+}
+
+void ptserve_cb_dir(ptserve_message_t *request) {
+ char *c, *path = request->path;
+ const char *range_hdr;
+ /* strip protocol and location if present */
+ if((c = strstr(path, "://")) != NULL) {
+ path = c + 3;
+ if((c = strchr(path, '/')) != NULL) {
+ path = c + 1;
+ } else {
+ path = "/";
+ }
+ }
+ /* strip leading '/' */
+ if(path[0] == '/') { path++; }
+ if(range_hdr = ptserve_message_get_header(request, "Range")) {
+ off_t start = 0, len = 0;
+ sscanf(range_hdr, "Range: bytes=%li-%li", &start, &len);
+ ptserve_send_range(request->socket_fd, request->ptserve->rootfd, path, start, len);
+ } else {
+ ptserve_send_file(request->socket_fd, request->ptserve->rootfd, path);
+ }
+}
+
+ptserve_t *ptserve_serve_cbat(int fd, ptserve_response_cb_t *cb, void *data) {
+ ptserve_t *ptserve = ptserve_new();
+ if(ptserve == NULL) {
+ free(ptserve);
+ return NULL;
+ }
+ ptserve->rootfd = fd;
+ ptserve->response_cb = cb;
+ ptserve->data = data;
+ ptserve_serve(ptserve);
+ return ptserve;
+}
+
+ptserve_t *ptserve_serve_cb(ptserve_response_cb_t *cb, void *data) {
+ return ptserve_serve_cbat(AT_FDCWD, cb, data);
+}
+
+ptserve_t *ptserve_serve_dirat(int fd, const char *path) {
+ ptserve_t *ptserve = ptserve_new();
+ int rootfd = openat(fd, path, O_RDONLY | O_DIRECTORY);
+ if(ptserve == NULL || (ptserve->rootfd = rootfd) < 0) {
+ free(ptserve);
+ return NULL;
+ }
+ ptserve->response_cb = ptserve_cb_dir;
+ ptserve_listen(ptserve);
+ /* pthread_create(&ptserve->_tid, NULL, (void* (*)(void*)) ptserve_serve, ptserve); */
+ /* pthread_detach(ptserve->_tid); */
+ ptserve->_pid = fork();
+ if(ptserve->_pid == 0) {
+ ptserve_serve(ptserve);
+ }
+ return ptserve;
+}
+
+ptserve_t *ptserve_serve_dir(const char *path) {
+ return ptserve_serve_dirat(AT_FDCWD, path);
+}
+
+/*****************************************************************************
+ * tests
+ ****************************************************************************/
+
+void ptserve_set_proxy(ptserve_t *ptserve) {
+ setenv("http_proxy", ptserve->url, 1);
+}
+#if 0
+int main(int argc, char *argv[]) {
+ ptserve_t *ptserve = ptserve_serve_cbat(AT_FDCWD, ptserve_cb_dir, NULL);
+ ptserve_listen(ptserve);
+ printf("listening on port %d\n", ptserve->port);
+ ptserve_serve(ptserve);
+ return 0;
+}
+
+int main_nocb(int argc, char *argv[]) {
+ int fd;
+ ptserve_t *ptserve = ptserve_new();
+ ptserve_listen(ptserve);
+ printf("listening on port %d\n", ptserve->port);
+ while((fd = ptserve_accept(ptserve)) >= 0) {
+ ptserve_message_t *msg = ptserve_message_new(ptserve, fd);
+ ptserve_cb_dir(msg);
+ ptserve_message_free(msg);
+ }
+ ptserve_free(ptserve);
+}
+#endif
+
+#endif /* PTSERVE_C */
+
+/* vim: set ts=2 sw=2 noet: */
diff --git a/test/alpm/tap.c b/test/alpm/tap.c
new file mode 100644
index 00000000..dcff2add
--- /dev/null
+++ b/test/alpm/tap.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2014-2015 Andrew Gregory <andrew.gregory.8(a)gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Project URL: http://github.com/andrewgregory/tap.c
+ */
+
+#ifndef TAP_C
+#define TAP_C
+
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int _tap_tests_planned = 0;
+static int _tap_tests_run = 0;
+static int _tap_tests_failed = 0;
+static const char *_tap_todo = NULL;
+
+#define _tap_output stdout
+#define _tap_failure_output stderr
+#define _tap_todo_output stdout
+
+#ifndef TAP_EXIT_SUCCESS
+#define TAP_EXIT_SUCCESS EXIT_SUCCESS
+#endif
+
+#ifndef TAP_EXIT_FAILURE
+#define TAP_EXIT_FAILURE EXIT_FAILURE
+#endif
+
+#ifndef TAP_EXIT_ASSERT
+#define TAP_EXIT_ASSERT TAP_EXIT_FAILURE
+#endif
+
+void tap_plan(int test_count);
+void tap_skip_all(const char *reason, ...)
+ __attribute__ ((format (printf, 1, 2)));
+void tap_done_testing(void);
+int tap_finish(void);
+void tap_todo(const char *reason);
+void tap_skip(int count, const char *reason, ...)
+ __attribute__ ((format (printf, 2, 3)));
+void tap_bail(const char *reason, ...)
+ __attribute__ ((format (printf, 1, 2)));
+void tap_diag(const char *message, ...)
+ __attribute__ ((format (printf, 1, 2)));
+void tap_note(const char *message, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+int tap_get_testcount_planned(void);
+int tap_get_testcount_run(void);
+int tap_get_testcount_failed(void);
+const char *tap_get_todo(void);
+
+#define tap_assert(x) \
+ if(!(x)) { tap_bail("ASSERT FAILED: '%s'", #x); exit(TAP_EXIT_ASSERT); }
+
+#define tap_ok(...) _tap_ok(__FILE__, __LINE__, __VA_ARGS__)
+#define tap_vok(success, args) _tap_vok(__FILE__, __LINE__, success, args)
+#define tap_is_float(...) _tap_is_float(__FILE__, __LINE__, __VA_ARGS__)
+#define tap_is_int(...) _tap_is_int(__FILE__, __LINE__, __VA_ARGS__)
+#define tap_is_str(...) _tap_is_str(__FILE__, __LINE__, __VA_ARGS__)
+
+int _tap_ok(const char *file, int line, int success, const char *name, ...)
+ __attribute__ ((format (printf, 4, 5)));
+int _tap_vok(const char *file, int line,
+ int success, const char *name, va_list args)
+ __attribute__ ((format (printf, 4, 0)));
+int _tap_is_float(const char *file, int line,
+ double got, double expected, double delta, const char *name, ...)
+ __attribute__ ((format (printf, 6, 7)));
+int _tap_is_int(const char *file, int line,
+ intmax_t got, intmax_t expected, const char *name, ...)
+ __attribute__ ((format (printf, 5, 6)));
+int _tap_is_str(const char *file, int line,
+ const char *got, const char *expected, const char *name, ...)
+ __attribute__ ((format (printf, 5, 6)));
+
+#define TAP_VPRINT_MSG(stream, msg) if(msg) { \
+ va_list args; \
+ va_start(args, msg); \
+ fputc(' ', stream); \
+ vfprintf(stream, msg, args); \
+ va_end(args); \
+ }
+
+
+void tap_plan(int test_count)
+{
+ _tap_tests_planned = test_count;
+ fprintf(_tap_output, "1..%d\n", test_count);
+ fflush(_tap_output);
+}
+
+void tap_skip_all(const char *reason, ...)
+{
+ FILE *stream = _tap_output;
+ fputs("1..0 # SKIP", _tap_output);
+ TAP_VPRINT_MSG(stream, reason);
+ fputc('\n', _tap_output);
+ fflush(_tap_output);
+}
+
+void tap_done_testing(void)
+{
+ tap_plan(_tap_tests_run);
+}
+
+int tap_finish(void)
+{
+ if(_tap_tests_run != _tap_tests_planned) {
+ tap_diag("Looks like you planned %d tests but ran %d.",
+ _tap_tests_planned, _tap_tests_run);
+ }
+ return _tap_tests_run == _tap_tests_planned
+ && _tap_tests_failed == 0 ? TAP_EXIT_SUCCESS : TAP_EXIT_FAILURE;
+}
+
+int tap_get_testcount_planned(void)
+{
+ return _tap_tests_planned;
+}
+
+int tap_get_testcount_run(void)
+{
+ return _tap_tests_run;
+}
+
+int tap_get_testcount_failed(void)
+{
+ return _tap_tests_failed;
+}
+
+const char *tap_get_todo(void)
+{
+ return _tap_todo;
+}
+
+void tap_todo(const char *reason)
+{
+ _tap_todo = reason;
+}
+
+void tap_skip(int count, const char *reason, ...)
+{
+ FILE *stream = _tap_output;
+ while(count--) {
+ fprintf(_tap_output, "ok %d # SKIP", ++_tap_tests_run);
+ TAP_VPRINT_MSG(stream, reason);
+ fputc('\n', _tap_output);
+ }
+ fflush(_tap_output);
+}
+
+void tap_bail(const char *reason, ...)
+{
+ FILE *stream = _tap_output;
+ fputs("Bail out!", _tap_output);
+ TAP_VPRINT_MSG(stream, reason);
+ fputc('\n', _tap_output);
+ fflush(_tap_output);
+}
+
+void tap_diag(const char *message, ...)
+{
+ FILE *stream = _tap_todo ? _tap_todo_output : _tap_failure_output;
+
+ fputs("#", stream);
+ TAP_VPRINT_MSG(stream, message);
+ fputc('\n', stream);
+ fflush(stream);
+
+}
+
+void tap_note(const char *message, ...)
+{
+ FILE *stream = _tap_output;
+ fputs("#", _tap_output);
+ TAP_VPRINT_MSG(stream, message);
+ fputc('\n', _tap_output);
+ fflush(_tap_output);
+}
+
+int _tap_vok(const char *file, int line,
+ int success, const char *name, va_list args)
+{
+ const char *result;
+ if(success) {
+ result = "ok";
+ if(_tap_todo) ++_tap_tests_failed;
+ } else {
+ result = "not ok";
+ if(!_tap_todo) ++_tap_tests_failed;
+ }
+
+ fprintf(_tap_output, "%s %d", result, ++_tap_tests_run);
+
+ if(name) {
+ fputs(" - ", _tap_output);
+ vfprintf(_tap_output, name, args);
+ }
+
+ if(_tap_todo) {
+ fputs(" # TODO", _tap_output);
+ if(*_tap_todo) {
+ fputc(' ', _tap_output);
+ fputs(_tap_todo, _tap_output);
+ }
+ }
+
+ fputc('\n', _tap_output);
+ fflush(_tap_output);
+
+ if(!success && file) {
+ /* TODO add test name if available */
+ tap_diag(" Failed%s test at %s line %d.",
+ _tap_todo ? " (TODO)" : "", file, line);
+ }
+
+ return success;
+}
+
+#define TAP_OK(success, name) do { \
+ va_list args; \
+ va_start(args, name); \
+ _tap_vok(file, line, success, name, args); \
+ va_end(args); \
+ } while(0)
+
+int _tap_ok(const char *file, int line,
+ int success, const char *name, ...)
+{
+ TAP_OK(success, name);
+ return success;
+}
+
+int _tap_is_float(const char *file, int line,
+ double got, double expected, double delta, const char *name, ...)
+{
+ double diff = (expected > got ? expected - got : got - expected);
+ int match = diff < delta;
+ TAP_OK(match, name);
+ if(!match) {
+ tap_diag(" got: '%f'", got);
+ tap_diag(" expected: '%f'", expected);
+ tap_diag(" delta: '%f'", diff);
+ tap_diag(" allowed: '%f'", delta);
+ }
+ return match;
+}
+
+int _tap_is_int(const char *file, int line,
+ intmax_t got, intmax_t expected, const char *name, ...)
+{
+ int match = got == expected;
+ TAP_OK(match, name);
+ if(!match) {
+ tap_diag(" got: '%" PRIdMAX "'", got);
+ tap_diag(" expected: '%" PRIdMAX "'", expected);
+ }
+ return match;
+}
+
+int _tap_is_str(const char *file, int line,
+ const char *got, const char *expected, const char *name, ...)
+{
+ int match;
+ if(got && expected) {
+ match = (strcmp(got, expected) == 0);
+ } else {
+ match = (got == expected);
+ }
+ TAP_OK(match, name);
+ if(!match) {
+ tap_diag(" got: '%s'", got);
+ tap_diag(" expected: '%s'", expected);
+ }
+ return match;
+}
+
+#undef TAP_OK
+#undef TAP_VPRINT_MSG
+
+#endif /* TAP_C */
diff --git a/test/alpm/tests/.gitignore b/test/alpm/tests/.gitignore
new file mode 100644
index 00000000..d06c5240
--- /dev/null
+++ b/test/alpm/tests/.gitignore
@@ -0,0 +1,3 @@
+.deps/
+.libs/
+*.t
diff --git a/test/alpm/tests/Makefile.am b/test/alpm/tests/Makefile.am
new file mode 100644
index 00000000..a3724e3f
--- /dev/null
+++ b/test/alpm/tests/Makefile.am
@@ -0,0 +1,21 @@
+check_PROGRAMS = \
+ add_remove.t \
+ cached_part_file.t \
+ part_file_in_secondary_cache.t
+
+noinst_PROGRAMS = $(check_PROGRAMS)
+
+EXTRA_DIST = $(check_PROGRAMS)
+
+AM_CPPFLAGS = \
+ -imacros $(top_builddir)/config.h \
+ -I$(top_srcdir)/lib/libalpm \
+ -DLOCALEDIR=\"@localedir@\"
+
+AM_CFLAGS = -g -D_GNU_SOURCE -pthread
+
+LDADD = $(LTLIBINTL) $(top_builddir)/lib/libalpm/.libs/libalpm.la
+
+%.t: %.c
+
+# vim:set noet:
diff --git a/test/alpm/tests/TESTS b/test/alpm/tests/TESTS
new file mode 100644
index 00000000..26b0fa51
--- /dev/null
+++ b/test/alpm/tests/TESTS
@@ -0,0 +1,3 @@
+TESTS += test/alpm/tests/add_remove.t
+TESTS += test/alpm/tests/cached_part_file.t
+TESTS += test/alpm/tests/part_file_in_secondary_cache.t
diff --git a/test/alpm/tests/add_remove.c b/test/alpm/tests/add_remove.c
new file mode 100644
index 00000000..13899570
--- /dev/null
+++ b/test/alpm/tests/add_remove.c
@@ -0,0 +1,56 @@
+#include "../alpmtest.h"
+
+/* install and them remove a package with a single handle */
+/* http://lists.archlinux.org/pipermail/pacman-dev/2015-February/019906.html */
+
+pt_env_t *pt = NULL;
+alpm_handle_t *handle = NULL;
+
+void cleanup(void)
+{
+ alpm_release(handle);
+ pt_cleanup(pt);
+}
+
+int main(void)
+{
+ pt_pkg_t *pkg;
+ alpm_pkg_t *lpkg;
+ alpm_handle_t *handle;
+ alpm_list_t *data = NULL;
+ const char *pkg_db_path = "var/lib/pacman/local/foo-1-1";
+
+ ASSERT(atexit(cleanup) == 0);
+
+ ASSERT(pt = pt_init(NULL));
+ ASSERT(pkg = pt_pkg_new(pt, "foo", "1-1"));
+ ASSERT(pt_pkg_writeat(pt->rootfd, "foo.pkg.tar", pkg) == 0);
+
+ ASSERT(handle = alpm_initialize(pt->root, pt->dbpath, NULL));
+ ASSERT(alpm_pkg_load(handle, pt_path(pt, "foo.pkg.tar"), 1, 0, &lpkg) == 0);
+
+ /* install the package */
+ ASSERT(alpm_trans_init(handle, 0) == 0);
+ ASSERT(alpm_add_pkg(handle, lpkg) == 0);
+ ASSERT(alpm_trans_prepare(handle, &data) == 0);
+ ASSERT(alpm_trans_commit(handle, &data) == 0);
+ ASSERT(alpm_trans_release(handle) == 0);
+ ASSERT(lpkg = alpm_db_get_pkg(alpm_get_localdb(handle), "foo"));
+ ASSERT(faccessat(pt->rootfd, pkg_db_path, F_OK, 0) == 0);
+
+ /* remove the package */
+ tap_plan(7);
+ tap_is_int(alpm_trans_init(handle, 0), 0, "alpm_trans_init");
+ tap_is_int(alpm_remove_pkg(handle, lpkg), 0, "alpm_remove_pkg");
+ tap_is_int(alpm_trans_prepare(handle, &data), 0, "alpm_trans_prepare");
+ tap_is_int(alpm_trans_commit(handle, &data), 0, "alpm_trans_commit");
+ tap_is_int(alpm_trans_release(handle), 0, "alpm_trans_release");
+
+ /* make sure the removal was actually performed */
+ tap_ok(alpm_db_get_pkg(alpm_get_localdb(handle), "foo") == NULL,
+ "foo removed from local cache");
+ tap_ok(faccessat(pt->rootfd, pkg_db_path, F_OK, 0) == -1
+ && errno == ENOENT, "foo entry removed from db");
+
+ return tap_finish();
+}
diff --git a/test/alpm/tests/cached_part_file.c b/test/alpm/tests/cached_part_file.c
new file mode 100644
index 00000000..5811ebad
--- /dev/null
+++ b/test/alpm/tests/cached_part_file.c
@@ -0,0 +1,65 @@
+#include "../alpmtest.h"
+
+/* install a package with a completed .part file in the cache (FS#35789) */
+
+pt_env_t *pt = NULL;
+alpm_handle_t *handle = NULL;
+int file_downloaded = 0;
+
+void cleanup(void)
+{
+ alpm_release(handle);
+ pt_cleanup(pt);
+}
+
+void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total)
+{
+ file_downloaded = 1;
+}
+
+int main(void)
+{
+ pt_pkg_t *pkg;
+ pt_db_t *db;
+ alpm_pkg_t *lpkg;
+ alpm_db_t *adb;
+ alpm_list_t *data = NULL;
+
+ ASSERT(atexit(cleanup) == 0);
+
+ ASSERT(pt = pt_init(NULL));
+
+ ASSERT(pkg = pt_pkg_new(pt, "foo", "1-1"));
+ ASSERT(pkg->filename = strdup("foo.pkg.tar"));
+ ASSERT(pt_pkg_writeat(pt->rootfd, "tmp/foo.pkg.tar.part", pkg) == 0);
+
+ ASSERT(db = pt_db_new(pt, "sync"));
+ ASSERT(pt_db_add_pkg(db, pkg));
+ ASSERT(pt_install_db(pt, db) == 0);
+
+ ASSERT(handle = alpm_initialize(pt->root, pt->dbpath, NULL));
+ ASSERT(alpm_option_add_cachedir(handle, pt_path(pt, "tmp")) == 0);
+ ASSERT(adb = alpm_register_syncdb(handle, "sync", 0));
+ ASSERT(alpm_db_add_server(adb, "http://foo") == 0);
+ ASSERT(lpkg = alpm_db_get_pkg(adb, "foo"));
+
+ tap_plan(8);
+ tap_is_int(alpm_trans_init(handle, 0), 0, "alpm_trans_init");
+ tap_is_int(alpm_add_pkg(handle, lpkg), 0, "alpm_add_pkg");
+ tap_is_int(alpm_trans_prepare(handle, &data), 0, "alpm_trans_prepare");
+
+ tap_todo("don't fail on .part files");
+ tap_is_int(alpm_trans_commit(handle, &data), 0, "alpm_trans_commit");
+ tap_todo(NULL);
+
+ tap_is_int(alpm_trans_release(handle), 0, "alpm_trans_release");
+
+ tap_todo("don't fail on .part files");
+ tap_ok(alpm_db_get_pkg(alpm_get_localdb(handle), "foo") != NULL, "foo in local cache");
+ tap_ok(faccessat(pt->dbpathfd, "local/foo-1-1", F_OK, 0) == 0, "foo entry in local db");
+ tap_todo(NULL);
+
+ tap_ok(file_downloaded == 0, ".part file used");
+
+ return tap_finish();
+}
diff --git a/test/alpm/tests/part_file_in_secondary_cache.c b/test/alpm/tests/part_file_in_secondary_cache.c
new file mode 100644
index 00000000..cbf519a6
--- /dev/null
+++ b/test/alpm/tests/part_file_in_secondary_cache.c
@@ -0,0 +1,102 @@
+#include "../alpmtest.h"
+
+/* install a package with a partial .part file in a secondary cache */
+
+pt_env_t *pt = NULL;
+ptserve_t *ptserve = NULL;
+alpm_handle_t *handle = NULL;
+off_t total_download = 0;
+off_t actual_download = 0;
+
+void cleanup(void)
+{
+ alpm_release(handle);
+ pt_cleanup(pt);
+ ptserve_free(ptserve);
+}
+
+off_t getsize(int dirfd, const char *path)
+{
+ struct stat s;
+ return fstatat(dirfd, path, &s, AT_SYMLINK_NOFOLLOW) == 0 ? s.st_size : -1;
+}
+
+void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total)
+{
+ if(file_xfered == file_total) {
+ actual_download += file_xfered;
+ }
+}
+
+void cb_dl_total(off_t total)
+{
+ total_download += total;
+}
+
+int main(void)
+{
+ int fd;
+ const char *cpath = "secondary/foo.pkg.tar.part";
+ off_t csize;
+ pt_pkg_t *pkg;
+ pt_db_t *db;
+ alpm_pkg_t *lpkg;
+ alpm_db_t *adb;
+ alpm_list_t *data = NULL;
+
+ ASSERT(atexit(cleanup) == 0);
+
+ ASSERT(pt = pt_init(NULL));
+
+ ASSERT(pkg = pt_pkg_new(pt, "foo", "1-1"));
+ ASSERT(pkg->filename = strdup("foo.pkg.tar"));
+
+ /* write partial copy to our cache */
+ ASSERT(pt_pkg_writeat(pt->rootfd, cpath, pkg) == 0);
+ ASSERT((csize = getsize(pt->rootfd, cpath)) > 2);
+ ASSERT(pkg->csize = pt_asprintf("%lu", csize));
+ ASSERT((fd = openat(pt->rootfd, cpath, O_WRONLY)) >= 0);
+ ASSERT(ftruncate(fd, csize / 2) == 0);
+ ASSERT(close(fd) == 0);
+
+ /* write full copy to server */
+ ASSERT(pt_pkg_writeat(pt->rootfd, "srv/foo.pkg.tar", pkg) == 0);
+ ASSERT(ptserve = ptserve_serve_dirat(pt->rootfd, "srv/"));
+
+ ASSERT(db = pt_db_new(pt, "sync"));
+ ASSERT(pt_db_add_pkg(db, pkg));
+ ASSERT(pt_install_db(pt, db) == 0);
+
+ ASSERT(handle = alpm_initialize(pt->root, pt->dbpath, NULL));
+ ASSERT(alpm_option_add_cachedir(handle, pt_path(pt, "primary")) == 0);
+ ASSERT(alpm_option_add_cachedir(handle, pt_path(pt, "secondary")) == 0);
+ ASSERT(alpm_option_set_totaldlcb(handle, cb_dl_total) == 0);
+ ASSERT(alpm_option_set_dlcb(handle, cb_dl_progress) == 0);
+
+ ASSERT(adb = alpm_register_syncdb(handle, "sync", 0));
+ ASSERT(alpm_db_add_server(adb, ptserve->url) == 0);
+ ASSERT(lpkg = alpm_db_get_pkg(adb, "foo"));
+
+ tap_plan(10);
+ tap_is_int(alpm_trans_init(handle, 0), 0, "alpm_trans_init");
+ tap_is_int(alpm_add_pkg(handle, lpkg), 0, "alpm_add_pkg");
+ tap_is_int(alpm_trans_prepare(handle, &data), 0, "alpm_trans_prepare");
+ tap_is_int(alpm_trans_commit(handle, &data), 0, "alpm_trans_commit");
+ tap_is_int(alpm_trans_release(handle), 0, "alpm_trans_release");
+
+ tap_is_int(total_download, csize - csize / 2, "predicted download size");
+
+ tap_todo("use .part files in secondary caches");
+
+ tap_is_int(actual_download, csize - csize / 2, "actual download size");
+ tap_ok(faccessat(pt->rootfd, "secondary/foo.pkg.tar", F_OK, 0) == 0,
+ "downloaded to secondary");
+ tap_ok(faccessat(pt->rootfd, "secondary/foo.pkg.tar.part", F_OK, 0) == -1
+ && errno == ENOENT, ".part file removed");
+ tap_ok(faccessat(pt->rootfd, "primary/foo.pkg.tar", F_OK, 0) == -1
+ && errno == ENOENT, "package not downloaded to primary");
+
+ tap_todo(NULL);
+
+ return tap_finish();
+}
--
2.12.2
1
0
It would be great if there was a way to customize the list of PKGBUILD attributes supported by makepkg without having to edit the installed copy of makepkg. My use-case is mainly for use with the --printsrcinfo option but I'm sure it would be useful in other areas as well. I'd like to submit a patch for it but I thought it best to see what everyone thought about the feature before spending time on it. My initial thinking is that that simple text files with one attribute per line could be placed in /etc/makepkg.d. Perhaps something along these lines:
/etc/makepkg.d/attributes.single
/etc/makepkg.d/attributes.multi
/etc/makepkg.d/attributes-march.single
/etc/makepkg.d/attributes-march.multi
Looking forward to your comments and also any guidance on preferred implementation details.
--
Dustin Falgout
Email: dustin(a)falgout.us
Github: lots0logs
2
5
Signed-off-by: Andrew Gregory <andrew.gregory.8(a)gmail.com>
---
lib/libalpm/handle.c | 1 +
src/pacman/conf.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index b6b27881..502a5d9e 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -92,6 +92,7 @@ void _alpm_handle_free(alpm_handle_t *handle)
FREELIST(handle->noextract);
FREELIST(handle->ignorepkg);
FREELIST(handle->ignoregroup);
+ FREELIST(handle->overwrite_files);
alpm_list_free_inner(handle->assumeinstalled, (alpm_list_fn_free)alpm_dep_free);
alpm_list_free(handle->assumeinstalled);
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 261c8213..a283d7f4 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -143,6 +143,7 @@ int config_free(config_t *oldconfig)
FREELIST(oldconfig->assumeinstalled);
FREELIST(oldconfig->noupgrade);
FREELIST(oldconfig->noextract);
+ FREELIST(oldconfig->overwrite_files);
free(oldconfig->configfile);
free(oldconfig->rootdir);
free(oldconfig->dbpath);
--
2.12.2
1
0