Split out manifest and lock into their own files

This commit is contained in:
Sam Boyer 2016-04-28 10:02:44 -04:00
Родитель 310aa87ba4
Коммит f14e377797
4 изменённых файлов: 192 добавлений и 188 удалений

134
lock.go Normal file
Просмотреть файл

@ -0,0 +1,134 @@
package vsolver
// Lock represents data from a lock file (or however the implementing tool
// chooses to store it) at a particular version that is relevant to the
// satisfiability solving process.
//
// In general, the information produced by vsolver on finding a successful
// solution is all that would be necessary to constitute a lock file, though
// tools can include whatever other information they want in their storage.
type Lock interface {
// Indicates the version of the solver used to generate this lock data
//SolverVersion() string
// The hash of inputs to vsolver that resulted in this lock data
InputHash() []byte
// Projects returns the list of LockedProjects contained in the lock data.
Projects() []LockedProject
}
// LockedProject is a single project entry from a lock file. It expresses the
// project's name, one or both of version and underlying revision, the URI for
// accessing it, and the path at which it should be placed within a vendor
// directory.
//
// TODO note that sometime soon, we also plan to allow pkgs. this'll change
type LockedProject struct {
n ProjectName
v UnpairedVersion
r Revision
path, uri string
}
// SimpleLock is a helper for tools to easily describe lock data when they know
// that no hash, or other complex information, is available.
type SimpleLock []LockedProject
var _ Lock = SimpleLock{}
// InputHash always returns an empty string for SimpleLock. This makes it useless
// as a stable lock to be written to disk, but still useful for some ephemeral
// purposes.
func (SimpleLock) InputHash() []byte {
return nil
}
// Projects returns the entire contents of the SimpleLock.
func (l SimpleLock) Projects() []LockedProject {
return l
}
// NewLockedProject creates a new LockedProject struct with a given name,
// version, upstream repository URI, and on-disk path at which the project is to
// be checked out under a vendor directory.
//
// Note that passing a nil version will cause a panic. This is a correctness
// measure to ensure that the solver is never exposed to a version-less lock
// entry. Such a case would be meaningless - the solver would have no choice but
// to simply dismiss that project. By creating a hard failure case via panic
// instead, we are trying to avoid inflicting the resulting pain on the user by
// instead forcing a decision on the Analyzer implementation.
func NewLockedProject(n ProjectName, v Version, uri, path string) LockedProject {
if v == nil {
panic("must provide a non-nil version to create a LockedProject")
}
lp := LockedProject{
n: n,
uri: uri,
path: path,
}
switch tv := v.(type) {
case Revision:
lp.r = tv
case branchVersion:
lp.v = tv
case semVersion:
lp.v = tv
case plainVersion:
lp.v = tv
case versionPair:
lp.r = tv.r
lp.v = tv.v
}
return lp
}
// Name returns the name of the locked project.
func (lp LockedProject) Name() ProjectName {
return lp.n
}
// Version assembles together whatever version and/or revision data is
// available into a single Version.
func (lp LockedProject) Version() Version {
if lp.r == "" {
return lp.v
}
if lp.v == nil {
return lp.r
}
return lp.v.Is(lp.r)
}
// URI returns the upstream URI of the locked project.
func (lp LockedProject) URI() string {
return lp.uri
}
// Path returns the path relative to the vendor directory to which the locked
// project should be checked out.
func (lp LockedProject) Path() string {
return lp.path
}
func (lp LockedProject) toAtom() ProjectAtom {
pa := ProjectAtom{
Name: lp.n,
}
if lp.v == nil {
pa.Version = lp.r
} else if lp.r != "" {
pa.Version = lp.v.Is(lp.r)
} else {
pa.Version = lp.v
}
return pa
}

50
manifest.go Normal file
Просмотреть файл

@ -0,0 +1,50 @@
package vsolver
// Manifest represents the data from a manifest file (or however the
// implementing tool chooses to store it) at a particular version that is
// relevant to the satisfiability solving process:
//
// - A list of dependencies: project name, and a constraint
// - A list of development-time dependencies (e.g. for testing - only
// the root project's are incorporated)
//
// Finding a solution that satisfies the constraints expressed by all of these
// dependencies (and those from all other projects, transitively), is what the
// solver does.
//
// Note that vsolver does perform static analysis on all projects' codebases;
// if dependencies it finds through that analysis are missing from what the
// Manifest lists, it is considered an error that will eliminate that version
// from consideration in the solving algorithm.
type Manifest interface {
Name() ProjectName
GetDependencies() []ProjectDep
GetDevDependencies() []ProjectDep
}
// SimpleManifest is a helper for tools to enumerate manifest data. It's
// generally intended for ephemeral manifests, such as those Analyzers create on
// the fly for projects with no manifest metadata, or metadata through a foreign
// tool's idioms.
type SimpleManifest struct {
N ProjectName
P []ProjectDep
DP []ProjectDep
}
var _ Manifest = SimpleManifest{}
// Name returns the name of the project described by the manifest.
func (m SimpleManifest) Name() ProjectName {
return m.N
}
// GetDependencies returns the project's dependencies.
func (m SimpleManifest) GetDependencies() []ProjectDep {
return m.P
}
// GetDependencies returns the project's test dependencies.
func (m SimpleManifest) GetDevDependencies() []ProjectDep {
return m.DP
}

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

