# --- preferences # load standard environment variables . $HOME/.shenv # '>' is a nice prompt char because it need not be followed by a # space. It is easy to distinguish the command from the prompt PS1='\[\e[1m\]$(exit_code=$?; test $exit_code -eq 0 || printf %s $exit_code " ")${debian_chroot:+($debian_chroot)}\u@\h:\w>\[\e[0m\]' # if this is an xterm set its title to user@host:dir # (this doesn't stop the likes of ncmpcpp setting a title) case "$TERM" in xterm*|rxvt*) PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h:\w\a\]$PS1" ;; *) ;; esac # enable better completion if [ -f /etc/bash_completion ]; then . /etc/bash_completion fi # enable undistract-me if [ -f /usr/share/undistract-me/long-running.bash ]; then . /usr/share/undistract-me/long-running.bash notify_when_long_running_commands_finish_install fi # history settings HISTCONTROL=ignorespace:ignoredups HISTSIZE=5000 HISTFILESIZE=5000 HISTIGNORE="ls" # colon-separated shopt -s histappend # make less more friendly for non-text input files; see lesspipe(1) if [ -x /usr/bin/lesspipe ]; then eval "$(lesspipe)" fi # --- aliases alias ls="ls --color=auto --literal --classify" alias grep="grep --colour=auto" alias g="git" alias ga="git annex" alias e="$EDITOR" alias mrs="src-register-all && mr -m status" alias d="emacsclient -c -n -e '(dired \".\")' >/dev/null" alias m="emacsclient -c -n -e '(progn (magit-status \".\") \ (delete-other-windows))' >/dev/null" alias ta="tmux new-session -A -s default" alias rax="screen -URaAx" alias new-login-shell="exec su -l $USER" # get new UNIX group without relog alias whitenoise="echo -en \"\033]0;whitenoise\a\";\ cvlc --quiet --loop ~/annex/media/sounds/R*.ogg" # useful to check whether a rebase introduced any changes to files alias rld="git diff @{1}..@{0}" alias athvpn="sshuttle -r athena 0/0 --dns" alias soffice-pdf="soffice --headless --convert-to pdf" alias host-suite-build-deps='mk-build-deps -ir -s sudo -t \ "apt-get --no-install-recommends"' alias sid-build-deps='mk-build-deps -ir -s sudo -t \ "apt-get -o Debug::pkgProblemResolver=yes -t sid --no-install-recommends"' alias bts-policy="bts user debian-policy@packages.debian.org \ , package debian-policy , " alias dak-rdeps="ssh mirror.ftp-master.debian.org dak rm -Rn" alias b="bts --mbox show" alias afsid="apt-file --filter-suites unstable" alias dinstall="curl https://ftp-master.debian.org/dinstall.status;echo -n 'Right now: ';date -u '+%a %b %d %T %Z %Y (%s)'" # use with care, in order for this to actually provide a security advantage alias update-debian-known-hosts="scp master.debian.org:/etc/ssh/ssh_known_hosts ~/src/dotfiles/.ssh/known_hosts_debian" alias grepcopy="grep --color=always -Eir '(copyright|©)' * | less -R" alias test-package-plan="find \ $HOME/.cabal/packages/hackage.haskell.org/01-index.tar \ -newermt '4 hours ago' | xargs test -z \ && cabal --no-require-sandbox update; \ schroot -c haskell -d $HOME -- /bin/sh -c \ \"cd src/package-plan && perl test-packages.pl\"" # from dgit-user(7), this pushes a non-native package through sbuild # without an orig.tar for the version in the first changelog entry. # Useful for sbuilding an unreleased version of a package I maintain # upstream alias sbuild-prerelease="sbuild --dpkg-source-opts='-Zgzip -z1 --format=1.0 -sn'" # alias develacc='sudo machinectl shell spw@develacc \ # $(sudo enter-develacc /bin/sh -c "getent passwd spw | cut -d: -f7")' # alias develaccr='sudo machinectl shell root@develacc \ # $(sudo enter-develacc /bin/sh -c "getent passwd root | cut -d: -f7")' # alias does not call `git develacc` because we want manual # verification of what is to be pushed (i.e. `git diff # master..develacc/develacc-iris` to check patch queue is sane) alias push-develacc-dotfiles-branch="git push \ -f origin develacc/develacc-$(hostname -s):develacc-$(hostname -s)" alias spin-this-host-now='(cd /usr/local/propellor && sudo ./propellor)' # --- more powerful aliases built with shell functions # run a package build and the full suite of checks that I can do # locally before an upload. Generally I use this on an UNRELEASED # package and then use `dgit push-source` for the actual upload sbuild-preupload() { local dgit="" local sbuild="" for key in "$@"; do case $key in --gbp|--dpm|--quilt=*) dgit="$dgit $key" shift ;; *) sbuild="$sbuild $key" shift ;; esac done case $(pwd) in *src/DHG_packages/p*) sbuild $sbuild \ --no-run-lintian --run-piuparts --run-autopkgtest ;; *) eval dgit $dgit sbuild $sbuild \ --no-run-lintian --run-piuparts --run-autopkgtest esac lintian } # release process for almost all of the Debian packages I maintain debrel () { ( set -e local branch="$(git symbolic-ref HEAD | sed 's|refs/heads/||')" if ! (git diff-index --quiet --cached HEAD && \ git diff-files --quiet && \ test -z "$(git status --porcelain)" \ ) >/dev/null 2>&1; then echo >&2 "must commit first" exit 1 fi if [[ $branch =~ ^wip/ ]]; then echo >&2 "you don't want to upload a wip/ branch" exit 1 fi if [ "$(dpkg-parsechangelog -SDistribution)" = "UNRELEASED" ]; then debchange --release # pauses for user confirmation git commit --include debian/changelog \ -m"finalise changelog for $(dpkg-parsechangelog -SVersion) upload" fi dgit push-source "$@" git push --follow-tags # # if origin is not salsa, we might also want to push to salsa # # (.mrconfig.in should contain `git remote add -f salsa # # salsa:foo/bar` for this repo) # if git remote | grep -q salsa \ # && git branch --contains salsa/$branch \ # | grep -qE " $branch$"; then # git push --follow-tags salsa $branch:$branch # fi ) } package-plan-unpack () { package="$1" patches="$HOME/src/package-plan/patches/${package%-*}/${package##*-}" cd /tmp cabal unpack --pristine "$package" cd "$package" mkdir -p "$patches" ln -s "$patches" patches ls "$(readlink $patches)" } # tidy up if I deleted files from stowed repos without properly # restowing kill-broken-stowed-symlinks () { find "$HOME" -xtype l | while read -r link; do if readlink "$link" | grep --quiet "^[../]*/.STOW/"; then rm "$link" fi done } # install package(s) and immediately mark as auto installed, so it # will get cleaned up by the next autoclean. # --no-install-recommends is needed as otherwise packages are manually # installed beyond those specified on the command line install-as-auto () { if [[ $EUID -ne 0 ]]; then sudo apt-get --no-install-recommends install "$@" sudo apt-mark auto "$@" else apt-get --no-install-recommends install "$@" apt-mark auto "$@" fi } # when mosh isn't installed on the server, but tmux is, use this to # get a fairly persistent set of remote shell sessions. I used to use # autossh here, but that means surprise dialogs asking to authorise # use of an SSH key; instead, just hit to restart a window's # connection when it's convenient # # (The reason that I get prompted is because I have a short # ServerAliveInterval and low ServerAliveCountMax, but that's # desirable, because unresponsive SSH sessions are a massive pain) smux () { case "$2" in "") ssh -t "$1" "tmux new-session -A -s default" ;; *) ssh -t "$1" "tmux new-session -A -s $2" ;; esac } # try to get an upstream remote upstream-remote-from-copyright () { toplevel="$(git rev-parse --show-toplevel)" source="$(grep ^Source: $toplevel/debian/copyright | awk -F': ' '{print $2}')" git remote add -f upstream "$source" } # PDF word count pdfwords () { pdftotext "$1" - | wc -w } # also see soffice-pdf alias above soffice-pdf-all () { for f in *.doc *.docx; do soffice --headless --convert-to pdf "$f" done } # Debian archive processing logs alias tail-dak="ssh ftp-master.debian.org tail -F \ /srv/ftp-master.debian.org/log/current" alias tail-queued="ssh ssh.upload.debian.org tail -F \ /srv/upload.debian.org/queued/run/log" grep-dak () { ssh ftp-master.debian.org grep "$@" /srv/ftp-master.debian.org/log/current } grep-queued () { ssh ssh.upload.debian.org grep "$@" /srv/upload.debian.org/queued/run/log } secs () { for i in $(seq $1 -1 1); do echo $i sleep 1 done echo 0 } # sometimes a remote SSH session cannot get at my forwarded SSH agent # because an unwanted instance of gpg-agent running on the remote host # gets in the way. this is a way to kill off that unwanted agent. we # also need to restart the multiplexed SSH connection to get agent # forwarding working again. I think this problem is mostly caused by # the fact that I use gnupg as my SSH agent kill-remote-gpg () { ssh "$1" 'rm -f $XDG_RUNTIME_DIR/gnupg/*' ssh -O exit "$1" } # build debs from a Linux kernel source tree *without* calling `make clean`. # # The -dbg deb takes some time to build. To get rid of it when it's # not needed: scripts/config --disable DEBUG_INFO bindeb-pkg () { ver="$(make kernelversion)" date="$(date +%Y%m%d+%H%M)" arch="$(dpkg --print-architecture)" make -j$((2 * $(nproc))) bindeb-pkg \ LOCALVERSION=-spw \ KDEB_PKGVERSION=$ver-$date \ "$@" echo "sudo apt-get install \ ../linux-{image,headers}-$ver-spw_$ver-${date}_$arch.deb" } # --- host-specific aliases/functions # ftp-master.debian.org if [ -d "/srv/ftp-master.debian.org" ]; then alias newlocks="cd /srv/ftp-master.debian.org/lock/new/ && ls -l" newlock () { touch /srv/ftp-master.debian.org/lock/new/"$1" } newunlock () { rm /srv/ftp-master.debian.org/lock/new/"$1" } pn () { cd /srv/ftp-master.debian.org/queue/new # we need VISUAL=emacsclient because dak's utils.call_editor # fails when VISUAL contains both the editor's name and some # arguments to it, as mine does if [[ $1 ]]; then VISUAL=emacsclient dak process-new "$1"*changes else VISUAL=emacsclient dak process-new -b fi } fi # not ftp-master.debian.org # this is useful for processing removal requests # (credits to Mark Wooding) # # alternative, by me, but involves spawning another process or two: # # command -v dak >/dev/null \ # || alias dak="perl -MString::ShellQuote \ # -we'system qw(ssh -t ftp-master.debian.org dak), shell_quote @ARGV'" if ! command -v dak >/dev/null; then dak () { local i local c= for i; do # implicit "in $@" c="$c '${i/\'/\'\\\'\'}'" done ssh -t ftp-master.debian.org dak "$c" } fi