Skip to content

Commit

Permalink
Store goo files unextracted in cache, ensure checksum match on reins…
Browse files Browse the repository at this point in the history
…tall (#32)
  • Loading branch information
adjackura authored Jan 2, 2018
1 parent 228b3a7 commit b18e545
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 67 deletions.
6 changes: 3 additions & 3 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ import (

// PackageState describes the state of a package on a client.
type PackageState struct {
SourceRepo, DownloadURL, Checksum, UnpackDir string
PackageSpec *goolib.PkgSpec
InstalledFiles map[string]string
SourceRepo, DownloadURL, Checksum, LocalPath, UnpackDir string
PackageSpec *goolib.PkgSpec
InstalledFiles map[string]string
}

// GooGetState describes the overall package state on a client.
Expand Down
3 changes: 1 addition & 2 deletions download/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@ import (
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"strings"

"path"

humanize "github.com/dustin/go-humanize"
"github.com/google/googet/client"
"github.com/google/googet/goolib"
Expand Down
3 changes: 2 additions & 1 deletion googet.goospec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "googet",
"version": "2.11.0@1",
"version": "2.12.0@1",
"arch": "x86_64",
"authors": "[email protected]",
"license": "http://www.apache.org/licenses/LICENSE-2.0",
Expand All @@ -12,6 +12,7 @@
"path": "install.ps1"
},
"releaseNotes": [
"2.12.0 - Store goo files unextracted in cache, ensure checksum match on reinstall.",
"2.11.0 - Add allowunsafeurl config option to enable HTTP repos, otherwise disable.",
" - Force the use of a package checksum when downloading from a repository.",
"2.10.1 - Semver compatibility bug fix for '0' patch numbers.",
Expand Down
117 changes: 58 additions & 59 deletions install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,7 @@ func FromRepo(pi goolib.PackageInfo, repo, cache string, rm client.RepoMap, arch
return err
}

dir, err := extractPkg(dst)
if err != nil {
return err
}

insFiles, err := installPkg(dir, rs.PackageSpec, dbOnly)
insFiles, err := installPkg(dst, rs.PackageSpec, dbOnly)
if err != nil {
return err
}
Expand All @@ -122,22 +117,15 @@ func FromRepo(pi goolib.PackageInfo, repo, cache string, rm client.RepoMap, arch
fmt.Printf("Installation of %s.%s.%s and all dependencies completed\n", pi.Name, pi.Arch, pi.Ver)
// Clean up old version, if applicable.
pi = goolib.PackageInfo{Name: pi.Name, Arch: pi.Arch, Ver: ""}
if st, err := state.GetPackageState(pi); err == nil {
if !dbOnly {
cleanOldFiles(st, insFiles)
}
if err := oswrap.RemoveAll(st.UnpackDir); err != nil {
logger.Error(err)
}
if err := state.Remove(pi); err != nil {
return err
}
if err := cleanOld(state, pi, insFiles, dbOnly); err != nil {
return err
}

state.Add(client.PackageState{
SourceRepo: repo,
DownloadURL: strings.TrimSuffix(repo, filepath.Base(repo)) + rs.Source,
Checksum: rs.Checksum,
UnpackDir: dir,
LocalPath: dst,
PackageSpec: rs.PackageSpec,
InstalledFiles: insFiles,
})
Expand Down Expand Up @@ -187,12 +175,7 @@ func FromDisk(arg, cache string, state *client.GooGetState, dbOnly, ri bool) err
return err
}

dir, err := extractPkg(dst)
if err != nil {
return err
}

insFiles, err := installPkg(dir, zs, dbOnly)
insFiles, err := installPkg(dst, zs, dbOnly)
if err != nil {
return err
}
Expand All @@ -208,19 +191,12 @@ func FromDisk(arg, cache string, state *client.GooGetState, dbOnly, ri bool) err

// Clean up old version, if applicable.
pi := goolib.PackageInfo{Name: zs.Name, Arch: zs.Arch, Ver: ""}
if st, err := state.GetPackageState(pi); err == nil {
if !dbOnly {
cleanOldFiles(st, insFiles)
}
if err := oswrap.RemoveAll(st.UnpackDir); err != nil {
logger.Error(err)
}
if err := state.Remove(pi); err != nil {
return err
}
if err := cleanOld(state, pi, insFiles, dbOnly); err != nil {
return err
}

state.Add(client.PackageState{
UnpackDir: dir,
LocalPath: dst,
PackageSpec: zs,
InstalledFiles: insFiles,
})
Expand All @@ -232,29 +208,32 @@ func Reinstall(ps client.PackageState, state client.GooGetState, rd bool, proxyS
pi := goolib.PackageInfo{Name: ps.PackageSpec.Name, Arch: ps.PackageSpec.Arch, Ver: ps.PackageSpec.Version}
logger.Infof("Starting reinstall of %s.%s, version %s", pi.Name, pi.Arch, pi.Ver)
fmt.Printf("Reinstalling %s.%s %s and dependencies...\n", pi.Name, pi.Arch, pi.Ver)
_, err := oswrap.Stat(ps.UnpackDir)
f, err := os.Open(ps.LocalPath)
if err != nil && !os.IsNotExist(err) {
return err
}
if os.IsNotExist(err) {
logger.Infof("Package directory does not exist for %s.%s.%s, redownloading...", pi.Name, pi.Arch, pi.Ver)
logger.Infof("Local package does not exist for %s.%s.%s, redownloading...", pi.Name, pi.Arch, pi.Ver)
rd = true
}
dir := ps.UnpackDir
// Force redownload if checksum does not match.
// If checksum is empty this was a local install so ignore.
if !rd && ps.Checksum != "" && goolib.Checksum(f) != ps.Checksum {
logger.Info("Local package checksum does not match, redownloading...")
rd = true
}
f.Close()

if rd {
if ps.DownloadURL == "" {
return fmt.Errorf("can not redownload %s.%s.%s, DownloadURL not saved", pi.Name, pi.Arch, pi.Ver)
}
dst := ps.UnpackDir + ".goo"
if err := download.Package(ps.DownloadURL, dst, ps.Checksum, proxyServer); err != nil {
if err := download.Package(ps.DownloadURL, ps.LocalPath, ps.Checksum, proxyServer); err != nil {
return fmt.Errorf("error redownloading package: %v", err)
}
dir, err = extractPkg(dst)
if err != nil {
return err
}
}
if _, err := installPkg(dir, ps.PackageSpec, false); err != nil {

if _, err := installPkg(ps.LocalPath, ps.PackageSpec, false); err != nil {
return fmt.Errorf("error reinstalling package: %v", err)
}

Expand Down Expand Up @@ -286,17 +265,6 @@ func copyPkg(src, dst string) (retErr error) {
return retErr
}

func extractPkg(pkg string) (string, error) {
dir, err := download.ExtractPkg(pkg)
if err != nil {
return "", err
}
if err := oswrap.Remove(pkg); err != nil {
logger.Errorf("error cleaning up package file: %v", err)
}
return dir, nil
}

// NeedsInstallation checks if a package version needs installation.
func NeedsInstallation(pi goolib.PackageInfo, state client.GooGetState) (bool, error) {
for _, p := range state {
Expand Down Expand Up @@ -409,6 +377,23 @@ func resolveDst(dst string) string {
return dst
}

func cleanOld(state *client.GooGetState, pi goolib.PackageInfo, insFiles map[string]string, dbOnly bool) error {
st, err := state.GetPackageState(pi)
if err != nil {
return nil
}
if !dbOnly {
cleanOldFiles(st, insFiles)
}
if st.LocalPath != "" && oswrap.RemoveAll(st.LocalPath) != nil {
logger.Error(err)
}
if st.UnpackDir != "" && oswrap.RemoveAll(st.UnpackDir) != nil {
logger.Error(err)
}
return state.Remove(pi)
}

func cleanOldFiles(oldState client.PackageState, insFiles map[string]string) {
if len(oldState.InstalledFiles) == 0 {
return
Expand All @@ -434,8 +419,14 @@ func cleanOldFiles(oldState client.PackageState, insFiles map[string]string) {
}
}

func installPkg(dir string, ps *goolib.PkgSpec, dbOnly bool) (map[string]string, error) {
func installPkg(pkg string, ps *goolib.PkgSpec, dbOnly bool) (map[string]string, error) {
dir, err := download.ExtractPkg(pkg)
if err != nil {
return nil, err
}

logger.Infof("Executing install of package %q", filepath.Base(dir))

toRemove = []string{}
// Try to cleanup moved files after package is installed.
defer func() {
Expand All @@ -452,10 +443,18 @@ func installPkg(dir string, ps *goolib.PkgSpec, dbOnly bool) (map[string]string,
return nil, err
}
}
if dbOnly {
return insFiles, nil

if !dbOnly {
if err := system.Install(dir, ps); err != nil {
return nil, err
}
}
return insFiles, system.Install(dir, ps)

if err := oswrap.RemoveAll(dir); err != nil {
logger.Error(err)
}

return insFiles, nil
}

func listDeps(pi goolib.PackageInfo, rm client.RepoMap, repo string, dl []goolib.PackageInfo, archs []string) ([]goolib.PackageInfo, error) {
Expand Down
38 changes: 36 additions & 2 deletions install/install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ limitations under the License.
package install

import (
"archive/tar"
"compress/gzip"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"reflect"
Expand Down Expand Up @@ -135,22 +139,52 @@ func TestInstallPkg(t *testing.T) {

defer oswrap.RemoveAll(dst)

f, err := os.Create(filepath.Join(src, "test.goo"))
if err != nil {
log.Fatal(err)
}
defer oswrap.Remove(f.Name())

gw := gzip.NewWriter(f)
tw := tar.NewWriter(gw)

files := []string{"test1", "test2", "test3"}
want := map[string]string{dst: ""}
for _, n := range files {
f, err := oswrap.Create(filepath.Join(src, n))
if err != nil {
t.Fatalf("Failed to create test file: %v", err)
}

fi, err := f.Stat()
if err != nil {
t.Fatal(err)
}
fih, err := tar.FileInfoHeader(fi, "")
if err != nil {
t.Fatal(err)
}
if err := tw.WriteHeader(fih); err != nil {
t.Fatal(err)
}
if _, err := io.Copy(tw, f); err != nil {
t.Fatal(err)
}

want[filepath.Join(dst, n)] = goolib.Checksum(f)
if err := f.Close(); err != nil {
t.Fatalf("Failed to close test file: %v", err)
}
}

ps := goolib.PkgSpec{Files: map[string]string{filepath.Base(src): dst}}
tw.Close()
gw.Close()
if err := f.Close(); err != nil {
log.Fatal(err)
}

got, err := installPkg(filepath.Dir(src), &ps, false)
ps := goolib.PkgSpec{Files: map[string]string{"./": dst}}
got, err := installPkg(f.Name(), &ps, false)
if err != nil {
t.Fatalf("Error running installPkg: %v", err)
}
Expand Down

0 comments on commit b18e545

Please sign in to comment.