#!/bin/sh ## Licensed under: ## MIT Public License ## http://www.opensource.org/licenses/MIT ## Copyright (c) 2015, Brian Bennett ## pkgsrc package module for cfengine # Set up mock environment if necessary if [ -n $CFENGINE_TEST_PKGSRC_MOCK ]; then alias pkgin='./mock_pkgin' alias pkg_info='./mock_pkg_info' fi # Add pkgsrc paths export PATH=@PREFIX@/bin:@PREFIX@/sbin:$PATH export MACHINE_ARCH=@MACHINE_ARCH@ export PKG_ROOT=@PREFIX@ export PKG_INSTALL_CONF=@PKG_SYSCONFBASE@/pkg_install.conf LEVEL=0 fatal () { echo "ErrorMessage=$@" exit 2 } warn () { [ $LEVEL -gt 0 ] && echo "[TRACE]: $*" >&2 } supports_api_version () { echo 1 } repo_install () { # If a version number is specified, insert a dash between the name and # version [ -n "$Version" ] && ver="-$Version" pkgin -y in "${Name}${ver}" > /dev/null if [ $? -gt 0 ]; then fatal "Error installing ${Name}${ver}" fi } file_install () { # The specified config file might, for example override signature reqs: # VERIFIED_INSTALLATION=never pkg_add -U -C "$PKG_INSTALL_CONF" "$File" > /dev/null if [ $? -gt 0 ]; then echo "Error installing ${File}" fi } remove () { # If a version number is specified, insert a dash between the name and # version [ -n "$Version" ] && ver="-$Version" pkgin -y rm "${Name}${ver}" > /dev/null } list_installed () { parse_pkg_data "$(pkgin -p list)" } list_updates () { # The difference between list-updates and list-updates-local, it seems # is that list-updates expects to refresh from the upstream repo. pkgin -f update >&2 list_updates_local } list_updates_local () { parse_pkg_data "$(pkgin -pl '<' ls)" } get_package_data () { if echo "$File" | grep '/' >/dev/null; then # If there's a / in $File then we'll expec this to be a 'file' install. # This is reliable because 1) pkgsrc packages don't have / in the name # and because cfengine can't install a PackageType=file from a relative # path. # # The package will be installed with pkg_add later, which also supports # arbitrary HTTP locations. echo "PackageType=file" # To appease cfengine, we'll take the basename of the package passed. echo "Name=$(echo "$File" | sed 's/.*\///g')" else # If $File does not contain /, it must be in an existing remote repo, # because cfengine can't install files from relative paths. echo "PackageType=repo" # Cfengine expects a *single* matching package. So sort and return the # most recent. If a version is specified it can partial match, in which # case we'll again take the latest. If there's no match on the name # or version, return nothing. # There's possibly a bug here because we're already emitting that the # PackageType is repo. parse_pkg_data "$(pkgin -pP avail | grep "^$File" | grep "$Version;" | sort -n | tail -1)" fi } parse_pkg_data () { # This is a bit tricky. # pkgin is called with parsable format and separates fields with ';'. # Packages are further sub-split between name and version with '-', but # package names may also contain '-'. To complicate matters, package # versions can have '-' as well. # Take the example package mozilla-rootcerts-1.0.20141117nb1 # $1 is the package-version compound. Discard the description in $2.. # Split $1 on 'separator' and store in array 'package'. Return length 'l' # 'version' is the last element of array 'package' # Now the tricky bit. We've split the package name, so now must reassemble # it with dashes in tact, without the version number. # For each element less 1 in 'package', if this is the first iteration # print the element. On subsequent passes print "-element" # Finally print the version and the machine architecture as well. echo "$*" | awk -F';' ' { separator="-" l=split($1,package,separator) version=package[l] printf("Name=") for (i=1ength;i1) { printf("-") } printf("%s",package[i]) } printf("\nVersion=%s\n",version) printf("Architecture=%s\n",ENVIRON["MACHINE_ARCH"]) }' } # Cfengine passes data on STDIN. Absorb that and convert to shell variables. while IFS= read -r -u 0 line; do eval "$line" # options can be passed multiple times so we need to avoid clobbering # previous instances. Plus, what we really want to eval is the value of # each option. if [ -n "$options" ]; then eval "$options" fi done case "$1" in supports-api-version) supports_api_version;; repo-install) repo_install;; file-install) file_install;; remove) remove;; list-installed) list_installed;; list-updates) list_updates;; list-updates-local) list_updates_local;; get-package-data) get_package_data;; *) fatal "Invalid operation";; esac