hdiutil

package module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2026 License: MIT Imports: 10 Imported by: 1

README

hdiutil

Build Go Reference Go Report Card Codecov License

Package hdiutil provides a Go wrapper around the macOS hdiutil command-line tool for creating, manipulating, and signing DMG disk images.

Note: This package requires macOS — it wraps native macOS tooling (hdiutil, codesign, xcrun, bless).

Features

Image formats UDZO (zlib, default), UDBZ (bzip2), ULFO (lzfse), ULMO (lzma)
Filesystems HFS+ (default, with tuned allocation parameters) and APFS
Workflow orchestration Runner manages the full lifecycle: create, mount, modify, convert, sign, notarize
Sandbox-safe images Produce DMGs openable by sandboxed macOS applications
Code signing & notarization Integrated codesign and Apple notarytool/stapler support
JSON configuration Load/save Config from JSON files for CI/CD pipelines
Input sanitization Rejects null bytes and dash-prefixed paths to prevent argument injection
Dry-run mode Simulate() option previews all hdiutil invocations without executing them
Testable Typed CommandExecutor interface with WithExecutor and Simulate options for mock injection

Installation

go get al.essio.dev/pkg/hdiutil

Quick start

package main

import (
	"log"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := &hdiutil.Config{
		SourceDir:  "./dist",
		OutputPath: "MyApp.dmg",
		VolumeName: "My App",
	}

	runner := hdiutil.New(cfg)
	defer runner.Cleanup()

	// 1. Validate config, create temp directory.
	if err := runner.Setup(); err != nil {
		log.Fatal(err)
	}

	// 2. Create a writable temporary image populated from SourceDir.
	if err := runner.Start(); err != nil {
		log.Fatal(err)
	}

	// 3. (Optional) Mount, modify contents, unmount.
	// if err := runner.AttachDiskImage(); err != nil { log.Fatal(err) }
	// ... copy files, customise .DS_Store, etc.
	// _ = runner.Bless()           // mark bootable (no-op unless Config.Bless is set)
	// _ = runner.DetachDiskImage() // fixes permissions and unmounts

	// 4. Convert to final compressed DMG.
	if err := runner.FinalizeDMG(); err != nil {
		log.Fatal(err)
	}

	// 5. (Optional) Sign and notarize — no-ops when credentials are empty.
	if err := runner.Codesign(); err != nil {
		log.Fatal(err)
	}
	if err := runner.Notarize(); err != nil {
		log.Fatal(err)
	}
}

Sandbox-safe images

cfg := &hdiutil.Config{
	SourceDir:   "./dist",
	OutputPath:  "MyApp.dmg",
	SandboxSafe: true,
	FileSystem:  "HFS+", // APFS is not supported in sandbox-safe mode
}

Runner lifecycle

The Runner goes through a fixed sequence of steps — calling methods out of order returns an error.

Setup ➜ Start ➜ [Attach ➜ modify ➜ Bless ➜ Detach] ➜ FinalizeDMG ➜ [Codesign] ➜ [Notarize]
  │                        optional                                      optional
  └─ validates config, creates temp dir

License

This package is part of the unixtools project and is released under the same license.

Documentation

Overview

Package hdiutil provides a Go wrapper around the macOS hdiutil command-line tool for creating, manipulating, and signing DMG disk images.

Supported formats and filesystems

The following compressed image formats are supported via [Config.ImageFormat]:

  • UDZO — zlib compression (level 9). This is the default and the most widely compatible format.
  • UDBZ — bzip2 compression (level 9). Better compression ratio than UDZO at the cost of slower creation and extraction.
  • ULFO — lzfse compression. Apple's modern codec; fast with good ratios, but only supported on macOS 10.11+.
  • ULMO — lzma compression. Highest compression ratio, slowest speed.

The following filesystem types are supported via [Config.FileSystem]:

  • HFS+ — the default; includes tuned allocation parameters (-fsargs -c c=64,a=16,e=16).
  • APFS — Apple File System. Cannot be combined with [Config.SandboxSafe].

Configuration

A Config struct holds all settings for image creation. It can be built programmatically or deserialized from JSON with Config.FromJSON. Configs can also be serialized with Config.ToJSON for round-tripping through pipelines or storage.

