Skip to content

Commit cfa9715

Browse files
authored
feature: add extract command to extract embedded tool binaries (#624)
Signed-off-by: Harper, Jason M <jason.m.harper@intel.com>
1 parent 5e0056b commit cfa9715

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

cmd/root.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"perfspect/cmd/report"
3131
"perfspect/cmd/telemetry"
3232
"perfspect/internal/app"
33+
"perfspect/internal/script"
3334
"perfspect/internal/util"
3435

3536
"github.com/pkg/errors"
@@ -114,6 +115,7 @@ Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
114115
rootCmd.AddCommand(config.Cmd)
115116
rootCmd.AddGroup([]*cobra.Group{{ID: "other", Title: "Other Commands:"}}...)
116117
rootCmd.AddCommand(updateCmd)
118+
rootCmd.AddCommand(extractCmd)
117119
// Global (persistent) flags
118120
rootCmd.PersistentFlags().BoolVar(&flagDebug, app.FlagDebugName, false, "enable debug logging and retain temporary directories")
119121
rootCmd.PersistentFlags().BoolVar(&flagSyslog, app.FlagSyslogName, false, "write logs to syslog instead of a file")
@@ -489,6 +491,29 @@ func getLatestManifest() (manifest, error) {
489491
return latestManifest, nil
490492
}
491493

494+
// define the extract command
495+
const (
496+
extractCommandName = "extract"
497+
)
498+
499+
var extractCmd = &cobra.Command{
500+
GroupID: "other",
501+
Use: extractCommandName,
502+
Short: "Extract the embedded resources (for developers)",
503+
RunE: func(cmd *cobra.Command, args []string) error {
504+
appContext := cmd.Parent().Context().Value(app.Context{}).(app.Context)
505+
// extract the internal/script module's embedded resources
506+
err := util.ExtractAllResources(script.Resources, appContext.OutputDir)
507+
if err != nil {
508+
slog.Error("Failed to extract script resources", slog.String("error", err.Error()))
509+
fmt.Printf("Error: failed to extract script resources: %v\n", err)
510+
return err
511+
}
512+
fmt.Printf("Extracted script resources to %s\n", appContext.OutputDir)
513+
return nil
514+
},
515+
}
516+
492517
// SyslogHandler is a slog.Handler that logs to syslog.
493518
type SyslogHandler struct {
494519
writer *syslog.Writer

internal/util/util.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,31 @@ func GeoMean(vals []float64) (val float64) {
208208
return
209209
}
210210

211+
// ExtractAllResources recurcively extracts all resources as files into the specified directory.
212+
func ExtractAllResources(resources embed.FS, dir string) error {
213+
// walk the embedded filesystem starting at "resources"
214+
return fs.WalkDir(resources, "resources", func(path string, d fs.DirEntry, err error) error {
215+
if err != nil {
216+
return err
217+
}
218+
relPath, err := filepath.Rel("resources", path)
219+
if err != nil {
220+
return err
221+
}
222+
relPath = filepath.Join(dir, relPath)
223+
if d.IsDir() {
224+
if relPath == "." {
225+
return nil
226+
}
227+
// create directory
228+
return os.MkdirAll(relPath, 0700)
229+
}
230+
// extract file
231+
_, err = ExtractResource(resources, path, filepath.Dir(relPath))
232+
return err
233+
})
234+
}
235+
211236
// ExtractResource extracts a resource from the given embed.FS and saves it to the specified temporary directory.
212237
// It returns the path to the saved resource file and any error encountered during the process.
213238
func ExtractResource(resources embed.FS, resourcePath string, tempDir string) (string, error) {

0 commit comments

Comments
 (0)