Add check that dep pkgs exist on selected project

This commit is contained in:
Sam Boyer 2016-06-22 00:03:51 -04:00
Родитель 67a37f94ac
Коммит 4a028ebe5b
4 изменённых файлов: 126 добавлений и 2 удалений

Просмотреть файл

@ -307,3 +307,76 @@ func (e *checkeeHasProblemPackagesFailure) traceString() string {
return buf.String()
}
type depHasProblemPackagesFailure struct {
goal Dependency
v Version
pl []string
prob map[string]error
}
func (e *depHasProblemPackagesFailure) Error() string {
fcause := func(pkg string) string {
var cause string
if err, has := e.prob[pkg]; has {
cause = fmt.Sprintf("does not contain usable Go code (%T).", err)
} else {
cause = "is missing."
}
return cause
}
if len(e.pl) == 1 {
return fmt.Sprintf(
"Could not introduce %s at %s, as it requires package %s from %s, but in version %s that package %s",
e.goal.Depender.Ident.errString(),
e.goal.Depender.Version,
e.pl[0],
e.goal.Dep.Ident.errString(),
e.v,
fcause(e.pl[0]),
)
}
var buf bytes.Buffer
fmt.Fprintf(
&buf, "Could not introduce %s at %s, as it requires problematic packages from %s (current version %s):",
e.goal.Depender.Ident.errString(),
e.goal.Depender.Version,
e.goal.Dep.Ident.errString(),
e.v,
)
for _, pkg := range e.pl {
fmt.Fprintf(&buf, "\t%s %s", pkg, fcause(pkg))
}
return buf.String()
}
func (e *depHasProblemPackagesFailure) traceString() string {
var buf bytes.Buffer
fcause := func(pkg string) string {
var cause string
if err, has := e.prob[pkg]; has {
cause = fmt.Sprintf("has parsing err (%T).", err)
} else {
cause = "is missing"
}
return cause
}
fmt.Fprintf(
&buf, "%s at %s depping on %s at %s has problem subpkg(s):",
e.goal.Depender.Ident.errString(),
e.goal.Depender.Version,
e.goal.Dep.Ident.errString(),
e.v,
)
for _, pkg := range e.pl {
fmt.Fprintf(&buf, "\t%s %s", pkg, fcause(pkg))
}
return buf.String()
}

Просмотреть файл

@ -35,6 +35,9 @@ func (s *solver) checkProject(a atomWithPackages) error {
if err := s.checkDepsDisallowsSelected(a, dep); err != nil {
return err
}
if err := s.checkPackageImportsFromDepExist(a, dep); err != nil {
return err
}
// TODO add check that fails if adding this atom would create a loop
}
@ -70,6 +73,9 @@ func (s *solver) checkPackage(a atomWithPackages) error {
if err := s.checkDepsDisallowsSelected(a, dep); err != nil {
return err
}
if err := s.checkPackageImportsFromDepExist(a, dep); err != nil {
return err
}
}
return nil
@ -135,10 +141,12 @@ func (s *solver) checkRequiredPackagesExist(a atomWithPackages) error {
}
if len(fp) > 0 {
return &checkeeHasProblemPackagesFailure{
e := &checkeeHasProblemPackagesFailure{
goal: a.atom,
failpkg: fp,
}
s.logSolve(e)
return e
}
return nil
}
@ -228,3 +236,44 @@ func (s *solver) checkIdentMatches(a atomWithPackages, cdep completeDep) error {
return nil
}
// checkPackageImportsFromDepExist ensures that, if the dep is already selected,
// the newly-required set of packages being placed on it exist and are valid.
func (s *solver) checkPackageImportsFromDepExist(a atomWithPackages, cdep completeDep) error {
sel, is := s.sel.selected(cdep.ProjectDep.Ident)
if !is {
// dep is not already selected; nothing to do
return nil
}
ptree, err := s.b.listPackages(sel.atom.Ident, sel.atom.Version)
if err != nil {
// TODO handle this more gracefully
return err
}
e := &depHasProblemPackagesFailure{
goal: Dependency{
Depender: a.atom,
Dep: cdep,
},
v: sel.atom.Version,
prob: make(map[string]error),
}
for _, pkg := range cdep.pl {
perr, has := ptree.Packages[pkg]
if !has || perr.Err != nil {
e.pl = append(e.pl, pkg)
if has {
e.prob[pkg] = perr.Err
}
}
}
if len(e.pl) > 0 {
s.logSolve(e)
return e
}
return nil
}

Просмотреть файл

@ -345,7 +345,7 @@ var bimodalFixtures = map[string]bimodalFixture{
pkg("d", "a/nonexistent"),
),
},
errp: []string{"d", "a"},
errp: []string{"d", "a", "d"},
},
}

Просмотреть файл

@ -303,6 +303,8 @@ func getFailureCausingProjects(err error) (projs []string) {
projs = append(projs, string(atom.Ident.LocalName))
}
}
case *depHasProblemPackagesFailure:
projs = append(projs, string(e.goal.Depender.Ident.LocalName), string(e.goal.Dep.Ident.LocalName))
default:
panic("unknown failtype")
}