Config.Validate must be called (either directly or implicitly through Runner.Setup) before the lazy option functions ([Config.FilesystemOpts], [Config.ImageFormatOpts], [Config.VolumeSizeOpts], [Config.VolumeNameOpt]) become usable. Calling them before validation panics.

Required fields:

  • [Config.SourceDir] — directory whose contents are copied into the DMG.
  • [Config.OutputPath] — destination path; must end in ".dmg".

Optional fields with defaults:

  • [Config.VolumeName] — defaults to the output filename without extension (e.g. "MyApp.dmg" → "MyApp").
  • [Config.VolumeSizeMb] — when zero, hdiutil sizes the image automatically.
  • [Config.ImageFormat] — defaults to "UDZO".
  • [Config.FileSystem] — defaults to "HFS+".

Runner lifecycle

New creates a Runner from a Config. The Runner must go through a fixed sequence of steps; calling methods out of order returns an error (typically ErrNeedInit).

cfg := &hdiutil.Config{
	SourceDir:  "path/to/source",
	OutputPath: "output.dmg",
	VolumeName: "MyVolume",
}

runner := hdiutil.New(cfg)
defer runner.Cleanup()

// 1. Validate config, create temp directory.
if err := runner.Setup(); err != nil {
	log.Fatal(err)
}

// 2. Create a writable temporary image populated from SourceDir.
if err := runner.Start(); err != nil {
	log.Fatal(err)
}

// 3. (Optional) Mount the image, modify contents, mark bootable, unmount.
if err := runner.AttachDiskImage(); err != nil {
	log.Fatal(err)
}
// ... copy additional files into runner.MountDir, customise .DS_Store, etc.
_ = runner.Bless()           // mark as bootable (no-op unless Config.Bless is set)
_ = runner.DetachDiskImage() // fixes permissions and unmounts

// 4. Convert the writable image to the final compressed format.
if err := runner.FinalizeDMG(); err != nil {
	log.Fatal(err)
}

// 5. (Optional) Sign and notarize.
if err := runner.Codesign(); err != nil {  // no-op when SigningIdentity is empty
	log.Fatal(err)
}
if err := runner.Notarize(); err != nil {  // no-op when NotarizeCredentials is empty
	log.Fatal(err)
}

Runner.Cleanup removes the temporary working directory and is safe to call multiple times.

Sandbox-safe images

Setting [Config.SandboxSafe] uses a two-step process (hdiutil makehybrid + convert) that produces images openable by sandboxed macOS applications. APFS cannot be used in this mode; attempting it returns ErrSandboxAPFS. The Runner.Bless step is also skipped for sandbox-safe images.

Code signing and notarization

When [Config.SigningIdentity] is set, Runner.Codesign signs the final DMG and verifies the signature with --deep --strict. When [Config.NotarizeCredentials] is set to a keychain profile name, Runner.Notarize submits the DMG via xcrun notarytool and staples the ticket with xcrun stapler. Both methods are no-ops when their respective config fields are empty.

Verbosity

[Config.HDIUtilVerbosity] controls the flags passed to hdiutil:

  • 0 — no flag (default).
  • 1 — -quiet.
  • 2 — -verbose.
  • 3+ — -debug.

Negative values are treated as 0.

Logging

Internal log messages are discarded by default. Call SetLogWriter with os.Stderr (or any io.Writer) to enable them.

Dry-run mode

Passing the Simulate option to New logs every external command without executing it, which is useful for previewing the hdiutil invocations that would be made. Simulate mode can also be toggled at runtime via Runner.SetSimulate.

Input sanitization

Config.Validate rejects values that could lead to OS command argument injection:

  • Null bytes in any string field (SourceDir, OutputPath, VolumeName, SigningIdentity, NotarizeCredentials).
  • Paths (SourceDir, OutputPath) that start with a dash after filepath.Clean, which could be misinterpreted as flags by external commands.

Error handling

Sentinel errors are defined for every category of failure and can be matched with errors.Is:

Testing

