From: Christian Weiske Date: Tue, 12 Dec 2023 20:21:07 +0000 (+0100) Subject: Initial commit X-Git-Url: https://git.cweiske.de/carddav-git-backup.git/commitdiff_plain/d2046cd2d915777e96c0d495c05a1a8d9c0cb1ef Initial commit --- d2046cd2d915777e96c0d495c05a1a8d9c0cb1ef diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a944a35 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +contacts +README.html diff --git a/.gitignore-contacts b/.gitignore-contacts new file mode 100644 index 0000000..11cc80f --- /dev/null +++ b/.gitignore-contacts @@ -0,0 +1,2 @@ +.password-* +vdirsyncer-status diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..8c7c536 --- /dev/null +++ b/README.rst @@ -0,0 +1,39 @@ +Backup CardDAV vCards into git +============================== + +Small script to backup address books stored a CardDAV server into +a local git repository for backup purposes. +Git commit messages contain the names of modified, added and deleted contacts +so it's easy to find out when someone was modified, and thus easy to find +lost contacts. + +Tested with vdirsyncer 0.19.2 and Nextcloud 23. + + +Setup +----- +1. Install `vdirsyncer`__ 0.19.x +2. Clone this repository +3. Run ``./backup.sh``. Directory ``contacts`` will be created and a + sample sync configuration will be added +4. In ``contacts`` directory adjust ``vdirsyncer-config`` + and test it with:: + + vdirsyncer --config=vdirsyncer-config discover + + Create all local collections when asked. +5. In ``contacts`` run:: + + vdirsyncer --config=vdirsyncer-config metasync + +6. Run ``./backup.sh`` which should commit all contacts to git. +7. Setup a cronjob on your home server to run ``backup.sh`` every night + + +__ http://vdirsyncer.pimutils.org/en/stable/ + + +About +----- +This script was written by `Christian Weiske `_ +and is licensed under the AGPL v3. diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..763250d --- /dev/null +++ b/backup.sh @@ -0,0 +1,40 @@ +#!/bin/sh +# download vcard contacts into contacts/ and commit them to git +set -e + +export GIT_AUTHOR_NAME="vcard backup" +export GIT_AUTHOR_EMAIL="vcard-backup@home.cweiske.de" +export GIT_COMMITTER_NAME="vcard backup" +export GIT_COMMITTER_EMAIL="vcard-backup@home.cweiske.de" + +[ -d contacts ] || mkdir contacts + +cd contacts +[ -d .git ] || git init +[ -f .gitignore ] || cp ../.gitignore-contacts .gitignore + +if [ ! -f vdirsyncer-config ]; then + cp ../vdirsyncer-config.example vdirsyncer-config + echo "Adjust contacts/vdirsyncer-config first" + exit 1 +fi + +# commit configuration files if necessary +conffiles=".gitignore vdirsyncer-config" +metamod=$(git status --porcelain $conffiles) +if [ -n "$metamod" ]; then + git add $conffiles + git commit $conffiles -m 'Update configuration' +fi + +# sync and commit vcards +vdirsyncer --config=vdirsyncer-config --verbosity WARNING sync +numchanged=$(git status --porcelain | wc -l) +if [ $numchanged -eq 0 ]; then + exit 0 +fi + +git add . +../create-commit-message.sh > tmp-msg +git commit --quiet --file=tmp-msg +rm tmp-msg diff --git a/create-commit-message.sh b/create-commit-message.sh new file mode 100755 index 0000000..070f79a --- /dev/null +++ b/create-commit-message.sh @@ -0,0 +1,63 @@ +#!/bin/sh +#create a nice commit message that contains the names +# of all modified, added and deleted contacts +# to make it easier to find changes in the git history +set -e + +numadd=$(git status --porcelain -uno|grep ^A|wc -l) +numdel=$(git status --porcelain -uno|grep ^D|wc -l) +nummod=$(git status --porcelain -uno|grep ^M|wc -l) +if [ "$numadd" -eq 0 -a "$numdel" -eq 0 -a "$nummod" -eq 0 ]; then + exit 0 +fi + +echo "Backup $(date +%F): ~$nummod +$numadd -$numdel" +echo + +for addressbook in $(ls -1d */* | grep -v vdirsyncer-status/); do + user=$(echo $addressbook | cut -d/ -f1) + addressbookTitle=$(cat $addressbook/displayname) + + added=$(git status --porcelain -uno\ + | grep ^A.*$addressbook.*vcf$\ + | cut -b 4-\ + | xargs -L1 grep ^FN:\ + | cut -b 4-\ + | sort) + modified=$(git status --porcelain -uno\ + | grep ^M.*$addressbook.*vcf$\ + | cut -b 4-\ + | xargs -L1 grep ^FN:\ + | cut -b 4-\ + | sort) + deleted=$(git status --porcelain -uno\ + | grep ^D.*$addressbook.*vcf$\ + | cut -b 4-\ + | xargs --replace={} git diff --cached -- {}\ + | grep ^-FN:\ + | cut -b 5-\ + | sort) + + if [ -n "$added" -o -n "$modified" -o -n "$deleted" ]; then + echo "$user: $addressbookTitle" + echo "---------" + + if [ -n "$added" ]; then + echo "Added:" + echo "$added" | sed 's/^/- /' + echo + fi + + if [ -n "$modified" ]; then + echo "Modified:" + echo "$modified" | sed 's/^/- /' + echo + fi + + if [ -n "$deleted" ]; then + echo "Deleted:" + echo "$deleted" | sed 's/^/- /' + echo + fi + fi +done diff --git a/vdirsyncer-config.example b/vdirsyncer-config.example new file mode 100644 index 0000000..e9e6dc6 --- /dev/null +++ b/vdirsyncer-config.example @@ -0,0 +1,25 @@ +[general] +status_path = "./vdirsyncer-status/" + +[pair anna] +a = "remote__anna" +b = "local__anna" +#collections = ["from a", "from b"] +#collections = ["from a"] +collections = ["contacts", "geburtstagsliste"] +conflict_resolution = "a wins" +metadata = ["displayname"] + + +[storage local__anna] +type = "filesystem" +path = "./anna/" +fileext = ".vcf" + + +[storage remote_anna] +type = "carddav" +url = "https://cloud.example.org/remote.php/carddav/" +username = "anna@example.org" +password.fetch = ["command", "cat", "./.password-anna"] +read_only = true