Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Unified Diff: go/src/infra/tools/cipd/reader.go

Issue 1129043003: cipd: Refactor client to make it more readable. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « go/src/infra/tools/cipd/pkgdef_test.go ('k') | go/src/infra/tools/cipd/reader_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: go/src/infra/tools/cipd/reader.go
diff --git a/go/src/infra/tools/cipd/reader.go b/go/src/infra/tools/cipd/reader.go
deleted file mode 100644
index 5370c25100a44a7db5c2ccab5e121504d24bcde2..0000000000000000000000000000000000000000
--- a/go/src/infra/tools/cipd/reader.go
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package cipd
-
-import (
- "archive/zip"
- "crypto/sha1"
- "encoding/hex"
- "fmt"
- "io"
- "io/ioutil"
- "os"
-)
-
-// PackageInstance represents a binary package file.
-type PackageInstance interface {
- // Close shuts down the package and its data provider.
- Close() error
- // PackageName returns package name, as defined in the manifest.
- PackageName() string
- // InstanceID returns id that identifies particular built of the package. It's a hash of the package data.
- InstanceID() string
- // Files returns a list of files inside the package.
- Files() []File
- // DataReader returns reader that reads raw package data.
- DataReader() io.ReadSeeker
-}
-
-// OpenInstance verifies package SHA1 hash (instanceID if not empty string) and
-// prepares a package instance for extraction. If the call succeeds,
-// PackageInstance takes ownership of io.ReadSeeker. If it also implements
-// io.Closer, it will be closed when package.Close() is called. If an error is
-// returned, io.ReadSeeker remains unowned and caller is responsible for closing
-// it (if required).
-func OpenInstance(r io.ReadSeeker, instanceID string) (PackageInstance, error) {
- out := &packageInstance{data: r}
- err := out.open(instanceID)
- if err != nil {
- return nil, err
- }
- return out, nil
-}
-
-// OpenInstanceFile opens a package instance file on disk.
-func OpenInstanceFile(path string, instanceID string) (inst PackageInstance, err error) {
- file, err := os.Open(path)
- if err != nil {
- return
- }
- inst, err = OpenInstance(file, instanceID)
- if err != nil {
- file.Close()
- }
- return
-}
-
-// ExtractInstance extracts all files from a package instance into a destination.
-func ExtractInstance(inst PackageInstance, dest Destination) error {
- err := dest.Begin()
- if err != nil {
- return err
- }
-
- // Do not leave garbage around in case of a panic.
- needToEnd := true
- defer func() {
- if needToEnd {
- dest.End(false)
- }
- }()
-
- // Use a nested function in a loop for defers.
- extractRegularFile := func(f File) error {
- out, err := dest.CreateFile(f.Name(), f.Executable())
- if err != nil {
- return err
- }
- defer out.Close()
- in, err := f.Open()
- if err != nil {
- return err
- }
- defer in.Close()
- _, err = io.Copy(out, in)
- return err
- }
-
- extractSymlinkFile := func(f File) error {
- target, err := f.SymlinkTarget()
- if err != nil {
- return err
- }
- return dest.CreateSymlink(f.Name(), target)
- }
-
- files := inst.Files()
- for i, f := range files {
- log.Infof("[%d/%d] inflating %s", i+1, len(files), f.Name())
- if f.Symlink() {
- err = extractSymlinkFile(f)
- } else {
- err = extractRegularFile(f)
- }
- if err != nil {
- break
- }
- }
-
- needToEnd = false
- if err == nil {
- err = dest.End(true)
- } else {
- // Ignore error in 'End' and return the original error.
- dest.End(false)
- }
-
- return err
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// PackageInstance implementation.
-
-type packageInstance struct {
- data io.ReadSeeker
- dataSize int64
- instanceID string
- zip *zip.Reader
- files []File
- manifest Manifest
-}
-
-// open reads the package data , verifies SHA1 hash and reads manifest.
-func (inst *packageInstance) open(instanceID string) error {
- // Calculate SHA1 of the data to verify it matches expected instanceID.
- _, err := inst.data.Seek(0, os.SEEK_SET)
- if err != nil {
- return err
- }
- hash := sha1.New()
- _, err = io.Copy(hash, inst.data)
- if err != nil {
- return err
- }
- inst.dataSize, err = inst.data.Seek(0, os.SEEK_CUR)
- if err != nil {
- return err
- }
- calculatedSHA1 := hex.EncodeToString(hash.Sum(nil))
- if instanceID != "" && instanceID != calculatedSHA1 {
- return fmt.Errorf("Package SHA1 hash mismatch")
- }
- inst.instanceID = calculatedSHA1
-
- // List files inside and package manifest.
- inst.zip, err = zip.NewReader(&readerAt{r: inst.data}, inst.dataSize)
- if err != nil {
- return err
- }
- inst.files = make([]File, len(inst.zip.File))
- for i, zf := range inst.zip.File {
- inst.files[i] = &fileInZip{z: zf}
- if inst.files[i].Name() == manifestName {
- inst.manifest, err = readManifestFile(inst.files[i])
- if err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-func (inst *packageInstance) Close() error {
- if inst.data != nil {
- if closer, ok := inst.data.(io.Closer); ok {
- closer.Close()
- }
- inst.data = nil
- }
- inst.dataSize = 0
- inst.instanceID = ""
- inst.zip = nil
- inst.files = []File{}
- inst.manifest = Manifest{}
- return nil
-}
-
-func (inst *packageInstance) InstanceID() string { return inst.instanceID }
-func (inst *packageInstance) PackageName() string { return inst.manifest.PackageName }
-func (inst *packageInstance) Files() []File { return inst.files }
-func (inst *packageInstance) DataReader() io.ReadSeeker { return inst.data }
-
-////////////////////////////////////////////////////////////////////////////////
-// Utilities.
-
-// readManifestFile decodes manifest file zipped inside the package.
-func readManifestFile(f File) (Manifest, error) {
- r, err := f.Open()
- if err != nil {
- return Manifest{}, err
- }
- defer r.Close()
- return readManifest(r)
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// File interface implementation via zip.File.
-
-type fileInZip struct {
- z *zip.File
-}
-
-func (f *fileInZip) Name() string { return f.z.Name }
-func (f *fileInZip) Symlink() bool { return (f.z.Mode() & os.ModeSymlink) != 0 }
-
-func (f *fileInZip) Executable() bool {
- if f.Symlink() {
- return false
- }
- return (f.z.Mode() & 0100) != 0
-}
-
-func (f *fileInZip) Size() uint64 {
- if f.Symlink() {
- return 0
- }
- return f.z.UncompressedSize64
-}
-
-func (f *fileInZip) SymlinkTarget() (string, error) {
- if !f.Symlink() {
- return "", fmt.Errorf("Not a symlink: %s", f.Name())
- }
- r, err := f.z.Open()
- if err != nil {
- return "", err
- }
- defer r.Close()
- data, err := ioutil.ReadAll(r)
- if err != nil {
- return "", err
- }
- return string(data), nil
-}
-
-func (f *fileInZip) Open() (io.ReadCloser, error) {
- if f.Symlink() {
- return nil, fmt.Errorf("Opening a symlink is not allowed: %s", f.Name())
- }
- return f.z.Open()
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ReaderAt implementation via ReadSeeker. Not concurrency safe, moves file
-// pointer around without any locking. Works OK in the context of OpenInstance
-// function though (where OpenInstance takes sole ownership of io.ReadSeeker).
-
-type readerAt struct {
- r io.ReadSeeker
-}
-
-func (r *readerAt) ReadAt(data []byte, off int64) (int, error) {
- _, err := r.r.Seek(off, os.SEEK_SET)
- if err != nil {
- return 0, err
- }
- return r.r.Read(data)
-}
« no previous file with comments | « go/src/infra/tools/cipd/pkgdef_test.go ('k') | go/src/infra/tools/cipd/reader_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698