The CommandExecutor interface and the WithExecutor functional option allow injecting a mock executor into New, so tests can verify command arguments and simulate failures without invoking real binaries. CommandExecutor uses typed methods (Hdiutil, Codesign, Xcrun, Chmod, Bless) rather than a generic Run(name, args...) to ensure that only known commands can be executed and that static analysis tools see literal command names in each exec.Command call.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvSourceDir indicates the source directory is empty or invalid.
	ErrInvSourceDir = errors.New("invalid source directory")
	// ErrVolumeSize indicates that a negative volume size.
	ErrVolumeSize = errors.New("volume size must be >= 0")
	// ErrInvFormatOpt indicates an unsupported image format was specified.
	ErrInvFormatOpt = errors.New("invalid image format")
	// ErrInvFilesystemOpt indicates an unsupported filesystem type was specified.
	ErrInvFilesystemOpt = errors.New("invalid image filesystem")
	// ErrCreateDir indicates a failure to create a temporary working directory.
	ErrCreateDir = errors.New("couldn't create directory")
	// ErrImageFileExt indicates the output path doesn't have a .dmg extension.
	ErrImageFileExt = errors.New("output file must have a .dmg extension")
	// ErrMountImage indicates failure to attach/mount the disk image.
	ErrMountImage = errors.New("couldn't attach disk image")
	// ErrCodesignFailed indicates the codesign command failed or signature verification failed.
	ErrCodesignFailed = errors.New("codesign command failed")
	// ErrNotarizeFailed indicates Apple notarization or stapling failed.
	ErrNotarizeFailed = errors.New("notarization failed")
	// ErrSandboxAPFS indicates an attempt to create a sandbox-safe APFS image, which is unsupported.
	ErrSandboxAPFS = errors.New("creating an APFS disk image that is sandbox safe is not supported")
	// ErrNeedInit indicates Runner.Setup was not called before attempting operations.
	ErrNeedInit = errors.New("runner not properly initialized, call Setup() first")
	// ErrUnsafeArg indicates a config value contains characters unsafe for command arguments.
	ErrUnsafeArg = errors.New("argument contains unsafe characters")
)

Error variables for common failure conditions during DMG creation.

View Source
var HdiutilExe string

Functions

func SetLogWriter

func SetLogWriter(w io.Writer)

SetLogWriter configures the output writer for verbose logging. By default, verbose logging is discarded. Pass os.Stdout or os.Stderr to enable logging output.

Example
package main

import (
	"bytes"
	"fmt"
	"os"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	var buf bytes.Buffer
	hdiutil.SetLogWriter(&buf)
	defer hdiutil.SetLogWriter(os.Stderr)

	cfg := &hdiutil.Config{
		SourceDir:  "./dist",
		OutputPath: "MyApp.dmg",
	}

	runner := hdiutil.New(cfg, hdiutil.Simulate())
	defer runner.Cleanup()

	_ = runner.Setup()
	_ = runner.Start()

	// Log output was captured in buf.
	fmt.Println(buf.Len() > 0)
}
Output:
true

Types

type CommandExecutor

type CommandExecutor interface {
	Hdiutil(args ...string) error
	HdiutilOutput(args ...string) (string, error)
	Codesign(args ...string) error
	Xcrun(args ...string) error
	XcrunOutput(args ...string) (string, error)
	Chmod(args ...string) error
	Bless(args ...string) error
}

CommandExecutor defines the interface for executing external commands. Each method corresponds to a specific allowed command, ensuring that only known binaries can be invoked and satisfying static analysis requirements.

type Config

