Specify paths correctly
[GrooveNet.git] / SongSync.sh
1 #!/bin/bash
2
3 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
4 source "$DIR/config.sh"
5
6 if [ "$1" = "apply" ]; then
7 num_songs_files=$(find "${DIR}" -name "songs.*.txt" -printf "%f\n" | wc -l)
8
9 if [ "$num_songs_files" = "1" ]; then
10 echo "Everything up to date"
11 exit
12 fi
13
14 if [ "$num_songs_files" -gt "2" ]; then
15 echo "More than 2 songs files, something went wrong last time?"
16 exit
17 fi
18
19 new_songs_file=$(find "${DIR}" -name "songs.*.txt" -printf "%f\n" | sort -r | head -n1)
20 old_songs_file=$(find "${DIR}" -name "songs.*.txt" -printf "%f\n" | sort -r | tail -n1)
21
22 diff=$(diff -u "${DIR}/$old_songs_file" "${DIR}/$new_songs_file")
23
24 # path => hash
25 declare -A adds
26 # path => hash
27 declare -A removes
28 # path => path
29 declare -A moves
30
31 # algorithm
32 # remove everything with a -
33 # move the folder to /tmp (rm it if it's already there) and name it using the hash
34 # download everything with a +
35 # first check if it's in /tmp and copy it over from there
36 # determine which files need cache invalidation
37 # they will be files with the same path appearing in adds and removes
38 #
39 # one downside of this approach is it will result in redownloading files already
40 # on disk instead of moving them
41 while read -r m; do
42 if [[ "${m:0:2}" = "++" ]] || [[ "${m:0:2}" = "--" ]] || [[ "${m:0:2}" = "@@" ]]; then
43 continue
44 fi
45
46 hash=$(echo "$m" | cut -sd ' ' -f1)
47 hash="${hash:1}"
48 path=$(echo "$m" | cut -sd / -f5,6)
49
50 if [[ "${m:0:1}" = "+" ]]; then
51 if ! [ -z "${adds[${path}]}" ]; then
52 echo "More than one SM file in ${path}, aborting"
53 exit
54 fi
55
56 if [ "${removes[${path}]}" = "$hash" ]; then
57 echo "Same hash ($hash) and path ($path) in adds and removes. Ignoring."
58 unset 'removes[$path]'
59 continue
60 fi
61
62 adds["${path}"]+="$hash"
63 fi
64
65 if [[ "${m:0:1}" = "-" ]]; then
66 # It can happan that a path is already in removes if there are multiple SM files in a directory
67 # this should not really happen since there's the check above that refuses to add any files with that
68 # problem. However when I do the initial sync on our machines they will have problematic files.
69 #
70 # So just ignore it, the path is already in the removes list, so it will be nuked.
71 #
72 # I suppose it could happen that one of these borked paths were moved to a different location, but
73 # in that case thered be multiple sms in the adds path. So... I guess its OK.
74 if [ -z "${removes[${path}]}" ]; then
75 if [ "${adds[${path}]}" = "$hash" ]; then
76 echo "Same hash ($hash) and path ($path) in adds and removes. Ignoring."
77 unset 'adds[$path]'
78 continue
79 fi
80
81 removes["${path}"]+="$hash"
82 fi
83 fi
84 done <<< "$diff"
85
86 for removal_path in "${!removes[@]}"; do
87 if [ -d "/tmp/${removes[$removal_path]}" ]; then
88 echo "/tmp/${removes[$removal_path]} already exists, skipping"
89 continue
90 fi
91
92 echo "Moving ${removal_path} to /tmp/${removes[$removal_path]}"
93 mv "${path_to_songs}/${removal_path}" "/tmp/${removes[$removal_path]}"
94 crc32="$(echo -n "/Songs/${removal_path}/" | gzip -c | tail -c8 | hexdump -n4 -e '"%u"')"
95 rm "${path_to_song_cache}/${crc32}"
96
97 pack_dir=$(echo "$removal_path" | cut -sd / -f1)
98 count="$( find "${path_to_songs}/${pack_dir}" -mindepth 1 -maxdepth 1 | wc -l )"
99 if [ $count -eq 0 ] ; then
100 echo "${pack_dir} is now empty, deleting"
101 rmdir "${path_to_songs}/${pack_dir}"
102 fi
103
104 done
105
106 for add_path in "${!adds[@]}"; do
107 pack_dir=$(echo "$add_path" | cut -sd / -f1)
108 if ! [ -z "${removes[${add_path}]}" ]; then
109 crc32="$(echo -n "/Songs/${add_path}/" | gzip -c | tail -c8 | hexdump -n4 -e '"%u"')"
110 echo "CACHE INVALIDATION NEEDED FOR ${add_path} : ${crc32}"
111 rm "${path_to_song_cache}/${crc32}"
112 fi
113
114 if ! [ -d "${path_to_songs}/${add_path}" ]; then
115 echo "Creating dir for: ${add_path}"
116 mkdir -p "${path_to_songs}/${pack_dir}"
117 fi
118
119 # The file existed previously, just move that over.
120 if [ -d "/tmp/${adds[$add_path]}" ]; then
121 echo "Moving /tmp/${adds[$add_path]} to ${path_to_songs}/${add_path}"
122 mv "/tmp/${adds[$add_path]}" "${path_to_songs}/${add_path}"
123 continue
124 fi
125
126 echo "Downloading files"
127 escaped_add_path="/mnt/media/Simfiles/"$(echo "$add_path" | sed 's/ /\\\\\\ /g' | sed "s/'/\\\\\\\\\\\'/g" | sed "s/(/\\\\\\\\\\\\(/g" | sed "s/)/\\\\\\\\\\\\\\)/g" | sed "s/&/\\\\\\\\\\\&/g" | sed "s/\`/\\\\\\\\\\\\\`/g")
128 scp_command="scp -r groovenet@cameron1729.xyz:$escaped_add_path \"${path_to_songs}/${pack_dir}\""
129 echo "$scp_command"
130 eval "$scp_command"
131 done
132
133 rm "${old_songs_file}"
134 fi