зеркало из https://github.com/golang/dep.git
Add SourceManager.ListPackages(), and friends
This commit is contained in:
Родитель
3c76704b86
Коммит
4dd7ce0831
24
bridge.go
24
bridge.go
|
@ -25,10 +25,12 @@ type sourceBridge interface {
|
|||
deduceRemoteRepo(path string) (*remoteRepo, error)
|
||||
}
|
||||
|
||||
func newBridge(sm SourceManager, downgrade bool) sourceBridge {
|
||||
func newBridge(name ProjectName, root string, sm SourceManager, downgrade bool) sourceBridge {
|
||||
return &bridge{
|
||||
sm: sm,
|
||||
sortdown: downgrade,
|
||||
name: name,
|
||||
root: root,
|
||||
vlists: make(map[ProjectName][]Version),
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +56,14 @@ type bridge struct {
|
|||
// true for downgrades.
|
||||
sortdown bool
|
||||
|
||||
// The name of the root project we're operating on. Used to redirect some
|
||||
// calls that would ordinarily go to the SourceManager to a root-specific
|
||||
// logical path, instead.
|
||||
name ProjectName
|
||||
|
||||
// The path to the base directory of the root project.
|
||||
root string
|
||||
|
||||
// Map of project root name to their available version list. This cache is
|
||||
// layered on top of the proper SourceManager's cache; the only difference
|
||||
// is that this keeps the versions sorted in the direction required by the
|
||||
|
@ -358,6 +368,18 @@ func (b *bridge) computeRootReach(path string) ([]string, error) {
|
|||
return listExternalDeps(path, path, true)
|
||||
}
|
||||
|
||||
// listPackages lists all the packages contained within the given project at a
|
||||
// particular version.
|
||||
//
|
||||
// Special handling is done for the root project.
|
||||
func (b *bridge) listPackages(id ProjectIdentifier, v Version) (map[string]string, error) {
|
||||
if id.LocalName != b.name {
|
||||
return b.sm.ListPackages(b.key(id), v)
|
||||
}
|
||||
|
||||
return listPackages(b.root, string(b.name), true)
|
||||
}
|
||||
|
||||
// verifyRoot ensures that the provided path to the project root is in good
|
||||
// working condition. This check is made only once, at the beginning of a solve
|
||||
// run.
|
||||
|
|
|
@ -258,6 +258,65 @@ func listExternalDeps(basedir, projname string, main bool) ([]string, error) {
|
|||
return ex, nil
|
||||
}
|
||||
|
||||
// listPackages lists all packages, optionally including main packages,
|
||||
// contained at or below the provided path.
|
||||
//
|
||||
// Directories without any valid Go files are excluded. Directories with
|
||||
// multiple packages are excluded. (TODO - maybe accommodate that?)
|
||||
//
|
||||
// A map of import path to package name is returned.
|
||||
func listPackages(basedir, prefix string, main bool) (map[string]string, error) {
|
||||
ctx := build.Default
|
||||
ctx.UseAllFiles = true // optimistic, but we do it for the first try
|
||||
exm := make(map[string]string)
|
||||
|
||||
err := filepath.Walk(basedir, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil && err != filepath.SkipDir {
|
||||
return err
|
||||
}
|
||||
if !fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip a few types of dirs
|
||||
if !localSrcDir(fi) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
// Scan for dependencies, and anything that's not part of the local
|
||||
// package gets added to the scan list.
|
||||
p, err := ctx.ImportDir(path, 0)
|
||||
var imps []string
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case *build.NoGoError:
|
||||
return nil
|
||||
case *build.MultiplePackageError:
|
||||
// Multiple package names declared in the dir, which causes
|
||||
// ImportDir() to choke; use our custom iterative scanner.
|
||||
imps, err = IterativeScan(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if prefix == "" {
|
||||
exm[path] = path
|
||||
} else {
|
||||
exm[path] = prefix + os.PathSeparator + path
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return exm, nil
|
||||
}
|
||||
|
||||
func localSrcDir(fi os.FileInfo) bool {
|
||||
// Ignore _foo and .foo
|
||||
if strings.HasPrefix(fi.Name(), "_") || strings.HasPrefix(fi.Name(), ".") {
|
||||
|
|
|
@ -22,6 +22,7 @@ type ProjectManager interface {
|
|||
ExportVersionTo(Version, string) error
|
||||
ExternalReach(Version) (map[string][]string, error)
|
||||
ListExternal(Version) ([]string, error)
|
||||
ListPackages(Version) (map[string]string, error)
|
||||
}
|
||||
|
||||
type ProjectAnalyzer interface {
|
||||
|
@ -207,6 +208,40 @@ func (pm *projectManager) ListExternal(v Version) ([]string, error) {
|
|||
return ex, err
|
||||
}
|
||||
|
||||
func (pm *projectManager) ListPackages(v Version) (map[string]string, error) {
|
||||
var err error
|
||||
if err = pm.ensureCacheExistence(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pm.crepo.mut.Lock()
|
||||
// Check out the desired version for analysis
|
||||
if pv, ok := v.(PairedVersion); ok {
|
||||
// Always prefer a rev, if it's available
|
||||
err = pm.crepo.r.UpdateVersion(pv.Underlying().String())
|
||||
} else {
|
||||
// If we don't have a rev, ensure the repo is up to date, otherwise we
|
||||
// could have a desync issue
|
||||
if !pm.crepo.synced {
|
||||
err = pm.crepo.r.Update()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not fetch latest updates into repository")
|
||||
}
|
||||
pm.crepo.synced = true
|
||||
}
|
||||
err = pm.crepo.r.UpdateVersion(v.String())
|
||||
}
|
||||
|
||||
// Nothing within the SourceManager is responsible for computing deps of a
|
||||
// root package; it's assumed we're always operating on libraries.
|
||||
// Consequently, we never want to include main packages, so we hardcode
|
||||
// false for the third param.
|
||||
ex, err := listPackages(filepath.Join(pm.ctx.GOPATH, "src", string(pm.n)), string(pm.n), true)
|
||||
pm.crepo.mut.Unlock()
|
||||
|
||||
return ex, err
|
||||
}
|
||||
|
||||
func (pm *projectManager) ensureCacheExistence() error {
|
||||
// Technically, methods could could attempt to return straight from the
|
||||
// metadata cache even if the repo cache doesn't exist on disk. But that
|
||||
|
|
|
@ -165,7 +165,7 @@ func prepareSolver(opts SolveOpts, sm SourceManager) (*solver, error) {
|
|||
|
||||
s := &solver{
|
||||
o: opts,
|
||||
b: newBridge(sm, opts.Downgrade),
|
||||
b: newBridge(o.N, o.Root, sm, opts.Downgrade),
|
||||
tl: opts.TraceLogger,
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ type SourceManager interface {
|
|||
VendorCodeExists(ProjectName) (bool, error)
|
||||
ExternalReach(ProjectName, Version) (map[string][]string, error)
|
||||
ListExternal(ProjectName, Version) ([]string, error)
|
||||
ListPackages(ProjectName, Version) (map[string]string, error)
|
||||
ExportProject(ProjectName, Version, string) error
|
||||
Release()
|
||||
// Flush()
|
||||
|
@ -119,6 +120,15 @@ func (sm *sourceManager) ListExternal(n ProjectName, v Version) ([]string, error
|
|||
return pmc.pm.ListExternal(v)
|
||||
}
|
||||
|
||||
func (sm *sourceManager) ListPackages(n ProjectName, v Version) ([]string, error) {
|
||||
pmc, err := sm.getProjectManager(n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pmc.pm.ListPackages(v)
|
||||
}
|
||||
|
||||
func (sm *sourceManager) ListVersions(n ProjectName) ([]Version, error) {
|
||||
pmc, err := sm.getProjectManager(n)
|
||||
if err != nil {
|
||||
|
|
Загрузка…
Ссылка в новой задаче