type Config struct {
	// VolumeName is the name of the mounted volume. If empty, it defaults to the output filename without extension.
	VolumeName string `json:"volume_name,omitempty"`
	// VolumeSizeMb specifies the volume size in megabytes. If zero, hdiutil determines the size automatically.
	VolumeSizeMb int64 `json:"volume_size_mb,omitempty"`
	// SandboxSafe enables sandbox-safe mode. Cannot be used with APFS filesystem.
	SandboxSafe bool `json:"sandbox_safe,omitempty"`
	// Bless marks the volume as bootable.
	Bless bool `json:"bless,omitempty"`
	// FileSystem specifies the filesystem type (e.g., "HFS+", "APFS"). Defaults to "HFS+".
	FileSystem string `json:"filesystem,omitempty"`
	// SigningIdentity specifies the signing identity to use.
	SigningIdentity string `json:"signing_identity,omitempty"`
	// NotarizeCredentials contains credentials for Apple notarization.
	NotarizeCredentials string `json:"notarize_credentials,omitempty"`
	// ImageFormat specifies the DMG format (e.g., "UDZO", "UDBZ", "ULFO", "ULMO"). Defaults to "UDZO".
	ImageFormat string `json:"image_format,omitempty"`

	// HDIUtilVerbosity controls the verbosity level of hdiutil output.
	HDIUtilVerbosity int `json:"hdiutil_verbosity,omitempty"`

	// OutputPath is the destination path for the created DMG file. Must have .dmg extension.
	OutputPath string `json:"output_path,omitempty"`
	// SourceDir is the directory containing files to include in the DMG.
	SourceDir string `json:"source_dir,omitempty"`

	// FilesystemOpts returns the hdiutil arguments for the configured filesystem.
	// Only available after calling Validate.
	FilesystemOpts OptFn[[]string] `json:"-"`
	// ImageFormatOpts returns the hdiutil arguments for the configured image format.
	// Only available after calling Validate.
	ImageFormatOpts OptFn[[]string] `json:"-"`
	// VolumeSizeOpts returns the hdiutil arguments for the configured volume size.
	// Only available after calling Validate.
	VolumeSizeOpts OptFn[[]string] `json:"-"`
	// VolumeNameOpt returns the resolved volume name.
	// Only available after calling Validate.
	VolumeNameOpt OptFn[string] `json:"-"`
	// contains filtered or unexported fields
}

Config holds the configuration for creating a DMG disk image.

func (*Config) FromJSON

func (c *Config) FromJSON(r io.Reader) error

FromJSON populates the Config from a JSON reader.

Example
package main

import (
	"fmt"
	"strings"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	jsonStr := `{
		"source_dir": "./dist",
		"output_path": "MyApp.dmg",
		"volume_name": "My App",
		"image_format": "ULFO"
	}`

	cfg := &hdiutil.Config{}
	if err := cfg.FromJSON(strings.NewReader(jsonStr)); err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(cfg.SourceDir)
	fmt.Println(cfg.OutputPath)
	fmt.Println(cfg.VolumeName)
	fmt.Println(cfg.ImageFormat)
}
Output:
./dist
MyApp.dmg
My App
ULFO

func (*Config) ToJSON

func (c *Config) ToJSON(w io.Writer) error

ToJSON writes the Config to a JSON writer.

Example
package main

import (
	"bytes"
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := &hdiutil.Config{
		SourceDir:  "./dist",
		OutputPath: "MyApp.dmg",
		VolumeName: "My App",
		FileSystem: "HFS+",
	}

	var buf bytes.Buffer
	if err := cfg.ToJSON(&buf); err != nil {
		fmt.Println(err)
		return
	}

	fmt.Print(buf.String())
}
Output:
{
  "volume_name": "My App",
  "filesystem": "HFS+",
  "output_path": "MyApp.dmg",
  "source_dir": "./dist"
}

func (*Config) Validate

func (c *Config) Validate() error

Validate checks the configuration for errors and initializes the option functions. It must be called before using FilesystemOpts, ImageFormatOpts, VolumeSizeOpts, or VolumeNameOpt. Returns an error if:

  • Any string field contains a null byte
  • SourceDir or OutputPath starts with a dash (argument injection)
  • SourceDir is empty
  • OutputPath does not have a .dmg extension
  • ImageFormat is invalid
  • FileSystem is invalid
  • SandboxSafe is enabled with APFS filesystem
Example
package main

import (
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := hdiutil.Config{
		SourceDir:  "./dist",
		OutputPath: "MyApp.dmg",
		VolumeName: "My App",
	}

	err := cfg.Validate()
	fmt.Println(err)
}
Output:
<nil>
Example (InvalidFormat)
package main

import (
	"errors"
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := hdiutil.Config{
		SourceDir:   "./dist",
		OutputPath:  "MyApp.dmg",
		ImageFormat: "INVALID",
	}

	err := cfg.Validate()
	fmt.Println(errors.Is(err, hdiutil.ErrInvFormatOpt))
}
Output:
true
Example (MissingExtension)
package main

import (
	"errors"
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := hdiutil.Config{
		SourceDir:  "./dist",
		OutputPath: "MyApp.iso",
	}

	err := cfg.Validate()
	fmt.Println(errors.Is(err, hdiutil.ErrImageFileExt))
}
Output:
true
Example (SandboxSafeAPFS)
package main

import (
	"errors"
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := hdiutil.Config{
		SourceDir:   "./dist",
		OutputPath:  "MyApp.dmg",
		SandboxSafe: true,
		FileSystem:  "APFS",
	}

	err := cfg.Validate()
	fmt.Println(errors.Is(err, hdiutil.ErrSandboxAPFS))
}
Output:
true
Example (UnsafeArg)
package main

import (
	"errors"
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := hdiutil.Config{
		SourceDir:  "src\x00evil",
		OutputPath: "test.dmg",
	}

	err := cfg.Validate()
	fmt.Println(errors.Is(err, hdiutil.ErrUnsafeArg))
}
Output:
true
Example (WithFormat)
package main

import (
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := hdiutil.Config{
		SourceDir:   "./dist",
		OutputPath:  "MyApp.dmg",
		ImageFormat: "UDBZ",
		FileSystem:  "APFS",
	}

	err := cfg.Validate()
	fmt.Println(err)
}
Output:
<nil>

type OptFn

type OptFn[T string | []string] func() T

OptFn is a function type that returns a value of type T when called. It is used to lazily compute configuration options after validation.

type Option

type Option func(*Runner)

Option is a functional option for configuring a Runner.

func Simulate added in v0.2.0

func Simulate() Option

Simulate returns an Option that enables simulate mode on a Runner. When enabled, the Runner skips executing external commands and operates in dry-run mode.

Example
package main

import (
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := &hdiutil.Config{
		SourceDir:  "./dist",
		OutputPath: "MyApp.dmg",
		VolumeName: "My App",
	}

	runner := hdiutil.New(cfg, hdiutil.Simulate())
	defer runner.Cleanup()

	if err := runner.Setup(); err != nil {
		fmt.Println(err)
		return
	}

	// All commands are logged but not executed.
	if err := runner.Start(); err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("ok")
}
Output:
ok

func WithExecutor

func WithExecutor(e CommandExecutor) Option

WithExecutor returns an Option that sets the Runner's CommandExecutor to the provided executor. Useful for injecting a mock or custom executor (for testing or alternative command implementations).

Example
mock := &noopExecutor{}

cfg := &hdiutil.Config{
	SourceDir:  "./dist",
	OutputPath: "MyApp.dmg",
	VolumeName: "My App",
}

runner := hdiutil.New(cfg, hdiutil.WithExecutor(mock))
defer runner.Cleanup()

if err := runner.Setup(); err != nil {
	fmt.Println(err)
	return
}

if err := runner.Start(); err != nil {
	fmt.Println(err)
	return
}

fmt.Println("ok")
Output:
ok

type Runner

type Runner struct {
	*Config
	// contains filtered or unexported fields
}

Runner orchestrates the DMG creation process, including image creation, mounting, file copying, code signing, and notarization.

func New

func New(c *Config, opts ...Option) *Runner

New creates a new Runner with the provided configuration. New creates a Runner configured with the provided Config and applies any functional options. It initializes the Runner with a default realCommandExecutor. The returned Runner is not initialized for operation; call Setup on it before use.

Example
package main

import (
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := &hdiutil.Config{
		SourceDir:  "./dist",
		OutputPath: "MyApp.dmg",
		VolumeName: "My App",
	}

	runner := hdiutil.New(cfg, hdiutil.Simulate())
	defer runner.Cleanup()

	if err := runner.Setup(); err != nil {
		fmt.Println(err)
		return
	}

	if err := runner.Start(); err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("ok")
}
Output:
ok
Example (FullWorkflow)
package main

