github.com/joey-fossa/fossa-cli@v0.7.34-0.20190708193710-569f1e8679f0/buildtools/pip/pipdeptree.go (about)

     1  package pip
     2  
     3  import (
     4  	"encoding/json"
     5  	"io/ioutil"
     6  	"os"
     7  
     8  	"github.com/pkg/errors"
     9  
    10  	"github.com/fossas/fossa-cli/buildtools/pip/bindata"
    11  	"github.com/fossas/fossa-cli/exec"
    12  )
    13  
    14  //go:generate go-bindata -pkg bindata -modtime 1 -o ./bindata/bindata.go ./bindata/pipdeptree.py
    15  
    16  type DepTree struct {
    17  	Package      string `json:"package_name"`
    18  	Resolved     string `json:"installed_version"`
    19  	Target       string `json:"required_version"`
    20  	Dependencies []DepTree
    21  }
    22  
    23  func (p *Pip) DepTree() ([]DepTree, error) {
    24  	// Write helper to disk.
    25  	src, err := bindata.Asset("bindata/pipdeptree.py")
    26  	if err != nil {
    27  		return nil, errors.Wrap(err, "could not read `pipdeptree` helper")
    28  	}
    29  
    30  	pipdeptreeFile, err := ioutil.TempFile("", "fossa-cli-pipdeptree-")
    31  	if err != nil {
    32  		return nil, errors.Wrap(err, "could not create temp file to write `pipdeptree` helper")
    33  	}
    34  	defer pipdeptreeFile.Close()
    35  	defer os.Remove(pipdeptreeFile.Name())
    36  
    37  	n, err := pipdeptreeFile.Write(src)
    38  	if len(src) != n || err != nil {
    39  		return nil, errors.Wrap(err, "could not write `pipdeptree` helper")
    40  	}
    41  	err = pipdeptreeFile.Sync()
    42  	if err != nil {
    43  		return nil, errors.Wrap(err, "could not flush `pipdeptree` helper to storage")
    44  	}
    45  
    46  	// Run helper.
    47  	out, _, err := exec.Run(exec.Cmd{
    48  		Name: p.PythonCmd,
    49  		Argv: []string{pipdeptreeFile.Name(), "--local-only", "--json-tree"},
    50  	})
    51  	if err != nil {
    52  		return nil, errors.Wrap(err, "could not run `pipdeptree`")
    53  	}
    54  
    55  	// Parse output.
    56  	var parsed []DepTree
    57  	err = json.Unmarshal([]byte(out), &parsed)
    58  	if err != nil {
    59  		return nil, errors.Wrap(err, "could not parse `pipdeptree` output")
    60  	}
    61  
    62  	return parsed, nil
    63  }