blob: 677be5a7f8e1110cf51796f4b47e4a3b51717e61 [file] [log] [blame]
Jeff Gaston043d21f2019-03-20 14:53:42 -04001#!/bin/bash
2#
3# Copyright (C) 2019 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17set -e
18
19supportRoot="$(cd $(dirname $0)/.. && pwd)"
20checkoutRoot="$(cd ${supportRoot}/../.. && pwd)"
21
Jeff Gastonfd450352020-01-31 16:39:32 -050022function die() {
23 echo "$@" >&2
24 exit 1
25}
26
Jeff Gaston043d21f2019-03-20 14:53:42 -040027function usage() {
Jeff Gastonfd450352020-01-31 16:39:32 -050028 violation="$1"
29 die "
30 Usage: $0 <git treeish>
31 $0 <path>:<git treeish> <path>:<git treeish>
32
33 Validates that libraries built from the given versions are the same as
34 the build outputs built at HEAD. This can be used to validate that a refactor
35 did not change the outputs. If a git treeish is given with no path, the path is considered to be frameworks/support
36
37 Example: $0 HEAD^
38 Example: $0 prebuilts/androidx/external:HEAD^ frameworks/support:work^
39
40 * A git treeish is what you type when you run 'git checkout <git treeish>'
41 See also https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish .
42 "
Jeff Gaston043d21f2019-03-20 14:53:42 -040043 return 1
44}
45
Jeff Gastonfd450352020-01-31 16:39:32 -050046# Fills in a default repository path of "frameworks/support:" for any args that don't specify
47# their repository. Given an input of: "work^ prebuilts/androidx/external:HEAD^", should return
48# "frameworks/support:work^ prebuilts/androidx/external:HEAD^".
49function expandCommitArgs() {
50 inputSpecs="$@"
51 outputSpecs=""
52 for spec in $inputSpecs; do
53 if echo "$spec" | grep -v ":" >/dev/null; then
54 spec="frameworks/support:$spec"
55 fi
56 outputSpecs="$outputSpecs $spec"
57 done
58 echo $outputSpecs
59}
60
61# Given a list of paths like "frameworks/support prebuilts/androidx/external",
62# runs `git checkout -` in each
63function uncheckout() {
64 repositoryPaths="$@"
65 for repositoryPath in $repositoryPaths; do
66 echoAndDo git -C "$checkoutRoot/$repositoryPath" checkout -
67 done
68}
69# Given a list of version specs like "a/b:c d/e:f", returns just the paths: "a/b d/e"
70function getParticipatingProjectPaths() {
71 specs="$@"
72 result=""
73 for arg in $specs; do
74 echo parsing $arg >&2
75 repositoryPath="$(echo $arg | sed 's|\([^:]*\):\([^:]*\)|\1|')"
76 otherVersion="$(echo $arg | sed 's|\([^:]*\):\([^:]*\)|\2|')"
77 if [ "$otherVersion" != "HEAD" ]; then
78 result="$result $repositoryPath"
79 fi
80 done
81 echo $result
82}
83# Given a list of paths, returns a string containing the currently checked-out version of each
84function getCurrentCommits() {
85 repositoryPaths="$@"
86 result=""
87 for repositoryPath in $repositoryPaths; do
88 currentVersion="$(cd $checkoutRoot/$repositoryPath && git log -1 --format=%H)"
89 result="$result $repositoryPath:$currentVersion"
90 done
91 echo $result
92}
93function echoAndDo() {
94 echo "$*"
95 eval "$*"
96}
97# Given a list of version specs like "a/b:c d/e:f", checks out the appropriate version in each
98# In this example it would be `cd a/b && git checkout e` and `cd e/e && git checkout f`
99function checkout() {
100 versionSpecs="$1"
101 for versionSpec in $versionSpecs; do
102 project="$(echo $versionSpec | sed 's|\([^:]*\):\([^:]*\)|\1|')"
103 ref="$(echo $versionSpec | sed 's|\([^:]*\):\([^:]*\)|\2|')"
104 echo "checking out $ref in project $project"
105 echoAndDo git -C "$checkoutRoot/$project" checkout "$ref"
106 done
107}
108function doBuild() {
Jeff Gaston6c1c2ec2020-07-01 14:11:43 -0400109 # build androidx
Jeff Gaston04bf7de2020-02-13 19:21:09 -0500110 echoAndDo ./gradlew createArchive generateDocs --no-daemon --rerun-tasks --offline
Jeff Gastonf2c5b702020-01-31 16:57:31 -0500111 archiveName="top-of-tree-m2repository-all-0.zip"
112 echoAndDo unzip -q "${tempOutPath}/dist/${archiveName}" -d "${tempOutPath}/dist/${archiveName}.unzipped"
Jeff Gastonfd450352020-01-31 16:39:32 -0500113}
114
115oldCommits="$(expandCommitArgs $@)"
116projectPaths="$(getParticipatingProjectPaths $oldCommits)"
Jeff Gastonbcf56d62020-02-14 17:37:52 -0500117if echo $projectPaths | grep external/dokka >/dev/null; then
118 if [ "$BUILD_DOKKA" == "" ]; then
119 echo "It doesn't make sense to include the external/dokka project without also setting BUILD_DOKKA=true. Did you mean to set BUILD_DOKKA=true?"
120 exit 1
121 fi
122fi
Jeff Gastonfd450352020-01-31 16:39:32 -0500123echo old commits: $oldCommits
124if [ "$oldCommits" == "" ]; then
Jeff Gaston043d21f2019-03-20 14:53:42 -0400125 usage
126fi
Jeff Gastonfd450352020-01-31 16:39:32 -0500127newCommits="$(getCurrentCommits $projectPaths)"
Jeff Gaston6c1c2ec2020-07-01 14:11:43 -0400128cd "$supportRoot"
Jeff Gastonfd450352020-01-31 16:39:32 -0500129echo new commits: $newCommits
Jeff Gaston043d21f2019-03-20 14:53:42 -0400130
131oldOutPath="${checkoutRoot}/out-old"
132newOutPath="${checkoutRoot}/out-new"
133tempOutPath="${checkoutRoot}/out"
134
Jeff Gaston043d21f2019-03-20 14:53:42 -0400135
136rm -rf "$oldOutPath" "$newOutPath" "$tempOutPath"
137
138echo building new commit
Jeff Gaston043d21f2019-03-20 14:53:42 -0400139doBuild
140mv "$tempOutPath" "$newOutPath"
141
Jeff Gaston043d21f2019-03-20 14:53:42 -0400142echo building previous commit
Jeff Gastonfd450352020-01-31 16:39:32 -0500143
144checkout "$oldCommits"
Jeff Gaston043d21f2019-03-20 14:53:42 -0400145if doBuild; then
146 echo previous build succeeded
147else
148 echo previous build failed
Jeff Gastonfd450352020-01-31 16:39:32 -0500149 uncheckout "$projectPaths"
Jeff Gaston043d21f2019-03-20 14:53:42 -0400150 exit 1
151fi
Jeff Gastonfd450352020-01-31 16:39:32 -0500152uncheckout "$projectPaths"
Jeff Gaston043d21f2019-03-20 14:53:42 -0400153mv "$tempOutPath" "$oldOutPath"
154
155echo
156echo diffing results
157# Don't care about maven-metadata files because they have timestamps in them
158# We might care to know whether .sha1 or .md5 files have changed, but changes in those files will always be accompanied by more meaningful changes in other files, so we don't need to show changes in .sha1 or .md5 files
Jeff Gastonf2c5b702020-01-31 16:57:31 -0500159# We also don't care about several specific files, either
Jeff Gaston6c1c2ec2020-07-01 14:11:43 -0400160echoAndDo diff -r -x "*.md5*" -x "*.sha*" -x "*maven-metadata.xml" -x buildSrc.jar -x jetifier-standalone.zip -x jetpad-integration.jar -x "top-of-tree-m2repository-all-0.zip" -x noto-emoji-compat-java.jar -x versionedparcelable-annotation.jar -x dokkaTipOfTreeDocs-0.zip -x fakeannotations.jar -x "doclava*.jar" "$oldOutPath/dist" "$newOutPath/dist"
Jeff Gaston043d21f2019-03-20 14:53:42 -0400161echo end of difference