Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # Copyright (C) 2020 The Android Open Source Project |
| 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # See the License for the specific language governing permissions and |
| 14 | # limitations under the License. |
| 15 | |
| 16 | # Exports AppSearch Androidx code to Framework |
| 17 | # |
| 18 | # NOTE: This will remove and replace all files in the |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 19 | # packages/modules/AppSearch path. |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 20 | # |
| 21 | # Example usage (from root dir of androidx workspace): |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 22 | # $ ./frameworks/support/appsearch/exportToFramework.py "$HOME/android/master" "<jetpack git sha>" |
Alexander Dorokhine | f5f7888 | 2021-04-29 12:12:06 -0700 | [diff] [blame] | 23 | |
| 24 | # Special directives supported by this script: |
| 25 | # |
| 26 | # Causes the file where it appears to not be copied at all: |
| 27 | # @exportToFramework:skipFile() |
| 28 | # |
| 29 | # Causes the text appearing between startStrip() and endStrip() to be removed during export: |
| 30 | # // @exportToFramework:startStrip() ... // @exportToFramework:endStrip() |
| 31 | # |
| 32 | # Replaced with @hide: |
| 33 | # <!--@exportToFramework:hide--> |
| 34 | # |
| 35 | # Replaced with @CurrentTimeMillisLong: |
| 36 | # /*@exportToFramework:CurrentTimeMillisLong*/ |
| 37 | # |
| 38 | # Removes the text appearing between ifJetpack() and else(), and causes the text appearing between |
| 39 | # else() and --> to become uncommented, to support framework-only Javadocs: |
| 40 | # <!--@exportToFramework:ifJetpack()--> |
| 41 | # Jetpack-only Javadoc |
| 42 | # <!--@exportToFramework:else() |
| 43 | # Framework-only Javadoc |
| 44 | # --> |
| 45 | # Note: Using the above pattern, you can hide a method in Jetpack but unhide it in Framework like |
| 46 | # this: |
| 47 | # <!--@exportToFramework:ifJetpack()-->@hide<!--@exportToFramework:else()--> |
| 48 | |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 49 | import os |
| 50 | import re |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 51 | import subprocess |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 52 | import sys |
| 53 | |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 54 | # Jetpack paths relative to frameworks/support/appsearch |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 55 | JETPACK_API_ROOT = 'appsearch/src/main/java/androidx/appsearch' |
Alexander Dorokhine | a70da60 | 2020-09-22 03:34:44 -0700 | [diff] [blame] | 56 | JETPACK_API_TEST_ROOT = 'appsearch/src/androidTest/java/androidx/appsearch' |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 57 | JETPACK_IMPL_ROOT = 'appsearch-local-storage/src/main/java/androidx/appsearch' |
| 58 | JETPACK_IMPL_TEST_ROOT = 'appsearch-local-storage/src/androidTest/java/androidx/appsearch' |
| 59 | JETPACK_TEST_UTIL_ROOT = 'appsearch-test-util/src/main/java/androidx/appsearch' |
| 60 | JETPACK_TEST_UTIL_TEST_ROOT = 'appsearch-test-util/src/androidTest/java/androidx/appsearch' |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 61 | |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 62 | # Framework paths relative to packages/modules/AppSearch |
Alexander Dorokhine | 20d1f2d | 2020-12-04 00:37:27 -0800 | [diff] [blame] | 63 | FRAMEWORK_API_ROOT = 'framework/java/external/android/app/appsearch' |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 64 | FRAMEWORK_API_TEST_ROOT = 'testing/coretests/src/android/app/appsearch/external' |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 65 | FRAMEWORK_IMPL_ROOT = 'service/java/com/android/server/appsearch/external' |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 66 | FRAMEWORK_IMPL_TEST_ROOT = 'testing/servicestests/src/com/android/server/appsearch/external' |
| 67 | FRAMEWORK_TEST_UTIL_ROOT = 'testing/testutils/src/android/app/appsearch/testutil/external' |
| 68 | FRAMEWORK_TEST_UTIL_TEST_ROOT = 'testing/servicestests/src/android/app/appsearch/testutil/external' |
| 69 | FRAMEWORK_CTS_TEST_ROOT = '../../../cts/tests/appsearch/src/com/android/cts/appsearch/external' |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 70 | GOOGLE_JAVA_FORMAT = ( |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 71 | '../../../prebuilts/tools/common/google-java-format/google-java-format') |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 72 | |
| 73 | # Miscellaneous constants |
Alexander Dorokhine | fe6e1b4 | 2022-03-02 21:57:13 -0800 | [diff] [blame] | 74 | SHA_FILE_NAME = 'synced_jetpack_sha.txt' |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 75 | |
| 76 | |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 77 | class ExportToFramework: |
| 78 | def __init__(self, jetpack_appsearch_root, framework_appsearch_root): |
| 79 | self._jetpack_appsearch_root = jetpack_appsearch_root |
| 80 | self._framework_appsearch_root = framework_appsearch_root |
Alexander Dorokhine | aaa6e81c | 2021-04-19 23:26:43 -0700 | [diff] [blame] | 81 | self._written_files = [] |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 82 | |
Alexander Dorokhine | 20d1f2d | 2020-12-04 00:37:27 -0800 | [diff] [blame] | 83 | def _PruneDir(self, dir_to_prune): |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 84 | for walk_path, walk_folders, walk_files in os.walk(dir_to_prune): |
| 85 | for walk_filename in walk_files: |
| 86 | abs_path = os.path.join(walk_path, walk_filename) |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 87 | print('Prune: remove "%s"' % abs_path) |
| 88 | os.remove(abs_path) |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 89 | |
Alexander Dorokhine | 968bbd3 | 2020-12-30 02:06:11 -0800 | [diff] [blame] | 90 | def _TransformAndCopyFile( |
| 91 | self, source_path, dest_path, transform_func=None, ignore_skips=False): |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 92 | with open(source_path, 'r') as fh: |
| 93 | contents = fh.read() |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 94 | |
Alexander Dorokhine | 968bbd3 | 2020-12-30 02:06:11 -0800 | [diff] [blame] | 95 | if not ignore_skips and '@exportToFramework:skipFile()' in contents: |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 96 | print('Skipping: "%s" -> "%s"' % (source_path, dest_path), file=sys.stderr) |
| 97 | return |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 98 | |
Alexander Dorokhine | 3f4deb2 | 2022-03-17 12:45:30 -0700 | [diff] [blame] | 99 | copyToPath = re.search(r'@exportToFramework:copyToPath\(([^)]+)\)', contents) |
| 100 | if copyToPath: |
| 101 | dest_path = os.path.join(self._framework_appsearch_root, copyToPath.group(1)) |
| 102 | |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 103 | print('Copy: "%s" -> "%s"' % (source_path, dest_path), file=sys.stderr) |
| 104 | if transform_func: |
| 105 | contents = transform_func(contents) |
| 106 | os.makedirs(os.path.dirname(dest_path), exist_ok=True) |
| 107 | with open(dest_path, 'w') as fh: |
| 108 | fh.write(contents) |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 109 | |
Alexander Dorokhine | aaa6e81c | 2021-04-19 23:26:43 -0700 | [diff] [blame] | 110 | # Save file for future formatting |
| 111 | self._written_files.append(dest_path) |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 112 | |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 113 | def _TransformCommonCode(self, contents): |
Alexander Dorokhine | aaa6e81c | 2021-04-19 23:26:43 -0700 | [diff] [blame] | 114 | # Apply stripping |
Alexander Dorokhine | ebd84fe | 2020-12-30 01:19:03 -0800 | [diff] [blame] | 115 | contents = re.sub( |
Alexander Dorokhine | f5f7888 | 2021-04-29 12:12:06 -0700 | [diff] [blame] | 116 | r'\/\/ @exportToFramework:startStrip\(\).*?\/\/ @exportToFramework:endStrip\(\)', |
| 117 | '', |
| 118 | contents, |
| 119 | flags=re.DOTALL) |
| 120 | |
| 121 | # Apply if/elses in javadocs |
| 122 | contents = re.sub( |
| 123 | r'<!--@exportToFramework:ifJetpack\(\)-->.*?<!--@exportToFramework:else\(\)(.*?)-->', |
| 124 | r'\1', |
| 125 | contents, |
| 126 | flags=re.DOTALL) |
Alexander Dorokhine | aaa6e81c | 2021-04-19 23:26:43 -0700 | [diff] [blame] | 127 | |
| 128 | # Add additional imports if required |
| 129 | imports_to_add = [] |
| 130 | if '@exportToFramework:CurrentTimeMillisLong' in contents: |
| 131 | imports_to_add.append('android.annotation.CurrentTimeMillisLong') |
Alexander Dorokhine | e51b4b0 | 2021-05-04 11:15:07 -0700 | [diff] [blame] | 132 | if '@exportToFramework:UnsupportedAppUsage' in contents: |
| 133 | imports_to_add.append('android.compat.annotation.UnsupportedAppUsage') |
Alexander Dorokhine | aaa6e81c | 2021-04-19 23:26:43 -0700 | [diff] [blame] | 134 | for import_to_add in imports_to_add: |
| 135 | contents = re.sub( |
| 136 | r'^(\s*package [^;]+;\s*)$', r'\1\nimport %s;\n' % import_to_add, contents, |
| 137 | flags=re.MULTILINE) |
| 138 | |
| 139 | # Apply in-place replacements |
Alexander Dorokhine | fe6e1b4 | 2022-03-02 21:57:13 -0800 | [diff] [blame] | 140 | contents = (contents |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 141 | .replace('androidx.appsearch.app', 'android.app.appsearch') |
| 142 | .replace( |
| 143 | 'androidx.appsearch.localstorage.', |
| 144 | 'com.android.server.appsearch.external.localstorage.') |
| 145 | .replace('androidx.appsearch', 'android.app.appsearch') |
| 146 | .replace( |
| 147 | 'androidx.annotation.GuardedBy', |
| 148 | 'com.android.internal.annotations.GuardedBy') |
| 149 | .replace( |
| 150 | 'androidx.annotation.VisibleForTesting', |
| 151 | 'com.android.internal.annotations.VisibleForTesting') |
Alexander Dorokhine | ebd84fe | 2020-12-30 01:19:03 -0800 | [diff] [blame] | 152 | .replace('androidx.annotation.', 'android.annotation.') |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 153 | .replace('androidx.collection.ArrayMap', 'android.util.ArrayMap') |
| 154 | .replace('androidx.collection.ArraySet', 'android.util.ArraySet') |
| 155 | .replace( |
| 156 | 'androidx.core.util.ObjectsCompat', |
| 157 | 'java.util.Objects') |
Alexander Dorokhine | 9961ca4 | 2021-04-02 15:28:08 -0700 | [diff] [blame] | 158 | # Preconditions.checkNotNull is replaced with Objects.requireNonNull. We add both |
| 159 | # imports and let google-java-format sort out which one is unused. |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 160 | .replace( |
Alexander Dorokhine | 9961ca4 | 2021-04-02 15:28:08 -0700 | [diff] [blame] | 161 | 'import androidx.core.util.Preconditions;', |
| 162 | 'import java.util.Objects; import com.android.internal.util.Preconditions;') |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 163 | .replace('import androidx.annotation.RestrictTo;', '') |
Alexander Dorokhine | ebd84fe | 2020-12-30 01:19:03 -0800 | [diff] [blame] | 164 | .replace('@RestrictTo(RestrictTo.Scope.LIBRARY)', '') |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 165 | .replace('@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)', '') |
Alexander Dorokhine | 9961ca4 | 2021-04-02 15:28:08 -0700 | [diff] [blame] | 166 | .replace('Preconditions.checkNotNull(', 'Objects.requireNonNull(') |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 167 | .replace('ObjectsCompat.', 'Objects.') |
Alexander Dorokhine | fe6e1b4 | 2022-03-02 21:57:13 -0800 | [diff] [blame] | 168 | |
Alexander Dorokhine | aaa6e81c | 2021-04-19 23:26:43 -0700 | [diff] [blame] | 169 | .replace('/*@exportToFramework:CurrentTimeMillisLong*/', '@CurrentTimeMillisLong') |
Alexander Dorokhine | e51b4b0 | 2021-05-04 11:15:07 -0700 | [diff] [blame] | 170 | .replace('/*@exportToFramework:UnsupportedAppUsage*/', '@UnsupportedAppUsage') |
Alexander Dorokhine | f5f7888 | 2021-04-29 12:12:06 -0700 | [diff] [blame] | 171 | .replace('<!--@exportToFramework:hide-->', '@hide') |
Alexander Dorokhine | 968bbd3 | 2020-12-30 02:06:11 -0800 | [diff] [blame] | 172 | .replace('// @exportToFramework:skipFile()', '') |
Alexander Dorokhine | a70da60 | 2020-09-22 03:34:44 -0700 | [diff] [blame] | 173 | ) |
Alexander Dorokhine | 3f4deb2 | 2022-03-17 12:45:30 -0700 | [diff] [blame] | 174 | contents = re.sub(r'\/\/ @exportToFramework:copyToPath\([^)]+\)', '', contents) |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 175 | |
Alexander Dorokhine | fe6e1b4 | 2022-03-02 21:57:13 -0800 | [diff] [blame] | 176 | # Jetpack methods have the Async suffix, but framework doesn't. Strip the Async suffix |
| 177 | # to allow the same documentation to compile for both. |
| 178 | contents = re.sub(r'(#[a-zA-Z0-9_]+)Async}', r'\1}', contents) |
Alexander Dorokhine | fff89ed | 2022-03-15 23:16:10 -0700 | [diff] [blame] | 179 | contents = re.sub( |
| 180 | r'(\@see [^#]+#[a-zA-Z0-9_]+)Async$', r'\1', contents, flags=re.MULTILINE) |
Alexander Dorokhine | fe6e1b4 | 2022-03-02 21:57:13 -0800 | [diff] [blame] | 181 | return contents |
| 182 | |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 183 | def _TransformTestCode(self, contents): |
Alexander Dorokhine | a70da60 | 2020-09-22 03:34:44 -0700 | [diff] [blame] | 184 | contents = (contents |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 185 | .replace('androidx.appsearch.testutil.', 'android.app.appsearch.testutil.') |
Alexander Dorokhine | ebd84fe | 2020-12-30 01:19:03 -0800 | [diff] [blame] | 186 | .replace( |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 187 | 'package androidx.appsearch.testutil;', |
| 188 | 'package android.app.appsearch.testutil;') |
Alexander Dorokhine | ebd84fe | 2020-12-30 01:19:03 -0800 | [diff] [blame] | 189 | .replace( |
Alexander Dorokhine | b73353c | 2021-01-06 01:16:18 -0800 | [diff] [blame] | 190 | 'androidx.appsearch.localstorage.LocalStorage', |
| 191 | 'android.app.appsearch.AppSearchManager') |
Alexander Dorokhine | ebd84fe | 2020-12-30 01:19:03 -0800 | [diff] [blame] | 192 | .replace('LocalStorage.', 'AppSearchManager.') |
Alexander Dorokhine | a70da60 | 2020-09-22 03:34:44 -0700 | [diff] [blame] | 193 | ) |
Alexander Dorokhine | b73353c | 2021-01-06 01:16:18 -0800 | [diff] [blame] | 194 | for shim in ['AppSearchSession', 'GlobalSearchSession', 'SearchResults']: |
| 195 | contents = re.sub(r"([^a-zA-Z])(%s)([^a-zA-Z0-9])" % shim, r'\1\2Shim\3', contents) |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 196 | return self._TransformCommonCode(contents) |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 197 | |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 198 | def _TransformAndCopyFolder(self, source_dir, dest_dir, transform_func=None): |
| 199 | for currentpath, folders, files in os.walk(source_dir): |
| 200 | dir_rel_to_root = os.path.relpath(currentpath, source_dir) |
| 201 | for filename in files: |
| 202 | source_abs_path = os.path.join(currentpath, filename) |
| 203 | dest_path = os.path.join(dest_dir, dir_rel_to_root, filename) |
| 204 | self._TransformAndCopyFile(source_abs_path, dest_path, transform_func) |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 205 | |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 206 | def _ExportApiCode(self): |
Alexander Dorokhine | 2463600 | 2020-12-16 02:44:29 -0800 | [diff] [blame] | 207 | # Prod source |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 208 | api_source_dir = os.path.join(self._jetpack_appsearch_root, JETPACK_API_ROOT) |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 209 | api_dest_dir = os.path.join(self._framework_appsearch_root, FRAMEWORK_API_ROOT) |
Alexander Dorokhine | 2463600 | 2020-12-16 02:44:29 -0800 | [diff] [blame] | 210 | |
| 211 | # Unit tests |
| 212 | api_test_source_dir = os.path.join(self._jetpack_appsearch_root, JETPACK_API_TEST_ROOT) |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 213 | api_test_dest_dir = os.path.join(self._framework_appsearch_root, FRAMEWORK_API_TEST_ROOT) |
Alexander Dorokhine | 4939496 | 2020-11-17 03:04:42 -0800 | [diff] [blame] | 214 | |
Alexander Dorokhine | 2463600 | 2020-12-16 02:44:29 -0800 | [diff] [blame] | 215 | # CTS tests |
Alexander Dorokhine | 8b61217 | 2021-05-10 15:51:47 -0700 | [diff] [blame] | 216 | cts_test_source_dir = os.path.join(api_test_source_dir, 'cts') |
Alexander Dorokhine | 2463600 | 2020-12-16 02:44:29 -0800 | [diff] [blame] | 217 | cts_test_dest_dir = os.path.join(self._framework_appsearch_root, FRAMEWORK_CTS_TEST_ROOT) |
| 218 | |
| 219 | # Test utils |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 220 | test_util_source_dir = os.path.join(self._jetpack_appsearch_root, JETPACK_TEST_UTIL_ROOT) |
Alexander Dorokhine | 2463600 | 2020-12-16 02:44:29 -0800 | [diff] [blame] | 221 | test_util_dest_dir = os.path.join(self._framework_appsearch_root, FRAMEWORK_TEST_UTIL_ROOT) |
| 222 | |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 223 | # Prune existing files |
Alexander Dorokhine | 20d1f2d | 2020-12-04 00:37:27 -0800 | [diff] [blame] | 224 | self._PruneDir(api_dest_dir) |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 225 | self._PruneDir(api_test_dest_dir) |
Alexander Dorokhine | 2463600 | 2020-12-16 02:44:29 -0800 | [diff] [blame] | 226 | self._PruneDir(cts_test_dest_dir) |
| 227 | self._PruneDir(test_util_dest_dir) |
Alexander Dorokhine | 4939496 | 2020-11-17 03:04:42 -0800 | [diff] [blame] | 228 | |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 229 | # Copy api classes. We can't use _TransformAndCopyFolder here because we |
| 230 | # need to specially handle the 'app' package. |
Alexander Dorokhine | 2463600 | 2020-12-16 02:44:29 -0800 | [diff] [blame] | 231 | print('~~~ Copying API classes ~~~') |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 232 | def _TransformApiCode(contents): |
| 233 | contents = contents.replace( |
| 234 | 'package androidx.appsearch.app;', |
| 235 | 'package android.app.appsearch;') |
| 236 | return self._TransformCommonCode(contents) |
| 237 | for currentpath, folders, files in os.walk(api_source_dir): |
| 238 | dir_rel_to_root = os.path.relpath(currentpath, api_source_dir) |
| 239 | for filename in files: |
| 240 | # Figure out what folder to place them into |
| 241 | source_abs_path = os.path.join(currentpath, filename) |
| 242 | if dir_rel_to_root == 'app': |
| 243 | # Files in the 'app' folder live in the root of the platform tree |
| 244 | dest_path = os.path.join(api_dest_dir, filename) |
| 245 | else: |
| 246 | dest_path = os.path.join(api_dest_dir, dir_rel_to_root, filename) |
| 247 | self._TransformAndCopyFile(source_abs_path, dest_path, _TransformApiCode) |
Alexander Dorokhine | 4939496 | 2020-11-17 03:04:42 -0800 | [diff] [blame] | 248 | |
Alexander Dorokhine | 2463600 | 2020-12-16 02:44:29 -0800 | [diff] [blame] | 249 | # Copy api unit tests. We can't use _TransformAndCopyFolder here because we need to skip the |
| 250 | # 'util' and 'cts' subfolders. |
| 251 | print('~~~ Copying API unit tests ~~~') |
| 252 | for currentpath, folders, files in os.walk(api_test_source_dir): |
| 253 | if (currentpath.startswith(cts_test_source_dir) or |
| 254 | currentpath.startswith(test_util_source_dir)): |
| 255 | continue |
| 256 | dir_rel_to_root = os.path.relpath(currentpath, api_test_source_dir) |
| 257 | for filename in files: |
| 258 | source_abs_path = os.path.join(currentpath, filename) |
| 259 | dest_path = os.path.join(api_test_dest_dir, dir_rel_to_root, filename) |
| 260 | self._TransformAndCopyFile(source_abs_path, dest_path, self._TransformTestCode) |
| 261 | |
| 262 | # Copy CTS tests |
| 263 | print('~~~ Copying CTS tests ~~~') |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 264 | self._TransformAndCopyFolder( |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 265 | cts_test_source_dir, cts_test_dest_dir, transform_func=self._TransformTestCode) |
Alexander Dorokhine | 2463600 | 2020-12-16 02:44:29 -0800 | [diff] [blame] | 266 | |
| 267 | # Copy test utils |
| 268 | print('~~~ Copying test utils ~~~') |
| 269 | self._TransformAndCopyFolder( |
| 270 | test_util_source_dir, test_util_dest_dir, transform_func=self._TransformTestCode) |
Alexander Dorokhine | 968bbd3 | 2020-12-30 02:06:11 -0800 | [diff] [blame] | 271 | for iface_file in ( |
| 272 | 'AppSearchSession.java', 'GlobalSearchSession.java', 'SearchResults.java'): |
| 273 | dest_file_name = os.path.splitext(iface_file)[0] + 'Shim.java' |
| 274 | self._TransformAndCopyFile( |
| 275 | os.path.join(api_source_dir, 'app/' + iface_file), |
| 276 | os.path.join(test_util_dest_dir, dest_file_name), |
| 277 | transform_func=self._TransformTestCode, |
| 278 | ignore_skips=True) |
Alexander Dorokhine | 4939496 | 2020-11-17 03:04:42 -0800 | [diff] [blame] | 279 | |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 280 | def _ExportImplCode(self): |
| 281 | impl_source_dir = os.path.join(self._jetpack_appsearch_root, JETPACK_IMPL_ROOT) |
| 282 | impl_test_source_dir = os.path.join(self._jetpack_appsearch_root, JETPACK_IMPL_TEST_ROOT) |
| 283 | impl_dest_dir = os.path.join(self._framework_appsearch_root, FRAMEWORK_IMPL_ROOT) |
| 284 | impl_test_dest_dir = os.path.join(self._framework_appsearch_root, FRAMEWORK_IMPL_TEST_ROOT) |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 285 | test_util_test_source_dir = os.path.join( |
| 286 | self._jetpack_appsearch_root, JETPACK_TEST_UTIL_TEST_ROOT) |
| 287 | test_util_test_dest_dir = os.path.join( |
| 288 | self._framework_appsearch_root, FRAMEWORK_TEST_UTIL_TEST_ROOT) |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 289 | |
| 290 | # Prune |
| 291 | self._PruneDir(impl_dest_dir) |
| 292 | self._PruneDir(impl_test_dest_dir) |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 293 | self._PruneDir(test_util_test_dest_dir) |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 294 | |
| 295 | # Copy impl classes |
| 296 | def _TransformImplCode(contents): |
| 297 | contents = (contents |
| 298 | .replace('package androidx.appsearch', |
| 299 | 'package com.android.server.appsearch.external') |
| 300 | .replace('com.google.android.icing.protobuf.', 'com.google.protobuf.') |
| 301 | ) |
| 302 | return self._TransformCommonCode(contents) |
| 303 | self._TransformAndCopyFolder( |
| 304 | impl_source_dir, impl_dest_dir, transform_func=_TransformImplCode) |
| 305 | |
| 306 | # Copy servicestests |
| 307 | def _TransformImplTestCode(contents): |
| 308 | contents = (contents |
| 309 | .replace('package androidx.appsearch', |
| 310 | 'package com.android.server.appsearch.external') |
| 311 | .replace('com.google.android.icing.proto.', |
Alexander Dorokhine | 004405e | 2021-06-28 23:04:30 -0700 | [diff] [blame] | 312 | 'com.android.server.appsearch.icing.proto.') |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 313 | .replace('com.google.android.icing.protobuf.', |
| 314 | 'com.android.server.appsearch.protobuf.') |
| 315 | ) |
| 316 | return self._TransformTestCode(contents) |
| 317 | self._TransformAndCopyFolder( |
| 318 | impl_test_source_dir, impl_test_dest_dir, transform_func=_TransformImplTestCode) |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 319 | self._TransformAndCopyFolder( |
| 320 | test_util_test_source_dir, |
| 321 | test_util_test_dest_dir, |
| 322 | transform_func=self._TransformTestCode) |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 323 | |
Alexander Dorokhine | aaa6e81c | 2021-04-19 23:26:43 -0700 | [diff] [blame] | 324 | def _FormatWrittenFiles(self): |
| 325 | google_java_format_cmd = [GOOGLE_JAVA_FORMAT, '--aosp', '-i'] + self._written_files |
| 326 | print('$ ' + ' '.join(google_java_format_cmd)) |
| 327 | subprocess.check_call(google_java_format_cmd, cwd=self._framework_appsearch_root) |
| 328 | |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 329 | def ExportCode(self): |
| 330 | self._ExportApiCode() |
| 331 | self._ExportImplCode() |
Alexander Dorokhine | aaa6e81c | 2021-04-19 23:26:43 -0700 | [diff] [blame] | 332 | self._FormatWrittenFiles() |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 333 | |
Alexander Dorokhine | fe6e1b4 | 2022-03-02 21:57:13 -0800 | [diff] [blame] | 334 | def WriteShaFile(self, sha): |
| 335 | """Copies the git sha of the most recent public CL into a file on the framework side. |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 336 | |
| 337 | This file is used for tracking, to determine what framework is synced to. |
| 338 | |
Alexander Dorokhine | fe6e1b4 | 2022-03-02 21:57:13 -0800 | [diff] [blame] | 339 | You must always provide a sha of a submitted submitted git commit. If you abandon the CL |
| 340 | pointed to by this sha, the next person syncing framework will be unable to find what CL it |
| 341 | is synced to. |
Alexander Dorokhine | ccfcb7b | 2022-03-25 12:05:45 -0700 | [diff] [blame] | 342 | |
| 343 | The previous content of the sha file, if any, is returned. |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 344 | """ |
Alexander Dorokhine | fe6e1b4 | 2022-03-02 21:57:13 -0800 | [diff] [blame] | 345 | file_path = os.path.join(self._framework_appsearch_root, SHA_FILE_NAME) |
Alexander Dorokhine | ccfcb7b | 2022-03-25 12:05:45 -0700 | [diff] [blame] | 346 | old_sha = None |
| 347 | if os.path.isfile(file_path): |
| 348 | with open(file_path, 'r') as fh: |
| 349 | old_sha = fh.read().rstrip() |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 350 | with open(file_path, 'w') as fh: |
Alexander Dorokhine | fe6e1b4 | 2022-03-02 21:57:13 -0800 | [diff] [blame] | 351 | print(sha, file=fh) |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 352 | print('Wrote "%s"' % file_path) |
Alexander Dorokhine | ccfcb7b | 2022-03-25 12:05:45 -0700 | [diff] [blame] | 353 | return old_sha |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 354 | |
| 355 | |
| 356 | if __name__ == '__main__': |
Alexander Dorokhine | 4939496 | 2020-11-17 03:04:42 -0800 | [diff] [blame] | 357 | if len(sys.argv) != 3: |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 358 | print('Usage: %s <path/to/framework/checkout> <git sha of head jetpack commit>' % ( |
| 359 | sys.argv[0]), |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 360 | file=sys.stderr) |
| 361 | sys.exit(1) |
Alexander Dorokhine | fe6e1b4 | 2022-03-02 21:57:13 -0800 | [diff] [blame] | 362 | if sys.argv[2].startswith('I'): |
| 363 | print('Error: Git sha "%s" looks like a changeid. Please provide a git sha instead.' % ( |
| 364 | sys.argv[2]), |
| 365 | file=sys.stderr) |
| 366 | sys.exit(1) |
| 367 | |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 368 | source_dir = os.path.normpath(os.path.dirname(sys.argv[0])) |
| 369 | dest_dir = os.path.normpath(sys.argv[1]) |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 370 | dest_dir = os.path.join(dest_dir, 'packages/modules/AppSearch') |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 371 | if not os.path.isdir(dest_dir): |
| 372 | print('Destination path "%s" does not exist or is not a directory' % ( |
Alexander Dorokhine | 1412650 | 2021-10-20 23:27:34 -0700 | [diff] [blame] | 373 | dest_dir), |
Alexander Dorokhine | b1145b3 | 2020-09-17 23:33:37 -0700 | [diff] [blame] | 374 | file=sys.stderr) |
| 375 | sys.exit(1) |
Alexander Dorokhine | 727d91a | 2020-11-19 23:21:26 -0800 | [diff] [blame] | 376 | exporter = ExportToFramework(source_dir, dest_dir) |
| 377 | exporter.ExportCode() |
Alexander Dorokhine | ccfcb7b | 2022-03-25 12:05:45 -0700 | [diff] [blame] | 378 | |
| 379 | # Update the sha file |
| 380 | new_sha = sys.argv[2] |
| 381 | old_sha = exporter.WriteShaFile(new_sha) |
| 382 | if old_sha and old_sha != new_sha: |
| 383 | print('Command to diff old version to new version:') |
| 384 | print(' git log %s..%s -- appsearch/' % (old_sha, new_sha)) |