Skip to content

Instantly share code, notes, and snippets.

@Hayao0819
Last active May 27, 2021 14:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hayao0819/d0df4d19b155b28fdfb14bc38b4ed8cb to your computer and use it in GitHub Desktop.
Save Hayao0819/d0df4d19b155b28fdfb14bc38b4ed8cb to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
set -eu
script_path="$( cd -P "$( dirname "$(readlink -f "${0}")" )" && pwd )"
pacman_dbpath="$(pacman-conf "DBPath")"
debug=false
work_dir="/tmp/expac"
expac_version="0.1"
msg_error(){ echo "[expac] Error ${*}" 1>&2; }
msg_info (){ echo "[expac] Info ${*}" 1>&2; }
msg_warn (){ echo "[expac] Warn ${*}" 1>&2; }
msg_debug(){ [[ "${debug}" = true ]] && echo "[expac] Debug ${*}" 1>&2; return 0;}
_help() {
echo "usage ${0} [options] [package]"
echo
echo " General options:"
echo " -h | --help This help message"
echo
echo " --debug Enable debug mode"
echo " --dbpath Set datebase dir"
}
# readdb <file> <section>
readdb(){
local _path="${1}" _section="${2}" _dblines _line _in_section=false
readarray -t _dblines < "${_path}"
for _line in "${_dblines[@]}"; do
case "${_line}" in
"%${_section}%")
_in_section=true
continue
;;
"%"*"%")
_in_section=false
continue
;;
esac
[[ "${_in_section}" = true ]] && [[ -n "${_line}" ]] && echo "${_line}"
done
}
# exportpkg <package>cat
exportpkg(){
local _version _package="${1}" _datebase _filelist=()
# Check package
if ! pacman -Qq "${_package}" 1> /dev/null 2>&1; then
msg_error "${_package} is not installed"
exit 1
fi
# Set package info
_package="$(pacman -Q "${_package}" 2> /dev/null | cut -d " " -f 1)"
_version="$(pacman -Q "${_package}" 2> /dev/null | cut -d " " -f 2)"
_datebase="${pacman_dbpath}/local/${_package}-${_version}"
msg_debug "Package datebase is ${_datebase}"
# Read datebase
msg_info "Loading package datebase ..."
readarray -t _db_filelist < <(readdb "${_datebase}/files" FILES | grep -v "/$")
readarray -t _db_depends < <(readdb "${_datebase}/desc" "DEPENDS")
for _data in "NAME" "VERSION" "BASE" "DESC" "URL" "ARCH" "BUILDDATE" "INSTALLDATE" "PACKAGER" "SIZE" "LICENSE" "VALIDATION"; do
#readarray -t "_db_${_data,,}" < <(readdb "${_datebase}/desc" "${_data}")
printf -v "_db_${_data,,}" "$(readdb "${_datebase}/desc" "${_data}")"
done
# Create BUILDINFO
msg_info "Creating .BUILDINFO ..."
mkdir -p "${work_dir}/${_package}"
local _buildinfo="${work_dir}/${_package}/.BUILDINFO" _write_buildinfo
function _write_buildinfo(){ echo "${1} = ${2}" >> "${_buildinfo}"; }
echo -n > "${_buildinfo}"
_write_buildinfo "format" "1"
_write_buildinfo "pkgname" "${_package}"
_write_buildinfo "pkgbase" "${_db_base}"
_write_buildinfo "pkgver" "${_db_version}"
_write_buildinfo "pkgarch" "${_db_arch}"
_write_buildinfo "packager" "${_db_packager}"
_write_buildinfo "builddate" "${_db_builddate}"
_write_buildinfo "builddir" "${work_dir}/${_package}"
while read -r _pkg; do
_write_buildinfo "installed" "${_pkg}-$(readdb "${pacman_dbpath}/local/${_pkg}/desc" "ARCH")"
done < <(pacman -Q --color never | tr " " "-")
# Create PKGINFO
msg_info "Creating .PKGINFO ..."
local _write_pkginfo _pkginfo="${work_dir}/${_package}/.PKGINFO"
function _write_pkginfo(){ echo "${1} = ${2}" >> "${_pkginfo}"; }
echo "# Generated by expac ${expac_version}" > "${_pkginfo}"
_write_pkginfo "pkgname" "${_package}"
_write_pkginfo "pkgbase" "${_db_base}"
_write_pkginfo "pkgver" "${_db_version}"
_write_pkginfo "pkgdesc" "${_db_desc}"
_write_pkginfo "url" "${_db_url}"
_write_pkginfo "builddate" "${_db_builddate}"
_write_pkginfo "packager" "${_db_packager}"
_write_pkginfo "size" "${_db_size}"
_write_pkginfo "arch" "${_db_arch}"
_write_pkginfo "license" "${_db_license}"
for _pkg in "${_db_depends[@]}"; do
_write_pkginfo "depend" "${_pkg}"
done
# Create MTREE
msg_info "Creating .MTRE ..."
cp -a "${_datebase}/mtree" "${work_dir}/${_package}/.MTREE"
# Copy files
for _file in "${_db_filelist[@]}"; do
if [[ -f "/${_file}" ]]; then
msg_info "Copying ${_file}"
mkdir -p "${work_dir}/${_package}/$(dirname "${_file}")"
cp -a "/${_file}" "${work_dir}/${_package}/$(dirname "${_file}")"
else
msg_warn "${_file} was not found"
fi
done
# Create archive
(
cd "${work_dir}/${_package}"
readarray -t _archive_list < <(find ./ -mindepth 1 -maxdepth 1 -printf "%P\n")
tar -v -c -I zstd -f "${script_path}/${_package}-${_db_version}-${_db_arch}.pkg.tar.zst" "${_archive_list[@]}"
)
}
# Parse options
OPTS=("h")
OPTL=("debug" "help" "dbpath:")
if ! OPT=$(getopt -o "$(printf "%s," "${OPTS[@]}")" -l "$(printf "%s," "${OPTL[@]}")" -- "${@}"); then
exit 1
fi
eval set -- "${OPT}"
msg_debug "Argument: ${OPT}"
unset OPT OPTS OPTL
while true; do
case "${1}" in
--debug)
debug=true
shift 1
;;
--dbpath)
pacman_dbpath="${2}"
shift 2
;;
-h | --help)
_help
exit 0
;;
--)
shift
break
;;
*)
msg_error "Invalid argument '${1}'"
_help
exit 1
;;
esac
done
for pkg in "${@}"; do
exportpkg "${pkg}"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment