MCPcopy
hub / github.com/electerm/electerm / installFromDmg

Function installFromDmg

npm/install.js:301–371  ·  view source on GitHub ↗

* Mount a DMG, copy the .app to /Applications, then detach * @param {string} dmgPath - Path to the DMG file * @returns {Promise } - Path to the installed app

(dmgPath)

Source from the content-addressed store, hash-verified

299 * @returns {Promise<string>} - Path to the installed app
300 */
301function installFromDmg (dmgPath) {
302 return new Promise((resolve, reject) => {
303 // Step 1: Mount the DMG
304 console.log(' Mounting DMG...')
305 execFile('hdiutil', ['attach', dmgPath, '-nobrowse', '-readonly'], (err, stdout) => {
306 if (err) {
307 reject(new Error(`Failed to mount DMG: ${err.message}`))
308 return
309 }
310
311 // Parse mount point
312 const mountMatch = stdout.match(/(\/Volumes\/[^\n]+)/)
313 if (!mountMatch) {
314 reject(new Error('Could not find mount point'))
315 return
316 }
317
318 const mountPoint = mountMatch[1].trim()
319 console.log(` Mounted at: ${mountPoint}`)
320
321 // Step 2: Find the .app bundle
322 try {
323 const entries = fs.readdirSync(mountPoint)
324 const appFile = entries.find(e => e.endsWith('.app'))
325
326 if (!appFile) {
327 // Try to detach before rejecting
328 execFileSyncIgnore('hdiutil', ['detach', mountPoint])
329 reject(new Error('No .app bundle found in DMG'))
330 return
331 }
332
333 const appSource = join(mountPoint, appFile)
334 const appDest = `/Applications/${appFile}`
335
336 // Check if app already exists
337 if (fs.existsSync(appDest)) {
338 console.log(` Existing app found at ${appDest}, replacing...`)
339 // Remove existing app
340 rm('-rf', appDest)
341 }
342
343 // Step 3: Copy the app to /Applications
344 console.log(` Installing ${appFile} to /Applications...`)
345 execFile('cp', ['-R', appSource, appDest], (cpErr) => {
346 // Step 4: Detach the DMG (always, regardless of copy result)
347 console.log(' Detaching DMG...')
348 execFile('hdiutil', ['detach', mountPoint], (detachErr) => {
349 if (detachErr) {
350 console.log(' Warning: Failed to detach DMG:', detachErr.message)
351 } else {
352 console.log(' DMG detached')
353 }
354
355 if (cpErr) {
356 reject(new Error(`Failed to copy app: ${cpErr.message}`))
357 return
358 }

Callers 2

runMacFunction · 0.85
runMac10Function · 0.85

Calls 2

execFileSyncIgnoreFunction · 0.85
resolveFunction · 0.85

Tested by

no test coverage detected