class TestFileFinder(MatchTestTemplate, TestWithTmpDir): def add(self, path): ensure_parent_dir(self.tmppath(path)) open(self.tmppath(path), 'wb').write(path) def do_check(self, pattern, result): if result: self.assertTrue(self.finder.contains(pattern)) else: self.assertFalse(self.finder.contains(pattern)) self.assertEqual(sorted(list(f for f, c in self.finder.find(pattern))), sorted(result)) def test_file_finder(self): self.finder = FileFinder(self.tmpdir) self.do_match_test() self.add('foo/.foo') self.add('foo/.bar/foo') self.assertTrue(self.finder.contains('foo/.foo')) self.assertTrue(self.finder.contains('foo/.bar')) self.assertTrue('foo/.foo' in [f for f, c in self.finder.find('foo/.foo')]) self.assertTrue('foo/.bar/foo' in [f for f, c in self.finder.find('foo/.bar')]) self.assertEqual(sorted([f for f, c in self.finder.find('foo/.*')]), ['foo/.bar/foo', 'foo/.foo']) for pattern in ['foo', '**', '**/*', '**/foo', 'foo/*']: self.assertFalse('foo/.foo' in [f for f, c in self.finder.find(pattern)]) self.assertFalse('foo/.bar/foo' in [f for f, c in self.finder.find(pattern)]) self.assertEqual(sorted([f for f, c in self.finder.find(pattern)]), sorted([f for f, c in self.finder if mozpack.path.match(f, pattern)]))
def unpack_msix(input_msix, output, log=None, verbose=False): r"""Unpack the given MSIX to the given output directory. MSIX packages are ZIP files, but they are Zip64/version 4.5 ZIP files, so `mozjar.py` doesn't yet handle. Unpack using `unzip{.exe}` for simplicity. In addition, file names inside the MSIX package are URL quoted. URL unquote here. """ log( logging.INFO, "msix", { "input_msix": input_msix, "output": output, }, "Unpacking input MSIX '{input_msix}' to directory '{output}'", ) unzip = find_sdk_tool("unzip.exe", log=log) if not unzip: raise ValueError("unzip is required; set UNZIP or PATH") subprocess.check_call( [unzip, input_msix, "-d", output] + (["-q"] if not verbose else []), universal_newlines=True, ) # Sanity check: is this an MSIX? temp_finder = FileFinder(output) if not temp_finder.contains("AppxManifest.xml"): raise ValueError("MSIX file does not contain 'AppxManifest.xml'?") # Files in the MSIX are URL encoded/quoted; unquote here. for dirpath, dirs, files in os.walk(output): # This is a one way to update (in place, for os.walk) the variable `dirs` while iterating # over it and `files`. for i, (p, var) in itertools.chain( enumerate((f, files) for f in files), enumerate((g, dirs) for g in dirs) ): q = urllib.parse.unquote(p) if p != q: log( logging.DEBUG, "msix", { "dirpath": dirpath, "p": p, "q": q, }, "URL unquoting '{p}' -> '{q}' in {dirpath}", ) var[i] = q os.rename(os.path.join(dirpath, p), os.path.join(dirpath, q)) # The "package root" of our MSIX packages is like "Mozilla Firefox Beta Package Root", i.e., it # varies by channel. This is an easy way to determine it. for p, _ in temp_finder.find("**/application.ini"): relpath = os.path.split(p)[0] # The application executable, like `firefox.exe`, is in this directory. return mozpath.normpath(mozpath.join(output, relpath))