Merge "Fix Bazel APEX wrapper to resolve symlinks of any number of levels."
diff --git a/rules/apex/bazel_apexer_wrapper.py b/rules/apex/bazel_apexer_wrapper.py
index f1a7651..e7d6584 100644
--- a/rules/apex/bazel_apexer_wrapper.py
+++ b/rules/apex/bazel_apexer_wrapper.py
@@ -49,15 +49,28 @@
         full_apex_filepath = "/".join([input_dir, apex_filepath])
         # Because Bazel execution root is a symlink forest, all the input files are symlinks, these
         # include the dependency files declared in the BUILD files as well as the files declared
-        # and created in the bzl files. For sandbox runs the former are two level symlinks and
+        # and created in the bzl files. For sandbox runs the former are two or more level symlinks and
         # latter are one level symlinks. For non-sandbox runs, the former are one level symlinks
         # and the latter are actual files. Here are some examples:
         #
+        # Two level symlinks:
         # system/timezone/output_data/version/tz_version ->
         # /usr/local/google/home/...out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
         # execroot/__main__/system/timezone/output_data/version/tz_version ->
         # /usr/local/google/home/.../system/timezone/output_data/version/tz_version
         #
+        # Three level symlinks:
+        # bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/libcrypto.so ->
+        # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+        # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/libcrypto.so ->
+        # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+        # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/
+        # liblibcrypto_stripped.so ->
+        # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+        # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/
+        # liblibcrypto_unstripped.so
+        #
+        # One level symlinks:
         # bazel-out/android_target-fastbuild/bin/system/timezone/apex/apex_manifest.pb ->
         # /usr/local/google/home/.../out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
         # execroot/__main__/bazel-out/android_target-fastbuild/bin/system/timezone/apex/
@@ -67,7 +80,7 @@
             bazel_input_file = os.readlink(bazel_input_file)
 
             # For sandbox run these are the 2nd level symlinks and we need to resolve
-            if os.path.islink(bazel_input_file) and 'execroot/__main__' in bazel_input_file:
+            while os.path.islink(bazel_input_file) and 'execroot/__main__' in bazel_input_file:
                 bazel_input_file = os.readlink(bazel_input_file)
 
         shutil.copyfile(bazel_input_file, full_apex_filepath, follow_symlinks=False)
diff --git a/rules/apex/bazel_apexer_wrapper_test.sh b/rules/apex/bazel_apexer_wrapper_test.sh
index 26e5ec6..274cbdd 100755
--- a/rules/apex/bazel_apexer_wrapper_test.sh
+++ b/rules/apex/bazel_apexer_wrapper_test.sh
@@ -38,6 +38,7 @@
 # 3. a one-level symlink
 # 4. a two-level symlink with "execroot/__main__" in the path
 # 5. a two-level sumlink without "execroot/__main__" in the path
+# 6. a three-level symlink with "execroot/__main__" in the path
 echo "test file1" > "${input_dir}/file1"
 echo "test file2" > "${input_dir}/file2"
 mkdir -p "${input_dir}/execroot/__main__"
@@ -45,6 +46,7 @@
 ln -s "${input_dir}/file2" "${input_dir}/execroot/__main__/middle_sym"
 ln -s "${input_dir}/execroot/__main__/middle_sym" "${input_dir}/two_level_sym_in_execroot"
 ln -s "${input_dir}/one_level_sym" "${input_dir}/two_level_sym_not_in_execroot"
+ln -s "${input_dir}/two_level_sym_in_execroot" "${input_dir}/three_level_sym_in_execroot"
 
 # Create the APEX manifest file
 manifest_dir=$(mktemp -d)
@@ -69,6 +71,7 @@
 dir4,one_level_sym,"${input_dir}/one_level_sym"
 dir5,two_level_sym_in_execroot,"${input_dir}/two_level_sym_in_execroot"
 dir6,two_level_sym_not_in_execroot,"${input_dir}/two_level_sym_not_in_execroot"
+dir7,three_level_sym_in_execroot,"${input_dir}/three_level_sym_in_execroot"
 " > ${bazel_apexer_wrapper_manifest_file}
 
 #############################################
@@ -108,6 +111,9 @@
 # │   ├── dir6
 # │   │   └── two_level_sym_not_in_execroot -> /tmp/tmp.evJh21oYGG/file1
 #             (two level symlink resolve only one level otherwise)
+# │   ├── dir7
+# │   │   └── three_level_sym_in_execroot
+#             (three level symlink resolve if the path contains execroot/__main__)
 # └── test.apex
 
 # b/215129834:
@@ -126,6 +132,7 @@
 diff ${input_dir}/file1 ${output_dir}/dir4/one_level_sym
 diff ${input_dir}/file2 ${output_dir}/dir5/two_level_sym_in_execroot
 [ `readlink ${output_dir}/dir6/two_level_sym_not_in_execroot` = "${input_dir}/file1" ]
+diff ${input_dir}/file2 ${output_dir}/dir7/three_level_sym_in_execroot
 
 cleanup