blob: 48ec64bea16118e721949dd22267d37e68075905 [file] [log] [blame]
Alexander Dorokhineb1145b32020-09-17 23:33:37 -07001#!/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 Dorokhine14126502021-10-20 23:27:34 -070019# packages/modules/AppSearch path.
Alexander Dorokhineb1145b32020-09-17 23:33:37 -070020#
21# Example usage (from root dir of androidx workspace):
Alexander Dorokhine14126502021-10-20 23:27:34 -070022# $ ./frameworks/support/appsearch/exportToFramework.py "$HOME/android/master" "<jetpack git sha>"
Alexander Dorokhinef5f78882021-04-29 12:12:06 -070023
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 Dorokhineb1145b32020-09-17 23:33:37 -070049import os
50import re
Alexander Dorokhine727d91a2020-11-19 23:21:26 -080051import subprocess
Alexander Dorokhineb1145b32020-09-17 23:33:37 -070052import sys
53
Alexander Dorokhine727d91a2020-11-19 23:21:26 -080054# Jetpack paths relative to frameworks/support/appsearch
Alexander Dorokhineb1145b32020-09-17 23:33:37 -070055JETPACK_API_ROOT = 'appsearch/src/main/java/androidx/appsearch'
Alexander Dorokhinea70da602020-09-22 03:34:44 -070056JETPACK_API_TEST_ROOT = 'appsearch/src/androidTest/java/androidx/appsearch'
Alexander Dorokhine14126502021-10-20 23:27:34 -070057JETPACK_IMPL_ROOT = 'appsearch-local-storage/src/main/java/androidx/appsearch'
58JETPACK_IMPL_TEST_ROOT = 'appsearch-local-storage/src/androidTest/java/androidx/appsearch'
59JETPACK_TEST_UTIL_ROOT = 'appsearch-test-util/src/main/java/androidx/appsearch'
60JETPACK_TEST_UTIL_TEST_ROOT = 'appsearch-test-util/src/androidTest/java/androidx/appsearch'
Alexander Dorokhine727d91a2020-11-19 23:21:26 -080061
Alexander Dorokhine14126502021-10-20 23:27:34 -070062# Framework paths relative to packages/modules/AppSearch
Alexander Dorokhine20d1f2d2020-12-04 00:37:27 -080063FRAMEWORK_API_ROOT = 'framework/java/external/android/app/appsearch'
Alexander Dorokhine14126502021-10-20 23:27:34 -070064FRAMEWORK_API_TEST_ROOT = 'testing/coretests/src/android/app/appsearch/external'
Alexander Dorokhineb1145b32020-09-17 23:33:37 -070065FRAMEWORK_IMPL_ROOT = 'service/java/com/android/server/appsearch/external'
Alexander Dorokhine14126502021-10-20 23:27:34 -070066FRAMEWORK_IMPL_TEST_ROOT = 'testing/servicestests/src/com/android/server/appsearch/external'
67FRAMEWORK_TEST_UTIL_ROOT = 'testing/testutils/src/android/app/appsearch/testutil/external'
68FRAMEWORK_TEST_UTIL_TEST_ROOT = 'testing/servicestests/src/android/app/appsearch/testutil/external'
69FRAMEWORK_CTS_TEST_ROOT = '../../../cts/tests/appsearch/src/com/android/cts/appsearch/external'
Alexander Dorokhine727d91a2020-11-19 23:21:26 -080070GOOGLE_JAVA_FORMAT = (
Alexander Dorokhine14126502021-10-20 23:27:34 -070071 '../../../prebuilts/tools/common/google-java-format/google-java-format')
Alexander Dorokhine727d91a2020-11-19 23:21:26 -080072
73# Miscellaneous constants
Alexander Dorokhinefe6e1b42022-03-02 21:57:13 -080074SHA_FILE_NAME = 'synced_jetpack_sha.txt'
Alexander Dorokhineb1145b32020-09-17 23:33:37 -070075
76
Alexander Dorokhine727d91a2020-11-19 23:21:26 -080077class 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 Dorokhineaaa6e81c2021-04-19 23:26:43 -070081 self._written_files = []
Alexander Dorokhineb1145b32020-09-17 23:33:37 -070082
Alexander Dorokhine20d1f2d2020-12-04 00:37:27 -080083 def _PruneDir(self, dir_to_prune):
Alexander Dorokhine727d91a2020-11-19 23:21:26 -080084 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 Dorokhine727d91a2020-11-19 23:21:26 -080087 print('Prune: remove "%s"' % abs_path)
88 os.remove(abs_path)
Alexander Dorokhineb1145b32020-09-17 23:33:37 -070089
Alexander Dorokhine968bbd32020-12-30 02:06:11 -080090 def _TransformAndCopyFile(
91 self, source_path, dest_path, transform_func=None, ignore_skips=False):
Alexander Dorokhine727d91a2020-11-19 23:21:26 -080092 with open(source_path, 'r') as fh:
93 contents = fh.read()
Alexander Dorokhineb1145b32020-09-17 23:33:37 -070094
Alexander Dorokhine968bbd32020-12-30 02:06:11 -080095 if not ignore_skips and '@exportToFramework:skipFile()' in contents:
Alexander Dorokhine727d91a2020-11-19 23:21:26 -080096 print('Skipping: "%s" -> "%s"' % (source_path, dest_path), file=sys.stderr)
97 return
Alexander Dorokhineb1145b32020-09-17 23:33:37 -070098
Alexander Dorokhine3f4deb22022-03-17 12:45:30 -070099 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 Dorokhine727d91a2020-11-19 23:21:26 -0800103 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 Dorokhineb1145b32020-09-17 23:33:37 -0700109
Alexander Dorokhineaaa6e81c2021-04-19 23:26:43 -0700110 # Save file for future formatting
111 self._written_files.append(dest_path)
Alexander Dorokhineb1145b32020-09-17 23:33:37 -0700112
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800113 def _TransformCommonCode(self, contents):
Alexander Dorokhineaaa6e81c2021-04-19 23:26:43 -0700114 # Apply stripping
Alexander Dorokhineebd84fe2020-12-30 01:19:03 -0800115 contents = re.sub(
Alexander Dorokhinef5f78882021-04-29 12:12:06 -0700116 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 Dorokhineaaa6e81c2021-04-19 23:26:43 -0700127
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 Dorokhinee51b4b02021-05-04 11:15:07 -0700132 if '@exportToFramework:UnsupportedAppUsage' in contents:
133 imports_to_add.append('android.compat.annotation.UnsupportedAppUsage')
Alexander Dorokhineaaa6e81c2021-04-19 23:26:43 -0700134 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 Dorokhinefe6e1b42022-03-02 21:57:13 -0800140 contents = (contents
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800141 .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 Dorokhineebd84fe2020-12-30 01:19:03 -0800152 .replace('androidx.annotation.', 'android.annotation.')
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800153 .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 Dorokhine9961ca42021-04-02 15:28:08 -0700158 # Preconditions.checkNotNull is replaced with Objects.requireNonNull. We add both
159 # imports and let google-java-format sort out which one is unused.
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800160 .replace(
Alexander Dorokhine9961ca42021-04-02 15:28:08 -0700161 'import androidx.core.util.Preconditions;',
162 'import java.util.Objects; import com.android.internal.util.Preconditions;')
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800163 .replace('import androidx.annotation.RestrictTo;', '')
Alexander Dorokhineebd84fe2020-12-30 01:19:03 -0800164 .replace('@RestrictTo(RestrictTo.Scope.LIBRARY)', '')
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800165 .replace('@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)', '')
Alexander Dorokhine9961ca42021-04-02 15:28:08 -0700166 .replace('Preconditions.checkNotNull(', 'Objects.requireNonNull(')
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800167 .replace('ObjectsCompat.', 'Objects.')
Alexander Dorokhinefe6e1b42022-03-02 21:57:13 -0800168
Alexander Dorokhineaaa6e81c2021-04-19 23:26:43 -0700169 .replace('/*@exportToFramework:CurrentTimeMillisLong*/', '@CurrentTimeMillisLong')
Alexander Dorokhinee51b4b02021-05-04 11:15:07 -0700170 .replace('/*@exportToFramework:UnsupportedAppUsage*/', '@UnsupportedAppUsage')
Alexander Dorokhinef5f78882021-04-29 12:12:06 -0700171 .replace('<!--@exportToFramework:hide-->', '@hide')
Alexander Dorokhine968bbd32020-12-30 02:06:11 -0800172 .replace('// @exportToFramework:skipFile()', '')
Alexander Dorokhinea70da602020-09-22 03:34:44 -0700173 )
Alexander Dorokhine3f4deb22022-03-17 12:45:30 -0700174 contents = re.sub(r'\/\/ @exportToFramework:copyToPath\([^)]+\)', '', contents)
Alexander Dorokhineb1145b32020-09-17 23:33:37 -0700175
Alexander Dorokhinefe6e1b42022-03-02 21:57:13 -0800176 # 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 Dorokhinefff89ed2022-03-15 23:16:10 -0700179 contents = re.sub(
180 r'(\@see [^#]+#[a-zA-Z0-9_]+)Async$', r'\1', contents, flags=re.MULTILINE)
Alexander Dorokhinefe6e1b42022-03-02 21:57:13 -0800181 return contents
182
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800183 def _TransformTestCode(self, contents):
Alexander Dorokhinea70da602020-09-22 03:34:44 -0700184 contents = (contents
Alexander Dorokhine14126502021-10-20 23:27:34 -0700185 .replace('androidx.appsearch.testutil.', 'android.app.appsearch.testutil.')
Alexander Dorokhineebd84fe2020-12-30 01:19:03 -0800186 .replace(
Alexander Dorokhine14126502021-10-20 23:27:34 -0700187 'package androidx.appsearch.testutil;',
188 'package android.app.appsearch.testutil;')
Alexander Dorokhineebd84fe2020-12-30 01:19:03 -0800189 .replace(
Alexander Dorokhineb73353c2021-01-06 01:16:18 -0800190 'androidx.appsearch.localstorage.LocalStorage',
191 'android.app.appsearch.AppSearchManager')
Alexander Dorokhineebd84fe2020-12-30 01:19:03 -0800192 .replace('LocalStorage.', 'AppSearchManager.')
Alexander Dorokhinea70da602020-09-22 03:34:44 -0700193 )
Alexander Dorokhineb73353c2021-01-06 01:16:18 -0800194 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 Dorokhine727d91a2020-11-19 23:21:26 -0800196 return self._TransformCommonCode(contents)
Alexander Dorokhineb1145b32020-09-17 23:33:37 -0700197
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800198 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 Dorokhineb1145b32020-09-17 23:33:37 -0700205
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800206 def _ExportApiCode(self):
Alexander Dorokhine24636002020-12-16 02:44:29 -0800207 # Prod source
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800208 api_source_dir = os.path.join(self._jetpack_appsearch_root, JETPACK_API_ROOT)
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800209 api_dest_dir = os.path.join(self._framework_appsearch_root, FRAMEWORK_API_ROOT)
Alexander Dorokhine24636002020-12-16 02:44:29 -0800210
211 # Unit tests
212 api_test_source_dir = os.path.join(self._jetpack_appsearch_root, JETPACK_API_TEST_ROOT)
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800213 api_test_dest_dir = os.path.join(self._framework_appsearch_root, FRAMEWORK_API_TEST_ROOT)
Alexander Dorokhine49394962020-11-17 03:04:42 -0800214
Alexander Dorokhine24636002020-12-16 02:44:29 -0800215 # CTS tests
Alexander Dorokhine8b612172021-05-10 15:51:47 -0700216 cts_test_source_dir = os.path.join(api_test_source_dir, 'cts')
Alexander Dorokhine24636002020-12-16 02:44:29 -0800217 cts_test_dest_dir = os.path.join(self._framework_appsearch_root, FRAMEWORK_CTS_TEST_ROOT)
218
219 # Test utils
Alexander Dorokhine14126502021-10-20 23:27:34 -0700220 test_util_source_dir = os.path.join(self._jetpack_appsearch_root, JETPACK_TEST_UTIL_ROOT)
Alexander Dorokhine24636002020-12-16 02:44:29 -0800221 test_util_dest_dir = os.path.join(self._framework_appsearch_root, FRAMEWORK_TEST_UTIL_ROOT)
222
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800223 # Prune existing files
Alexander Dorokhine20d1f2d2020-12-04 00:37:27 -0800224 self._PruneDir(api_dest_dir)
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800225 self._PruneDir(api_test_dest_dir)
Alexander Dorokhine24636002020-12-16 02:44:29 -0800226 self._PruneDir(cts_test_dest_dir)
227 self._PruneDir(test_util_dest_dir)
Alexander Dorokhine49394962020-11-17 03:04:42 -0800228
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800229 # Copy api classes. We can't use _TransformAndCopyFolder here because we
230 # need to specially handle the 'app' package.
Alexander Dorokhine24636002020-12-16 02:44:29 -0800231 print('~~~ Copying API classes ~~~')
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800232 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 Dorokhine49394962020-11-17 03:04:42 -0800248
Alexander Dorokhine24636002020-12-16 02:44:29 -0800249 # 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 Dorokhine727d91a2020-11-19 23:21:26 -0800264 self._TransformAndCopyFolder(
Alexander Dorokhine14126502021-10-20 23:27:34 -0700265 cts_test_source_dir, cts_test_dest_dir, transform_func=self._TransformTestCode)
Alexander Dorokhine24636002020-12-16 02:44:29 -0800266
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 Dorokhine968bbd32020-12-30 02:06:11 -0800271 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 Dorokhine49394962020-11-17 03:04:42 -0800279
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800280 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 Dorokhine14126502021-10-20 23:27:34 -0700285 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 Dorokhine727d91a2020-11-19 23:21:26 -0800289
290 # Prune
291 self._PruneDir(impl_dest_dir)
292 self._PruneDir(impl_test_dest_dir)
Alexander Dorokhine14126502021-10-20 23:27:34 -0700293 self._PruneDir(test_util_test_dest_dir)
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800294
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 Dorokhine004405e2021-06-28 23:04:30 -0700312 'com.android.server.appsearch.icing.proto.')
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800313 .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 Dorokhine14126502021-10-20 23:27:34 -0700319 self._TransformAndCopyFolder(
320 test_util_test_source_dir,
321 test_util_test_dest_dir,
322 transform_func=self._TransformTestCode)
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800323
Alexander Dorokhineaaa6e81c2021-04-19 23:26:43 -0700324 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 Dorokhine727d91a2020-11-19 23:21:26 -0800329 def ExportCode(self):
330 self._ExportApiCode()
331 self._ExportImplCode()
Alexander Dorokhineaaa6e81c2021-04-19 23:26:43 -0700332 self._FormatWrittenFiles()
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800333
Alexander Dorokhinefe6e1b42022-03-02 21:57:13 -0800334 def WriteShaFile(self, sha):
335 """Copies the git sha of the most recent public CL into a file on the framework side.
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800336
337 This file is used for tracking, to determine what framework is synced to.
338
Alexander Dorokhinefe6e1b42022-03-02 21:57:13 -0800339 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 Dorokhineccfcb7b2022-03-25 12:05:45 -0700342
343 The previous content of the sha file, if any, is returned.
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800344 """
Alexander Dorokhinefe6e1b42022-03-02 21:57:13 -0800345 file_path = os.path.join(self._framework_appsearch_root, SHA_FILE_NAME)
Alexander Dorokhineccfcb7b2022-03-25 12:05:45 -0700346 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 Dorokhine727d91a2020-11-19 23:21:26 -0800350 with open(file_path, 'w') as fh:
Alexander Dorokhinefe6e1b42022-03-02 21:57:13 -0800351 print(sha, file=fh)
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800352 print('Wrote "%s"' % file_path)
Alexander Dorokhineccfcb7b2022-03-25 12:05:45 -0700353 return old_sha
Alexander Dorokhineb1145b32020-09-17 23:33:37 -0700354
355
356if __name__ == '__main__':
Alexander Dorokhine49394962020-11-17 03:04:42 -0800357 if len(sys.argv) != 3:
Alexander Dorokhine14126502021-10-20 23:27:34 -0700358 print('Usage: %s <path/to/framework/checkout> <git sha of head jetpack commit>' % (
359 sys.argv[0]),
Alexander Dorokhineb1145b32020-09-17 23:33:37 -0700360 file=sys.stderr)
361 sys.exit(1)
Alexander Dorokhinefe6e1b42022-03-02 21:57:13 -0800362 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 Dorokhineb1145b32020-09-17 23:33:37 -0700368 source_dir = os.path.normpath(os.path.dirname(sys.argv[0]))
369 dest_dir = os.path.normpath(sys.argv[1])
Alexander Dorokhine14126502021-10-20 23:27:34 -0700370 dest_dir = os.path.join(dest_dir, 'packages/modules/AppSearch')
Alexander Dorokhineb1145b32020-09-17 23:33:37 -0700371 if not os.path.isdir(dest_dir):
372 print('Destination path "%s" does not exist or is not a directory' % (
Alexander Dorokhine14126502021-10-20 23:27:34 -0700373 dest_dir),
Alexander Dorokhineb1145b32020-09-17 23:33:37 -0700374 file=sys.stderr)
375 sys.exit(1)
Alexander Dorokhine727d91a2020-11-19 23:21:26 -0800376 exporter = ExportToFramework(source_dir, dest_dir)
377 exporter.ExportCode()
Alexander Dorokhineccfcb7b2022-03-25 12:05:45 -0700378
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))