summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2023-05-21 19:04:14 -0400
committerAndrew Cady <d@jerkface.net>2023-05-21 19:04:14 -0400
commit729b61170638365c04458963018edea1ca067e7e (patch)
tree0e622b8fa3d6bf3835cffcdfa04553891bc12224
parentcba8b36d788761e185adcf6af7cf396e66a3cd8a (diff)
pretty good
-rwxr-xr-xgo.sh60
1 files changed, 44 insertions, 16 deletions
diff --git a/go.sh b/go.sh
index 7d678bc..23d06d0 100755
--- a/go.sh
+++ b/go.sh
@@ -1,4 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2MAX_AGE_SECONDS=60
2 3
3read_config() 4read_config()
4{ 5{
@@ -7,7 +8,7 @@ read_config()
7 8
8check_dependencies() 9check_dependencies()
9{ 10{
10 for c in flock jq btrfs pv mv 11 for c in flock jq btrfs pv realpath stat date mv ln rm
11 do 12 do
12 command -v $c >/dev/null 13 command -v $c >/dev/null
13 done 14 done
@@ -23,43 +24,70 @@ is_subvolume()
23 btrfs subvolume show -- "$1" >/dev/null 2>&1 24 btrfs subvolume show -- "$1" >/dev/null 2>&1
24} 25}
25 26
27get_age()
28{
29 now=$(date +%s)
30 then=$(stat -L -c %Y "$1")
31 echo $((now - then))
32}
33
34remove_old_link()
35{
36 if [ -L "$1" ] && [ "$(get_age "$1")" -gt "$2" ]
37 then
38 rm -- "$1"
39 fi
40}
41
26set -e 42set -e
27check_dependencies 43check_dependencies
28check_user_is_root 44check_user_is_root
29 45
30if [ $# != 1 ] 46if [ $# = 1 ]
31then 47then
48 config_file=$1
49else
32 echo "Usage: $0 <config.json>" >&2 50 echo "Usage: $0 <config.json>" >&2
33 exit 1 51 exit 1
34fi 52fi
35 53
36[ -r "$1" ] 54[ -r "$config_file" ]
37exec 3<>"$1" 55exec 3<>"$config_file"
38flock -n 3 56flock -n 3
39declare -A config 57declare -A config
40read_config <&3 58read_config <&3
41 59
42src=${config[source]} 60src=${config[source]}
43dst=${config[destination]} 61dst=${config[destination]}
44head=${config[head]} 62remote_head=${config[head]}
45new_snapshot=${src%/}/.snapshot~$(date -Ins)
46 63
47is_subvolume "$src" 64is_subvolume "$src"
48if [ "$head" ] 65local_head_link=${src%/}/.snapshot~HEAD
66
67remove_old_link "$local_head_link" "$MAX_AGE_SECONDS"
68
69if [ -e "$local_head_link" ]
49then 70then
50 is_subvolume "$head" 71 local_head=$(realpath -e "$local_head_link")
72else
73 new_snapshot=${src%/}/.snapshot~$(date -Ins)
74 btrfs subvolume snapshot -r -- "$src" "$new_snapshot"
75 # We don't need to create this link at all.
76 ln -rs -T "$new_snapshot" "$local_head_link"
77 local_head=$new_snapshot
51fi 78fi
52mkdir -p "$dst"
53 79
54btrfs subvolume snapshot -r "$src" "$new_snapshot" 80is_subvolume "$local_head"
55btrfs send "$new_snapshot" ${head:+ -p "$head"} | pv | btrfs receive "$dst"
56jq --arg h "$head" '. | .head=$h' <"$1" >."$1"~tmp
57mv -T -- ."$1"~tmp "$1"
58 81
59#printf "%s\n" "$new_snapshot" > "$head"~tmp 82if [ "${local_head##*/}" = "${remote_head##*/}" ]
60#mv -T -- "$head"~tmp "$head" 83then
84 echo "Up-to-date." >&2
85 exit
86fi
61 87
62# parent of $src on $dst is $parent 88btrfs send ${remote_head:+ -p "$remote_head"} -- "$local_head" | pv | btrfs receive -- "$dst"
89jq --arg h "$local_head" '. | .head=$h' <"$config_file" >."$config_file"~tmp
90mv -T -- ."$config_file"~tmp "$config_file"
63 91
64### OK, basic idea: 92### OK, basic idea:
65# 93#