@ -336,15 +336,16 @@ func (s *solver) getLockVersionIfValid(ref ProjectName) (ProjectAtom, error) {
// If the project is specifically marked for changes, then don't look for a
// locked version.
if _, explicit := s.latest[ref]; explicit || s.o.ChangeAll {
// For projects with an upstream or cache repository, it's safe to
// ignore what's in the lock, because there's presumably more versions
// to be found and attempted in the repository. If it's only in vendor,
// though, then we have to try to use what's in the lock, because that's
// the only version we'll be able to get.
if exist, _ := s.sm.RepoExists(ref); exist {
return nilpa, nil
}
// For projects without an upstream or cache repository, we still have
// to try to use what they have in the lock, because that's the only
// version we'll be able to actually get for them.
//
// However, if a change was expressly requested for something that
// However, if a change was *expressly* requested for something that
// exists only in vendor, then that guarantees we don't have enough
// information to complete a solution. In that case, error out.
if explicit {

185
types.go
Просмотреть файл

@ -1,8 +1,8 @@
package vsolver
type ProjectIdentifier struct {
Name ProjectName
NetworkURI string
LocalName ProjectName
NetworkName string
}
type ProjectName string
@ -30,184 +30,3 @@ type ProjectInfo struct {
Manifest
Lock
}
// LockedProject is a single project entry from a lock file. It expresses the
// project's name, one or both of version and underlying revision, the URI for
// accessing it, and the path at which it should be placed within a vendor
// directory.
//
// TODO note that sometime soon, we also plan to allow pkgs. this'll change
type LockedProject struct {
n ProjectName
v UnpairedVersion
r Revision
path, uri string
}
// NewLockedProject creates a new LockedProject struct with a given name,
// version, upstream repository URI, and on-disk path at which the project is to
// be checked out under a vendor directory.
//
// Note that passing a nil version will cause a panic. This is a correctness
// measure to ensure that the solver is never exposed to a version-less lock
// entry. Such a case would be meaningless - the solver would have no choice but
// to simply dismiss that project. By creating a hard failure case via panic
// instead, we are trying to avoid inflicting the resulting pain on the user by
// instead forcing a decision on the Analyzer implementation.
func NewLockedProject(n ProjectName, v Version, uri, path string) LockedProject {
if v == nil {
panic("must provide a non-nil version to create a LockedProject")
}
lp := LockedProject{
n: n,
uri: uri,
path: path,
}
switch tv := v.(type) {
case Revision:
lp.r = tv
case branchVersion:
lp.v = tv
case semVersion:
lp.v = tv
case plainVersion:
lp.v = tv
case versionPair:
lp.r = tv.r
lp.v = tv.v
}
return lp
}
// Name returns the name of the locked project.
func (lp LockedProject) Name() ProjectName {
return lp.n
}
// Version assembles together whatever version and/or revision data is
// available into a single Version.
func (lp LockedProject) Version() Version {
if lp.r == "" {
return lp.v
}
if lp.v == nil {
return lp.r
}
return lp.v.Is(lp.r)
}
// URI returns the upstream URI of the locked project.
func (lp LockedProject) URI() string {
return lp.uri
}
// Path returns the path relative to the vendor directory to which the locked
// project should be checked out.
func (lp LockedProject) Path() string {
return lp.path
}
func (lp LockedProject) toAtom() ProjectAtom {
pa := ProjectAtom{
Name: lp.n,
}
if lp.v == nil {
pa.Version = lp.r
} else if lp.r != "" {
pa.Version = lp.v.Is(lp.r)
} else {
pa.Version = lp.v
}
return pa
}
// Manifest represents the data from a manifest file (or however the
// implementing tool chooses to store it) at a particular version that is
// relevant to the satisfiability solving process:
//
// - A list of dependencies: project name, and a constraint
// - A list of development-time dependencies (e.g. for testing - only
// the root project's are incorporated)
//
// Finding a solution that satisfies the constraints expressed by all of these
// dependencies (and those from all other projects, transitively), is what the
// solver does.
//
// Note that vsolver does perform static analysis on all projects' codebases;
// if dependencies it finds through that analysis are missing from what the
// Manifest lists, it is considered an error that will eliminate that version
// from consideration in the solving algorithm.
type Manifest interface {
Name() ProjectName
GetDependencies() []ProjectDep
GetDevDependencies() []ProjectDep
}
// Lock represents data from a lock file (or however the implementing tool
// chooses to store it) at a particular version that is relevant to the
// satisfiability solving process.
//
// In general, the information produced by vsolver on finding a successful
// solution is all that would be necessary to constitute a lock file, though
// tools can include whatever other information they want in their storage.
type Lock interface {
// Indicates the version of the solver used to generate this lock data
//SolverVersion() string
// The hash of inputs to vsolver that resulted in this lock data
InputHash() []byte
// Projects returns the list of LockedProjects contained in the lock data.
Projects() []LockedProject
}
// SimpleLock is a helper for tools to simply enumerate lock data when they know
// that no hash, or other complex information, is available.
type SimpleLock []LockedProject
var _ Lock = SimpleLock{}
// InputHash always returns an empty string for SimpleLock. This makes it useless
// as a stable lock to be written to disk, but still useful for some ephemeral
// purposes.
func (SimpleLock) InputHash() []byte {
return nil
}
// Projects returns the entire contents of the SimpleLock.
func (l SimpleLock) Projects() []LockedProject {
return l
}
// SimpleManifest is a helper for tools to enumerate manifest data. It's
// intended for ephemeral manifests, such as those created by Analyzers on the
// fly.
type SimpleManifest struct {
N ProjectName
P []ProjectDep
DP []ProjectDep
}
var _ Manifest = SimpleManifest{}
// Name returns the name of the project described by the manifest.
func (m SimpleManifest) Name() ProjectName {
return m.N
}
// GetDependencies returns the project's dependencies.
func (m SimpleManifest) GetDependencies() []ProjectDep {
return m.P
}
// GetDependencies returns the project's test dependencies.
func (m SimpleManifest) GetDevDependencies() []ProjectDep {
return m.DP
}