import (
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := &hdiutil.Config{
		SourceDir:   "./dist",
		OutputPath:  "MyApp.dmg",
		VolumeName:  "My App",
		ImageFormat: "UDBZ",
		FileSystem:  "HFS+",
	}

	runner := hdiutil.New(cfg, hdiutil.Simulate())
	defer runner.Cleanup()

	if err := runner.Setup(); err != nil {
		fmt.Println(err)
		return
	}

	if err := runner.Start(); err != nil {
		fmt.Println(err)
		return
	}

	if err := runner.FinalizeDMG(); err != nil {
		fmt.Println(err)
		return
	}

	// Codesign and Notarize are no-ops without credentials.
	if err := runner.Codesign(); err != nil {
		fmt.Println(err)
		return
	}

	if err := runner.Notarize(); err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("ok")
}
Output:
ok
Example (SandboxSafe)
package main

import (
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := &hdiutil.Config{
		SourceDir:   "./dist",
		OutputPath:  "MyApp.dmg",
		SandboxSafe: true,
	}

	runner := hdiutil.New(cfg, hdiutil.Simulate())
	defer runner.Cleanup()

	if err := runner.Setup(); err != nil {
		fmt.Println(err)
		return
	}

	if err := runner.Start(); err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("ok")
}
Output:
ok

func (*Runner) AttachDiskImage

func (r *Runner) AttachDiskImage() error

AttachDiskImage mounts the temporary disk image and stores the mount point. The image is attached with -nobrowse (hidden from Finder) and -noverify flags. Returns ErrMountImage if it fails or the mount point cannot be determined.

func (*Runner) Bless

func (r *Runner) Bless() error

Bless marks the mounted volume as bootable using the bless command. This operation is skipped if Config.Bless is false or if SandboxSafe mode is enabled. Bless is typically used for bootable installer images.

func (*Runner) Cleanup

func (r *Runner) Cleanup()

Cleanup removes temporary files and directories created during the DMG build process. Should be called when the Runner is no longer needed, typically via defer.

func (*Runner) Codesign

func (r *Runner) Codesign() error

Codesign signs the final DMG with the specified signing identity and verifies the signature. If no SigningIdentity is configured, this method returns nil without action. Returns ErrCodesignFailed if signing or verification fails.

func (*Runner) DetachDiskImage

func (r *Runner) DetachDiskImage() error

DetachDiskImage unmounts the disk image after fixing file permissions. Should be called after all modifications to the mounted volume are complete.

func (*Runner) FinalizeDMG

func (r *Runner) FinalizeDMG() error

FinalizeDMG converts the temporary writable image to the final compressed format specified in the configuration (e.g., UDZO, UDBZ, ULFO, ULMO).

func (*Runner) Notarize

func (r *Runner) Notarize() error

Notarize submits the DMG to Apple's notarization service and staples the ticket. Requires NotarizeCredentials to be set with a valid keychain profile name. If no credentials are configured, this method returns nil without action. Returns ErrNotarizeFailed if notarization submission or stapling fails.

func (*Runner) SetSimulate added in v0.2.0

func (r *Runner) SetSimulate(simulate bool)

SetSimulate enables or disables simulate mode at runtime. When enabled, all external commands are logged but not executed.

Example
package main

import (
	"fmt"

	"al.essio.dev/pkg/hdiutil"
)

func main() {
	cfg := &hdiutil.Config{
		SourceDir:  "./dist",
		OutputPath: "MyApp.dmg",
	}

	runner := hdiutil.New(cfg, hdiutil.Simulate())
	defer runner.Cleanup()

	if err := runner.Setup(); err != nil {
		fmt.Println(err)
		return
	}

	// Toggle simulate mode at runtime.
	runner.SetSimulate(false)
	runner.SetSimulate(true)

	fmt.Println("ok")
}
Output:
ok

func (*Runner) Setup

func (r *Runner) Setup() error

Setup validates the configuration and initializes the Runner for use. It creates temporary directories and prepares internal state. Must be called before Start or any other operation methods. Returns an error if validation fails or temporary directory creation fails.

func (*Runner) Start

func (r *Runner) Start() error

Start begins the DMG creation process by creating a temporary writable disk image. It uses either the standard or sandbox-safe creation method based on configuration. Returns ErrNeedInit if Setup was not called first.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL