Skip to content

Instantly share code, notes, and snippets.

@u1and0
Last active November 24, 2020 10:23
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 u1and0/8bd32ade8d95988b52b03a1b08297b96 to your computer and use it in GitHub Desktop.
Save u1and0/8bd32ade8d95988b52b03a1b08297b96 to your computer and use it in GitHub Desktop.
bacpac_lt_arch

Welcome to bacpac! For instructions, see the README file.

bacpac

bacpac is a backup and restore script for Arch Linux's pacman configuration data and manually installed packages.

Dependencies

  • bash for the script itself
  • git and diffutils for backing up current packages and configuration
  • sudo and grep for restoring packages and configuration
  • ...that's all!

Getting started

Setting up bacpac for the first time is super-easy; the only requirement is a GitHub account to sync your packages. To get started, read the following instructions:

  1. Create a GitHub account if you don't already have one.

  2. Fire up a terminal.

  3. git clone https://github.com/tech4david/bacpac

  4. cd bacpac

  5. ./bacpac init

  6. Follow the instructions displayed on the terminal.

Please report any issues you find with bacpac here or submit a pull request.

#compdef bacpac
# bacpac zsh completion
# ____________________________
# Maintainer: u1and0<e01.ando60@gmail.com>
# Update: -
# Create: 2019-01-04
# -------------------
_bacpac() {
_values -w\
'mode' \
'init[Initializes bacpac for the first time]' \
'backup[Backs up current packages and configuration]' \
'list[List backed up packages in packages.list]' \
'diff[Show diff of backup packages and now packages]' \
'restore[Restores packages and configuration]' \
'update[Update bacpac to the latest version]'
}
#!/usr/bin/bash
# Copyright (c) 2015, David Bailey <robocoder.db@gmail.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
bacpac-usage() {
echo 'bacpac version 0.2.0'
echo 'Copyright (c) 2015 David Bailey <robocoder.db@gmail.com>'
echo
echo "usage: $0 init|backup|list|diff|restore|update|clean"
echo " or: $0 help"
echo
echo 'init: Initializes bacpac for the first time'
echo 'backup: Backs up current packages and configuration'
echo 'list: List backed up packages in packages.list'
echo 'diff: Show diff between backup packages and now packages'
echo 'restore: Restores packages and configuration'
echo 'update: Update bacpac to the latest version'
echo 'clean: Deletes temporary directory'
echo 'help: Shows this message'
echo
}
bacpac-check-dependencies() {
if [[ ! -f '/usr/bin/pacman' ]]; then
echo 'You must be using Arch Linux to use bacpac'
echo
exit 1
fi
rm -f 'tmp/notinstalled.list'
if [[ ! -f '/usr/bin/bash' ]]; then
echo 'bash' >> 'tmp/notinstalled.list'
fi
if [[ ! -f '/usr/bin/git' ]]; then
echo 'git' >> 'tmp/notinstalled.list'
fi
if [[ ! -f '/usr/bin/diff' ]]; then
echo 'diffutils' >> 'tmp/notinstalled.list'
fi
if [[ ! -f '/usr/bin/sudo' ]]; then
echo 'sudo' >> 'tmp/notinstalled.list'
fi
if [[ ! -f '/usr/bin/grep' ]]; then
echo 'grep' >> 'tmp/notinstalled.list'
fi
if [[ -f 'tmp/notinstalled.list' ]]; then
echo 'You need to install the following packages to use bacpac:'
cat 'tmp/notinstalled.list'
echo "If they are installed to another location, please symlink them into /usr/bin or"
echo 'modify the script as you see fit.'
echo
exit 1
fi
}
bacpac-setup() {
bacpac-check-dependencies
cd "$(dirname "${BASH_SOURCE[0]}")"
mkdir -p tmp
pacman -Qqe > 'tmp/packages.list'
cp '/etc/pacman.d/mirrorlist' 'tmp/mirrorlist'
cp '/etc/pacman.conf' 'tmp/pacman.conf'
}
bacpac-backup() {
${diff_command} "$1" "tmp/$1"
if [ $? -ne 0 ]; then
echo "Modifications to '$1' since last backup:"
read -p "Back up $1? [Y/n] " response
if [[ "$response" =~ ^[Yy]$ || "$response" == '' ]]; then
mv "tmp/$1" "$1"
git add "$1"
git commit -m "Update $1 with bacpac"
git push &&
echo "Successfully backed up $1" ||
echo "Error backing up $1"
fi
else
echo "No modifications to '$1' since last backup"
fi
echo
}
bacpac-list() {
cat $(dirname $0)/packages.list
}
bacpac-diff() {
${diff_command} $(dirname $0)/packages.list <(pacman -Qqe)
}
bacpac-restore() {
if cmp --silent "$1" "$2"; then
echo "$1 is identical to $2; no need to restore"
else
read -p "Restore $1 to $2? [Y/n] " response
if [[ "$response" =~ ^[Yy]$ || "$response" == '' ]]; then
sudo cp "$1" "$2" &&
echo "Successfully restored $1 to $2" ||
echo "Error restoring $1 to $2"
else
echo "Not restoring $1 to $2"
fi
fi
echo
}
bacpac-package-restore-install() {
grep -F -x -v -f 'tmp/packages.list' 'packages.list' > 'tmp/install.list'
rm -f 'tmp/caninstall.list'
rm -f 'tmp/cannotinstall.list'
while read package; do
if pacman -Si $package &> '/dev/null'; then
echo $package >> 'tmp/caninstall.list'
else
echo $package >> 'tmp/cannotinstall.list'
fi
done < 'tmp/install.list'
if [[ -s 'tmp/cannotinstall.list' ]]; then
echo 'The following packages cannot be installed:'
cat 'tmp/cannotinstall.list'
echo 'These packages may have been installed from the AUR or another repository.'
echo 'Please install them manually later.'
echo
fi
if [[ -s 'tmp/caninstall.list' ]]; then
cat 'tmp/caninstall.list'
read -p 'Install the above packages? [Y/n] ' response
if [[ "$response" =~ ^[Yy]$ || "$response" == '' ]]; then
cat 'tmp/caninstall.list' | sudo pacman -Sy - &&
echo 'Successfully installed the above packages' ||
echo 'Error installing the above packages'
else
echo 'Not installing the above packages'
fi
else
echo 'No packages to install'
fi
echo
}
bacpac-package-restore-remove() {
grep -F -x -v -f 'packages.list' 'tmp/packages.list' > 'tmp/remove.list'
if [[ -s 'tmp/remove.list' ]]; then
cat 'tmp/remove.list'
read -p 'Remove the above packages? [Y/n] ' response
if [[ "$response" =~ ^[Yy]$ || "$response" == '' ]]; then
cat 'tmp/remove.list' | sudo pacman -Rsn - &&
echo 'Successfully removed the above packages' ||
echo 'Error removing the above packages'
else
echo 'Not removing the above packages'
fi
else
echo 'No packages to remove'
fi
echo
}
bacpac-init() {
bacpac-check-dependencies
git remote remove origin
echo 'Welcome to bacpac!'
echo 'To begin, go to https://gist.github.com/ and create a new secret Gist with any'
echo 'name and content'
read -p 'Press ENTER when finished'
read -p 'Now, copy and paste, or type out the URL in the address bar here: ' url
git remote add origin $url
if git push -f --set-upstream origin master; then
echo 'Successfully initialized the repository'
echo
else
echo 'Error initializing the repository'
echo "Please run 'bacpac init' again until successful, or bacpac will not work"
echo 'properly.'
echo
exit 1
fi
bacpac-setup
bacpac-backup 'packages.list'
bacpac-backup 'mirrorlist'
bacpac-backup 'pacman.conf'
echo 'Ready to go!'
echo
echo 'To backup your current packages and configuration, simply run the following at'
echo 'any time:'
echo
echo ' ./bacpac backup'
echo
echo 'To restore your packages and configuration on another computer or after'
echo 'reinstalling the operating system, run the following:'
echo
echo " git clone $url bacpac"
echo ' cd bacpac'
echo ' ./bacpac restore'
echo
echo 'To update bacpac, which you should do every few days to stay up-to-date, run the'
echo 'following:'
echo
echo ' ./bacpac update'
echo
echo 'You can find the URL above by going to https://gist.github.com/ and signing in'
echo 'to view your Gists, so you do not need to write it down. You only need to'
echo 'remember your GitHub username and password.'
echo
echo 'Have fun!'
echo
}
bacpac-update() {
git remote remove updates
git remote add updates 'https://github.com/tech4david/bacpac'
if git fetch updates; then
mv 'packages.list' 'tmp/packages.list'
mv 'mirrorlist' 'tmp/mirrorlist'
mv 'pacman.conf' 'tmp/pacman.conf'
git merge updates/master -X theirs -m 'Update bacpac'
mv 'tmp/packages.list' 'packages.list'
mv 'tmp/mirrorlist' 'mirrorlist'
mv 'tmp/pacman.conf' 'pacman.conf'
bash post-update
git add --all
git commit -m 'Restore data after updating'
git push
echo 'Successfully updated bacpac'
echo
else
echo 'Error updating bacpac'
echo
exit 1
fi
}
if [[ "$#" != 1 ]]; then
bacpac-usage
exit 1
fi
type colordiff >/dev/null 2>&1 &&
diff_command="$(which colordiff) -u" ||
diff_command="$(which diff) -u"
if [[ "$1" == init ]]; then
bacpac-init
elif [[ "$1" == backup ]]; then
bacpac-setup
bacpac-backup 'packages.list'
bacpac-backup 'mirrorlist'
bacpac-backup 'pacman.conf'
elif [[ "$1" == list ]]; then
bacpac-list
elif [[ "$1" == diff ]]; then
bacpac-diff
elif [[ "$1" == restore ]]; then
bacpac-setup
bacpac-restore 'mirrorlist' '/etc/pacman.d/mirrorlist'
bacpac-restore 'pacman.conf' '/etc/pacman.conf'
bacpac-package-restore-install
bacpac-package-restore-remove
elif [[ "$1" == update ]]; then
bacpac-setup
bacpac-update
elif [[ "$1" == clean ]]; then
rm -rf tmp
elif [[ "$1" == help ]]; then
bacpac-usage
else
bacpac-usage
exit 1
fi
################################################################################
################# Arch Linux mirrorlist generated by Reflector #################
################################################################################
# With: reflector --verbose --country Japan -l 10 --sort rate --save /etc/pacman.d/mirrorlist
# When: 2019-02-01 00:18:35 UTC
# From: https://www.archlinux.org/mirrors/status/json/
# Retrieved: 2019-02-01 00:18:34 UTC
# Last Check: 2019-02-01 00:05:22 UTC
Server = http://ftp.jaist.ac.jp/pub/Linux/ArchLinux/$repo/os/$arch
Server = http://mirrors.cat.net/archlinux/$repo/os/$arch
Server = https://mirrors.cat.net/archlinux/$repo/os/$arch
Server = https://ftp.jaist.ac.jp/pub/Linux/ArchLinux/$repo/os/$arch
Server = https://jpn.mirror.pkgbuild.com/$repo/os/$arch
Server = http://ftp.tsukuba.wide.ad.jp/Linux/archlinux/$repo/os/$arch
Server = rsync://ftp.jaist.ac.jp/pub/Linux/ArchLinux/$repo/os/$arch
Server = rsync://jpn.mirror.pkgbuild.com/packages/$repo/os/$arch
Server = rsync://ftp.tsukuba.wide.ad.jp/archlinux/$repo/os/$arch
arch-install-scripts
aria2
atool
autoconf
automake
binutils
bison
catdoc
colordiff
cronie
ctags
diffutils
docx2txt
fakeroot
fd
file
flex
fzf
gcc
gettext
git
global
grep
groff
gzip
htop
hub
inetutils
iputils
less
libtool
licenses
linux-firmware
logrotate
m4
make
man-db
man-pages-ja
nkf
openssh
patch
perl-text-markdown
pigz
pkgconf
poppler
procps-ng
psmisc
pygmentize
python-neovim
ranger
ripgrep
sed
sudo
sysfsutils
tar
texinfo
tig
tmux
unzip
vimpager
w3m
which
yay
zip
zsh
#
# /etc/pacman.conf
#
# See the pacman.conf(5) manpage for option and repository directives
#
# GENERAL OPTIONS
#
[options]
# The following paths are commented out with their default values listed.
# If you wish to use different paths, uncomment and update the paths.
#RootDir = /
#DBPath = /var/lib/pacman/
#CacheDir = /var/cache/pacman/pkg/
#LogFile = /var/log/pacman.log
#GPGDir = /etc/pacman.d/gnupg/
#HookDir = /etc/pacman.d/hooks/
HoldPkg = pacman glibc
#XferCommand = /usr/bin/curl -C - -f %u > %o
#XferCommand = /usr/bin/curl --proxy proxy.company.com:80 -C - -f %u > %o
#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
#XferCommand = /usr/bin/wget --passive-ftp --proxy=on -c -O %o %u
#XferCommand = /usr/bin/aria2c --allow-overwrite=true --continue=true --file-allocation=none --log-level=error --max-tries=2 --max-connection-per-server=2 --max-file-not-found=5 --min-split-size=5M --no-conf --remote-time=true --summary-interval=60 --timeout=5 --dir=/ --out %o %u
#CleanMethod = KeepInstalled
#UseDelta = 0.7
Architecture = auto
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
#IgnorePkg =
#IgnoreGroup =
#NoUpgrade =
#NoExtract =
# Misc options
#UseSyslog
Color
#TotalDownload
CheckSpace
#VerbosePkgLists
# By default, pacman accepts packages signed by keys that its local keyring
# trusts (see pacman-key and its man page), as well as unsigned packages.
SigLevel = PackageRequired
# SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional
#RemoteFileSigLevel = Required
# NOTE: You must run `pacman-key --init` before first using pacman; the local
# keyring can then be populated with the keys of all official Arch Linux
# packagers with `pacman-key --populate archlinux`.
#
# REPOSITORIES
# - can be defined here or included from another file
# - pacman will search repositories in the order defined here
# - local/custom mirrors can be added here or in separate files
# - repositories listed first will take precedence when packages
# have identical names, regardless of version number
# - URLs will have $repo replaced by the name of the current repo
# - URLs will have $arch replaced by the name of the architecture
#
# Repository entries are of the format:
# [repo-name]
# Server = ServerName
# Include = IncludePath
#
# The header [repo-name] is crucial - it must be present and
# uncommented to enable the repo.
#
# The testing repositories are disabled by default. To enable, uncomment the
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
#[testing]
#Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
[extra]
Include = /etc/pacman.d/mirrorlist
#[community-testing]
#Include = /etc/pacman.d/mirrorlist
[community]
Include = /etc/pacman.d/mirrorlist
# If you want to run 32 bit applications on your x86_64 system,
# enable the multilib repositories as required here.
#[multilib-testing]
#Include = /etc/pacman.d/mirrorlist
#[multilib]
#Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
# tips on creating your own repositories.
#[custom]
#SigLevel = Optional TrustAll
#Server = file:///home/custompkgs
[archlinuxfr]
SigLevel = Never
Server = http://repo.archlinux.fr/$arch
# This function is just here in case we need to do anything after updating
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment