Пример #1
0
func benchCheckVersion(c, v string, b *testing.B) {
	version, _ := semver.NewVersion(v)
	constraint, _ := semver.NewConstraint(c)

	for i := 0; i < b.N; i++ {
		constraint.Check(version)
	}
}
Пример #2
0
func benchValidateVersion(c, v string, b *testing.B) {
	version, _ := semver.NewVersion(v)
	constraint, _ := semver.NewConstraint(c)

	for i := 0; i < b.N; i++ {
		constraint.Validate(version)
	}
}
Пример #3
0
// Resolve resolves dependencies and returns a lock file with the resolution.
func (r *Resolver) Resolve(reqs *chartutil.Requirements, repoNames map[string]string) (*chartutil.RequirementsLock, error) {
	d, err := HashReq(reqs)
	if err != nil {
		return nil, err
	}

	// Now we clone the dependencies, locking as we go.
	locked := make([]*chartutil.Dependency, len(reqs.Dependencies))
	missing := []string{}
	for i, d := range reqs.Dependencies {
		constraint, err := semver.NewConstraint(d.Version)
		if err != nil {
			return nil, fmt.Errorf("dependency %q has an invalid version/constraint format: %s", d.Name, err)
		}

		repoIndex, err := repo.LoadIndexFile(r.helmhome.CacheIndex(repoNames[d.Name]))
		if err != nil {
			return nil, fmt.Errorf("no cached repo found. (try 'helm repo update'). %s", err)
		}

		vs, ok := repoIndex.Entries[d.Name]
		if !ok {
			return nil, fmt.Errorf("%s chart not found in repo %s", d.Name, d.Repository)
		}

		locked[i] = &chartutil.Dependency{
			Name:       d.Name,
			Repository: d.Repository,
		}
		found := false
		// The version are already sorted and hence the first one to satisfy the constraint is used
		for _, ver := range vs {
			v, err := semver.NewVersion(ver.Version)
			if err != nil || len(ver.URLs) == 0 {
				// Not a legit entry.
				continue
			}
			if constraint.Check(v) {
				found = true
				locked[i].Version = v.Original()
				break
			}
		}

		if !found {
			missing = append(missing, d.Name)
		}
	}
	if len(missing) > 0 {
		return nil, fmt.Errorf("Can't get a valid version for repositories %s. Try changing the version constraint in requirements.yaml", strings.Join(missing, ", "))
	}
	return &chartutil.RequirementsLock{
		Generated:    time.Now(),
		Digest:       d,
		Dependencies: locked,
	}, nil
}
Пример #4
0
func wizardLookInto(d *cfg.Dependency) bool {
	_, err := semver.NewConstraint(d.Reference)

	// The existing version is already a valid semver constraint so we skip suggestions.
	if err == nil {
		return false
	}

	return true
}
Пример #5
0
// VersionOK returns true if the given version meets the constraints.
//
// It returns false if the version string or constraint is unparsable or if the
// version does not meet the constraint.
func (d *Dependency) VersionOK(version string) bool {
	c, err := semver.NewConstraint(d.Version)
	if err != nil {
		return false
	}
	v, err := semver.NewVersion(version)
	if err != nil {
		return false
	}

	return c.Check(v)
}
Пример #6
0
func validateChartVersion(cf *chart.Metadata) error {
	if cf.Version == "" {
		return errors.New("version is required")
	}

	version, err := semver.NewVersion(cf.Version)

	if err != nil {
		return fmt.Errorf("version '%s' is not a valid SemVer", cf.Version)
	}

	c, err := semver.NewConstraint("> 0")
	valid, msg := c.Validate(version)

	if !valid && len(msg) > 0 {
		return fmt.Errorf("version %v", msg[0])
	}

	return nil
}
Пример #7
0
func validateChartVersion(cf *chart.Metadata) (lintError support.LintError) {
	if cf.Version == "" {
		lintError = fmt.Errorf("Chart.yaml: 'version' value is required")
		return
	}

	version, err := semver.NewVersion(cf.Version)

	if err != nil {
		lintError = fmt.Errorf("Chart.yaml: version '%s' is not a valid SemVer", cf.Version)
		return
	}

	c, err := semver.NewConstraint("> 0")
	valid, msg := c.Validate(version)

	if !valid && len(msg) > 0 {
		lintError = fmt.Errorf("Chart.yaml: 'version' %v", msg[0])
	}

	return
}
Пример #8
0
func determineDependency(v, dep *cfg.Dependency, dest string) *cfg.Dependency {
	repo, err := v.GetRepo(dest)
	if err != nil {
		singleWarn("Unable to access repo for %s\n", v.Name)
		singleInfo("Keeping %s %s", v.Name, v.Reference)
		return v
	}

	vIsRef := repo.IsReference(v.Reference)
	depIsRef := repo.IsReference(dep.Reference)

	// Both are references and they are different ones.
	if vIsRef && depIsRef {
		singleWarn("Conflict: %s ref is %s, but also asked for %s\n", v.Name, v.Reference, dep.Reference)
		singleInfo("Keeping %s %s", v.Name, v.Reference)
		return v
	} else if vIsRef {
		// The current one is a reference and the suggestion is a SemVer constraint.
		con, err := semver.NewConstraint(dep.Reference)
		if err != nil {
			singleWarn("Version issue for %s: '%s' is neither a reference or semantic version constraint\n", dep.Name, dep.Reference)
			singleInfo("Keeping %s %s", v.Name, v.Reference)
			return v
		}

		ver, err := semver.NewVersion(v.Reference)
		if err != nil {
			// The existing version is not a semantic version.
			singleWarn("Conflict: %s version is %s, but also asked for %s\n", v.Name, v.Reference, dep.Reference)
			singleInfo("Keeping %s %s", v.Name, v.Reference)
			return v
		}

		if con.Check(ver) {
			singleInfo("Keeping %s %s because it fits constraint '%s'", v.Name, v.Reference, dep.Reference)
			return v
		}
		singleWarn("Conflict: %s version is %s but does not meet constraint '%s'\n", v.Name, v.Reference, dep.Reference)
		singleInfo("Keeping %s %s", v.Name, v.Reference)
		return v
	} else if depIsRef {

		con, err := semver.NewConstraint(v.Reference)
		if err != nil {
			singleWarn("Version issue for %s: '%s' is neither a reference or semantic version constraint\n", v.Name, v.Reference)
			singleInfo("Keeping %s %s", v.Name, v.Reference)
			return v
		}

		ver, err := semver.NewVersion(dep.Reference)
		if err != nil {
			singleWarn("Conflict: %s version is %s, but also asked for %s\n", v.Name, v.Reference, dep.Reference)
			singleInfo("Keeping %s %s", v.Name, v.Reference)
			return v
		}

		if con.Check(ver) {
			v.Reference = dep.Reference
			singleInfo("Using %s %s because it fits constraint '%s'", v.Name, v.Reference, v.Reference)
			return v
		}
		singleWarn("Conflict: %s semantic version constraint is %s but '%s' does not meet the constraint\n", v.Name, v.Reference, v.Reference)
		singleInfo("Keeping %s %s", v.Name, v.Reference)
		return v
	}
	// Neither is a vcs reference and both could be semantic version
	// constraints that are different.

	_, err = semver.NewConstraint(dep.Reference)
	if err != nil {
		// dd.Reference is not a reference or a valid constraint.
		singleWarn("Version %s %s is not a reference or valid semantic version constraint\n", dep.Name, dep.Reference)
		singleInfo("Keeping %s %s", v.Name, v.Reference)
		return v
	}

	_, err = semver.NewConstraint(v.Reference)
	if err != nil {
		// existing.Reference is not a reference or a valid constraint.
		// We really should never end up here.
		singleWarn("Version %s %s is not a reference or valid semantic version constraint\n", v.Name, v.Reference)

		v.Reference = dep.Reference
		v.Pin = ""
		singleInfo("Using %s %s because it is a valid version", v.Name, v.Reference)
		return v
	}

	// Both versions are constraints. Try to merge them.
	// If either comparison has an || skip merging. That's complicated.
	ddor := strings.Index(dep.Reference, "||")
	eor := strings.Index(v.Reference, "||")
	if ddor == -1 && eor == -1 {
		// Add the comparisons together.
		newRef := v.Reference + ", " + dep.Reference
		v.Reference = newRef
		v.Pin = ""
		singleInfo("Combining %s semantic version constraints %s and %s", v.Name, v.Reference, dep.Reference)
		return v
	}
	singleWarn("Conflict: %s version is %s, but also asked for %s\n", v.Name, v.Reference, dep.Reference)
	singleInfo("Keeping %s %s", v.Name, v.Reference)
	return v
}
Пример #9
0
// mergeDeps merges any dependency array into deps.
func mergeDeps(orig map[string]*yaml.Dependency, add []*yaml.Dependency, vend string) []string {
	mod := []string{}
	for _, dd := range add {
		// Add it unless it's already there.
		if existing, ok := orig[dd.Name]; !ok {
			orig[dd.Name] = dd
			Debug("Adding %s to the scan list", dd.Name)
			mod = append(mod, dd.Name)
		} else if existing.Reference == "" && dd.Reference != "" {
			// If a nested dep has finer dependency references than outside,
			// set the reference.
			existing.Reference = dd.Reference
			mod = append(mod, dd.Name)
		} else if dd.Reference != "" && existing.Reference != "" && dd.Reference != existing.Reference {
			// Check if one is a version and the other is a constraint. If the
			// version is in the constraint use that.
			dest := path.Join(vend, dd.Name)
			repo, err := existing.GetRepo(dest)
			if err != nil {
				Warn("Unable to access repo for %s\n", existing.Name)
				Info("Keeping %s %s", existing.Name, existing.Reference)
				continue
			}

			eIsRef := repo.IsReference(existing.Reference)
			ddIsRef := repo.IsReference(dd.Reference)

			// Both are references and different ones.
			if eIsRef && ddIsRef {
				Warn("Conflict: %s ref is %s, but also asked for %s\n", existing.Name, existing.Reference, dd.Reference)
				Info("Keeping %s %s", existing.Name, existing.Reference)
			} else if eIsRef {
				// Test ddIsRef is a constraint and if eIsRef is a semver
				// within that
				con, err := semver.NewConstraint(dd.Reference)
				if err != nil {
					Warn("Version issue for %s: '%s' is neither a reference or semantic version constraint\n", dd.Name, dd.Reference)
					Info("Keeping %s %s", existing.Name, existing.Reference)
					continue
				}

				ver, err := semver.NewVersion(existing.Reference)
				if err != nil {
					// The existing version is not a semantic version.
					Warn("Conflict: %s version is %s, but also asked for %s\n", existing.Name, existing.Reference, dd.Reference)
					Info("Keeping %s %s", existing.Name, existing.Reference)
					continue
				}

				if con.Check(ver) {
					Info("Keeping %s %s because it fits constraint '%s'", existing.Name, existing.Reference, dd.Reference)
				} else {
					Warn("Conflict: %s version is %s but does not meet constraint '%s'\n", existing.Name, existing.Reference, dd.Reference)
					Info("Keeping %s %s", existing.Name, existing.Reference)
				}

			} else if ddIsRef {
				// Test eIsRef is a constraint and if ddIsRef is a semver
				// within that
				con, err := semver.NewConstraint(existing.Reference)
				if err != nil {
					Warn("Version issue for %s: '%s' is neither a reference or semantic version constraint\n", existing.Name, existing.Reference)
					Info("Keeping %s %s", existing.Name, existing.Reference)
					continue
				}

				ver, err := semver.NewVersion(dd.Reference)
				if err != nil {
					// The dd version is not a semantic version.
					Warn("Conflict: %s version is %s, but also asked for %s\n", existing.Name, existing.Reference, dd.Reference)
					Info("Keeping %s %s", existing.Name, existing.Reference)
					continue
				}

				if con.Check(ver) {
					// Use the specific version if noted instead of the existing
					// constraint.
					existing.Reference = dd.Reference
					mod = append(mod, dd.Name)
					Info("Using %s %s because it fits constraint '%s'", existing.Name, dd.Reference, existing.Reference)
				} else {
					Warn("Conflict: %s semantic version constraint is %s but '%s' does not meet the constraint\n", existing.Name, existing.Reference, dd.Reference)
					Info("Keeping %s %s", existing.Name, existing.Reference)
				}
			} else {
				// Neither is a vcs reference and both could be semantic version
				// constraints that are different.

				_, err := semver.NewConstraint(dd.Reference)
				if err != nil {
					// dd.Reference is not a reference or a valid constraint.
					Warn("Version %s %s is not a reference or valid semantic version constraint\n", dd.Name, dd.Reference)
					Info("Keeping %s %s", existing.Name, existing.Reference)
					continue
				}

				_, err = semver.NewConstraint(existing.Reference)
				if err != nil {
					// existing.Reference is not a reference or a valid constraint.
					// We really should never end up here.
					Warn("Version %s %s is not a reference or valid semantic version constraint\n", existing.Name, existing.Reference)

					existing.Reference = dd.Reference
					mod = append(mod, dd.Name)
					Info("Using %s %s because it is a valid version", existing.Name, existing.Reference)
					continue
				}

				// Both versions are constraints. Try to merge them.
				// If either comparison has an || skip merging. That's complicated.
				ddor := strings.Index(dd.Reference, "||")
				eor := strings.Index(existing.Reference, "||")
				if ddor == -1 && eor == -1 {
					// Add the comparisons together.
					newRef := existing.Reference + ", " + dd.Reference
					existing.Reference = newRef
					mod = append(mod, dd.Name)
					Info("Combining %s semantic version constraints %s and %s", existing.Name, existing.Reference, dd.Reference)
				} else {
					Warn("Conflict: %s version is %s, but also asked for %s\n", existing.Name, existing.Reference, dd.Reference)
					Info("Keeping %s %s", existing.Name, existing.Reference)
				}
			}
		}
	}
	return mod
}
Пример #10
0
func benchNewConstraint(c string, b *testing.B) {
	for i := 0; i < b.N; i++ {
		semver.NewConstraint(c)
	}
}
Пример #11
0
// VcsVersion set the VCS version for a checkout.
func VcsVersion(dep *yaml.Dependency, vend string) error {
	// If there is no refernece configured there is nothing to set.
	if dep.Reference == "" {
		return nil
	}

	cwd := path.Join(vend, dep.Name)

	// When the directory is not empty and has no VCS directory it's
	// a vendored files situation.
	empty, err := isDirectoryEmpty(cwd)
	if err != nil {
		return err
	}
	_, err = v.DetectVcsFromFS(cwd)
	if empty == false && err == v.ErrCannotDetectVCS {
		Warn("%s appears to be a vendored package. Unable to set new version. Consider the '--update-vendored' flag.\n", dep.Name)
	} else {
		repo, err := dep.GetRepo(cwd)
		if err != nil {
			return err
		}

		ver := dep.Reference
		// Referenes in Git can begin with a ^ which is similar to semver.
		// If there is a ^ prefix we assume it's a semver constraint rather than
		// part of the git/VCS commit id.
		if repo.IsReference(ver) && !strings.HasPrefix(ver, "^") {
			Info("Setting version for %s to %s.\n", dep.Name, ver)
		} else {

			// Create the constraing first to make sure it's valid before
			// working on the repo.
			constraint, err := semver.NewConstraint(ver)

			// Make sure the constriant is valid. At this point it's not a valid
			// reference so if it's not a valid constrint we can exit early.
			if err != nil {
				Warn("The reference '%s' is not valid\n", ver)
				return err
			}

			// Get the tags and branches (in that order)
			refs, err := getAllVcsRefs(repo)
			if err != nil {
				return err
			}

			// Convert and filter the list to semver.Version instances
			semvers := getSemVers(refs)

			// Sort semver list
			sort.Sort(sort.Reverse(semver.Collection(semvers)))
			found := false
			for _, v := range semvers {
				if constraint.Check(v) {
					found = true
					// If the constrint passes get the original reference
					ver = v.Original()
					break
				}
			}
			if found {
				Info("Detected semantic version. Setting version for %s to %s.\n", dep.Name, ver)
			} else {
				Warn("Unable to find semantic version for constraint %s %s\n", dep.Name, ver)
			}
		}
		if err := repo.UpdateVersion(ver); err != nil {
			Error("Failed to set version to %s: %s\n", dep.Reference, err)
			return err
		}
	}

	return nil
}
Пример #12
0
// VcsVersion set the VCS version for a checkout.
func VcsVersion(dep *cfg.Dependency) error {

	// If the dependency has already been pinned we can skip it. This is a
	// faster path so we don't need to resolve it again.
	if dep.Pin != "" {
		msg.Debug("Dependency %s has already been pinned. Setting version skipped.", dep.Name)
		return nil
	}

	key, err := cp.Key(dep.Remote())
	if err != nil {
		msg.Die("Cache key generation error: %s", err)
	}
	location := cp.Location()
	cwd := filepath.Join(location, "src", key)

	// If there is no reference configured there is nothing to set.
	if dep.Reference == "" {
		// Before exiting update the pinned version
		repo, err := dep.GetRepo(cwd)
		if err != nil {
			return err
		}
		dep.Pin, err = repo.Version()
		if err != nil {
			return err
		}
		return nil
	}

	// When the directory is not empty and has no VCS directory it's
	// a vendored files situation.
	empty, err := gpath.IsDirectoryEmpty(cwd)
	if err != nil {
		return err
	}
	_, err = v.DetectVcsFromFS(cwd)
	if empty == false && err == v.ErrCannotDetectVCS {
		return fmt.Errorf("Cache directory missing VCS information for %s", dep.Name)
	}

	repo, err := dep.GetRepo(cwd)
	if err != nil {
		return err
	}

	ver := dep.Reference
	// References in Git can begin with a ^ which is similar to semver.
	// If there is a ^ prefix we assume it's a semver constraint rather than
	// part of the git/VCS commit id.
	if repo.IsReference(ver) && !strings.HasPrefix(ver, "^") {
		msg.Info("--> Setting version for %s to %s.\n", dep.Name, ver)
	} else {

		// Create the constraint first to make sure it's valid before
		// working on the repo.
		constraint, err := semver.NewConstraint(ver)

		// Make sure the constriant is valid. At this point it's not a valid
		// reference so if it's not a valid constrint we can exit early.
		if err != nil {
			msg.Warn("The reference '%s' is not valid\n", ver)
			return err
		}

		// Get the tags and branches (in that order)
		refs, err := getAllVcsRefs(repo)
		if err != nil {
			return err
		}

		// Convert and filter the list to semver.Version instances
		semvers := getSemVers(refs)

		// Sort semver list
		sort.Sort(sort.Reverse(semver.Collection(semvers)))
		found := false
		for _, v := range semvers {
			if constraint.Check(v) {
				found = true
				// If the constrint passes get the original reference
				ver = v.Original()
				break
			}
		}
		if found {
			msg.Info("--> Detected semantic version. Setting version for %s to %s.", dep.Name, ver)
		} else {
			msg.Warn("--> Unable to find semantic version for constraint %s %s", dep.Name, ver)
		}
	}
	if err := repo.UpdateVersion(ver); err != nil {
		return err
	}
	dep.Pin, err = repo.Version()
	if err != nil {
		return err
	}

	return nil
}