secret
Last active

Just for archlinux and still needs heavy testing

  • Download Gist
changeling.sh
Shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
#!/bin/bash
# Repo desc: Changes pkgver and pkgrel of installed package
#
# Changeling: Changes package ($1) version directly in pacman's db to a version given in $2 or $target_pkgver
# Example uses:
# Just downgrade to 0-0 to force update (default):
# changeling firefox-nightly
# For specific version:
# changeling firefox-nightly 666-666
#
# Author: Swift Geek swiftgeek@gmɐil.com
 
#TODO: Provide help message for bad amount of args
#TODO: Detect syntax error and write some message to log
# We don't care about epoch till somebody wants it
 
info_log() {
echo "changeling: $1" # Check if not null ?
echo "changeling: $1" >> /var/log/pacman.log #Disable stderr?
return 0
}
fail_log() {
echo "changeling: $1"
echo "changeling: $1" >> /var/log/pacman.log
exit 1
}
fail_msg() {
echo "changeling: $1"
exit 1
}
 
# Check for root and if has tty - run sudo
if [ $UID != 0 ]; then
tty -s
if [ $? = 0 ]; then
/usr/bin/sudo -i $(realpath -s $0) $@ && exit 0
exit 1
else
fail_msg "This script needs to be executed as root!"
fi
fi
 
 
# Set variables
target_pkgver=0-0
 
if [ -L "$0" ]; then
# If started from symlink
shname=`basename $0`
if [[ "$shname" =~ ^[a-z0-9@_+.-]+-[a-z0-9@_.]+-[0-9]+$ ]]; then
pkgname="${shname%-[a-z0-9@_.]*-[0-9]*}" # fix this perhaps * instead of + ? nah we know it's right from upper regex
target_pkgver=${shname:${#pkgname}+1}
elif [[ "$shname" =~ ^[a-z0-9@_+.-]+$ ]]; then
pkgname="$shname"
else
fail_msg "Invalid symlink filename - not a package"
fi
else
# If started via script
[ -z "$*" ] && fail_msg "No args were passed!"
[ $# -gt 2 ] && fail_msg "Too many arguments passed!"
[[ "$1" =~ ^[a-z0-9@_+.-]+$ ]] || fail_msg "First arg is not a valid pkgname"
pkgname="$1"
if [ -n "$2" ] && [[ "$2" =~ ^[a-z0-9@_.]+-[0-9]+$ ]]; then
target_pkgver="$2"
elif [ -n "$2" ]; then
fail_msg "Wrong format of second argument!"
fi
fi
 
#Check && query pacman
pgrep -x pacman > /dev/null
[ "$?" = "0" ] && fail_msg "Pacman is up and running"
 
/usr/bin/pacman -Qsq "$pkgname" > /dev/null
[ "$?" != "0" ] && fail_msg "Package not found?"
 
orig_pkgver=$(/usr/bin/pacman -Qs "^$pkgname\$" | grep 'local/' | awk '{print $2}')
if [ -z "$orig_pkgver" ] || [ -z $target_pkgver ] ; then
fail_msg "Pacman query failed"
elif [ "$orig_pkgver" = "$target_pkgver" ]; then
echo 'Already downgraded!'
exit 0
fi
pkgdir="/var/lib/pacman/local/${pkgname}" # WARNING: doesn't contain version
 
# Lock DB
[ -e /var/lib/pacman/db.lck ] && fail_msg "Pacman DB already locked!"
#RW stage
echo "$$" > /var/lib/pacman/db.lck
[ "$?" != 0 ] && fail_msg "Failed to lock pacman db"
 
info_log "Downgrading $pkgname $orig_pkgver to $target_pkgver"
 
# Actual changing
if [ -d "${pkgdir}-${orig_pkgver}" ]; then
sed -i '/\%VERSION\%/{n; s/.*/'"$target_pkgver"'/}' "${pkgdir}-${orig_pkgver}/desc"
[ "$?" != 0 ] && fail_log "Failed at sedding desc file. No harm was done"
mv "${pkgdir}-${orig_pkgver}" "${pkgdir}-${target_pkgver}"
[ "$?" != 0 ] && fail_log "Failed at renaming pkgdir. Pacman DB is slightly broken at this point"
else
fail_log "Pacman DB might be broken"
fi
 
rm /var/lib/pacman/db.lck
# RW stage gone
 
# Basic RO check
if [ -d "${pkgdir}-${target_pkgver}" ]; then
check_pkgver=$(awk '/^%VERSION%$/ { getline; print $0 }' "${pkgdir}-${target_pkgver}/desc" )
if [ "$check_pkgver" = "$target_pkgver" ]; then
info_log 'Success'
exit 0
else
fail_log "RO check failed."
fi
fi
 
fail_msg 'Failed wtf'

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.