/// <summary>
        /// Parse a version string
        /// </summary>
        /// <returns>false if the version is not a strict semver</returns>
        public static bool TryParse(string value, out SemanticVersion version)
        {
            version = null;

            if (value != null)
            {
                Version systemVersion = null;

                Tuple<string, string[], string> sections = ParseSections(value);

                // null indicates the string did not meet the rules
                if (sections != null && Version.TryParse(sections.Item1, out systemVersion))
                {
                    // validate the version string
                    string[] parts = sections.Item1.Split('.');

                    if (parts.Length != 3)
                    {
                        // versions must be 3 parts
                        return false;
                    }

                    foreach (var part in parts)
                    {
                        if (!IsValidPart(part, false))
                        {
                            // leading zeros are not allowed
                            return false;
                        }
                    }

                    // labels
                    if (sections.Item2 != null && !sections.Item2.All(s => IsValidPart(s, false)))
                    {
                        return false;
                    }

                    // build metadata
                    if (sections.Item3 != null && !IsValid(sections.Item3, true))
                    {
                        return false;
                    }

                    Version ver = NormalizeVersionValue(systemVersion);

                    version = new SemanticVersion(version: ver,
                                                releaseLabels: sections.Item2,
                                                metadata: sections.Item3 ?? string.Empty);

                    return true;
                }
            }

            return false;
        }
        private static string GetNormalizedString(SemanticVersion version)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(Format('V', version));

            if (version.IsPrerelease)
            {
                sb.Append('-');
                sb.Append(version.Release);
            }

            if (version.HasMetadata)
            {
                sb.Append('+');
                sb.Append(version.Metadata);
            }

            return sb.ToString();
        }
        /// <summary>
        /// Gives a hash code based on the normalized version string.
        /// </summary>
        public int GetHashCode(SemanticVersion version)
        {
            if (Object.ReferenceEquals(version, null))
            {
                return 0;
            }

            HashCodeCombiner combiner = new HashCodeCombiner();

            combiner.AddObject(version.Major);
            combiner.AddObject(version.Minor);
            combiner.AddObject(version.Patch);

            NuGetVersion nuGetVersion = version as NuGetVersion;
            if (nuGetVersion != null && nuGetVersion.Revision > 0)
            {
                combiner.AddObject(nuGetVersion.Revision);
            }

            if (_mode == VersionComparison.Default || _mode == VersionComparison.VersionRelease || _mode == VersionComparison.VersionReleaseMetadata)
            {
                if (version.IsPrerelease)
                {
                    combiner.AddObject(version.Release.ToUpperInvariant());
                }
            }

            if (_mode == VersionComparison.VersionReleaseMetadata)
            {
                if (version.HasMetadata)
                {
                    combiner.AddObject(version.Metadata);
                }
            }

            return combiner.CombinedHash;
        }
        private static string Format(char c, SemanticVersion version)
        {
            string s = null;

            switch (c)
            {
                case 'N':
                    s = GetNormalizedString(version);
                    break;
                case 'R':
                    s = version.Release;
                    break;
                case 'M':
                    s = version.Metadata;
                    break;
                case 'V':
                    s = FormatVersion(version);
                    break;
                case 'x':
                    s = String.Format(CultureInfo.InvariantCulture, "{0}", version.Major);
                    break;
                case 'y':
                    s = String.Format(CultureInfo.InvariantCulture, "{0}", version.Minor);
                    break;
                case 'z':
                    s = String.Format(CultureInfo.InvariantCulture, "{0}", version.Patch);
                    break;
                case 'r':
                    NuGetVersion nuGetVersion = version as NuGetVersion;
                    s = String.Format(CultureInfo.InvariantCulture, "{0}", nuGetVersion != null && nuGetVersion.IsLegacyVersion ? nuGetVersion.Version.Revision : 0);
                    break;
            }

            return s;
        }
        private static string FormatVersion(SemanticVersion version)
        {
            NuGetVersion nuGetVersion = version as NuGetVersion;
            bool legacy = nuGetVersion != null && nuGetVersion.IsLegacyVersion;

            return String.Format(CultureInfo.InvariantCulture, "{0}.{1}.{2}{3}", version.Major, version.Minor, version.Patch, 
                legacy ? String.Format(CultureInfo.InvariantCulture, ".{0}", nuGetVersion.Version.Revision) : null);
        }
        /// <summary>
        /// Compare versions.
        /// </summary>
        public int Compare(SemanticVersion x, SemanticVersion y)
        {
            if (Object.ReferenceEquals(x, y))
            {
                return 0;
            }

            if (Object.ReferenceEquals(y, null))
            {
                return 1;
            }

            if (Object.ReferenceEquals(x, null))
            {
                return -1;
            }

            if (x != null && y != null)
            {
                // compare version
                int result = x.Major.CompareTo(y.Major);
                if (result != 0)
                    return result;

                result = x.Minor.CompareTo(y.Minor);
                if (result != 0)
                    return result;

                result = x.Patch.CompareTo(y.Patch);
                if (result != 0)
                    return result;

                NuGetVersion legacyX = x as NuGetVersion;
                NuGetVersion legacyY = y as NuGetVersion;

                result = CompareLegacyVersion(legacyX, legacyY);
                if (result != 0)
                    return result;

                if (_mode != VersionComparison.Version)
                {
                    // compare release labels
                    if (x.IsPrerelease && !y.IsPrerelease)
                        return -1;

                    if (!x.IsPrerelease && y.IsPrerelease)
                        return 1;

                    if (x.IsPrerelease && y.IsPrerelease)
                    {
                        result = CompareReleaseLabels(x.ReleaseLabels, y.ReleaseLabels);
                        if (result != 0)
                            return result;
                    }

                    // compare the metadata
                    if (_mode == VersionComparison.VersionReleaseMetadata)
                    {
                        result = StringComparer.OrdinalIgnoreCase.Compare(x.Metadata ?? string.Empty, y.Metadata ?? string.Empty);
                        if (result != 0)
                            return result;
                    }
                }
            }

            return 0;
        }
 /// <summary>
 /// Compares the given versions using the VersionComparison mode.
 /// </summary>
 public static int Compare(SemanticVersion version1, SemanticVersion version2, VersionComparison versionComparison)
 {
     IVersionComparer comparer = new VersionComparer(versionComparison);
     return comparer.Compare(version1, version2);
 }
 /// <summary>
 /// Determines if both versions are equal.
 /// </summary>
 public bool Equals(SemanticVersion x, SemanticVersion y)
 {
     return Compare(x, y) == 0;
 }
        /// <summary>
        /// Creates a SemanticVersion from an existing SemanticVersion
        /// </summary>
        public SemanticVersion(SemanticVersion version)
            : this(version.Major, version.Minor, version.Patch, version.ReleaseLabels, version.Metadata)
        {

        }