/// <summary> /// Parse and return a dependency version /// The version string is either a simple version or an arithmetic range /// e.g. /// 1.0 --> 1.0 ≤ x /// (,1.0] --> x ≤ 1.0 /// (,1.0) --> x lt 1.0 /// [1.0] --> x == 1.0 /// (1.0,) --> 1.0 lt x /// (1.0, 2.0) --> 1.0 lt x lt 2.0 /// [1.0, 2.0] --> 1.0 ≤ x ≤ 2.0 /// /// </summary> /// <param name="value"></param> /// <returns></returns> public static DependencyVersion ParseDependencyVersion(string value) { var depVers = new DependencyVersion(); if (String.IsNullOrWhiteSpace(value)) { return depVers; } value = value.Trim(); char first = value.First(); char last = value.Last(); if (first != '(' && first != '[' && last != ']' && last != ')') { // Stand alone version depVers.IsMinInclusive = true; depVers.MinVersion = new SemanticVersion(value); return depVers; } // value must have length greater than 3 if (value.Length < 3) { return depVers; } // The first character must be [ or ( switch (value.First()) { case '[': depVers.IsMinInclusive = true; break; case '(': depVers.IsMinInclusive = false; break; default: // If not, return without setting anything return depVers; } // The last character must be ] or ) switch (value.Last()) { case ']': depVers.IsMaxInclusive = true; break; case ')': depVers.IsMaxInclusive = false; break; default: // If not, return without setting anything return depVers; } // Get rid of the two brackets value = value.Substring(1, value.Length - 2); // Split by comma, and make sure we don't get more than two pieces string[] parts = value.Split(','); // Wrong format if we have more than 2 parts or all the parts are empty if (parts.Length > 2 || parts.All(String.IsNullOrEmpty)) { return depVers; } // First part is min string minVersionString = parts[0]; // If there is only 1 part then first part will also be max string maxVersionString = (parts.Length == 2) ? parts[1] : parts[0]; // Get min version if we have it if (!String.IsNullOrWhiteSpace(minVersionString)) { depVers.MinVersion = new SemanticVersion(minVersionString); } // Get max version if we have it if (!String.IsNullOrWhiteSpace(maxVersionString)) { depVers.MaxVersion = new SemanticVersion(maxVersionString); } return depVers; }
/// <summary> /// Parses a dependency from the feed in the format: /// id or id:versionSpec, or id:versionSpec:targetFramework /// </summary> private static Tuple<string, DependencyVersion, string> ParseDependency(string value) { if (String.IsNullOrWhiteSpace(value)) { return null; } // IMPORTANT: Do not pass StringSplitOptions.RemoveEmptyEntries to this method, because it will break // if the version spec is null, for in that case, the Dependencies string sent down is "<id>::<target framework>". // We do want to preserve the second empty element after the split. string[] tokens = value.Trim().Split(new[] { ':' }); if (tokens.Length == 0) { return null; } // Trim the id string id = tokens[0].Trim(); // Parse the dependency version DependencyVersion depVer = new DependencyVersion(); if (tokens.Length > 1) { // Parse the version depVer = DependencyVersion.ParseDependencyVersion(tokens[1]); } // Get the target framework, returns empty string if none exists. var targetFramework = (tokens.Length > 2 && !String.IsNullOrEmpty(tokens[2])) ? tokens[2] : String.Empty; return Tuple.Create(id, depVer, targetFramework); }