Bug 1185666 - Move DMG unpack logic to a python script, support linux. r=mshal
MozReview-Commit-ID: inKT2BWof4
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/action/unpack_dmg.py
@@ -0,0 +1,35 @@
+# 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/.
+
+from __future__ import print_function
+
+from mozpack import dmg
+
+import argparse
+import sys
+
+
+def main(args):
+ parser = argparse.ArgumentParser(
+ description='Explode a DMG into its relevant files')
+
+ parser.add_argument('--dsstore', help='DSStore file from')
+ parser.add_argument('--background', help='Background file from')
+ parser.add_argument('--icon', help='Icon file from')
+
+ parser.add_argument('dmgfile', metavar='DMG_IN',
+ help='DMG File to Unpack')
+ parser.add_argument('outpath', metavar='PATH_OUT',
+ help='Location to put unpacked files')
+
+ options = parser.parse_args(args)
+
+ dmg.extract_dmg(dmgfile=options.dmgfile, output=options.outpath,
+ dsstore=options.dsstore, background=options.background,
+ icon=options.icon)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
--- a/python/mozbuild/mozpack/dmg.py
+++ b/python/mozbuild/mozpack/dmg.py
@@ -4,16 +4,17 @@
import buildconfig
import errno
import mozfile
import os
import platform
import shutil
import subprocess
+import sys
from mozbuild.util import ensureParentDir
is_linux = platform.system() == 'Linux'
def mkdir(dir):
if not os.path.isdir(dir):
@@ -26,18 +27,18 @@ def mkdir(dir):
def chmod(dir):
'Set permissions of DMG contents correctly'
subprocess.check_call(['chmod', '-R', 'a+rX,a-st,u+w,go-w', dir])
def rsync(source, dest):
'rsync the contents of directory source into directory dest'
- # Ensure a trailing slash so rsync copies the *contents* of source.
- if not source.endswith('/'):
+ # Ensure a trailing slash on directories so rsync copies the *contents* of source.
+ if not source.endswith('/') and os.path.isdir(source):
source += '/'
subprocess.check_call(['rsync', '-a', '--copy-unsafe-links',
source, dest])
def set_folder_icon(dir, tmpdir):
'Set HFS attributes of dir to use a custom icon'
if not is_linux:
@@ -151,8 +152,58 @@ def create_dmg(source_directory, output_
mkdir(os.path.dirname(full_target))
shutil.copyfile(source, full_target)
generate_hfs_file(stagedir, tmpdir, volume_name)
create_app_symlink(stagedir, tmpdir)
# Set the folder attributes to use a custom icon
set_folder_icon(stagedir, tmpdir)
chmod(stagedir)
create_dmg_from_staged(stagedir, output_dmg, tmpdir, volume_name)
+
+
+def extract_dmg_contents(dmgfile, destdir):
+ import buildconfig
+ if is_linux:
+ with mozfile.TemporaryDirectory() as tmpdir:
+ hfs_file = os.path.join(tmpdir, 'firefox.hfs')
+ subprocess.check_call([
+ buildconfig.substs['DMG_TOOL'],
+ 'extract',
+ dmgfile,
+ hfs_file
+ ],
+ # dmg is seriously chatty
+ stdout=open(os.devnull, 'wb'))
+ subprocess.check_call([
+ buildconfig.substs['HFS_TOOL'], hfs_file, 'extractall', '/', destdir])
+ else:
+ unpack_diskimage = os.path.join(buildconfig.topsrcdir, 'build', 'package',
+ 'mac_osx', 'unpack-diskimage')
+ unpack_mountpoint = os.path.join(
+ '/tmp', '{}-unpack'.format(buildconfig.substs['MOZ_APP_NAME']))
+ subprocess.check_call([unpack_diskimage, dmgfile, unpack_mountpoint,
+ destdir])
+
+
+def extract_dmg(dmgfile, output, dsstore=None, icon=None, background=None):
+ if platform.system() not in ('Darwin', 'Linux'):
+ raise Exception("Don't know how to extract a DMG on '%s'" % platform.system())
+
+ if is_linux:
+ check_tools('DMG_TOOL', 'MKFSHFS', 'HFS_TOOL')
+
+ with mozfile.TemporaryDirectory() as tmpdir:
+ extract_dmg_contents(dmgfile, tmpdir)
+ if os.path.islink(os.path.join(tmpdir, ' ')):
+ # Rsync will fail on the presence of this symlink
+ os.remove(os.path.join(tmpdir, ' '))
+ rsync(tmpdir, output)
+
+ if dsstore:
+ mkdir(os.path.dirname(dsstore))
+ rsync(os.path.join(tmpdir, '.DS_Store'), dsstore)
+ if background:
+ mkdir(os.path.dirname(background))
+ rsync(os.path.join(tmpdir, '.background', os.path.basename(background)),
+ background)
+ if icon:
+ mkdir(os.path.dirname(icon))
+ rsync(os.path.join(tmpdir, '.VolumeIcon.icns'), icon)
--- a/toolkit/mozapps/installer/upload-files.mk
+++ b/toolkit/mozapps/installer/upload-files.mk
@@ -205,40 +205,22 @@ endif
ifeq ($(MOZ_PKG_FORMAT),DMG)
PKG_SUFFIX = .dmg
_ABS_MOZSRCDIR = $(shell cd $(MOZILLA_DIR) && pwd)
PKG_DMG_SOURCE = $(MOZ_PKG_DIR)
INNER_MAKE_PACKAGE = $(call py_action,make_dmg,'$(PKG_DMG_SOURCE)' '$(PACKAGE)')
INNER_UNMAKE_PACKAGE = \
- set -ex; \
- rm -rf $(ABS_DIST)/unpack.tmp; \
- mkdir -p $(ABS_DIST)/unpack.tmp; \
- $(_ABS_MOZSRCDIR)/build/package/mac_osx/unpack-diskimage $(UNPACKAGE) /tmp/$(MOZ_PKG_APPNAME)-unpack $(ABS_DIST)/unpack.tmp; \
- rsync -a '$(ABS_DIST)/unpack.tmp/$(_APPNAME)' $(MOZ_PKG_DIR); \
- if test -n '$(MOZ_PKG_MAC_DSSTORE)' ; then \
- mkdir -p '$(dir $(MOZ_PKG_MAC_DSSTORE))'; \
- rsync -a '$(ABS_DIST)/unpack.tmp/.DS_Store' '$(MOZ_PKG_MAC_DSSTORE)'; \
- fi; \
- if test -n '$(MOZ_PKG_MAC_BACKGROUND)' ; then \
- mkdir -p '$(dir $(MOZ_PKG_MAC_BACKGROUND))'; \
- rsync -a '$(ABS_DIST)/unpack.tmp/.background/$(notdir $(MOZ_PKG_MAC_BACKGROUND))' '$(MOZ_PKG_MAC_BACKGROUND)'; \
- fi; \
- if test -n '$(MOZ_PKG_MAC_ICON)' ; then \
- mkdir -p '$(dir $(MOZ_PKG_MAC_ICON))'; \
- rsync -a '$(ABS_DIST)/unpack.tmp/.VolumeIcon.icns' '$(MOZ_PKG_MAC_ICON)'; \
- fi; \
- rm -rf $(ABS_DIST)/unpack.tmp; \
- if test -n '$(MOZ_PKG_MAC_RSRC)' ; then \
- cp $(UNPACKAGE) $(MOZ_PKG_APPNAME).tmp.dmg && \
- hdiutil unflatten $(MOZ_PKG_APPNAME).tmp.dmg && \
- { /Developer/Tools/DeRez -skip plst -skip blkx $(MOZ_PKG_APPNAME).tmp.dmg > '$(MOZ_PKG_MAC_RSRC)' || { rm -f $(MOZ_PKG_APPNAME).tmp.dmg && false; }; } && \
- rm -f $(MOZ_PKG_APPNAME).tmp.dmg; \
- fi
+ $(call py_action,unpack_dmg, \
+ $(if $(MOZ_PKG_MAC_DSSTORE),--dsstore '$(MOZ_PKG_MAC_DSSTORE)') \
+ $(if $(MOZ_PKG_MAC_BACKGROUND),--background '$(MOZ_PKG_MAC_BACKGROUND)') \
+ $(if $(MOZ_PKG_MAC_ICON),--icon '$(MOZ_PKG_MAC_ICON)') \
+ '$(UNPACKAGE)' '$(MOZ_PKG_DIR)' \
+ );
endif
ifdef MOZ_INTERNAL_SIGNING_FORMAT
MOZ_SIGN_PREPARED_PACKAGE_CMD=$(MOZ_SIGN_CMD) $(foreach f,$(MOZ_INTERNAL_SIGNING_FORMAT),-f $(f)) $(foreach i,$(SIGN_INCLUDES),-i $(i)) $(foreach x,$(SIGN_EXCLUDES),-x $(x))
ifeq (WINNT,$(OS_ARCH))
MOZ_SIGN_PREPARED_PACKAGE_CMD += --nsscmd '$(ABS_DIST)/bin/shlibsign$(BIN_SUFFIX) -v -i'
endif
endif