func()

in getdeps/untar.go [56:147]


func (pkg *Untar) Get(projectDir string, urlOverrides *URLOverrides, hashMode HashMode) error {
	// ignore file info, will use permissions from the tar metadata
	data, _, err := fetchAndVerify(pkg.Label, projectDir, pkg.URL, hashMode, &pkg.Hash, urlOverrides)
	if err != nil {
		return err
	}

	dir, _ := os.Getwd()
	log.Printf("%s: Uncompressing into %s...", pkg.Label, dir)

	// uncompress. We support gzip and xz.
	reader := bytes.NewReader(data)

	var archive io.Reader
	// gzip can be detected with http.DetectContentType, but xz is not
	// supported. So we match the magic bytes in the xz header, as specified in
	// the XZ file format Section 2.1.1.1, see
	// https://tukaani.org/xz/xz-file-format.txt .
	//
	// For gzip, the magic bytes are 1F 8B (starting at 0)
	// for xz the magic bytes are FD 37 7A 58 5A 00 (starting at 0)
	compressionType := detectCompressionType(data)
	switch compressionType {
	case CompressionTypeGzip:
		archive, err = gzip.NewReader(reader)
		// Close only required for gzip package
		defer archive.(io.ReadCloser).Close()
	case CompressionTypeXz:
		archive, err = xz.NewReader(reader)
	case CompressionTypeUnsupported:
		fallthrough
	default:
		return errors.New("unsupported compression type")
	}
	if err != nil {
		return err
	}

	// untar
	tarReader := tar.NewReader(archive)
	subdirParts := strings.Split(pkg.Subdir, "/")
entry:
	for {
		header, err := tarReader.Next()
		if err == io.EOF {
			break
		} else if err != nil {
			return err
		}

		var name string
		if len(pkg.Subdir) > 0 {
			nameParts := strings.Split(header.Name, "/")
			if len(nameParts) <= len(subdirParts) {
				continue entry
			}
			for i, p := range subdirParts {
				if nameParts[i] != p {
					continue entry
				}
			}
			name = filepath.Join(nameParts[len(subdirParts):]...)
			if len(name) == 0 {
				continue entry
			}
		} else {
			name = header.Name
		}

		info := header.FileInfo()

		if info.IsDir() {
			if err = os.MkdirAll(name, info.Mode()); err != nil {
				return err
			}
			continue
		}

		file, err := os.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())
		if err != nil {
			return err
		}
		if _, err = io.Copy(file, tarReader); err != nil {
			return err
		}
		if err = file.Close(); err != nil {
			return err
		}
	}

	return err
}