Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions internal/selfupdate/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func (u *Updater) plan(ctx context.Context, method Method, report Report, opts O
return plan, nil
}

plan.Asset = u.chooseReleaseAsset(ctx, report, opts, tag)
plan.Asset = u.chooseReleaseAsset(ctx, report, tag)

exists, err := u.Client.AssetExists(ctx, tag, plan.Asset.Name)
if err != nil {
Expand All @@ -183,10 +183,13 @@ func (u *Updater) plan(ctx context.Context, method Method, report Report, opts O

// chooseReleaseAsset picks the package on macOS only when the running binary
// lives where the package installs; otherwise the universal zip updates the
// binary in place when the release carries it.
func (u *Updater) chooseReleaseAsset(ctx context.Context, report Report, opts Options, tag string) Asset {
// binary in place when the release carries it. -force does not change the
// choice: reinstalling an equal version in place must not suddenly require
// root. Only when the release has no zip does -force fall through to the
// package, which then installs to PkgInstallDir as the target guard states.
func (u *Updater) chooseReleaseAsset(ctx context.Context, report Report, tag string) Asset {
asset := report.ReleaseAsset
if asset.Kind != KindPkg || opts.Force || sameDir(filepath.Dir(report.ExecutablePath), PkgInstallDir) {
if asset.Kind != KindPkg || sameDir(filepath.Dir(report.ExecutablePath), PkgInstallDir) {
return asset
}

Expand Down
26 changes: 26 additions & 0 deletions internal/selfupdate/updater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,32 @@ func TestUpdaterDarwinZipWhenNotInUsrLocalBin(t *testing.T) {
}
}

// TestUpdaterDarwinForceReinstallsInPlace covers `update -force -version <same>`
// from a go-installed copy: the universal zip must be used in place, without
// root and without the installer. Found by the first real run against v0.2.0.
func TestUpdaterDarwinForceReinstallsInPlace(t *testing.T) {
rig := newRig(t, "darwin", "v0.2.0")
z := DarwinZipAsset()
rig.gh.addArchive("v0.2.0", z.Name, z.ChecksumName, z.InnerName, []byte("same-version-fresh-copy"))
rig.gh.addAsset("v0.2.0", "machineid-darwin-universal.pkg", []byte("pkg"))
rig.exec.on("codesign --verify", ExecResult{})
rig.exec.on(rig.target+" -version", ExecResult{Stdout: "machineid v0.2.0"})

res, err := rig.u.Run(context.Background(), Options{CurrentVersion: "v0.2.0", Version: "v0.2.0", Force: true, AssumeYes: true})
if err != nil {
t.Fatalf("%v\n%s", err, rig.out.String())
}
if !res.Changed {
t.Errorf("-force should reinstall an equal version: %+v", res)
}
if got := mustRead(t, rig.target); string(got) != "same-version-fresh-copy" {
t.Errorf("target = %q", got)
}
if rig.exec.called("installer -pkg") {
t.Error("the package must not be used when the zip exists, even with -force")
}
}

func TestUpdaterDarwinNoZipRefusesOutsidePkgDir(t *testing.T) {
rig := newRig(t, "darwin", "v0.3.0")
rig.gh.addAsset("v0.3.0", "machineid-darwin-universal.pkg", []byte("pkg"))
Expand Down
Loading