-
Notifications
You must be signed in to change notification settings - Fork 59
/
Copy pathinstall.go
109 lines (89 loc) · 2.85 KB
/
install.go
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package msi
import (
"fmt"
"github.com/itchio/wharf/tlc"
"github.com/itchio/butler/butlerd"
"github.com/itchio/butler/cmd/elevate"
"github.com/itchio/butler/cmd/msi"
"github.com/itchio/butler/installer"
"github.com/itchio/butler/installer/bfs"
"github.com/pkg/errors"
)
func (m *Manager) Install(params *installer.InstallParams) (*installer.InstallResult, error) {
consumer := params.Consumer
// we need the installer on disk to run it. this'll err if it's not,
// and the caller is in charge of downloading it and calling us again.
f, err := installer.AsLocalFile(params.File)
if err != nil {
return nil, errors.WithStack(err)
}
angelParams := &bfs.SaveAngelsParams{
Consumer: consumer,
Folder: params.InstallFolderPath,
Receipt: params.ReceiptIn,
}
cancel := make(chan struct{})
defer close(cancel)
bfs.StartAsymptoticProgress(consumer, cancel)
infoRes, err := msi.Info(consumer, f.Name())
if err != nil {
return nil, errors.WithStack(err)
}
msiProductCode := infoRes.ProductCode
angelResult, err := bfs.SaveAngels(angelParams, func() error {
args := []string{
"--elevate",
"msi-install",
f.Name(),
"--target",
params.InstallFolderPath,
}
consumer.Infof("Attempting elevated MSI install")
res, err := installer.RunSelf(&installer.RunSelfParams{
Consumer: consumer,
Args: args,
})
if err != nil {
return errors.WithStack(err)
}
if res.ExitCode != 0 {
if res.ExitCode == elevate.ExitCodeAccessDenied {
msg := "User or system did not grant elevation privileges"
consumer.Errorf(msg)
return errors.WithStack(butlerd.CodeOperationAborted)
}
consumer.Errorf("Elevated MSI install failed (code %d, 0x%x), we're out of options", res.ExitCode, res.ExitCode)
return errors.New("Elevated MSI installation failed, this package is probably not compatible")
}
consumer.Infof("MSI package installed successfully.")
consumer.Infof("Making sure it installed in the directory we wanted...")
container, err := tlc.WalkDir(params.InstallFolderPath, &tlc.WalkOpts{
Filter: bfs.DotItchFilter(),
})
if err != nil {
return errors.WithStack(err)
}
if len(container.Files) == 0 {
consumer.Errorf("No files were found in the install folder after install.")
consumer.Errorf("The itch app won't be able to launch it.")
var installLocation = "<unknown>"
{
infoRes2, err := msi.Info(consumer, f.Name())
if err == nil && infoRes2.InstallLocation != "" {
installLocation = infoRes2.InstallLocation
}
}
consumer.Infof("Package install location: %s", installLocation)
return fmt.Errorf("The MSI package was installed in an unexpected location: %s", installLocation)
}
return nil
})
if err != nil {
return nil, errors.WithStack(err)
}
res := &installer.InstallResult{
Files: angelResult.Files,
MSIProductCode: msiProductCode,
}
return res, nil
}