Skip to content

Commit

Permalink
Use callback for printing update progress
Browse files Browse the repository at this point in the history
RELEASE_NOTES=n/a

Signed-off-by: Dominik Schulz <[email protected]>
  • Loading branch information
dominikschulz committed Feb 15, 2021
1 parent ce8498c commit c0bafa7
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 27 deletions.
2 changes: 1 addition & 1 deletion internal/action/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (s *Action) Update(c *cli.Context) error {
}

out.Print(ctx, "⚒ Checking for available updates ...")
if err := updater.Update(ctx, s.version); err != nil {
if err := updater.Update(ctx, s.version, out.Print); err != nil {
return ExitError(ExitUnknown, err, "Failed to update gopass: %s", err)
}
out.OK(ctx, "gopass is up to date")
Expand Down
32 changes: 16 additions & 16 deletions internal/updater/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"github.com/gopasspw/gopass/pkg/debug"
)

func extractFile(buf []byte, filename, dest string) error {
func extractFile(buf []byte, filename, dest string) (int64, error) {
var mode = os.FileMode(0755)

// if overwriting an existing binary retain it's mode flags
Expand All @@ -25,13 +25,13 @@ func extractFile(buf []byte, filename, dest string) error {

if err := os.Remove(dest); err != nil {
if !os.IsNotExist(err) {
return fmt.Errorf("unable to remove destination file: %q", err)
return 0, fmt.Errorf("unable to remove destination file: %q", err)
}
}

dfh, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE|os.O_EXCL, mode)
if err != nil {
return fmt.Errorf("failed to open file %q: %w", dest, err)
return 0, fmt.Errorf("failed to open file %q: %w", dest, err)
}
defer func() {
_ = dfh.Close()
Expand All @@ -42,22 +42,22 @@ func extractFile(buf []byte, filename, dest string) error {
case ".gz":
gzr, err := gzip.NewReader(rd)
if err != nil {
return err
return 0, err
}
return extractTar(gzr, dfh, dest)
case ".bz2":
return extractTar(bzip2.NewReader(rd), dfh, dest)
case ".zip":
return extractZip(buf, dfh, dest)
default:
return fmt.Errorf("unsupported")
return 0, fmt.Errorf("unsupported")
}
}

func extractZip(buf []byte, dfh io.WriteCloser, dest string) error {
func extractZip(buf []byte, dfh io.WriteCloser, dest string) (int64, error) {
zrd, err := zip.NewReader(bytes.NewReader(buf), int64(len(buf)))
if err != nil {
return err
return 0, err
}

for i := 0; i < len(zrd.File); i++ {
Expand All @@ -67,32 +67,32 @@ func extractZip(buf []byte, dfh io.WriteCloser, dest string) error {

file, err := zrd.File[i].Open()
if err != nil {
return fmt.Errorf("failed to read from zip file: %w", err)
return 0, fmt.Errorf("failed to read from zip file: %w", err)
}

n, err := io.Copy(dfh, file)
if err != nil {
dfh.Close()
os.Remove(dest)
return fmt.Errorf("failed to read gopass.exe from zip file: %w", err)
return 0, fmt.Errorf("failed to read gopass.exe from zip file: %w", err)
}
// success
debug.Log("wrote %d bytes to %v", n, dest)
return nil
return n, nil
}

return fmt.Errorf("file not found in archive")
return 0, fmt.Errorf("file not found in archive")
}

func extractTar(rd io.Reader, dfh io.WriteCloser, dest string) error {
func extractTar(rd io.Reader, dfh io.WriteCloser, dest string) (int64, error) {
tarReader := tar.NewReader(rd)
for {
header, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return fmt.Errorf("failed to read from tar file: %w", err)
return 0, fmt.Errorf("failed to read from tar file: %w", err)
}
name := filepath.Base(header.Name)
if header.Typeflag != tar.TypeReg {
Expand All @@ -106,11 +106,11 @@ func extractTar(rd io.Reader, dfh io.WriteCloser, dest string) error {
if err != nil {
dfh.Close()
os.Remove(dest)
return fmt.Errorf("failed to read gopass from tar file: %w", err)
return n, fmt.Errorf("failed to read gopass from tar file: %w", err)
}
// success
debug.Log("wrote %d bytes to %v", n, dest)
return nil
return n, nil
}
return fmt.Errorf("file not found in archive")
return 0, fmt.Errorf("file not found in archive")
}
34 changes: 24 additions & 10 deletions internal/updater/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,19 @@ var (
UpdateMoveAfterQuit = true
)

// PrintCallback is a method that can print formatted text, e.g. out.Print
type PrintCallback func(context.Context, string, ...interface{})

// Update will start th interactive update assistant
func Update(ctx context.Context, currentVersion semver.Version) error {
func Update(ctx context.Context, currentVersion semver.Version, printf PrintCallback) error {
if printf == nil {
printf = func(ctx context.Context, fmt string, args ...interface{}) {
// no-op
}
}

if err := IsUpdateable(ctx); err != nil {
out.Error(ctx, "Your gopass binary is externally managed. Can not update: %q", err)
printf(ctx, "Your gopass binary is externally managed. Can not update: %q", err)
return err
}

Expand All @@ -39,19 +48,20 @@ func Update(ctx context.Context, currentVersion semver.Version) error {
debug.Log("Current: %s - Latest: %s", currentVersion.String(), rel.Version.String())
// binary is newer or equal to the latest release -> nothing to do
if currentVersion.GTE(rel.Version) {
out.Print(ctx, "gopass is up to date (%s)", currentVersion.String())
printf(ctx, "gopass is up to date (%s)", currentVersion.String())
if gfu := os.Getenv("GOPASS_FORCE_UPDATE"); gfu == "" {
return nil
}
}

debug.Log("downloading SHA256SUMS ...")
out.Print(ctx, "latest version is %s", rel.Version.String())
out.Print(ctx, "downloading SHA256SUMS")
_, sha256sums, err := downloadAsset(ctx, rel.Assets, "SHA256SUMS")
if err != nil {
return err
}

debug.Log("downloading SHA256SUMS.sig ...")
out.Print(ctx, "downloading SHA256SUMS.sig")
_, sig, err := downloadAsset(ctx, rel.Assets, "SHA256SUMS.sig")
if err != nil {
return err
Expand All @@ -63,17 +73,17 @@ func Update(ctx context.Context, currentVersion semver.Version) error {
return fmt.Errorf("signature verification failed: %w", err)
}
if !ok {
return fmt.Errorf("GPG signature verification for SHA256SUMS failed")
return fmt.Errorf("GPG signature verification failed")
}
debug.Log("GPG signature OK!")
printf(ctx, "GPG signature verification succeeded")

ext := "tar.gz"
if runtime.GOOS == "windows" {
ext = "zip"
}

suffix := fmt.Sprintf("%s-%s.%s", runtime.GOOS, runtime.GOARCH, ext)
debug.Log("downloading tarball %q ...", suffix)
printf(ctx, "downloading gopass-%s", suffix)
dlFilename, buf, err := downloadAsset(ctx, rel.Assets, suffix)
if err != nil {
return err
Expand All @@ -90,14 +100,18 @@ func Update(ctx context.Context, currentVersion semver.Version) error {
if !bytes.Equal(wantHash, gotHash[:]) {
return fmt.Errorf("SHA256 hash mismatch, want %02x, got %02x", wantHash, gotHash)
}

debug.Log("hashsums match!")
printf(ctx, "downloaded gopass-%s", suffix)

debug.Log("extracting binary from tarball ...")
if err := extractFile(buf, dlFilename, dest); err != nil {
size, err := extractFile(buf, dlFilename, dest)
if err != nil {
return err
}
debug.Log("extracted %q to %q", dlFilename, dest)

debug.Log("success!")
printf(ctx, "saved %d bytes to %s", size, dest)
printf(ctx, "successfully updated gopass to version %s", rel.Version.String())
return nil
}

0 comments on commit c0bafa7

Please sign in to comment.