func Parse(r io.Reader) (*Tar, error) {

	i := &Tar{}

	gz, err := gzip.NewReader(r)
	if err != nil {
		return nil, err
	}
	defer gz.Close()

	tr := tar.NewReader(gz)

	for {
		hdr, err := tr.Next()

		if err == io.EOF {
			break // End of archive
		}
		if err != nil {
			return nil, err
		}

		switch hdr.Typeflag {
		case tar.TypeSymlink:
		case tar.TypeReg:
			switch filepath.Ext(hdr.Name) {
			case ".json":
				if strings.EqualFold(hdr.Name, "manifest.json") {
					rawJSON, err := ioutil.ReadAll(tr)
					if err != nil {
						return nil, err
					}
					var manifests []Manifest
					if err := json.Unmarshal(rawJSON, &manifests); err != nil {
						return nil, err
					}
					i.Manifest = manifests[0]
				} else {
					rawJSON, err := ioutil.ReadAll(tr)
					if err != nil {
						return nil, err
					}
					i.Config, err = NewFromJSON(rawJSON)
					if err != nil {
						return nil, err
					}
				}
			case ".tar":
				// if err = i.processLayerTar(hdr.Name, currentLayer, tar.NewReader(tr)); err != nil {
				if err = i.processLayerTar(hdr.Name, 0, tr); err != nil {
					return nil, err
				}
			}
		}
	}

	i.Tag = i.Manifest.RepoTags[0]
	i.Layers = make([]Layer, len(i.RefTrees))

	nonEmptyLayerIdx := 0 // TODO

	for _, history := range i.Config.History {
		if !history.EmptyLayer {
			for _, tree := range i.RefTrees {
				if strings.Contains(i.Manifest.Layers[nonEmptyLayerIdx], tree.Name) {
					history.Size = tree.FileSize
					i.Layers[nonEmptyLayerIdx] = &dockerLayer{
						history: history,
						index:   nonEmptyLayerIdx,
						tree:    tree,
						tarPath: i.Manifest.Layers[nonEmptyLayerIdx],
					}
				}
			}
			nonEmptyLayerIdx++
		}
	}

	return i, nil
}
// Parse parses an image tar.gz file
Parse parses an image tar.gz file
// Parse parses an image tar . gz file
func Parse(r io.Reader) (*Tar, error) {
	i := &Tar{}
	gz, err := gzip.NewReader(r)
	if err != nil {
		return nil, err
	}
	defer gz.Close()
	tr := tar.NewReader(gz)
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break 
		}
		if err != nil {
			return nil, err
		}
		switch hdr.Typeflag {
		case tar.TypeSymlink:
		case tar.TypeReg:
			switch filepath.Ext(hdr.Name) {
			case ".json":
				if strings.EqualFold(hdr.Name, "manifest.json") {
					rawJSON, err := ioutil.ReadAll(tr)
					if err != nil {
						return nil, err
					}
					var manifests []Manifest
					if err := json.Unmarshal(rawJSON, &manifests); err != nil {
						return nil, err
					}
					i.Manifest = manifests[0]
				} else {
					rawJSON, err := ioutil.ReadAll(tr)
					if err != nil {
						return nil, err
					}
					i.Config, err = NewFromJSON(rawJSON)
					if err != nil {
						return nil, err
					}
				}
			case ".tar":
				if err = i.processLayerTar(hdr.Name, 0, tr); err != nil {
					return nil, err
				}
			}
		}
	}
	i.Tag = i.Manifest.RepoTags[0]
	i.Layers = make([]Layer, len(i.RefTrees))
	nonEmptyLayerIdx := 0 
	for _, history := range i.Config.History {
		if !history.EmptyLayer {
			for _, tree := range i.RefTrees {
				if strings.Contains(i.Manifest.Layers[nonEmptyLayerIdx], tree.Name) {
					history.Size = tree.FileSize
					i.Layers[nonEmptyLayerIdx] = &dockerLayer{
						history: history,
						index:   nonEmptyLayerIdx,
						tree:    tree,
						tarPath: i.Manifest.Layers[nonEmptyLayerIdx],
					}
				}
			}
			nonEmptyLayerIdx++
		}
	}
	return i, nil
}
func Parse ( r io . Reader ) ( * Tar , error ) { i := & Tar { } gz , err := gzip . NewReader ( r ) if err != nil { return nil , err } defer gz . Close ( ) tr := tar . NewReader ( gz ) for { hdr , err := tr . Next ( ) if err == io . EOF { break } if err != nil { return nil , err } switch hdr . Typeflag { case tar . TypeSymlink : case tar . TypeReg : switch filepath . Ext ( hdr . Name ) { case " " : if strings . EqualFold ( hdr . Name , " " ) { rawJSON , err := ioutil . ReadAll ( tr ) if err != nil { return nil , err } var manifests [ ] Manifest if err := json . Unmarshal ( rawJSON , & manifests ) ; err != nil { return nil , err } i . Manifest = manifests [ 0 ] } else { rawJSON , err := ioutil . ReadAll ( tr ) if err != nil { return nil , err } i . Config , err = NewFromJSON ( rawJSON ) if err != nil { return nil , err } } case " " : if err = i . processLayerTar ( hdr . Name , 0 , tr ) ; err != nil { return nil , err } } } } i . Tag = i . Manifest . RepoTags [ 0 ] i . Layers = make ( [ ] Layer , len ( i . RefTrees ) ) nonEmptyLayerIdx := 0 for _ , history := range i . Config . History { if ! history . EmptyLayer { for _ , tree := range i . RefTrees { if strings . Contains ( i . Manifest . Layers [ nonEmptyLayerIdx ] , tree . Name ) { history . Size = tree . FileSize i . Layers [ nonEmptyLayerIdx ] = & dockerLayer { history : history , index : nonEmptyLayerIdx , tree : tree , tarPath : i . Manifest . Layers [ nonEmptyLayerIdx ] , } } } nonEmptyLayerIdx ++ } } return i , nil }
Parse parses an image tar.gz file
Parse parses an image tar . gz file
// End of archive // if err = i.processLayerTar(hdr.Name, currentLayer, tar.NewReader(tr)); err != nil { // TODO