github.com/golang/dep@v0.5.4/gps/manifest.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gps
     6  
     7  import "github.com/golang/dep/gps/pkgtree"
     8  
     9  // Manifest represents manifest-type data for a project at a particular version.
    10  // The constraints expressed in a manifest determine the set of versions that
    11  // are acceptable to try for a given project.
    12  //
    13  // Expressing a constraint in a manifest does not guarantee that a particular
    14  // dependency will be present. It only guarantees that if packages in the
    15  // project specified by the dependency are discovered through static analysis of
    16  // the (transitive) import graph, then they will conform to the constraint.
    17  //
    18  // This does entail that manifests can express constraints on projects they do
    19  // not themselves import. This is by design, but its implications are complex.
    20  // See the gps docs for more information: https://github.com/sdboyer/gps/wiki
    21  type Manifest interface {
    22  	// Returns a list of project-level constraints.
    23  	DependencyConstraints() ProjectConstraints
    24  }
    25  
    26  // RootManifest extends Manifest to add special controls over solving that are
    27  // only afforded to the root project.
    28  type RootManifest interface {
    29  	Manifest
    30  
    31  	// Overrides returns a list of ProjectConstraints that will unconditionally
    32  	// supersede any ProjectConstraint declarations made in either the root
    33  	// manifest, or in any dependency's manifest.
    34  	//
    35  	// Overrides are a special control afforded only to root manifests. Tool
    36  	// users should be encouraged to use them only as a last resort; they do not
    37  	// "play well with others" (that is their express goal), and overreliance on
    38  	// them can harm the ecosystem as a whole.
    39  	Overrides() ProjectConstraints
    40  
    41  	// IgnoredPackages returns a pkgtree.IgnoredRuleset, which comprises a set
    42  	// of import paths, or import path patterns, that are to be ignored during
    43  	// solving. These ignored import paths can be within the root project, or
    44  	// part of other projects. Ignoring a package means that both it and its
    45  	// (unique) imports will be disregarded by all relevant solver operations.
    46  	//
    47  	// It is an error to include a package in both the ignored and required
    48  	// sets.
    49  	IgnoredPackages() *pkgtree.IgnoredRuleset
    50  
    51  	// RequiredPackages returns a set of import paths to require. These packages
    52  	// are required to be present in any solution. The list can include main
    53  	// packages.
    54  	//
    55  	// It is meaningless to specify packages that are within the
    56  	// PackageTree of the ProjectRoot (though not an error, because the
    57  	// RootManifest itself does not report a ProjectRoot).
    58  	//
    59  	// It is an error to include a package in both the ignored and required
    60  	// sets.
    61  	RequiredPackages() map[string]bool
    62  }
    63  
    64  // SimpleManifest is a helper for tools to enumerate manifest data. It's
    65  // generally intended for ephemeral manifests, such as those Analyzers create on
    66  // the fly for projects with no manifest metadata, or metadata through a foreign
    67  // tool's idioms.
    68  type SimpleManifest struct {
    69  	Deps ProjectConstraints
    70  }
    71  
    72  var _ Manifest = SimpleManifest{}
    73  
    74  // DependencyConstraints returns the project's dependencies.
    75  func (m SimpleManifest) DependencyConstraints() ProjectConstraints {
    76  	return m.Deps
    77  }
    78  
    79  // simpleRootManifest exists so that we have a safe value to swap into solver
    80  // params when a nil Manifest is provided.
    81  type simpleRootManifest struct {
    82  	c, ovr ProjectConstraints
    83  	ig     *pkgtree.IgnoredRuleset
    84  	req    map[string]bool
    85  }
    86  
    87  func (m simpleRootManifest) DependencyConstraints() ProjectConstraints {
    88  	return m.c
    89  }
    90  func (m simpleRootManifest) Overrides() ProjectConstraints {
    91  	return m.ovr
    92  }
    93  func (m simpleRootManifest) IgnoredPackages() *pkgtree.IgnoredRuleset {
    94  	return m.ig
    95  }
    96  func (m simpleRootManifest) RequiredPackages() map[string]bool {
    97  	return m.req
    98  }
    99  
   100  // prepManifest ensures a manifest is prepared and safe for use by the solver.
   101  // This is mostly about ensuring that no outside routine can modify the manifest
   102  // while the solver is in-flight, but it also filters out any empty
   103  // ProjectProperties.
   104  //
   105  // This is achieved by copying the manifest's data into a new SimpleManifest.
   106  func prepManifest(m Manifest) SimpleManifest {
   107  	if m == nil {
   108  		return SimpleManifest{}
   109  	}
   110  
   111  	deps := m.DependencyConstraints()
   112  
   113  	rm := SimpleManifest{
   114  		Deps: make(ProjectConstraints, len(deps)),
   115  	}
   116  
   117  	for k, d := range deps {
   118  		// A zero-value ProjectProperties is equivalent to one with an
   119  		// anyConstraint{} in terms of how the solver will treat it. However, we
   120  		// normalize between these two by omitting such instances entirely, as
   121  		// it negates some possibility for false mismatches in input hashing.
   122  		if d.Constraint == nil {
   123  			if d.Source == "" {
   124  				continue
   125  			}
   126  			d.Constraint = anyConstraint{}
   127  		}
   128  
   129  		rm.Deps[k] = d
   130  	}
   131  
   132  	return rm
   133  }