diff options
author | Unknwon <u@gogs.io> | 2017-02-09 19:48:13 -0500 |
---|---|---|
committer | Unknwon <u@gogs.io> | 2017-02-09 19:48:13 -0500 |
commit | 2fd69f13d9599a6c58b47225565163fd7d87889f (patch) | |
tree | fd19e868e1c2e95a5fb83a268f6e393669d6ee79 /vendor/github.com/Unknwon/cae/zip/zip.go | |
parent | eb66060cd7b9bce996b1d75ae80ce1ef31d5ce62 (diff) |
vendor: check in vendors
Bye bye glide...
Diffstat (limited to 'vendor/github.com/Unknwon/cae/zip/zip.go')
-rw-r--r-- | vendor/github.com/Unknwon/cae/zip/zip.go | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/vendor/github.com/Unknwon/cae/zip/zip.go b/vendor/github.com/Unknwon/cae/zip/zip.go new file mode 100644 index 00000000..21086f82 --- /dev/null +++ b/vendor/github.com/Unknwon/cae/zip/zip.go @@ -0,0 +1,238 @@ +// Copyright 2013 Unknown +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +// Package zip enables you to transparently read or write ZIP compressed archives and the files inside them. +package zip + +import ( + "archive/zip" + "errors" + "io" + "os" + "path" + "strings" + + "github.com/Unknwon/cae" +) + +// A File represents a file or directory entry in archive. +type File struct { + *zip.FileHeader + oldName string // NOTE: unused, for future change name feature. + oldComment string // NOTE: unused, for future change comment feature. + absPath string // Absolute path of local file system. + tmpPath string +} + +// A ZipArchive represents a file archive, compressed with Zip. +type ZipArchive struct { + *zip.ReadCloser + FileName string + Comment string + NumFiles int + Flag int + Permission os.FileMode + + files []*File + isHasChanged bool + + // For supporting flushing to io.Writer. + writer io.Writer + isHasWriter bool +} + +// OpenFile is the generalized open call; most users will use Open +// instead. It opens the named zip file with specified flag +// (O_RDONLY etc.) if applicable. If successful, +// methods on the returned ZipArchive can be used for I/O. +// If there is an error, it will be of type *PathError. +func OpenFile(name string, flag int, perm os.FileMode) (*ZipArchive, error) { + z := new(ZipArchive) + err := z.Open(name, flag, perm) + return z, err +} + +// Create creates the named zip file, truncating +// it if it already exists. If successful, methods on the returned +// ZipArchive can be used for I/O; the associated file descriptor has mode +// O_RDWR. +// If there is an error, it will be of type *PathError. +func Create(name string) (*ZipArchive, error) { + os.MkdirAll(path.Dir(name), os.ModePerm) + return OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) +} + +// Open opens the named zip file for reading. If successful, methods on +// the returned ZipArchive can be used for reading; the associated file +// descriptor has mode O_RDONLY. +// If there is an error, it will be of type *PathError. +func Open(name string) (*ZipArchive, error) { + return OpenFile(name, os.O_RDONLY, 0) +} + +// New accepts a variable that implemented interface io.Writer +// for write-only purpose operations. +func New(w io.Writer) *ZipArchive { + return &ZipArchive{ + writer: w, + isHasWriter: true, + } +} + +// List returns a string slice of files' name in ZipArchive. +// Specify prefixes will be used as filters. +func (z *ZipArchive) List(prefixes ...string) []string { + isHasPrefix := len(prefixes) > 0 + names := make([]string, 0, z.NumFiles) + for _, f := range z.files { + if isHasPrefix && !cae.HasPrefix(f.Name, prefixes) { + continue + } + names = append(names, f.Name) + } + return names +} + +// AddEmptyDir adds a raw directory entry to ZipArchive, +// it returns false if same directory enry already existed. +func (z *ZipArchive) AddEmptyDir(dirPath string) bool { + dirPath = strings.Replace(dirPath, "\\", "/", -1) + + if !strings.HasSuffix(dirPath, "/") { + dirPath += "/" + } + + for _, f := range z.files { + if dirPath == f.Name { + return false + } + } + + dirPath = strings.TrimSuffix(dirPath, "/") + if strings.Contains(dirPath, "/") { + // Auto add all upper level directories. + z.AddEmptyDir(path.Dir(dirPath)) + } + z.files = append(z.files, &File{ + FileHeader: &zip.FileHeader{ + Name: dirPath + "/", + UncompressedSize: 0, + }, + }) + z.updateStat() + return true +} + +// AddDir adds a directory and subdirectories entries to ZipArchive. +func (z *ZipArchive) AddDir(dirPath, absPath string) error { + dir, err := os.Open(absPath) + if err != nil { + return err + } + defer dir.Close() + + // Make sure we have all upper level directories. + z.AddEmptyDir(dirPath) + + fis, err := dir.Readdir(0) + if err != nil { + return err + } + for _, fi := range fis { + curPath := absPath + "/" + fi.Name() + tmpRecPath := path.Join(dirPath, fi.Name()) + if fi.IsDir() { + if err = z.AddDir(tmpRecPath, curPath); err != nil { + return err + } + } else { + if err = z.AddFile(tmpRecPath, curPath); err != nil { + return err + } + } + } + return nil +} + +// updateStat should be called after every change for rebuilding statistic. +func (z *ZipArchive) updateStat() { + z.NumFiles = len(z.files) + z.isHasChanged = true +} + +// AddFile adds a file entry to ZipArchive. +func (z *ZipArchive) AddFile(fileName, absPath string) error { + fileName = strings.Replace(fileName, "\\", "/", -1) + absPath = strings.Replace(absPath, "\\", "/", -1) + + if cae.IsFilter(absPath) { + return nil + } + + f, err := os.Open(absPath) + if err != nil { + return err + } + defer f.Close() + + fi, err := f.Stat() + if err != nil { + return err + } + + file := new(File) + file.FileHeader, err = zip.FileInfoHeader(fi) + if err != nil { + return err + } + file.Name = fileName + file.absPath = absPath + + z.AddEmptyDir(path.Dir(fileName)) + + isExist := false + for _, f := range z.files { + if fileName == f.Name { + f = file + isExist = true + break + } + } + if !isExist { + z.files = append(z.files, file) + } + + z.updateStat() + return nil +} + +// DeleteIndex deletes an entry in the archive by its index. +func (z *ZipArchive) DeleteIndex(idx int) error { + if idx >= z.NumFiles { + return errors.New("index out of range of number of files") + } + + z.files = append(z.files[:idx], z.files[idx+1:]...) + return nil +} + +// DeleteName deletes an entry in the archive by its name. +func (z *ZipArchive) DeleteName(name string) error { + for i, f := range z.files { + if f.Name == name { + return z.DeleteIndex(i) + } + } + return errors.New("entry with given name not found") +} |