1#!/bin/sh
2#
3# A small script used to update the content of libcxx/ to a newer
4# version of libc++.
5#
6
7PROGDIR=$(dirname "$0")
8PROGNAME=$(basename "$0")
9
10# Assume this script is under tools/
11NDK_LIBCXX_DIR=$(cd "$PROGDIR"/.. && pwd)
12
13# Sanitize environment.
14set -e
15export LANG=C
16export LC_ALL=C
17
18# Helper functions
19VERBOSE=1
20
21run () {
22  if [ "$VERBOSE" -gt 1 ]; then
23    echo "COMMAND: $@"
24  fi
25  case $VERBOSE in
26    0|1)
27        "$@" >/dev/null 2>&1
28        ;;
29    2)
30        "$@" >/dev/null
31        ;;
32    *)
33        "$@"
34        ;;
35  esac
36}
37
38log () {
39  if [ "$VERBOSE" -gt 1 ]; then
40    printf "%s\n" "$@"
41  fi
42}
43
44get_config_field () {
45  cat "$NDK_LIBCXX_DIR"/upstream.config | awk '$1 == "'$1':" { print $2; }'
46}
47
48# Process command line.
49
50DO_HELP=
51NO_CLEANUP=
52
53for opt; do
54  case $opt in
55    --verbose)
56      VERBOSE=$(( $VERBOSE + 1 ))
57      ;;
58    --help)
59      DO_HELP=true
60      ;;
61    --no-cleanup)
62      NO_CLEANUP=true
63      ;;
64    -*)
65      echo "ERROR: Unknown option '$opt'. See --help."
66      exit 1
67      ;;
68  esac
69done
70
71if [ "$DO_HELP" ]; then
72    echo "Usage: $PROGNAME [options]"
73    echo ""
74    echo "This script is used to update the LLVM libc++ sources to a"
75    echo "more recent version."
76    echo ""
77    echo "Valid options:"
78    echo "   --help        Print this message."
79    echo "   --verbose     Increase verbosity."
80    echo "   --no-cleanup  Don't remove build directory on exit."
81    echo ""
82    exit 0
83fi
84
85# Create build directory.
86BUILD_DIR=/tmp/ndk-$USER/llvm-libc++/build
87mkdir -p "$BUILD_DIR" && rm -rf "$BUILD_DIR"/*
88
89# Ensure it is cleared when this script exits.
90run_on_exit () {
91  if [ -z "$NO_CLEANUP" ]; then
92    # Remove temporary build directory.
93    rm -rf "$BUILD_DIR"
94  fi
95}
96trap "run_on_exit \$?" EXIT QUIT HUP TERM INT
97
98# Get upstream SVN and revision number.
99SVN_URL=$(get_config_field svn)
100if [ -z "$SVN_URL" ]; then
101  echo "ERROR: Can't find SVN upstream in upstream.config!"
102  exit 1
103fi
104
105REVISION=$(get_config_field revision)
106if [ -z "$REVISION" ]; then
107  echo "ERROR: Can't find upstream revision in upstream.config!"
108  exit 1
109fi
110
111run cd $BUILD_DIR &&
112echo "Checking out $SVN_URL@$REVISION"
113run svn co $SVN_URL@$REVISION libcxx > /dev/null
114run cd libcxx
115
116echo "Creating git repository and 'master' branch."
117run git init
118echo \
119".gitignore
120.svn/
121" > .gitignore
122
123run git add .
124run git add -f .gitignore
125run git commit -m "upstream @$REVISION"
126
127echo "Create 'ndk' branch and apply patches.android/*"
128run git branch ndk master
129run git checkout ndk
130if [ -d "$NDK_LIBCXX_DIR/patches.android" ]; then
131  (
132    set +e;
133    run git am "$NDK_LIBCXX_DIR"/patches.android/*
134    if [ "$?" != 0 ]; then
135      echo "A problem occured while applying the patches!!"
136      exit 1
137    fi
138  )
139fi
140
141echo "Updating to newer upstream revision"
142run git checkout master
143run git tag revision-$REVISION HEAD
144
145run svn update
146NEW_REVISION=$(svn info | awk '$1 == "Revision:" { print $2; }')
147echo "Found new revision: $NEW_REVISION (was $REVISION)"
148
149ADDED_FILES=$(git ls-files -o --exclude-standard)
150MODIFIED_FILES=$(git ls-files -m)
151REMOVED_FILES=$(git ls-files -d)
152log "ADDED_FILES='$ADDED_FILES'"
153log "MODIFIED_FILES='$MODIFIED_FILES'"
154log "REMOVED_FILES='$REMOVED_FILES'"
155CHANGED=
156if [ -n "$ADDED_FILES" ]; then
157  run git add $ADDED_FILES
158  CHANGED=true
159fi
160if [ -n "$MODIFIED_FILES" ]; then
161  run git add $MODIFIED_FILES
162  CHANGED=true
163fi
164if [ -n "$REMOVED_FILES" ]; then
165  run git rm -f $REMOVED_FILES
166  CHANGED=true
167fi
168
169if [ -z "$CHANGED" ]; then
170  echo "No changes detected. Exiting."
171  exit 0
172fi
173
174ADDED_COUNT=$(echo "$ADDED_FILES" | wc -l)
175MODIFIED_COUNT=$(echo "$MODIFIED_FILES" | wc -l)
176REMOVED_COUNT=$(echo "$REMOVED_FILES" | wc -l)
177echo "Commiting changes ($ADDED_COUNT new, $MODIFIED_COUNT changed, $REMOVED_COUNT deleted)"
178run git commit -m "upstream @$NEW_REVISION"
179run git tag revision-$NEW_REVISION
180
181echo "Updating NDK branch."
182run git checkout ndk
183run git tag android-0 HEAD
184run git rebase revision-$NEW_REVISION
185
186echo "Re-creating new Android patches."
187run git format-patch -k -o "$BUILD_DIR"/patches.android revision-$NEW_REVISION
188run git format-patch -k -o "$BUILD_DIR"/patches.libcxx android-0
189
190echo "Updating local sources"
191run cd "$NDK_LIBCXX_DIR"/libcxx
192for PATCH in "$BUILD_DIR"/patches.libcxx/*.patch; do
193  (
194    set +e
195    run patch -p1 < "$PATCH"
196    if [ $? != 0 ]; then
197      echo "ERROR: Can't apply $PATCH properly!"
198      exit 1
199    fi
200  )
201done
202
203echo "Updating local patches"
204run cd "$NDK_LIBCXX_DIR"
205run git rm -f patches.android/*
206run cp "$BUILD_DIR"/patches.android/* patches.android/
207run git add patches.android/*
208
209echo "Updating upstream.config"
210sed -i -e "s|revision: $REVISION|revision: $NEW_REVISION|" "$NDK_LIBCXX_DIR"/upstream.config
211git add "$NDK_LIBCXX_DIR"/upstream.config
212
213echo "Done updating to $NEW_REVISION."
214