tools/update-packaging/make_incremental_update.sh

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rwxr-xr-x

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 #!/bin/bash
michael@0 2 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 5
michael@0 6 #
michael@0 7 # This tool generates incremental update packages for the update system.
michael@0 8 # Author: Darin Fisher
michael@0 9 #
michael@0 10
michael@0 11 . $(dirname "$0")/common.sh
michael@0 12
michael@0 13 # -----------------------------------------------------------------------------
michael@0 14
michael@0 15 print_usage() {
michael@0 16 notice "Usage: $(basename $0) [OPTIONS] ARCHIVE FROMDIR TODIR"
michael@0 17 notice ""
michael@0 18 notice "The differences between FROMDIR and TODIR will be stored in ARCHIVE."
michael@0 19 notice ""
michael@0 20 notice "Options:"
michael@0 21 notice " -h show this help text"
michael@0 22 notice " -f clobber this file in the installation"
michael@0 23 notice " Must be a path to a file to clobber in the partial update."
michael@0 24 notice " -q be less verbose"
michael@0 25 notice ""
michael@0 26 }
michael@0 27
michael@0 28 check_for_forced_update() {
michael@0 29 force_list="$1"
michael@0 30 forced_file_chk="$2"
michael@0 31
michael@0 32 local f
michael@0 33
michael@0 34 if [ "$forced_file_chk" = "precomplete" ]; then
michael@0 35 ## "true" *giggle*
michael@0 36 return 0;
michael@0 37 fi
michael@0 38
michael@0 39 if [ "${forced_file_chk##*.}" = "chk" ]
michael@0 40 then
michael@0 41 ## "true" *giggle*
michael@0 42 return 0;
michael@0 43 fi
michael@0 44
michael@0 45 for f in $force_list; do
michael@0 46 #echo comparing $forced_file_chk to $f
michael@0 47 if [ "$forced_file_chk" = "$f" ]; then
michael@0 48 ## "true" *giggle*
michael@0 49 return 0;
michael@0 50 fi
michael@0 51
michael@0 52 # If the file in the skip list ends with /*, do a prefix match.
michael@0 53 # This allows TorBrowser/Data/Browser/profile.default/extensions/https-everywhere@eff.org/* to be used to force all HTTPS Everywhere files to be updated.
michael@0 54 f_suffix=${f##*/}
michael@0 55 if [[ $f_suffix = "*" ]]; then
michael@0 56 f_prefix="${f%\/\*}";
michael@0 57 if [[ $forced_file_chk == $f_prefix* ]]; then
michael@0 58 ## 0 means "true"
michael@0 59 return 0;
michael@0 60 fi
michael@0 61 fi
michael@0 62 done
michael@0 63 ## 'false'... because this is bash. Oh yay!
michael@0 64 return 1;
michael@0 65 }
michael@0 66
michael@0 67 if [ $# = 0 ]; then
michael@0 68 print_usage
michael@0 69 exit 1
michael@0 70 fi
michael@0 71
michael@0 72 # The last .xpi is NoScript.
michael@0 73 ext_path='TorBrowser/Data/Browser/profile.default/extensions';
michael@0 74 # TODO: it would be better to pass this as a command line option.
michael@0 75 exts='https-everywhere@eff.org/* tor-launcher@torproject.org.xpi torbutton@torproject.org.xpi uriloader@pdf.js.xpi {73a6fe31-595d-460b-a920-fcc0f8843232}.xpi'
michael@0 76 requested_forced_updates='Contents/MacOS/TorBrowser.app/Contents/MacOS/firefox'
michael@0 77 for ext in $exts; do
michael@0 78 requested_forced_updates="$requested_forced_updates $ext_path/$ext"
michael@0 79 done
michael@0 80
michael@0 81
michael@0 82 # TODO: it would be better to pass this as a command line option.
michael@0 83 directories_to_remove='TorBrowser/Data/Browser/profile.default/extensions/https-everywhere@eff.org'
michael@0 84
michael@0 85 while getopts "hqf:" flag
michael@0 86 do
michael@0 87 case "$flag" in
michael@0 88 h) print_usage; exit 0
michael@0 89 ;;
michael@0 90 q) QUIET=1
michael@0 91 ;;
michael@0 92 f) requested_forced_updates="$requested_forced_updates $OPTARG"
michael@0 93 ;;
michael@0 94 ?) print_usage; exit 1
michael@0 95 ;;
michael@0 96 esac
michael@0 97 done
michael@0 98
michael@0 99 # -----------------------------------------------------------------------------
michael@0 100
michael@0 101 let arg_start=$OPTIND-1
michael@0 102 shift $arg_start
michael@0 103
michael@0 104 archive="$1"
michael@0 105 olddir="$2"
michael@0 106 newdir="$3"
michael@0 107 # Prevent the workdir from being inside the targetdir so it isn't included in
michael@0 108 # the update mar.
michael@0 109 if [ $(echo "$newdir" | grep -c '\/$') = 1 ]; then
michael@0 110 # Remove the /
michael@0 111 newdir=$(echo "$newdir" | sed -e 's:\/$::')
michael@0 112 fi
michael@0 113 workdir="$newdir.work"
michael@0 114 updatemanifestv2="$workdir/updatev2.manifest"
michael@0 115 updatemanifestv3="$workdir/updatev3.manifest"
michael@0 116 archivefiles="updatev2.manifest updatev3.manifest"
michael@0 117
michael@0 118 mkdir -p "$workdir"
michael@0 119
michael@0 120 # On Mac, the precomplete file added by Bug 386760 will cause OS X to reload the
michael@0 121 # Info.plist so it launches the right architecture, bug 600098
michael@0 122
michael@0 123 # Generate a list of all files in the target directory.
michael@0 124 pushd "$olddir"
michael@0 125 if test $? -ne 0 ; then
michael@0 126 exit 1
michael@0 127 fi
michael@0 128
michael@0 129 list_files oldfiles
michael@0 130 list_symlinks oldsymlinks oldsymlink_targets
michael@0 131 list_dirs olddirs
michael@0 132
michael@0 133 popd
michael@0 134
michael@0 135 pushd "$newdir"
michael@0 136 if test $? -ne 0 ; then
michael@0 137 exit 1
michael@0 138 fi
michael@0 139
michael@0 140 if [ ! -f "precomplete" ]; then
michael@0 141 notice "precomplete file is missing!"
michael@0 142 exit 1
michael@0 143 fi
michael@0 144
michael@0 145 list_dirs newdirs
michael@0 146 list_files newfiles
michael@0 147 list_symlinks newsymlinks newsymlink_targets
michael@0 148
michael@0 149 popd
michael@0 150
michael@0 151 # Add the type of update to the beginning of the update manifests.
michael@0 152 notice ""
michael@0 153 notice "Adding type instruction to update manifests"
michael@0 154 > "$updatemanifestv2"
michael@0 155 > "$updatemanifestv3"
michael@0 156 notice " type partial"
michael@0 157 echo "type \"partial\"" >> "$updatemanifestv2"
michael@0 158 echo "type \"partial\"" >> "$updatemanifestv3"
michael@0 159
michael@0 160 # If removal of any old, existing directories is desired, emit the appropriate
michael@0 161 # rmrfdir commands.
michael@0 162 notice ""
michael@0 163 notice "Adding directory removal instructions to update manifests"
michael@0 164 for dir_to_remove in $directories_to_remove; do
michael@0 165 # rmrfdir requires a trailing slash, so add one if missing.
michael@0 166 if ! [[ "$dir_to_remove" =~ /$ ]]; then
michael@0 167 dir_to_remove="${dir_to_remove}/"
michael@0 168 fi
michael@0 169 echo "rmrfdir \"$dir_to_remove\"" >> "$updatemanifestv2"
michael@0 170 echo "rmrfdir \"$dir_to_remove\"" >> "$updatemanifestv3"
michael@0 171 done
michael@0 172
michael@0 173 notice ""
michael@0 174 notice "Adding file patch and add instructions to update manifests"
michael@0 175
michael@0 176 num_oldfiles=${#oldfiles[*]}
michael@0 177 remove_array=
michael@0 178 num_removes=0
michael@0 179
michael@0 180 for ((i=0; $i<$num_oldfiles; i=$i+1)); do
michael@0 181 f="${oldfiles[$i]}"
michael@0 182
michael@0 183 # This file is created by Talkback, so we can ignore it
michael@0 184 if [ "$f" = "readme.txt" ]; then
michael@0 185 continue 1
michael@0 186 fi
michael@0 187
michael@0 188 # removed-files is excluded by make_incremental_updates.py so it is excluded
michael@0 189 # here for consistency.
michael@0 190 if [ "`basename "$f"`" = "removed-files" ]; then
michael@0 191 continue 1
michael@0 192 fi
michael@0 193
michael@0 194 # If this file exists in the new directory as well, then check if it differs.
michael@0 195 if [ -f "$newdir/$f" ]; then
michael@0 196
michael@0 197 if check_for_add_if_not_update "$f"; then
michael@0 198 # The full workdir may not exist yet, so create it if necessary.
michael@0 199 mkdir -p `dirname "$workdir/$f"`
michael@0 200 $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f"
michael@0 201 copy_perm "$newdir/$f" "$workdir/$f"
michael@0 202 make_add_if_not_instruction "$f" "$updatemanifestv3"
michael@0 203 archivefiles="$archivefiles \"$f\""
michael@0 204 continue 1
michael@0 205 fi
michael@0 206
michael@0 207 if check_for_forced_update "$requested_forced_updates" "$f"; then
michael@0 208 # The full workdir may not exist yet, so create it if necessary.
michael@0 209 mkdir -p `dirname "$workdir/$f"`
michael@0 210 $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f"
michael@0 211 copy_perm "$newdir/$f" "$workdir/$f"
michael@0 212 make_add_instruction "$f" "$updatemanifestv2" "$updatemanifestv3" 1
michael@0 213 archivefiles="$archivefiles \"$f\""
michael@0 214 continue 1
michael@0 215 fi
michael@0 216
michael@0 217 if ! diff "$olddir/$f" "$newdir/$f" > /dev/null; then
michael@0 218 # Compute both the compressed binary diff and the compressed file, and
michael@0 219 # compare the sizes. Then choose the smaller of the two to package.
michael@0 220 dir=$(dirname "$workdir/$f")
michael@0 221 mkdir -p "$dir"
michael@0 222 notice "diffing \"$f\""
michael@0 223 $MBSDIFF "$olddir/$f" "$newdir/$f" "$workdir/$f.patch"
michael@0 224 $BZIP2 -z9 "$workdir/$f.patch"
michael@0 225 $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f"
michael@0 226 copy_perm "$newdir/$f" "$workdir/$f"
michael@0 227 patchfile="$workdir/$f.patch.bz2"
michael@0 228 patchsize=$(get_file_size "$patchfile")
michael@0 229 fullsize=$(get_file_size "$workdir/$f")
michael@0 230
michael@0 231 if [ $patchsize -lt $fullsize ]; then
michael@0 232 make_patch_instruction "$f" "$updatemanifestv2" "$updatemanifestv3"
michael@0 233 mv -f "$patchfile" "$workdir/$f.patch"
michael@0 234 rm -f "$workdir/$f"
michael@0 235 archivefiles="$archivefiles \"$f.patch\""
michael@0 236 else
michael@0 237 make_add_instruction "$f" "$updatemanifestv2" "$updatemanifestv3"
michael@0 238 rm -f "$patchfile"
michael@0 239 archivefiles="$archivefiles \"$f\""
michael@0 240 fi
michael@0 241 fi
michael@0 242 else
michael@0 243 # remove instructions are added after add / patch instructions for
michael@0 244 # consistency with make_incremental_updates.py
michael@0 245 remove_array[$num_removes]=$f
michael@0 246 (( num_removes++ ))
michael@0 247 fi
michael@0 248 done
michael@0 249
michael@0 250 # Remove and re-add symlinks
michael@0 251 notice ""
michael@0 252 notice "Adding symlink remove/add instructions to update manifests"
michael@0 253 num_oldsymlinks=${#oldsymlinks[*]}
michael@0 254 for ((i=0; $i<$num_oldsymlinks; i=$i+1)); do
michael@0 255 link="${oldsymlinks[$i]}"
michael@0 256 verbose_notice " remove: $link"
michael@0 257 echo "remove \"$link\"" >> "$updatemanifestv2"
michael@0 258 echo "remove \"$link\"" >> "$updatemanifestv3"
michael@0 259 done
michael@0 260
michael@0 261 num_newsymlinks=${#newsymlinks[*]}
michael@0 262 for ((i=0; $i<$num_newsymlinks; i=$i+1)); do
michael@0 263 link="${newsymlinks[$i]}"
michael@0 264 target="${newsymlink_targets[$i]}"
michael@0 265 make_addsymlink_instruction "$link" "$target" "$updatemanifestv2" "$updatemanifestv3"
michael@0 266 done
michael@0 267
michael@0 268 # Newly added files
michael@0 269 notice ""
michael@0 270 notice "Adding file add instructions to update manifests"
michael@0 271 num_newfiles=${#newfiles[*]}
michael@0 272
michael@0 273 for ((i=0; $i<$num_newfiles; i=$i+1)); do
michael@0 274 f="${newfiles[$i]}"
michael@0 275
michael@0 276 # removed-files is excluded by make_incremental_updates.py so it is excluded
michael@0 277 # here for consistency.
michael@0 278 if [ "`basename "$f"`" = "removed-files" ]; then
michael@0 279 continue 1
michael@0 280 fi
michael@0 281
michael@0 282 # If we've already tested this file, then skip it
michael@0 283 for ((j=0; $j<$num_oldfiles; j=$j+1)); do
michael@0 284 if [ "$f" = "${oldfiles[j]}" ]; then
michael@0 285 continue 2
michael@0 286 fi
michael@0 287 done
michael@0 288
michael@0 289 dir=$(dirname "$workdir/$f")
michael@0 290 mkdir -p "$dir"
michael@0 291
michael@0 292 $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f"
michael@0 293 copy_perm "$newdir/$f" "$workdir/$f"
michael@0 294
michael@0 295 if check_for_add_if_not_update "$f"; then
michael@0 296 make_add_if_not_instruction "$f" "$updatemanifestv3"
michael@0 297 else
michael@0 298 make_add_instruction "$f" "$updatemanifestv2" "$updatemanifestv3"
michael@0 299 fi
michael@0 300
michael@0 301
michael@0 302 archivefiles="$archivefiles \"$f\""
michael@0 303 done
michael@0 304
michael@0 305 notice ""
michael@0 306 notice "Adding file remove instructions to update manifests"
michael@0 307 for ((i=0; $i<$num_removes; i=$i+1)); do
michael@0 308 f="${remove_array[$i]}"
michael@0 309 notice " remove \"$f\""
michael@0 310 echo "remove \"$f\"" >> "$updatemanifestv2"
michael@0 311 echo "remove \"$f\"" >> "$updatemanifestv3"
michael@0 312 done
michael@0 313
michael@0 314 # Add remove instructions for any dead files.
michael@0 315 notice ""
michael@0 316 notice "Adding file and directory remove instructions from file 'removed-files'"
michael@0 317 append_remove_instructions "$newdir" "$updatemanifestv2" "$updatemanifestv3"
michael@0 318
michael@0 319 notice ""
michael@0 320 notice "Adding directory remove instructions for directories that no longer exist"
michael@0 321 num_olddirs=${#olddirs[*]}
michael@0 322
michael@0 323 for ((i=0; $i<$num_olddirs; i=$i+1)); do
michael@0 324 f="${olddirs[$i]}"
michael@0 325 # If this dir doesn't exist in the new directory remove it.
michael@0 326 if [ ! -d "$newdir/$f" ]; then
michael@0 327 notice " rmdir $f/"
michael@0 328 echo "rmdir \"$f/\"" >> "$updatemanifestv2"
michael@0 329 echo "rmdir \"$f/\"" >> "$updatemanifestv3"
michael@0 330 fi
michael@0 331 done
michael@0 332
michael@0 333 $BZIP2 -z9 "$updatemanifestv2" && mv -f "$updatemanifestv2.bz2" "$updatemanifestv2"
michael@0 334 $BZIP2 -z9 "$updatemanifestv3" && mv -f "$updatemanifestv3.bz2" "$updatemanifestv3"
michael@0 335
michael@0 336 eval "$MAR -C \"$workdir\" -c output.mar $archivefiles"
michael@0 337 mv -f "$workdir/output.mar" "$archive"
michael@0 338
michael@0 339 # cleanup
michael@0 340 rm -fr "$workdir"
michael@0 341
michael@0 342 notice ""
michael@0 343 notice "Finished"
michael@0 344 notice ""

mercurial