Skip to content

Commit

Permalink
feat: add dmg configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
amr-crabnebula and Andreybest committed Nov 30, 2023
1 parent 0d12f48 commit 1f74c12
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .changes/dmg-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"cargo-packager": "patch"
---

Add `config.dmg` to configure the DMG on macOS.
115 changes: 115 additions & 0 deletions crates/packager/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,17 @@
"type": "null"
}
]
},
"dmg": {
"description": "Dmg configuration.",
"anyOf": [
{
"$ref": "#/definitions/DmgConfig"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
Expand Down Expand Up @@ -1082,6 +1093,110 @@
]
}
]
},
"DmgConfig": {
"description": "The Apple Disk Image (.dmg) configuration.",
"type": "object",
"properties": {
"background": {
"description": "Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.",
"type": [
"string",
"null"
]
},
"windowPosition": {
"description": "Position of volume window on screen.",
"anyOf": [
{
"$ref": "#/definitions/Position"
},
{
"type": "null"
}
]
},
"windowSize": {
"description": "Size of volume window.",
"anyOf": [
{
"$ref": "#/definitions/Size"
},
{
"type": "null"
}
]
},
"appPosition": {
"description": "Position of application file on window.",
"anyOf": [
{
"$ref": "#/definitions/Position"
},
{
"type": "null"
}
]
},
"appFolderPosition": {
"description": "Position of application folder on window.",
"anyOf": [
{
"$ref": "#/definitions/Position"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"Position": {
"description": "Position coordinates struct.",
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"description": "X coordinate.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"y": {
"description": "Y coordinate.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
},
"Size": {
"description": "Size struct.",
"type": "object",
"required": [
"height",
"width"
],
"properties": {
"width": {
"description": "Width.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"height": {
"description": "Height.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
}
}
91 changes: 91 additions & 0 deletions crates/packager/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,10 +470,94 @@ impl AppImageConfig {
}
}

/// Position coordinates struct.
#[derive(Default, Copy, Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct Position {
/// X coordinate.
pub x: u32,
/// Y coordinate.
pub y: u32,
}

/// Size struct.
#[derive(Default, Copy, Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct Size {
/// Width.
pub width: u32,
/// Height.
pub height: u32,
}

/// The Apple Disk Image (.dmg) configuration.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[non_exhaustive]
pub struct DmgConfig {
/// Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.
pub background: Option<PathBuf>,
/// Position of volume window on screen.
pub window_position: Option<Position>,
/// Size of volume window.
#[serde(alias = "window-size", alias = "window_size")]
pub window_size: Option<Size>,
/// Position of application file on window.
#[serde(alias = "app-position", alias = "app_position")]
pub app_position: Option<Position>,
/// Position of application folder on window.
#[serde(
alias = "application-folder-position",
alias = "application_folder_position"
)]
pub app_folder_position: Option<Position>,
}

impl DmgConfig {
/// Creates a new [`DmgConfig`].
pub fn new() -> Self {
Self::default()
}

/// Set an image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.
pub fn background<P: Into<PathBuf>>(mut self, path: P) -> Self {
self.background.replace(path.into());
self
}

/// Set the poosition of volume window on screen.
pub fn window_position(mut self, position: Position) -> Self {
self.window_position.replace(position);
self
}

/// Set the size of volume window.
pub fn window_size(mut self, size: Size) -> Self {
self.window_size.replace(size);
self
}

/// Set the poosition of app file on window.
pub fn app_position(mut self, position: Position) -> Self {
self.app_position.replace(position);
self
}

/// Set the position of application folder on window.
pub fn app_folder_position(mut self, position: Position) -> Self {
self.app_folder_position.replace(position);
self
}
}

/// The macOS configuration.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[non_exhaustive]
pub struct MacOsConfig {
/// MacOS frameworks that need to be packaged with the app.
///
Expand Down Expand Up @@ -1437,6 +1521,8 @@ pub struct Config {
pub wix: Option<WixConfig>,
/// Nsis configuration.
pub nsis: Option<NsisConfig>,
/// Dmg configuration.
pub dmg: Option<DmgConfig>,
}

impl Config {
Expand Down Expand Up @@ -1475,6 +1561,11 @@ impl Config {
self.appimage.as_ref()
}

/// Returns the [dmg](Config::dmg) specific configuration.
pub fn dmg(&self) -> Option<&DmgConfig> {
self.dmg.as_ref()
}

/// Returns the target triple of this config, if not set, fallsback to the current OS target triple.
pub fn target_triple(&self) -> String {
self.target_triple.clone().unwrap_or_else(|| {
Expand Down
91 changes: 68 additions & 23 deletions crates/packager/src/package/dmg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,55 +86,100 @@ pub(crate) fn package(ctx: &Context) -> crate::Result<Vec<PathBuf>> {
include_str!("eula-resources-template.xml"),
)?;

let mut args = vec![
let dmg = config.dmg();

let mut bundle_dmg_cmd = Command::new(&create_dmg_script_path);

let app_x = dmg
.and_then(|d| d.app_position.x)
.unwrap_or(180)
.to_string();
let app_y = dmg
.and_then(|d| d.app_position.y)
.unwrap_or(170)
.to_string();
let app_folder_x = dmg
.and_then(|d| d.app_folder_position.x)
.unwrap_or(480)
.to_string();
let app_folder_y = dmg
.and_then(|d| d.app_folder_position.y)
.unwrap_or(170)
.to_string();
let window_width = dmg
.and_then(|d| d.window_size.width)
.unwrap_or(600)
.to_string();
let window_height = dmg
.and_then(|d| d.window_size.height)
.unwrap_or(400)
.to_string();

bundle_dmg_cmd.args([
"--volname",
&config.product_name,
"--icon",
&app_bundle_file_name,
"180",
"170",
&app_x,
&app_y,
"--app-drop-link",
"480",
"170",
&app_folder_x,
&app_folder_y,
"--window-size",
"660",
"400",
&window_width,
&window_height,
"--hide-extension",
&app_bundle_file_name,
];
]);

let window_position = dmg
.and_then(|d| d.window_position)
.map(|p| (p.x.to_string(), p.y.to_string()));
if let Some((x, y)) = window_position {
bundle_dmg_cmd.arg("--window-pos");
bundle_dmg_cmd.arg(&x);
bundle_dmg_cmd.arg(&y);
}

let background_path = if let Some(background_path) = &dmg.and_then(|d| d.background) {
Some(env::current_dir()?.join(background_path))
} else {
None
};

if let Some(background_path) = &background_path {
bundle_dmg_cmd.arg("--background");
bundle_dmg_cmd.arg(background_path);
}

tracing::debug!("Creating icns file");
let icns_icon_path = util::create_icns_file(&intermediates_path, config)?
.map(|path| path.to_string_lossy().to_string());
let icns_icon_path = util::create_icns_file(&intermediates_path, config)?;
if let Some(icon) = &icns_icon_path {
args.push("--volicon");
args.push(icon);
bundle_dmg_cmd.arg("--volicon");
bundle_dmg_cmd.arg(icon);
}

let license_file = config.license_file.as_ref().map(|l| {
std::env::current_dir()
.unwrap()
.join(l)
.to_string_lossy()
.to_string()
});
let license_file = config
.license_file
.as_ref()
.map(|l| std::env::current_dir()?.join(l));
if let Some(license_path) = &license_file {
args.push("--eula");
args.push(license_path.as_str());
bundle_dmg_cmd.arg("--eula");
bundle_dmg_cmd.arg(license_path);
}

// Issue #592 - Building MacOS dmg files on CI
// https://github.com/tauri-apps/tauri/issues/592
if let Some(value) = std::env::var_os("CI") {
if value == "true" {
args.push("--skip-jenkins");
bundle_dmg_cmd.push("--skip-jenkins");
}
}

tracing::info!("Running create-dmg");

// execute the bundle script
Command::new(&create_dmg_script_path)
bundle_dmg_cmd
.current_dir(&out_dir)
.args(args)
.args(vec![dmg_name.as_str(), app_bundle_file_name.as_str()])
Expand Down
4 changes: 1 addition & 3 deletions crates/packager/src/package/wix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,10 +476,8 @@ fn build_wix_app_installer(ctx: &Context, wix_path: &Path) -> crate::Result<Vec<

let mut data = BTreeMap::new();

let app_version = convert_version(&config.version)?;

data.insert("product_name", to_json(&config.product_name));
data.insert("version", to_json(app_version));
data.insert("version", to_json(convert_version(&config.version)?));
let identifier = config.identifier();
let manufacturer = config.publisher();
data.insert("identifier", to_json(identifier));
Expand Down

0 comments on commit 1f74c12

Please sign in to comment.