Skip to content

Commit 14a7111

Browse files
Makeself-self extraction
1 parent 632019f commit 14a7111

File tree

2 files changed

+63
-7
lines changed

2 files changed

+63
-7
lines changed

pkg/common/filex/archive.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package filex
22

33
import (
4+
"bytes"
45
"fmt"
56
"github.com/mholt/archiver/v3"
67
"github.com/samber/lo"
78
"github.com/wttech/aemc/pkg/common/pathx"
9+
"io"
810
"os"
911
"path/filepath"
1012
)
@@ -82,3 +84,47 @@ func UnarchiveWithChanged(sourceFile, targetDir string) (bool, error) {
8284
}
8385
return true, nil
8486
}
87+
88+
// UnarchiveMakeself extracts tar.gz archive from a Makeself self-extracting shell script.
89+
// Makeself (https://makeself.io/) creates self-extracting archives by embedding a tar.gz archive after a shell header.
90+
// This function finds the gzip magic bytes (0x1f 0x8b) and extracts everything after it.
91+
func UnarchiveMakeself(scriptPath string, targetDir string) error {
92+
file, err := os.Open(scriptPath)
93+
if err != nil {
94+
return fmt.Errorf("cannot open Makeself script file '%s': %w", scriptPath, err)
95+
}
96+
defer file.Close()
97+
98+
// Read entire file to find embedded gzip archive
99+
data, err := io.ReadAll(file)
100+
if err != nil {
101+
return fmt.Errorf("cannot read Makeself script file '%s': %w", scriptPath, err)
102+
}
103+
104+
// Find gzip magic bytes (1f 8b) which mark the start of embedded tar.gz archive
105+
gzipMagic := []byte{0x1f, 0x8b}
106+
archiveStart := bytes.Index(data, gzipMagic)
107+
if archiveStart == -1 {
108+
return fmt.Errorf("cannot find gzip archive in Makeself script file '%s' (missing gzip magic bytes 0x1f 0x8b)", scriptPath)
109+
}
110+
111+
// Extract archive data to temporary file as sibling of the script file
112+
tmpFile, err := os.CreateTemp(filepath.Dir(scriptPath), filepath.Base(scriptPath)+"-*.tar.gz")
113+
if err != nil {
114+
return fmt.Errorf("cannot create temporary archive file in dir '%s' for Makeself extraction: %w", filepath.Dir(scriptPath), err)
115+
}
116+
tmpArchive := tmpFile.Name()
117+
tmpFile.Close()
118+
defer os.Remove(tmpArchive)
119+
120+
if err := os.WriteFile(tmpArchive, data[archiveStart:], 0644); err != nil {
121+
return fmt.Errorf("cannot write extracted Makeself archive data to temporary file '%s': %w", tmpArchive, err)
122+
}
123+
124+
// Unpack the tar.gz using standard archiver
125+
if err := Unarchive(tmpArchive, targetDir); err != nil {
126+
return fmt.Errorf("cannot unarchive extracted Makeself tar.gz '%s' to dir '%s': %w", tmpArchive, targetDir, err)
127+
}
128+
129+
return nil
130+
}

pkg/sdk.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -141,22 +141,32 @@ func (s SDK) unpackDispatcher() error {
141141
}
142142
log.Infof("unpacking SDK dispatcher tools ZIP '%s' to dir '%s'", zip, s.DispatcherDir())
143143
err = filex.Unarchive(zip, s.DispatcherDir())
144-
log.Infof("unpacked SDK dispatcher tools ZIP '%s' to dir '%s'", zip, s.DispatcherDir())
145144
if err != nil {
146145
return err
147146
}
147+
log.Infof("unpacked SDK dispatcher tools ZIP '%s' to dir '%s'", zip, s.DispatcherDir())
148148
} else {
149149
script, err := s.dispatcherToolsUnixScript()
150150
if err != nil {
151151
return err
152152
}
153-
log.Infof("unpacking SDK dispatcher tools using script '%s' to dir '%s'", script, s.DispatcherDir())
154-
cmd := execx.CommandShell([]string{script, "--target", s.DispatcherDir()})
155-
s.vendorManager.aem.CommandOutput(cmd)
156-
if err := cmd.Run(); err != nil {
157-
return fmt.Errorf("cannot run SDK dispatcher tools unpacking script '%s': %w", script, err)
153+
154+
// On Windows host, we cannot execute .sh script, so extract archive manually
155+
if osx.IsWindows() {
156+
log.Infof("extracting SDK dispatcher tools from Makeself script '%s' to dir '%s'", script, s.DispatcherDir())
157+
if err := filex.UnarchiveMakeself(script, s.DispatcherDir()); err != nil {
158+
return fmt.Errorf("cannot extract SDK dispatcher tools from Makeself script '%s': %w", script, err)
159+
}
160+
log.Infof("extracted SDK dispatcher tools from Makeself script '%s' to dir '%s'", script, s.DispatcherDir())
161+
} else {
162+
log.Infof("unpacking SDK dispatcher tools using script '%s' to dir '%s'", script, s.DispatcherDir())
163+
cmd := execx.CommandShell([]string{script, "--target", s.DispatcherDir()})
164+
s.vendorManager.aem.CommandOutput(cmd)
165+
if err := cmd.Run(); err != nil {
166+
return fmt.Errorf("cannot run SDK dispatcher tools unpacking script '%s': %w", script, err)
167+
}
168+
log.Infof("unpacked SDK dispatcher tools using script '%s' to dir '%s'", script, s.DispatcherDir())
158169
}
159-
log.Infof("unpacked SDK dispatcher tools using script '%s' to dir '%s'", script, s.DispatcherDir())
160170
}
161171
return nil
162172
}

0 commit comments

Comments
 (0)