aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--tools/android/aar_resources_extractor.py46
-rw-r--r--tools/android/aar_resources_extractor_test.py18
2 files changed, 49 insertions, 15 deletions
diff --git a/tools/android/aar_resources_extractor.py b/tools/android/aar_resources_extractor.py
index eb0d432027..61f9f4d397 100644
--- a/tools/android/aar_resources_extractor.py
+++ b/tools/android/aar_resources_extractor.py
@@ -40,23 +40,49 @@ gflags.MarkFlagAsRequired("output_res_dir")
def ExtractResources(aar, output_res_dir):
"""Extract resource from an `aar` file to the `output_res_dir` directory."""
aar_contains_no_resources = True
- output_res_dir_abs = os.path.normpath(
- os.path.join(os.getcwd(), output_res_dir))
+ output_res_dir_abs = os.path.abspath(output_res_dir)
for name in aar.namelist():
if name.startswith("res/"):
- fullpath = os.path.normpath(os.path.join(output_res_dir_abs, name))
- if os.name == "nt" and len(fullpath) >= 260: # MAX_PATH in <windows.h>
- with junction.TempJunction(os.path.dirname(fullpath)) as juncpath:
- shortpath = os.path.join(juncpath, os.path.basename(fullpath))
- aar.extract(name, shortpath)
+ if os.name == "nt":
+ fullpath = os.path.normpath(os.path.join(output_res_dir_abs, name))
+ if name[-1] == "/":
+ # The zip entry is a directory. Create a junction to it, which also
+ # takes care of creating the directory and all of its parents in a
+ # longpath-safe manner.
+ # We must pretend to have extracted this directory, even if it's
+ # empty, therefore we mustn't rely on creating it as a parent
+ # directory of a subsequently extracted zip entry (because there may
+ # be no such subsequent entry).
+ with junction.TempJunction(fullpath.rstrip("/")) as juncpath:
+ pass
+ else:
+ # The zip entry is a file. Create a junction to its parent directory,
+ # then open the compressed entry as a file object, so we can extract
+ # the data even if the extracted file's path would be too long.
+ # The tradeoff is that we lose the permission bits of the compressed
+ # file, but Unix permissions don't mean much on Windows anyway.
+ with junction.TempJunction(os.path.dirname(fullpath)) as juncpath:
+ extracted_path = os.path.join(juncpath, os.path.basename(fullpath))
+ with aar.open(name) as src_fd:
+ with open(extracted_path, "wb") as dest_fd:
+ dest_fd.write(src_fd.read())
else:
aar.extract(name, output_res_dir)
aar_contains_no_resources = False
+
if aar_contains_no_resources:
empty_xml_filename = output_res_dir + "/res/values/empty.xml"
- os.makedirs(os.path.dirname(empty_xml_filename))
- with open(empty_xml_filename, "wb") as empty_xml:
- empty_xml.write("<resources/>")
+ if os.name == "nt":
+ # Create a junction to the parent directory, because its path might be too
+ # long. Creating the junction also creates all parent directories.
+ with junction.TempJunction(os.path.dirname(empty_xml_filename)) as junc:
+ xmlpath = os.path.join(junc, os.path.basename(empty_xml_filename))
+ with open(xmlpath, "wb") as empty_xml:
+ empty_xml.write("<resources/>")
+ else:
+ os.makedirs(os.path.dirname(empty_xml_filename))
+ with open(empty_xml_filename, "wb") as empty_xml:
+ empty_xml.write("<resources/>")
def main():
diff --git a/tools/android/aar_resources_extractor_test.py b/tools/android/aar_resources_extractor_test.py
index b59e4160cb..d5f630b352 100644
--- a/tools/android/aar_resources_extractor_test.py
+++ b/tools/android/aar_resources_extractor_test.py
@@ -23,6 +23,10 @@ import zipfile
from tools.android import aar_resources_extractor
+def _HostPath(path):
+ return os.path.normpath(path)
+
+
class AarResourcesExtractorTest(unittest.TestCase):
"""Unit tests for aar_resources_extractor.py."""
@@ -33,14 +37,16 @@ class AarResourcesExtractorTest(unittest.TestCase):
shutil.rmtree("out_dir")
def DirContents(self, d):
- return [path + "/" + f for (path, _, files) in os.walk(d)
- for f in files]
+ return [
+ _HostPath(path + "/" + f)
+ for (path, _, files) in os.walk(d) for f in files
+ ]
def testNoResources(self):
aar = zipfile.ZipFile(StringIO.StringIO(), "w")
os.makedirs("out_dir")
aar_resources_extractor.ExtractResources(aar, "out_dir")
- self.assertEqual(["out_dir/res/values/empty.xml"],
+ self.assertEqual([_HostPath("out_dir/res/values/empty.xml")],
self.DirContents("out_dir"))
with open("out_dir/res/values/empty.xml", "r") as empty_xml:
self.assertEqual("<resources/>", empty_xml.read())
@@ -51,8 +57,10 @@ class AarResourcesExtractorTest(unittest.TestCase):
aar.writestr("res/layouts/layout.xml", "some layout")
os.makedirs("out_dir")
aar_resources_extractor.ExtractResources(aar, "out_dir")
- expected_resources = ["out_dir/res/values/values.xml",
- "out_dir/res/layouts/layout.xml"]
+ expected_resources = [
+ _HostPath("out_dir/res/values/values.xml"),
+ _HostPath("out_dir/res/layouts/layout.xml")
+ ]
self.assertItemsEqual(expected_resources, self.DirContents("out_dir"))
with open("out_dir/res/values/values.xml", "r") as values_xml:
self.assertEqual("some values", values_xml.read())