예제 #1
0
파일: zip_test.go 프로젝트: xuewuhen/cae
func TestCopy(t *testing.T) {
	Convey("Copy file from A to B", t, func() {
		Convey("Copy a file that does exist", func() {
			tmpPath := path.Join(os.TempDir(), "testdata/README.txt")
			So(cae.Copy(tmpPath, "testdata/README.txt"), ShouldBeNil)
			So(cae.IsExist(tmpPath), ShouldBeTrue)
		})

		Convey("Copy a file that does not exist", func() {
			So(cae.Copy(
				path.Join(os.TempDir(), "testdata/README.txt"),
				"testdata/404.txt"), ShouldNotBeNil)
		})
	})
}
예제 #2
0
// extractFile extracts file from ZipArchive to file system.
func (z *ZipArchive) extractFile(f *File) error {
	if !z.isHasWriter {
		for _, zf := range z.ReadCloser.File {
			if f.Name == zf.Name {
				return extractFile(zf, path.Dir(f.tmpPath))
			}
		}
	}
	return cae.Copy(f.tmpPath, f.absPath)
}
예제 #3
0
파일: write.go 프로젝트: xuewuhen/cae
// extractFile extracts file from TzArchive to file system.
func (tz *TzArchive) extractFile(f *File, tr *tar.Reader) error {
	if !tz.isHasWriter {
		for _, h := range tz.ReadCloser.File {
			if f.Name == h.Name {
				return extractFile(h, tr, f.absPath)
			}
		}
	}

	return cae.Copy(f.Name, f.absPath)
}
예제 #4
0
파일: write.go 프로젝트: xuewuhen/cae
// ExtractTo extracts the whole archive or the given files to the
// specified destination.
// It accepts a function as a middleware for custom operations.
func (tz *TzArchive) ExtractToFunc(destPath string, fn cae.HookFunc, entries ...string) (err error) {
	destPath = strings.Replace(destPath, "\\", "/", -1)
	isHasEntry := len(entries) > 0
	if Verbose {
		fmt.Println("Extracting " + tz.FileName + "...")
	}
	os.MkdirAll(destPath, os.ModePerm)

	// Copy post-added files.
	for _, f := range tz.files {
		if !cae.IsExist(f.absPath) {
			continue
		}

		relPath := path.Join(destPath, f.Name)
		os.MkdirAll(path.Dir(relPath), os.ModePerm)
		if err := cae.Copy(relPath, f.absPath); err != nil {
			return err
		}
	}

	tr, f, err := openFile(tz.FileName)
	if err != nil {
		return err
	}
	defer f.Close()

	for {
		h, err := tr.Next()
		if err == io.EOF {
			break
		} else if err != nil {
			return err
		}

		h.Name = strings.Replace(h.Name, "\\", "/", -1)

		// Directory.
		if h.Typeflag == tar.TypeDir {
			if isHasEntry {
				if cae.IsEntry(h.Name, entries) {
					if err = fn(h.Name, h.FileInfo()); err != nil {
						continue
					}
					os.MkdirAll(path.Join(destPath, h.Name), os.ModePerm)
				}
				continue
			}
			if err = fn(h.Name, h.FileInfo()); err != nil {
				continue
			}
			os.MkdirAll(path.Join(destPath, h.Name), os.ModePerm)
			continue
		}

		// File.
		if isHasEntry {
			if cae.IsEntry(h.Name, entries) {
				if err = fn(h.Name, h.FileInfo()); err != nil {
					continue
				}
				err = extractFile(h, tr, destPath)
			}
		} else {
			if err = fn(h.Name, h.FileInfo()); err != nil {
				continue
			}
			err = extractFile(h, tr, destPath)
		}
		if err != nil {
			return err
		}
	}
	return nil
}
예제 #5
0
파일: write.go 프로젝트: xuewuhen/cae
// Flush saves changes to original zip file if any.
func (tz *TzArchive) Flush() (err error) {
	if !tz.isHasChanged || (tz.ReadCloser == nil && !tz.isHasWriter) {
		return nil
	}

	// Extract to tmp path and pack back.
	tmpPath := path.Join(os.TempDir(), "cae", path.Base(tz.FileName))
	os.RemoveAll(tmpPath)
	os.MkdirAll(tmpPath, os.ModePerm)
	defer os.RemoveAll(tmpPath)

	// Copy post-added files.
	for _, f := range tz.files {
		if strings.HasSuffix(f.Name, "/") {
			os.MkdirAll(path.Join(tmpPath, f.Name), os.ModePerm)
			continue
		} else if !cae.IsExist(f.absPath) {
			continue
		}

		relPath := path.Join(tmpPath, f.Name)
		os.MkdirAll(path.Dir(relPath), os.ModePerm)
		if err := cae.Copy(relPath, f.absPath); err != nil {
			return err
		}
	}

	if !tz.isHasWriter {
		tz.ReadCloser, err = openReader(tz.FileName)
		if err != nil {
			return err
		}
		tz.syncFiles()

		tr, f, err := openFile(tz.FileName)
		if err != nil {
			return err
		}
		defer f.Close()

		i := 0
		for {
			h, err := tr.Next()
			if err == io.EOF {
				break
			} else if err != nil {
				return err
			}

			if h.Typeflag == tar.TypeDir {
				os.MkdirAll(path.Join(tmpPath, h.Name), os.ModePerm)
				continue
			}

			// Relative path inside zip temporary changed.
			fileName := tz.files[i].Name
			tz.files[i].Name = path.Join(tmpPath, fileName)
			if err := tz.extractFile(tz.files[i], tr); err != nil {
				return err
			}
			// Change back here.
			tz.files[i].Name = fileName
			i++
		}
	}

	if tz.isHasWriter {
		return packToWriter(tmpPath, tz.writer, defaultPackFunc, true)
	}

	if err := PackTo(tmpPath, tz.FileName); err != nil {
		return err
	}
	return tz.Open(tz.FileName, os.O_RDWR|os.O_TRUNC, tz.Permission)
}