def ExtractOneFile(aar, name, abs_output_dir): """Extract one file from the aar to the output directory.""" if os.name == "nt": fullpath = os.path.normpath(os.path.join(abs_output_dir, 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, abs_output_dir)
def main(): if os.name == "nt": with junction.TempJunction(os.path.dirname(FLAGS.input_aar)) as j_in: with junction.TempJunction(os.path.dirname( FLAGS.output_zip)) as j_out: Main(os.path.join(j_in, os.path.basename(FLAGS.input_aar)), os.path.join(j_out, os.path.basename(FLAGS.output_zip)), FLAGS.cpu, FLAGS.input_aar) else: Main(FLAGS.input_aar, FLAGS.output_zip, FLAGS.cpu, FLAGS.input_aar)
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.abspath(output_res_dir) for name in aar.namelist(): if name.startswith("res/"): 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" 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(b"<resources/>") else: os.makedirs(os.path.dirname(empty_xml_filename)) with open(empty_xml_filename, "wb") as empty_xml: empty_xml.write(b"<resources/>")
def testCreateJunction(self): def tempdir(): return self.ScratchDir("junc temp") target = self.ScratchDir("junc target") # Make the `target` path a non-normalized Windows path with a space in it. # TempJunction should still work. target = os.path.dirname(target) + "/junc target" juncpath = None with junction.TempJunction(target, testonly_mkdtemp=tempdir) as j: juncpath = j # Ensure that `j` created the junction. self.assertTrue(os.path.exists(target)) self.assertTrue(os.path.exists(juncpath)) # Create a file under the junction. filepath = os.path.join(juncpath, "file.txt") with open(filepath, "w") as f: f.write("hello") # Ensure we can reach the file via the junction and the target directory. self.assertTrue(os.path.exists(os.path.join(target, "file.txt"))) self.assertTrue(os.path.exists(os.path.join(juncpath, "file.txt"))) # Ensure that after the `with` block the junction and temp directories no # longer exist, but we can still reach the file via the target directory. self.assertTrue(os.path.exists(os.path.join(target, "file.txt"))) self.assertFalse(os.path.exists(os.path.join(juncpath, "file.txt"))) self.assertFalse(os.path.exists(juncpath)) self.assertFalse(os.path.exists(os.path.dirname(juncpath)))
def main(unused_argv): if os.name == "nt": # Shorten paths unconditionally, because the extracted paths in # ExtractEmbeddedJars (which we cannot yet predict, because they depend on # the names of the Zip entries) may be longer than MAX_PATH. aar_long = os.path.abspath(FLAGS.input_aar) proguard_long = os.path.abspath(FLAGS.output_proguard_file) with junction.TempJunction(os.path.dirname(aar_long)) as aar_junc: with junction.TempJunction( os.path.dirname(proguard_long)) as proguard_junc: _Main( os.path.join(aar_junc, os.path.basename(aar_long)), os.path.join(proguard_junc, os.path.basename(proguard_long))) else: _Main(FLAGS.input_aar, FLAGS.output_proguard_file)
def testCannotCreateJunction(self): def tempdir(): return self.ScratchDir("junc temp") target = self.ScratchDir("junc target") # Make the `target` path a non-normalized Windows path with a space in it. # TempJunction should still work. target = six.ensure_str(os.path.dirname(target)) + "/junc target" with junction.TempJunction(target, testonly_mkdtemp=tempdir) as j: self.assertTrue(os.path.exists(j)) try: # Ensure that TempJunction raises a JunctionCreationError if it cannot # create a junction. In this case the junction already exists in that # directory. with junction.TempJunction(target, testonly_mkdtemp=tempdir) as _: self.fail("Expected exception") except junction.JunctionCreationError: pass # expected
def WriteFileWithJunctions(filename, content): """Writes file including creating any junctions or directories necessary.""" 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(filename)) as junc: filename = os.path.join(junc, os.path.basename(filename)) else: os.makedirs(os.path.dirname(filename)) with open(filename, "wb") as openfile: openfile.write(content)
def WriteFileWithJunctions(filename, content): """Writes file including creating any junctions or directories necessary.""" def _WriteFile(filename): with open(filename, "wb") as openfile: openfile.write(content) 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(filename)) as junc: filename = os.path.join(junc, os.path.basename(filename)) # Write the file within scope of the TempJunction, otherwise the path in # `filename` would no longer be valid. _WriteFile(filename) else: os.makedirs(os.path.dirname(filename)) _WriteFile(filename)
def _AssertCreateJunctionWhenTargetsParentsDontExist(self, max_path=None): def tempdir(): return self.ScratchDir("junc temp") target = self.Path("this directory/should not\\yet exist") self.assertFalse( os.path.exists(os.path.dirname(os.path.dirname(target)))) # Make the `target` path a non-normalized Windows path with a space in it # which doesn't even exist. # TempJunction should still work; it should: # - normalize the path, and # - create all directories on the path # target = os.path.dirname(target) + "/junc target" juncpath = None with junction.TempJunction(target, testonly_mkdtemp=tempdir, testonly_maxpath=max_path) as j: juncpath = j # Ensure that `j` created the junction. self.assertTrue(os.path.exists(target)) self.assertTrue(os.path.exists(juncpath)) self.assertTrue( six.ensure_str(juncpath).endswith( os.path.join("junc temp", "j"))) self.assertTrue(os.path.isabs(juncpath)) # Create a file under the junction. filepath = os.path.join(juncpath, "some file.txt") with open(filepath, "w") as f: f.write("hello") # Ensure we can reach the file via the junction and the target directory. self.assertTrue( os.path.exists(os.path.join(target, "some file.txt"))) self.assertTrue( os.path.exists(os.path.join(juncpath, "some file.txt"))) # Ensure that after the `with` block the junction and temp directories no # longer exist, but we can still reach the file via the target directory. self.assertTrue(os.path.exists(os.path.join(target, "some file.txt"))) self.assertFalse( os.path.exists(os.path.join(juncpath, "some file.txt"))) self.assertFalse(os.path.exists(juncpath)) self.assertFalse(os.path.exists(os.path.dirname(juncpath)))
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)) 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) 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/>")