Skip to content

Commit df59f8f

Browse files
committed
downloader: decompress gzip in pure Go
Use compress/gzip directly instead of shelling out to a gzip binary. On Windows, gzip is not part of the base system, so the previous behaviour required Git for Windows or MSYS2 to be on PATH just to unpack a .tar.gz image during limactl create / start. Other formats (bzip2, xz, zstd) still go through the exec path, since they are less common in Lima image URLs and would need extra dependencies for in-process decompression. They can be migrated similarly in follow-ups if needed. Signed-off-by: Jan Dubois <jan.dubois@suse.com>
1 parent 6924004 commit df59f8f

1 file changed

Lines changed: 19 additions & 6 deletions

File tree

pkg/downloader/downloader.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package downloader
55

66
import (
77
"bytes"
8+
"compress/gzip"
89
"context"
910
"crypto/sha256"
1011
"errors"
@@ -549,26 +550,38 @@ func decompressLocal(ctx context.Context, decompressCmd, dst, src, ext, descript
549550
return err
550551
}
551552
defer out.Close()
552-
buf := new(bytes.Buffer)
553-
cmd := exec.CommandContext(ctx, decompressCmd, "-d") // -d --decompress
554-
cmd.Stdin = bar.NewProxyReader(in)
555-
cmd.Stdout = out
556-
cmd.Stderr = buf
557553
if !HideProgress {
558554
if description == "" {
559555
description = filepath.Base(src)
560556
}
561557
logrus.Infof("Decompressing %s\n", description)
562558
}
563559
bar.Start()
560+
defer bar.Finish()
561+
// Prefer a pure-Go path for gzip so the host does not need an external
562+
// gzip binary. This matters on Windows where gzip is not part of the
563+
// base system.
564+
if decompressCmd == "gzip" {
565+
gz, err := gzip.NewReader(bar.NewProxyReader(in))
566+
if err != nil {
567+
return err
568+
}
569+
defer gz.Close()
570+
_, err = io.Copy(out, gz)
571+
return err
572+
}
573+
buf := new(bytes.Buffer)
574+
cmd := exec.CommandContext(ctx, decompressCmd, "-d") // -d --decompress
575+
cmd.Stdin = bar.NewProxyReader(in)
576+
cmd.Stdout = out
577+
cmd.Stderr = buf
564578
err = cmd.Run()
565579
if err != nil {
566580
var exitErr *exec.ExitError
567581
if errors.As(err, &exitErr) {
568582
exitErr.Stderr = buf.Bytes()
569583
}
570584
}
571-
bar.Finish()
572585
return err
573586
}
574587

0 commit comments

Comments
 (0)