Feat(bundler) dmg bundler (#38)

* feat(cli) init tauri mode

Signed-off-by: Daniel Thompson-Yvetot <denjell@quasar.dev>

* feat(cli:init) add force & logging flags, full JSDoc

Signed-off-by: Daniel Thompson-Yvetot <denjell@quasar.dev>

* feat(cli:init) remove console.log

Signed-off-by: Daniel Thompson-Yvetot <denjell@quasar.dev>

* feat(cli:dev) get rust compile to finish

Signed-off-by: Daniel Thompson-Yvetot <denjell@quasar.dev>

* feat(cli:build) get rust compile to finish

Signed-off-by: Daniel Thompson-Yvetot <denjell@quasar.dev>

* feat(cli) set template with current working defaults

Signed-off-by: Daniel Thompson-Yvetot <denjell@quasar.dev>

* chore(version) bump

Signed-off-by: Daniel Thompson-Yvetot <denjell@quasar.dev>

* fix(typo)

Signed-off-by: Daniel Thompson-Yvetot <denjell@quasar.dev>

* fix(template): missing name warning

Signed-off-by: Daniel Thompson-Yvetot <denjell@quasar.dev>

* fix(bundler): correct repository link

Signed-off-by: Daniel Thompson-Yvetot <denjell@quasar.dev>

* feat(lib|cli) read config from tauriDir

* chore(cli) remove console.log statement

* fix(embedded-server) JS content type

* feat(template): add rust2018 flag

* chore(docs): remove docs

* add bash templates

* setup handlebars

* output both templates

* finish bundle_project logic

* comment and cleanup

* correct path

* fix(bundler): osx not ios

* feat(dmg): get it to work and look ok WIP
- add background image
- link seticon
This commit is contained in:
Tensor-Programming 2019-10-07 16:03:18 -04:00 committed by nothingismagick
parent 0fd0d2cf48
commit f3929c13d9
6 changed files with 228 additions and 0 deletions

View File

@ -134,3 +134,7 @@ stability.
This program is licensed either under the terms of the
[Apache Software License](http://www.apache.org/licenses/LICENSE-2.0), or the
[MIT License](https://opensource.org/licenses/MIT).
-> note, for bundle_dmg we have included a BSD 3 licenced binary `seticon`.
https://github.com/sveinbjornt/osxiconutils/blob/master/seticon.m
`tools/rust/cargo-tauri-bundle/src/bundle/templates/seticon`

View File

@ -1,6 +1,7 @@
mod category;
mod common;
mod deb_bundle;
mod dmg_bundle;
mod ios_bundle;
mod msi_bundle;
mod osx_bundle;
@ -18,9 +19,12 @@ pub fn bundle_project(settings: Settings) -> crate::Result<Vec<PathBuf>> {
paths.append(&mut match package_type {
PackageType::OsxBundle => osx_bundle::bundle_project(&settings)?,
PackageType::IosBundle => ios_bundle::bundle_project(&settings)?,
// use dmg bundler
// PackageType::OsxBundle => dmg_bundle::bundle_project(&settings)?,
PackageType::WindowsMsi => msi_bundle::bundle_project(&settings)?,
PackageType::Deb => deb_bundle::bundle_project(&settings)?,
PackageType::Rpm => rpm_bundle::bundle_project(&settings)?,
PackageType::Dmg => dmg_bundle::bundle_project(&settings)?,
});
}
Ok(paths)

View File

@ -0,0 +1,73 @@
use super::common;
use super::osx_bundle;
use crate::Settings;
use handlebars::Handlebars;
use lazy_static::lazy_static;
use std::collections::BTreeMap;
use std::fs::write;
use std::path::PathBuf;
use std::process::{Command, Stdio};
// Create handlebars template for shell scripts
lazy_static! {
static ref HANDLEBARS: Handlebars = {
let mut handlebars = Handlebars::new();
handlebars
.register_template_string("bundle_dmg", include_str!("templates/bundle_dmg"))
.unwrap();
handlebars
};
}
// create script files to bundle project and execute bundle_script.
pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
// generate the app.app folder
osx_bundle::bundle_project(settings)?;
// get uppercase string of app name
let upcase = settings.binary_name().to_uppercase();
// generate BTreeMap for templates
let mut sh_map = BTreeMap::new();
sh_map.insert("app_name", settings.binary_name());
sh_map.insert("app_name_upcase", &upcase);
let bundle_temp = HANDLEBARS
.render("bundle_dmg", &sh_map)
.or_else(|e| Err(e.to_string()))?;
// get the target path
let output_path = settings.project_out_directory();
// create paths for script
let bundle_sh = output_path.join("bundle_dmg.sh");
common::print_bundling(format!("{:?}", &output_path.join(format!("{}.dmg", &upcase))).as_str())?;
// write the scripts
write(&bundle_sh, bundle_temp).or_else(|e| Err(e.to_string()))?;
// chmod script for execution
Command::new("chmod")
.arg("777")
.arg(&bundle_sh)
.current_dir(output_path)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.expect("Failed to chmod script");
// execute the bundle script
Command::new(&bundle_sh)
.current_dir(output_path)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.expect("Failed to execute shell script");
Ok(vec![bundle_sh])
}

View File

@ -17,6 +17,7 @@ pub enum PackageType {
WindowsMsi,
Deb,
Rpm,
Dmg,
}
impl PackageType {
@ -28,6 +29,7 @@ impl PackageType {
"msi" => Some(PackageType::WindowsMsi),
"osx" => Some(PackageType::OsxBundle),
"rpm" => Some(PackageType::Rpm),
"dmg" => Some(PackageType::Dmg),
_ => None,
}
}
@ -39,6 +41,7 @@ impl PackageType {
PackageType::WindowsMsi => "msi",
PackageType::OsxBundle => "osx",
PackageType::Rpm => "rpm",
PackageType::Dmg => "dmg",
}
}

View File

@ -0,0 +1,144 @@
#!/usr/bin/env sh
# using sh because modern MacOS ships with zsh not bash
# some patterns "lifted" from:
# - https://github.com/andreyvit/create-dmg/blob/master/create-dmg
# - https://stackoverflow.com/a/97025
# - https://github.com/sindresorhus/create-dmg/blob/master/cli.js
set -e
MACOS_APP_NAME="{{app_name_upcase}}"
MACOS_APP_DIR="bundle/osx/{{app_name}}.app"
ICNS_FILE="app.app/Contents/Resources/icon.icns"
DMG_TEMP_NAME=/tmp/temp.dmg
MOUNT_DIR="/Volumes/${MACOS_APP_NAME}"
# Create the image
echo "Creating disk image..."
test -f "${DMG_TEMP_NAME}" && rm -f "${DMG_TEMP_NAME}"
test -f "${MACOS_APP_NAME}.dmg" && rm -f "${MACOS_APP_NAME}.dmg"
hdiutil create ${DMG_TEMP_NAME} -srcfolder bundle/osx -volname "${MACOS_APP_NAME}" -ov -format UDRW -size 10000k -fs HFS+ -fsargs "-c c=64,a=16,e=16" -anyowners -nospotlight
# mount it
echo "Mounting disk image..."
# try unmount dmg if it was mounted previously (e.g. developer mounted dmg, installed app and forgot to unmount it)
DEV_NAME=$(hdiutil info | egrep --color=never '^/dev/' | sed 1q | awk '{print $1}')
test -d "${MOUNT_DIR}" && hdiutil detach "${DEV_NAME}"
device=$(hdiutil attach -readwrite -noverify -noautoopen "${DMG_TEMP_NAME}" | \
egrep '^/dev/' | sed 1q | awk '{print $1}')
sleep 5
bless --folder "${MOUNT_DIR}" -label "${MACOS_APP_NAME}"
test -d "${MOUNT_DIR}/.background" || mkdir "${MOUNT_DIR}/.background"
cp ../../icons/bg.png "${MOUNT_DIR}"/.background/bg.png
# I couldn't get DeRez and Rez to work. Leaving it here in case its helpful in the future.
### DeRez -only icns "${MOUNT_DIR}/.VolumeIcon.icns" > "${MOUNT_DIR}/.VolumeIcon.rsrc"
### Rez -append "${MOUNT_DIR}/.VolumeIcon.rsrc" -o my_app.dmg
# This Works
cp '../../icons/icon.icns' "${MOUNT_DIR}/.VolumeIcon.icns"
VERSION=$(sw_vers -productVersion | cut -d'.' -f2)
if [ "$VERSION" -gt 12 ]; then
echo "Using SIPS v10.13+"
sips --i "${MOUNT_DIR}/.VolumeIcon.icns" # 10.13+
else
echo "Using SIPS v10.12-"
sips --addIcon "${MOUNT_DIR}/.VolumeIcon.icns"
fi
SetFile -c icnC "${MOUNT_DIR}/.VolumeIcon.icns"
SetFile -a C "${MOUNT_DIR}"
# Doesn't stick after the renaming
### ./seticon "${MOUNT_DIR}/${ICNS_FILE}" "${DMG_TEMP_NAME}"
# This does not work
### echo "read 'icns' (-16455) \"${MOUNT_DIR}/.VolumeIcon.icns\";" >> Icon.rsrc
### Rez -a Icon.rsrc -o FileName.ext
### DeRez -only icns "${MOUNT_DIR}/.VolumeIcon.icns" > "${MOUNT_DIR}/.Icon.rsrc"
### Rez -a Icon.rsrc -o "${MOUNT_DIR}/Icon$'\r'"
### SetFile -c icnC "${MOUNT_DIR}/.Icon.rsrc"
### SetFile -a C "${MOUNT_DIR}"
### SetFile -a "${MOUNT_DIR}/Icon$'\r'"
# this is from
# https://stackoverflow.com/questions/8371790/how-to-set-icon-on-file-or-directory-using-cli-on-os-x#8375093
### iconSource='../../icons/icon.icns'
### iconDestination="${MOUNT_DIR}"
### icon=/tmp/$(basename $iconSource)
### rsrc=/tmp/icon.rsrc
# Create icon from the iconSource
### cp $iconSource $icon
# Add icon to image file, meaning use itself as the icon
### sips -i $icon
# Take that icon and put it into a rsrc file
### DeRez -only icns $icon > $rsrc
# Apply the rsrc file to
### SetFile -a C "${iconDestination}"
# Create the magical Icon\r file
### touch "${iconDestination}/Icon$'\r'"
### Rez -append $rsrc -o "${iconDestination}/Icon?"
### SetFile -a V "${iconDestination}/Icon$'\r'"
echo '
tell application "Finder"
tell disk "'${MACOS_APP_NAME}'"
open
set current view of container window to icon view
set toolbar visible of container window to false
set statusbar visible of container window to false
set the bounds of container window to {400, 100, 885, 430}
set theViewOptions to the icon view options of container window
set arrangement of theViewOptions to not arranged
set icon size of theViewOptions to 110
set background picture of theViewOptions to file ".background:'bg.png'"
make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"}
set position of item "'app.app'" of container window to {100, 100}
set position of item "Applications" of container window to {375, 100}
update without registering applications
delay 5
close
end tell
end tell
' | osascript
chmod -Rf go-w /Volumes/"${MACOS_APP_NAME}"
sync
sync
hdiutil detach ${device}
# Some variations on format:
## UDZO Compressed image (default)
## UDRO Read-only image
## UDBZ Better compressed image
## UDRW Read/Write image
hdiutil convert "${DMG_TEMP_NAME}" -format UDBZ -imagekey zlib-level=9 -o "${MACOS_APP_NAME}"
./seticon ../../icons/icon.icns "${MACOS_APP_NAME}.dmg"
rm -f ${DMG_TEMP_NAME}
# This seems not to work as well at maintaining the icons :(
zip -r "${MACOS_APP_NAME}.dmg.zip" "${MACOS_APP_NAME}.dmg"
# FUTURE WORK
# SIGNER=$(security find-identity -v -p codesigning)
# codesign --sign 'Mac Developer' "${DMG_TEMP_NAME}"
# Add a license with Rez
# http://www.owsiak.org/adding-license-to-a-dmg-file-in-5-minutes-or-less/

Binary file not shown.