1#!/bin/bash
2# This Source Code Form is subject to the terms of the Mozilla Public
3# License, v. 2.0. If a copy of the MPL was not distributed with this
4# file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
6#
7# Code shared by update packaging scripts.
8# Author: Darin Fisher
9#
10
11# -----------------------------------------------------------------------------
12QUIET=0
13
14# By default just assume that these tools exist on our path
15MAR=${MAR:-mar}
16MBSDIFF=${MBSDIFF:-mbsdiff}
17if [[ -z "${MAR_OLD_FORMAT}" ]]; then
18  XZ=${XZ:-xz}
19  $XZ --version > /dev/null 2>&1
20  if [ $? -ne 0 ]; then
21    # If $XZ is not set and not found on the path then this is probably
22    # running on a windows buildbot. Some of the Windows build systems have
23    # xz.exe in topsrcdir/xz/. Look in the places this would be in both a
24    # mozilla-central and comm-central build.
25    XZ="$(dirname "$(dirname "$(dirname "$0")")")/xz/xz.exe"
26    $XZ --version > /dev/null 2>&1
27    if [ $? -ne 0 ]; then
28      XZ="$(dirname "$(dirname "$(dirname "$(dirname "$0")")")")/xz/xz.exe"
29      $XZ --version > /dev/null 2>&1
30      if [ $? -ne 0 ]; then
31        echo "xz was not found on this system!"
32        echo "exiting"
33        exit 1
34      fi
35    fi
36  fi
37else
38  MAR_OLD_FORMAT=1
39  BZIP2=${BZIP2:-bzip2}
40fi
41
42# -----------------------------------------------------------------------------
43# Helper routines
44
45notice() {
46  echo "$*" 1>&2
47}
48
49verbose_notice() {
50  if [ $QUIET -eq 0 ]; then
51    notice "$*"
52  fi
53}
54
55get_file_size() {
56  info=($(ls -ln "$1"))
57  echo ${info[4]}
58}
59
60copy_perm() {
61  reference="$1"
62  target="$2"
63
64  if [ -x "$reference" ]; then
65    chmod 0755 "$target"
66  else
67    chmod 0644 "$target"
68  fi
69}
70
71make_add_instruction() {
72  f="$1"
73  filev2="$2"
74  # The third param will be an empty string when a file add instruction is only
75  # needed in the version 2 manifest. This only happens when the file has an
76  # add-if-not instruction in the version 3 manifest. This is due to the
77  # precomplete file prior to the version 3 manifest having a remove instruction
78  # for this file so the file is removed before applying a complete update.
79  filev3="$3"
80
81  # Used to log to the console
82  if [ $4 ]; then
83    forced=" (forced)"
84  else
85    forced=
86  fi
87
88  is_extension=$(echo "$f" | grep -c 'distribution/extensions/.*/')
89  if [ $is_extension = "1" ]; then
90    # Use the subdirectory of the extensions folder as the file to test
91    # before performing this add instruction.
92    testdir=$(echo "$f" | sed 's/\(.*distribution\/extensions\/[^\/]*\)\/.*/\1/')
93    verbose_notice "     add-if \"$testdir\" \"$f\""
94    echo "add-if \"$testdir\" \"$f\"" >> "$filev2"
95    if [ ! $filev3 = "" ]; then
96      echo "add-if \"$testdir\" \"$f\"" >> "$filev3"
97    fi
98  else
99    verbose_notice "        add \"$f\"$forced"
100    echo "add \"$f\"" >> "$filev2"
101    if [ ! "$filev3" = "" ]; then
102      echo "add \"$f\"" >> "$filev3"
103    fi
104  fi
105}
106
107check_for_add_if_not_update() {
108  add_if_not_file_chk="$1"
109
110  if [ `basename $add_if_not_file_chk` = "channel-prefs.js" -o \
111       `basename $add_if_not_file_chk` = "update-settings.ini" ]; then
112    ## "true" *giggle*
113    return 0;
114  fi
115  ## 'false'... because this is bash. Oh yay!
116  return 1;
117}
118
119check_for_add_to_manifestv2() {
120  add_if_not_file_chk="$1"
121
122  if [ `basename $add_if_not_file_chk` = "update-settings.ini" ]; then
123    ## "true" *giggle*
124    return 0;
125  fi
126  ## 'false'... because this is bash. Oh yay!
127  return 1;
128}
129
130make_add_if_not_instruction() {
131  f="$1"
132  filev3="$2"
133
134  verbose_notice " add-if-not \"$f\" \"$f\""
135  echo "add-if-not \"$f\" \"$f\"" >> "$filev3"
136}
137
138make_patch_instruction() {
139  f="$1"
140  filev2="$2"
141  filev3="$3"
142
143  is_extension=$(echo "$f" | grep -c 'distribution/extensions/.*/')
144  if [ $is_extension = "1" ]; then
145    # Use the subdirectory of the extensions folder as the file to test
146    # before performing this add instruction.
147    testdir=$(echo "$f" | sed 's/\(.*distribution\/extensions\/[^\/]*\)\/.*/\1/')
148    verbose_notice "   patch-if \"$testdir\" \"$f.patch\" \"$f\""
149    echo "patch-if \"$testdir\" \"$f.patch\" \"$f\"" >> "$filev2"
150    echo "patch-if \"$testdir\" \"$f.patch\" \"$f\"" >> "$filev3"
151  else
152    verbose_notice "      patch \"$f.patch\" \"$f\""
153    echo "patch \"$f.patch\" \"$f\"" >> "$filev2"
154    echo "patch \"$f.patch\" \"$f\"" >> "$filev3"
155  fi
156}
157
158append_remove_instructions() {
159  dir="$1"
160  filev2="$2"
161  filev3="$3"
162
163  if [ -f "$dir/removed-files" ]; then
164    listfile="$dir/removed-files"
165  elif [ -f "$dir/Contents/Resources/removed-files" ]; then
166    listfile="$dir/Contents/Resources/removed-files"
167  fi
168  if [ -n "$listfile" ]; then
169    # Map spaces to pipes so that we correctly handle filenames with spaces.
170    files=($(cat "$listfile" | tr " " "|"  | sort -r))
171    num_files=${#files[*]}
172    for ((i=0; $i<$num_files; i=$i+1)); do
173      # Map pipes back to whitespace and remove carriage returns
174      f=$(echo ${files[$i]} | tr "|" " " | tr -d '\r')
175      # Trim whitespace
176      f=$(echo $f)
177      # Exclude blank lines.
178      if [ -n "$f" ]; then
179        # Exclude comments
180        if [ ! $(echo "$f" | grep -c '^#') = 1 ]; then
181          if [ $(echo "$f" | grep -c '\/$') = 1 ]; then
182            verbose_notice "      rmdir \"$f\""
183            echo "rmdir \"$f\"" >> "$filev2"
184            echo "rmdir \"$f\"" >> "$filev3"
185          elif [ $(echo "$f" | grep -c '\/\*$') = 1 ]; then
186            # Remove the *
187            f=$(echo "$f" | sed -e 's:\*$::')
188            verbose_notice "    rmrfdir \"$f\""
189            echo "rmrfdir \"$f\"" >> "$filev2"
190            echo "rmrfdir \"$f\"" >> "$filev3"
191          else
192            verbose_notice "     remove \"$f\""
193            echo "remove \"$f\"" >> "$filev2"
194            echo "remove \"$f\"" >> "$filev3"
195          fi
196        fi
197      fi
198    done
199  fi
200}
201
202# List all files in the current directory, stripping leading "./"
203# Pass a variable name and it will be filled as an array.
204list_files() {
205  count=0
206  temp_filelist=$(mktemp)
207  find . -type f \
208    ! -name "update.manifest" \
209    ! -name "updatev2.manifest" \
210    ! -name "updatev3.manifest" \
211    | sed 's/\.\/\(.*\)/\1/' \
212    | sort -r > "${temp_filelist}"
213  while read file; do
214    eval "${1}[$count]=\"$file\""
215    (( count++ ))
216  done < "${temp_filelist}"
217  rm "${temp_filelist}"
218}
219
220# List all directories in the current directory, stripping leading "./"
221list_dirs() {
222  count=0
223  temp_dirlist=$(mktemp)
224  find . -type d \
225    ! -name "." \
226    ! -name ".." \
227    | sed 's/\.\/\(.*\)/\1/' \
228    | sort -r > "${temp_dirlist}"
229  while read dir; do
230    eval "${1}[$count]=\"$dir\""
231    (( count++ ))
232  done < "${temp_dirlist}"
233  rm "${temp_dirlist}"
234}
235