Bug 846740 - Move most l10n-repack code under mozpack.packager, refactor it, and add a unit test. r=gps, a=bajaj
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 06 Mar 2013 07:26:32 +0100
changeset 132319 d2e33291adcd4716a8f5b0084cb32d9967c9be4a
parent 132318 745cae64974c85ce4fb224932dc68b9033db35d6
child 132320 9d56b37f1749567f4363b74e9978d777ae378e6b
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps, bajaj
bugs846740
milestone21.0a2
Bug 846740 - Move most l10n-repack code under mozpack.packager, refactor it, and add a unit test. r=gps, a=bajaj
python/mozbuild/mozpack/files.py
python/mozbuild/mozpack/packager/l10n.py
python/mozbuild/mozpack/test/test_packager.py
python/mozbuild/mozpack/test/test_packager_l10n.py
toolkit/mozapps/installer/l10n-repack.py
--- a/python/mozbuild/mozpack/files.py
+++ b/python/mozbuild/mozpack/files.py
@@ -267,18 +267,18 @@ class ManifestFile(BaseFile):
         to "webapprt/chrome". When packaging, the entry will be stored in
         jar:webapprt/omni.ja!/chrome/chrome.manifest, which means the entry
         will have to be relative to "chrome" instead of "webapprt/chrome". This
         doesn't really matter when serializing the entry, since this base path
         is not written out, but it matters when moving the entry at the same
         time, e.g. to jar:webapprt/omni.ja!/chrome.manifest, which we don't do
         currently but could in the future.
     '''
-    def __init__(self, base):
-        self._entries = []
+    def __init__(self, base, entries=None):
+        self._entries = entries if entries else []
         self._base = base
 
     def add(self, entry):
         '''
         Add the given entry to the manifest. Entries are rebased at open() time
         instead of add() time so that they can be more easily remove()d.
         '''
         assert isinstance(entry, ManifestEntry)
copy from toolkit/mozapps/installer/l10n-repack.py
copy to python/mozbuild/mozpack/packager/l10n.py
--- a/toolkit/mozapps/installer/l10n-repack.py
+++ b/python/mozbuild/mozpack/packager/l10n.py
@@ -25,110 +25,83 @@ from mozpack.chrome.manifest import (
     ManifestEntryWithRelPath,
     is_manifest,
     ManifestChrome,
     Manifest,
 )
 from mozpack.errors import errors
 from mozpack.packager.unpack import UnpackFinder
 from createprecomplete import generate_precomplete
-from argparse import ArgumentParser
-import buildconfig
-
-# Set of files or directories not listed in a chrome.manifest but that are
-# localized.
-NON_CHROME = set([
-    '**/crashreporter*.ini',
-    'searchplugins',
-    'dictionaries',
-    'hyphenation',
-    'defaults/profile',
-    'defaults/pref*/*-l10n.js',
-    'update.locale',
-    'extensions/langpack-*@*',
-    'distribution/extensions/langpack-*@*',
-])
 
 
-def repack(source, l10n, non_resources=[]):
-    finder = UnpackFinder(source)
-    l10n_finder = UnpackFinder(l10n)
-    copier = FileCopier()
-    if finder.kind == 'flat':
-        formatter = FlatFormatter(copier)
-    elif finder.kind == 'jar':
-        formatter = JarFormatter(copier, optimize=finder.optimizedjars)
-    elif finder.kind == 'omni':
-        formatter = OmniJarFormatter(copier, finder.omnijar,
-                                     optimize=finder.optimizedjars,
-                                     non_resources=non_resources)
+class LocaleManifestFinder(object):
+    def __init__(self, finder):
+        # Read all manifest entries
+        manifests = dict((p, m) for p, m in finder.find('**/*.manifest')
+                         if is_manifest(p))
+        assert all(isinstance(m, ManifestFile)
+                   for m in manifests.itervalues())
+        self.entries = [e for m in manifests.itervalues()
+                        for e in m if e.localized]
+        # Find unique locales used in these manifest entries.
+        self.locales = list(set(e.id for e in self.entries
+                                if isinstance(e, ManifestLocale)))
+        # Find all paths whose manifest are included by no other manifest.
+        includes = set(mozpack.path.join(e.base, e.relpath)
+                       for m in manifests.itervalues()
+                       for e in m if isinstance(e, Manifest))
+        self.bases = [mozpack.path.dirname(p)
+                      for p in set(manifests.keys()) - includes]
 
-    # Read all manifest entries from the packaged directory.
-    manifests = dict((p, m) for p, m in finder.find('**/*.manifest')
-                     if is_manifest(p))
-    assert all(isinstance(m, ManifestFile) for m in manifests.itervalues())
-    entries = [e for m in manifests.itervalues() for e in m if e.localized]
-    # Find unique locales used in these manifest entries.
-    locales = list(set(e.id for e in entries if isinstance(e, ManifestLocale)))
-    # Find all paths whose manifest are included by no other manifest.
-    includes = set(mozpack.path.join(e.base, e.relpath)
-                   for m in manifests.itervalues()
-                   for e in m if isinstance(e, Manifest))
-    bases = [mozpack.path.dirname(p) for p in set(manifests.keys()) - includes]
 
-    # Read all manifest entries from the langpack directory.
-    manifests = [m for p, m in l10n_finder.find('**/*.manifest')
-                 if is_manifest(p)]
-    assert all(isinstance(m, ManifestFile) for m in manifests)
-    l10n_entries = [e for m in manifests for e in m if e.localized]
-    # Find unique locales used in these manifest entries.
-    l10n_locales = list(set(e.id for e in l10n_entries
-                            if isinstance(e, ManifestLocale)))
+def _repack(app_finder, l10n_finder, copier, formatter, non_chrome=set()):
+    app = LocaleManifestFinder(app_finder)
+    l10n = LocaleManifestFinder(l10n_finder)
 
     # The code further below assumes there's only one locale replaced with
     # another one.
-    if len(locales) > 1 or len(l10n_locales) > 1:
+    if len(app.locales) > 1 or len(l10n.locales) > 1:
         errors.fatal("Multiple locales aren't supported")
-    locale = locales[0]
-    l10n_locale = l10n_locales[0]
+    locale = app.locales[0]
+    l10n_locale = l10n.locales[0]
 
     # For each base directory, store what path a locale chrome package name
     # corresponds to.
     # e.g., for the following entry under app/chrome:
     #     locale foo en-US path/to/files
     # keep track that the locale path for foo in app is
     # app/chrome/path/to/files.
     l10n_paths = {}
-    for e in l10n_entries:
+    for e in l10n.entries:
         if isinstance(e, ManifestChrome):
-            base = mozpack.path.basedir(e.path, bases)
-            if not base in l10n_paths:
-                l10n_paths[base] = {}
+            base = mozpack.path.basedir(e.path, app.bases)
+            l10n_paths.setdefault(base, {})
             l10n_paths[base][e.name] = e.path
 
     # For chrome and non chrome files or directories, store what langpack path
     # corresponds to a package path.
     paths = dict((e.path,
-                  l10n_paths[mozpack.path.basedir(e.path, bases)][e.name])
-                 for e in entries if isinstance(e, ManifestEntryWithRelPath))
+                  l10n_paths[mozpack.path.basedir(e.path, app.bases)][e.name])
+                 for e in app.entries
+                 if isinstance(e, ManifestEntryWithRelPath))
 
-    for pattern in NON_CHROME:
-        for base in bases:
+    for pattern in non_chrome:
+        for base in app.bases:
             path = mozpack.path.join(base, pattern)
-            left = set(p for p, f in finder.find(path))
+            left = set(p for p, f in app_finder.find(path))
             right = set(p for p, f in l10n_finder.find(path))
             for p in right:
                 paths[p] = p
             for p in left - right:
                 paths[p] = None
 
     # Create a new package, with non localized bits coming from the original
     # package, and localized bits coming from the langpack.
     packager = SimplePackager(formatter)
-    for p, f in finder:
+    for p, f in app_finder:
         if is_manifest(p):
             # Remove localized manifest entries.
             for e in [e for e in f if e.localized]:
                 f.remove(e)
         # If the path is one that needs a locale replacement, use the
         # corresponding file from the langpack.
         path = None
         if p in paths:
@@ -139,68 +112,63 @@ def repack(source, l10n, non_resources=[
             base = mozpack.path.basedir(p, paths.keys())
             if base:
                 subpath = mozpack.path.relpath(p, base)
                 path = mozpack.path.normpath(mozpack.path.join(paths[base],
                                                                subpath))
         if path:
             files = [f for p, f in l10n_finder.find(path)]
             if not len(files):
-                if base not in NON_CHROME:
-                    errors.error("Missing file: %s" % os.path.join(l10n, path))
+                if base not in non_chrome:
+                    errors.error("Missing file: %s" %
+                                 os.path.join(l10n_finder.base, path))
             else:
                 packager.add(path, files[0])
         else:
             packager.add(p, f)
 
     # Add localized manifest entries from the langpack.
     l10n_manifests = []
-    for base in set(e.base for e in l10n_entries):
-        m = ManifestFile(base)
-        for e in l10n_entries:
-            if e.base == base:
-                m.add(e)
+    for base in set(e.base for e in l10n.entries):
+        m = ManifestFile(base, [e for e in l10n.entries if e.base == base])
         path = mozpack.path.join(base, 'chrome.%s.manifest' % l10n_locale)
         l10n_manifests.append((path, m))
     bases = packager.get_bases()
     for path, m in l10n_manifests:
         base = mozpack.path.basedir(path, bases)
         packager.add(path, m)
         # Add a "manifest $path" entry in the top manifest under that base.
         m = ManifestFile(base)
         m.add(Manifest(base, mozpack.path.relpath(path, base)))
         packager.add(mozpack.path.join(base, 'chrome.manifest'), m)
 
     packager.close()
 
     # Add any remaining non chrome files.
-    for pattern in NON_CHROME:
+    for pattern in non_chrome:
         for base in bases:
             for p, f in l10n_finder.find(mozpack.path.join(base, pattern)):
                 if not formatter.contains(p):
                     formatter.add(p, f)
 
     # Transplant jar preloading information.
-    for path, log in finder.jarlogs.iteritems():
+    for path, log in app_finder.jarlogs.iteritems():
         assert isinstance(copier[path], Jarrer)
         copier[path].preload([l.replace(locale, l10n_locale) for l in log])
 
+
+def repack(source, l10n, non_resources=[], non_chrome=set()):
+    app_finder = UnpackFinder(source)
+    l10n_finder = UnpackFinder(l10n)
+    copier = FileCopier()
+    if app_finder.kind == 'flat':
+        formatter = FlatFormatter(copier)
+    elif app_finder.kind == 'jar':
+        formatter = JarFormatter(copier, optimize=app_finder.optimizedjars)
+    elif app_finder.kind == 'omni':
+        formatter = OmniJarFormatter(copier, app_finder.omnijar,
+                                     optimize=app_finder.optimizedjars,
+                                     non_resources=non_resources)
+
+    with errors.accumulate():
+        _repack(app_finder, l10n_finder, copier, formatter, non_chrome)
     copier.copy(source, skip_if_older=False)
     generate_precomplete(source)
-
-
-def main():
-    parser = ArgumentParser()
-    parser.add_argument('build',
-                        help='Directory containing the build to repack')
-    parser.add_argument('l10n',
-                        help='Directory containing the staged langpack')
-    parser.add_argument('--non-resource', nargs='+', metavar='PATTERN',
-                        default=[],
-                        help='Extra files not to be considered as resources')
-    args = parser.parse_args()
-
-    buildconfig.substs['USE_ELF_HACK'] = False
-    buildconfig.substs['PKG_SKIP_STRIP'] = True
-    repack(args.build, args.l10n, args.non_resource)
-
-if __name__ == "__main__":
-    main()
--- a/python/mozbuild/mozpack/test/test_packager.py
+++ b/python/mozbuild/mozpack/test/test_packager.py
@@ -82,16 +82,31 @@ class TestPreprocessManifest(unittest.Te
     def test_preprocess_manifest_defines(self):
         with MockedOpen({'manifest': MANIFEST}):
             preprocess_manifest(self.sink, 'manifest',
                                 {'baz': 1, 'SUFFIX': '.exe'})
         self.assertEqual(self.sink.log, self.EXPECTED_LOG +
                          [((self.MANIFEST_PATH, 10), 'add', 'baz', 'baz.exe')])
 
 
+class MockFinder(object):
+    def __init__(self, files):
+        self.files = files
+        self.log = []
+
+    def find(self, path):
+        self.log.append(path)
+        for f in sorted(self.files):
+            if mozpack.path.match(f, path):
+                yield f, self.files[f]
+
+    def __iter__(self):
+        return self.find('')
+
+
 class MockFormatter(object):
     def __init__(self):
         self.log = []
 
     def add_base(self, *args):
         self._log(errors.get_context(), 'add_base', *args)
 
     def add_manifest(self, *args):
@@ -173,27 +188,16 @@ class TestSimplePackager(unittest.TestCa
             (('manifest', 5), 'add', 'foo/bar/bar.html', bar_html),
         ])
 
         self.assertEqual(packager.get_bases(), set(['', 'qux']))
 
 
 class TestSimpleManifestSink(unittest.TestCase):
     def test_simple_manifest_parser(self):
-        class MockFinder(object):
-            def __init__(self, files):
-                self.files = files
-                self.log = []
-
-            def find(self, path):
-                self.log.append(path)
-                for f in sorted(self.files):
-                    if mozpack.path.match(f, path):
-                        yield f, self.files[f]
-
         formatter = MockFormatter()
         foobar = GeneratedFile('foobar')
         foobaz = GeneratedFile('foobaz')
         fooqux = GeneratedFile('fooqux')
         finder = MockFinder({
             'bin/foo/bar': foobar,
             'bin/foo/baz': foobaz,
             'bin/foo/qux': fooqux,
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozpack/test/test_packager_l10n.py
@@ -0,0 +1,112 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import unittest
+import mozunit
+from test_packager import MockFinder
+from mozpack.packager import l10n
+from mozpack.files import (
+    GeneratedFile,
+    ManifestFile,
+)
+from mozpack.chrome.manifest import (
+    Manifest,
+    ManifestLocale,
+    ManifestContent,
+)
+from mozpack.copier import FileRegistry
+from mozpack.packager.formats import FlatFormatter
+
+
+class TestL10NRepack(unittest.TestCase):
+    def test_l10n_repack(self):
+        foo = GeneratedFile('foo')
+        foobar = GeneratedFile('foobar')
+        qux = GeneratedFile('qux')
+        baz = GeneratedFile('baz')
+        dict_aa = GeneratedFile('dict_aa')
+        dict_bb = GeneratedFile('dict_bb')
+        dict_cc = GeneratedFile('dict_cc')
+        barbaz = GeneratedFile('barbaz')
+        app_finder = MockFinder({
+            'bar/foo': foo,
+            'chrome/foo/foobar': foobar,
+            'chrome/qux/qux.properties': qux,
+            'chrome/qux/baz/baz.properties': baz,
+            'chrome/chrome.manifest': ManifestFile('chrome', [
+                ManifestContent('chrome', 'foo', 'foo/'),
+                ManifestLocale('chrome', 'qux', 'en-US', 'qux/'),
+            ]),
+            'chrome.manifest':
+            ManifestFile('', [Manifest('', 'chrome/chrome.manifest')]),
+            'dict/aa': dict_aa,
+            'app/chrome/bar/barbaz.dtd': barbaz,
+            'app/chrome/chrome.manifest': ManifestFile('app/chrome', [
+                ManifestLocale('app/chrome', 'bar', 'en-US', 'bar/')
+            ]),
+            'app/chrome.manifest':
+            ManifestFile('app', [Manifest('app', 'chrome/chrome.manifest')]),
+            'app/dict/bb': dict_bb,
+            'app/dict/cc': dict_cc,
+        })
+        app_finder.jarlogs = {}
+        app_finder.base = 'app'
+        qux_l10n = GeneratedFile('qux_l10n')
+        baz_l10n = GeneratedFile('baz_l10n')
+        barbaz_l10n = GeneratedFile('barbaz_l10n')
+        l10n_finder = MockFinder({
+            'chrome/qux-l10n/qux.properties': qux_l10n,
+            'chrome/qux-l10n/baz/baz.properties': baz_l10n,
+            'chrome/chrome.manifest': ManifestFile(' chrome', [
+                ManifestLocale('chrome', 'qux', 'x-test', 'qux-l10n/'),
+            ]),
+            'chrome.manifest':
+            ManifestFile('', [Manifest('', 'chrome/chrome.manifest')]),
+            'dict/bb': dict_bb,
+            'dict/cc': dict_cc,
+            'app/chrome/bar-l10n/barbaz.dtd': barbaz_l10n,
+            'app/chrome/chrome.manifest': ManifestFile('app/chrome', [
+                ManifestLocale('app/chrome', 'bar', 'x-test', 'bar-l10n/')
+            ]),
+            'app/chrome.manifest':
+            ManifestFile('app', [Manifest('app', 'chrome/chrome.manifest')]),
+            'app/dict/aa': dict_aa,
+        })
+        l10n_finder.base = 'l10n'
+        copier = FileRegistry()
+        formatter = FlatFormatter(copier)
+
+        l10n._repack(app_finder, l10n_finder, copier, formatter, ['dict'])
+        self.maxDiff = None
+
+        repacked = {
+            'bar/foo': foo,
+            'chrome/foo/foobar': foobar,
+            'chrome/qux-l10n/qux.properties': qux_l10n,
+            'chrome/qux-l10n/baz/baz.properties': baz_l10n,
+            'chrome/chrome.manifest': ManifestFile('chrome', [
+                ManifestContent('chrome', 'foo', 'foo/'),
+                ManifestLocale('chrome', 'qux', 'x-test', 'qux-l10n/'),
+            ]),
+            'chrome.manifest':
+            ManifestFile('', [Manifest('', 'chrome/chrome.manifest')]),
+            'dict/bb': dict_bb,
+            'dict/cc': dict_cc,
+            'app/chrome/bar-l10n/barbaz.dtd': barbaz_l10n,
+            'app/chrome/chrome.manifest': ManifestFile('app/chrome', [
+                ManifestLocale('app/chrome', 'bar', 'x-test', 'bar-l10n/')
+            ]),
+            'app/chrome.manifest':
+            ManifestFile('app', [Manifest('app', 'chrome/chrome.manifest')]),
+            'app/dict/aa': dict_aa,
+        }
+
+        self.assertEqual(
+            dict((p, f.open().read()) for p, f in copier),
+            dict((p, f.open().read()) for p, f in repacked.iteritems())
+        )
+
+
+if __name__ == '__main__':
+    mozunit.main()
--- a/toolkit/mozapps/installer/l10n-repack.py
+++ b/toolkit/mozapps/installer/l10n-repack.py
@@ -2,39 +2,17 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 '''
 Replace localized parts of a packaged directory with data from a langpack
 directory.
 '''
 
-import os
-import mozpack.path
-from mozpack.packager.formats import (
-    FlatFormatter,
-    JarFormatter,
-    OmniJarFormatter,
-)
-from mozpack.packager import SimplePackager
-from mozpack.files import ManifestFile
-from mozpack.copier import (
-    FileCopier,
-    Jarrer,
-)
-from mozpack.chrome.manifest import (
-    ManifestLocale,
-    ManifestEntryWithRelPath,
-    is_manifest,
-    ManifestChrome,
-    Manifest,
-)
-from mozpack.errors import errors
-from mozpack.packager.unpack import UnpackFinder
-from createprecomplete import generate_precomplete
+from mozpack.packager import l10n
 from argparse import ArgumentParser
 import buildconfig
 
 # Set of files or directories not listed in a chrome.manifest but that are
 # localized.
 NON_CHROME = set([
     '**/crashreporter*.ini',
     'searchplugins',
@@ -43,164 +21,26 @@ NON_CHROME = set([
     'defaults/profile',
     'defaults/pref*/*-l10n.js',
     'update.locale',
     'extensions/langpack-*@*',
     'distribution/extensions/langpack-*@*',
 ])
 
 
-def repack(source, l10n, non_resources=[]):
-    finder = UnpackFinder(source)
-    l10n_finder = UnpackFinder(l10n)
-    copier = FileCopier()
-    if finder.kind == 'flat':
-        formatter = FlatFormatter(copier)
-    elif finder.kind == 'jar':
-        formatter = JarFormatter(copier, optimize=finder.optimizedjars)
-    elif finder.kind == 'omni':
-        formatter = OmniJarFormatter(copier, finder.omnijar,
-                                     optimize=finder.optimizedjars,
-                                     non_resources=non_resources)
-
-    # Read all manifest entries from the packaged directory.
-    manifests = dict((p, m) for p, m in finder.find('**/*.manifest')
-                     if is_manifest(p))
-    assert all(isinstance(m, ManifestFile) for m in manifests.itervalues())
-    entries = [e for m in manifests.itervalues() for e in m if e.localized]
-    # Find unique locales used in these manifest entries.
-    locales = list(set(e.id for e in entries if isinstance(e, ManifestLocale)))
-    # Find all paths whose manifest are included by no other manifest.
-    includes = set(mozpack.path.join(e.base, e.relpath)
-                   for m in manifests.itervalues()
-                   for e in m if isinstance(e, Manifest))
-    bases = [mozpack.path.dirname(p) for p in set(manifests.keys()) - includes]
-
-    # Read all manifest entries from the langpack directory.
-    manifests = [m for p, m in l10n_finder.find('**/*.manifest')
-                 if is_manifest(p)]
-    assert all(isinstance(m, ManifestFile) for m in manifests)
-    l10n_entries = [e for m in manifests for e in m if e.localized]
-    # Find unique locales used in these manifest entries.
-    l10n_locales = list(set(e.id for e in l10n_entries
-                            if isinstance(e, ManifestLocale)))
-
-    # The code further below assumes there's only one locale replaced with
-    # another one.
-    if len(locales) > 1 or len(l10n_locales) > 1:
-        errors.fatal("Multiple locales aren't supported")
-    locale = locales[0]
-    l10n_locale = l10n_locales[0]
-
-    # For each base directory, store what path a locale chrome package name
-    # corresponds to.
-    # e.g., for the following entry under app/chrome:
-    #     locale foo en-US path/to/files
-    # keep track that the locale path for foo in app is
-    # app/chrome/path/to/files.
-    l10n_paths = {}
-    for e in l10n_entries:
-        if isinstance(e, ManifestChrome):
-            base = mozpack.path.basedir(e.path, bases)
-            if not base in l10n_paths:
-                l10n_paths[base] = {}
-            l10n_paths[base][e.name] = e.path
-
-    # For chrome and non chrome files or directories, store what langpack path
-    # corresponds to a package path.
-    paths = dict((e.path,
-                  l10n_paths[mozpack.path.basedir(e.path, bases)][e.name])
-                 for e in entries if isinstance(e, ManifestEntryWithRelPath))
-
-    for pattern in NON_CHROME:
-        for base in bases:
-            path = mozpack.path.join(base, pattern)
-            left = set(p for p, f in finder.find(path))
-            right = set(p for p, f in l10n_finder.find(path))
-            for p in right:
-                paths[p] = p
-            for p in left - right:
-                paths[p] = None
-
-    # Create a new package, with non localized bits coming from the original
-    # package, and localized bits coming from the langpack.
-    packager = SimplePackager(formatter)
-    for p, f in finder:
-        if is_manifest(p):
-            # Remove localized manifest entries.
-            for e in [e for e in f if e.localized]:
-                f.remove(e)
-        # If the path is one that needs a locale replacement, use the
-        # corresponding file from the langpack.
-        path = None
-        if p in paths:
-            path = paths[p]
-            if not path:
-                continue
-        else:
-            base = mozpack.path.basedir(p, paths.keys())
-            if base:
-                subpath = mozpack.path.relpath(p, base)
-                path = mozpack.path.normpath(mozpack.path.join(paths[base],
-                                                               subpath))
-        if path:
-            files = [f for p, f in l10n_finder.find(path)]
-            if not len(files):
-                if base not in NON_CHROME:
-                    errors.error("Missing file: %s" % os.path.join(l10n, path))
-            else:
-                packager.add(path, files[0])
-        else:
-            packager.add(p, f)
-
-    # Add localized manifest entries from the langpack.
-    l10n_manifests = []
-    for base in set(e.base for e in l10n_entries):
-        m = ManifestFile(base)
-        for e in l10n_entries:
-            if e.base == base:
-                m.add(e)
-        path = mozpack.path.join(base, 'chrome.%s.manifest' % l10n_locale)
-        l10n_manifests.append((path, m))
-    bases = packager.get_bases()
-    for path, m in l10n_manifests:
-        base = mozpack.path.basedir(path, bases)
-        packager.add(path, m)
-        # Add a "manifest $path" entry in the top manifest under that base.
-        m = ManifestFile(base)
-        m.add(Manifest(base, mozpack.path.relpath(path, base)))
-        packager.add(mozpack.path.join(base, 'chrome.manifest'), m)
-
-    packager.close()
-
-    # Add any remaining non chrome files.
-    for pattern in NON_CHROME:
-        for base in bases:
-            for p, f in l10n_finder.find(mozpack.path.join(base, pattern)):
-                if not formatter.contains(p):
-                    formatter.add(p, f)
-
-    # Transplant jar preloading information.
-    for path, log in finder.jarlogs.iteritems():
-        assert isinstance(copier[path], Jarrer)
-        copier[path].preload([l.replace(locale, l10n_locale) for l in log])
-
-    copier.copy(source, skip_if_older=False)
-    generate_precomplete(source)
-
-
 def main():
     parser = ArgumentParser()
     parser.add_argument('build',
                         help='Directory containing the build to repack')
     parser.add_argument('l10n',
                         help='Directory containing the staged langpack')
     parser.add_argument('--non-resource', nargs='+', metavar='PATTERN',
                         default=[],
                         help='Extra files not to be considered as resources')
     args = parser.parse_args()
 
     buildconfig.substs['USE_ELF_HACK'] = False
     buildconfig.substs['PKG_SKIP_STRIP'] = True
-    repack(args.build, args.l10n, args.non_resource)
+    l10n.repack(args.build, args.l10n, args.non_resource, NON_CHROME)
+
 
 if __name__ == "__main__":
     main()