forked from atom/atom
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommand-installer.coffee
91 lines (73 loc) · 2.9 KB
/
command-installer.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
path = require 'path'
fs = require 'fs-plus'
runas = null # defer until used
symlinkCommand = (sourcePath, destinationPath, callback) ->
fs.unlink destinationPath, (error) ->
if error? and error?.code isnt 'ENOENT'
callback(error)
else
fs.makeTree path.dirname(destinationPath), (error) ->
if error?
callback(error)
else
fs.symlink sourcePath, destinationPath, callback
symlinkCommandWithPrivilegeSync = (sourcePath, destinationPath) ->
runas ?= require 'runas'
if runas('/bin/rm', ['-f', destinationPath], admin: true) isnt 0
throw new Error("Failed to remove '#{destinationPath}'")
if runas('/bin/mkdir', ['-p', path.dirname(destinationPath)], admin: true) isnt 0
throw new Error("Failed to create directory '#{destinationPath}'")
if runas('/bin/ln', ['-s', sourcePath, destinationPath], admin: true) isnt 0
throw new Error("Failed to symlink '#{sourcePath}' to '#{destinationPath}'")
module.exports =
class CommandInstaller
constructor: (@appVersion, @applicationDelegate) ->
getInstallDirectory: ->
"/usr/local/bin"
getResourcesDirectory: ->
process.resourcesPath
installShellCommandsInteractively: ->
showErrorDialog = (error) =>
@applicationDelegate.confirm
message: "Failed to install shell commands"
detailedMessage: error.message
@installAtomCommand true, (error) =>
if error?
showErrorDialog(error)
else
@installApmCommand true, (error) =>
if error?
showErrorDialog(error)
else
@applicationDelegate.confirm
message: "Commands installed."
detailedMessage: "The shell commands `atom` and `apm` are installed."
installAtomCommand: (askForPrivilege, callback) ->
programName = if @appVersion.includes("beta")
"atom-beta"
else
"atom"
commandPath = path.join(@getResourcesDirectory(), 'app', 'atom.sh')
@createSymlink commandPath, programName, askForPrivilege, callback
installApmCommand: (askForPrivilege, callback) ->
programName = if @appVersion.includes("beta")
"apm-beta"
else
"apm"
commandPath = path.join(@getResourcesDirectory(), 'app', 'apm', 'node_modules', '.bin', 'apm')
@createSymlink commandPath, programName, askForPrivilege, callback
createSymlink: (commandPath, commandName, askForPrivilege, callback) ->
return unless process.platform is 'darwin'
destinationPath = path.join(@getInstallDirectory(), commandName)
fs.readlink destinationPath, (error, realpath) ->
if realpath is commandPath
callback()
return
symlinkCommand commandPath, destinationPath, (error) ->
if askForPrivilege and error?.code is 'EACCES'
try
error = null
symlinkCommandWithPrivilegeSync(commandPath, destinationPath)
catch err
error = err
callback?(error)