Skip to content
This repository has been archived by the owner on Dec 6, 2022. It is now read-only.

Commit

Permalink
migrate from go-ipfs
Browse files Browse the repository at this point in the history
  • Loading branch information
whyrusleeping committed Aug 9, 2015
0 parents commit e8a5890
Showing 1 changed file with 109 additions and 0 deletions.
109 changes: 109 additions & 0 deletions extractor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package tar

import (
"archive/tar"
"io"
"os"
gopath "path"
fp "path/filepath"
"strings"
)

type Extractor struct {
Path string
}

func (te *Extractor) Extract(reader io.Reader) error {
tarReader := tar.NewReader(reader)

// Check if the output path already exists, so we know whether we should
// create our output with that name, or if we should put the output inside
// a preexisting directory
rootExists := true
rootIsDir := false
if stat, err := os.Stat(te.Path); err != nil && os.IsNotExist(err) {
rootExists = false
} else if err != nil {
return err
} else if stat.IsDir() {
rootIsDir = true
}

// files come recursively in order (i == 0 is root directory)
for i := 0; ; i++ {
header, err := tarReader.Next()
if err != nil && err != io.EOF {
return err
}
if header == nil || err == io.EOF {
break
}

if header.Typeflag == tar.TypeDir {
if err := te.extractDir(header, i); err != nil {
return err
}
continue
}

if err := te.extractFile(header, tarReader, i, rootExists, rootIsDir); err != nil {
return err
}
}
return nil
}

// outputPath returns the path at whicht o place tarPath
func (te *Extractor) outputPath(tarPath string) string {
elems := strings.Split(tarPath, "/") // break into elems
elems = elems[1:] // remove original root

path := fp.Join(elems...) // join elems
path = fp.Join(te.Path, path) // rebase on extractor root
return path
}

func (te *Extractor) extractDir(h *tar.Header, depth int) error {
path := te.outputPath(h.Name)

if depth == 0 {
// if this is the root root directory, use it as the output path for remaining files
te.Path = path
}

err := os.MkdirAll(path, 0755)
if err != nil {
return err
}

return nil
}

func (te *Extractor) extractFile(h *tar.Header, r *tar.Reader, depth int, rootExists bool, rootIsDir bool) error {
path := te.outputPath(h.Name)

if depth == 0 { // if depth is 0, this is the only file (we aren't 'ipfs get'ing a directory)
if rootExists && rootIsDir {
// putting file inside of a root dir.
fnameo := gopath.Base(h.Name)
fnamen := fp.Base(path)
// add back original name if lost.
if fnameo != fnamen {
path = fp.Join(path, fnameo)
}
} // else if old file exists, just overwrite it.
}

file, err := os.Create(path)
if err != nil {
return err
}
defer file.Close()

_, err = io.Copy(file, r)
if err != nil {
return err
}

return nil
}

0 comments on commit e8a5890

Please sign in to comment.