Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
PackageVersionRange.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // Original code from http://nuget.codeplex.com class SemanticVersion
3 // Copyright 2010-2014 Outercurve Foundation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 using System;
14 using System.Globalization;
15 using System.Linq;
16 using System.Text;
17 using SiliconStudio.Core;
18 
19 namespace SiliconStudio.Assets
20 {
21  /// <summary>
22  /// A dependency to a range of version.
23  /// </summary>
24  /// <remarks>
25  /// The version string is either a simple version or an arithmetic range
26  /// <code>
27  /// e.g.
28  /// 1.0 --> 1.0 ≤ x
29  /// (,1.0] --> x ≤ 1.0
30  /// (,1.0) --> x &lt; 1.0
31  /// [1.0] --> x == 1.0
32  /// (1.0,) --> 1.0 &lt; x
33  /// (1.0, 2.0) --> 1.0 &lt; x &lt; 2.0
34  /// [1.0, 2.0] --> 1.0 ≤ x ≤ 2.0
35  /// </code>
36  /// </remarks>
37  [DataContract("PackageVersionDependency")]
38  public sealed class PackageVersionRange
39  {
40  /// <summary>
41  /// Initializes a new instance of the <see cref="PackageVersionRange"/> class.
42  /// </summary>
44  {
45  }
46 
47  /// <summary>
48  /// Initializes a new instance of the <see cref="PackageVersionRange"/> class.
49  /// </summary>
50  /// <param name="version">The exact version.</param>
52  {
53  IsMinInclusive = true;
54  IsMaxInclusive = true;
55  MinVersion = version;
56  MaxVersion = version;
57  }
58 
59  /// <summary>
60  /// Initializes a new instance of the <see cref="PackageVersionRange" /> class.
61  /// </summary>
62  /// <param name="minVersion">The minimum version.</param>
63  /// <param name="minVersionInclusive">if set to <c>true</c> the minimum version is inclusive</param>
64  public PackageVersionRange(PackageVersion minVersion, bool minVersionInclusive)
65  {
66  IsMinInclusive = minVersionInclusive;
67  MinVersion = minVersion;
68  }
69 
70  /// <summary>
71  /// Gets or sets the minimum version.
72  /// </summary>
73  /// <value>The minimum version.</value>
74  [DataMember(10)]
75  public PackageVersion MinVersion { get; set; }
76 
77  /// <summary>
78  /// Gets or sets a value indicating whether the min version is inclusive.
79  /// </summary>
80  /// <value><c>true</c> if the min version is inclusive; otherwise, <c>false</c>.</value>
81  [DataMember(20)]
82  public bool IsMinInclusive { get; set; }
83 
84  /// <summary>
85  /// Gets or sets the maximum version.
86  /// </summary>
87  /// <value>The maximum version.</value>
88  [DataMember(30)]
89  public PackageVersion MaxVersion { get; set; }
90 
91  /// <summary>
92  /// Gets or sets a value indicating whether the max version is inclusive.
93  /// </summary>
94  /// <value><c>true</c> if the max version is inclusive; otherwise, <c>false</c>.</value>
95  [DataMember(40)]
96  public bool IsMaxInclusive { get; set; }
97 
98  /// <summary>
99  /// The safe range is defined as the highest build and revision for a given major and minor version
100  /// </summary>
102  {
103  return new PackageVersionRange
104  {
105  IsMinInclusive = true,
106  MinVersion = version,
107  MaxVersion = new PackageVersion(new Version(version.Version.Major, version.Version.Minor + 1))
108  };
109  }
110 
111  /// <summary>
112  /// Tries to parse a version dependency.
113  /// </summary>
114  /// <param name="value">The version dependency as a string.</param>
115  /// <param name="result">The parsed result.</param>
116  /// <returns><c>true</c> if successfuly parsed, <c>false</c> otherwise.</returns>
117  /// <exception cref="System.ArgumentNullException">value</exception>
118  public static bool TryParse(string value, out PackageVersionRange result)
119  {
120  if (value == null)
121  {
122  throw new ArgumentNullException("value");
123  }
124 
125  var versionSpec = new PackageVersionRange();
126  value = value.Trim();
127 
128  // First, try to parse it as a plain version string
129  PackageVersion version;
130  if (PackageVersion.TryParse(value, out version))
131  {
132  // A plain version is treated as an inclusive minimum range
133  result = new PackageVersionRange
134  {
135  MinVersion = version,
136  IsMinInclusive = true
137  };
138 
139  return true;
140  }
141 
142  // It's not a plain version, so it must be using the bracket arithmetic range syntax
143 
144  result = null;
145 
146  // Fail early if the string is too short to be valid
147  if (value.Length < 3)
148  {
149  return false;
150  }
151 
152  // The first character must be [ ot (
153  switch (value.First())
154  {
155  case '[':
156  versionSpec.IsMinInclusive = true;
157  break;
158  case '(':
159  versionSpec.IsMinInclusive = false;
160  break;
161  default:
162  return false;
163  }
164 
165  // The last character must be ] ot )
166  switch (value.Last())
167  {
168  case ']':
169  versionSpec.IsMaxInclusive = true;
170  break;
171  case ')':
172  versionSpec.IsMaxInclusive = false;
173  break;
174  default:
175  return false;
176  }
177 
178  // Get rid of the two brackets
179  value = value.Substring(1, value.Length - 2);
180 
181  // Split by comma, and make sure we don't get more than two pieces
182  string[] parts = value.Split(',');
183  if (parts.Length > 2)
184  {
185  return false;
186  }
187  if (parts.All(string.IsNullOrEmpty))
188  {
189  // If all parts are empty, then neither of upper or lower bounds were specified. Version spec is of the format (,]
190  return false;
191  }
192 
193  // If there is only one piece, we use it for both min and max
194  string minVersionString = parts[0];
195  string maxVersionString = (parts.Length == 2) ? parts[1] : parts[0];
196 
197  // Only parse the min version if it's non-empty
198  if (!string.IsNullOrWhiteSpace(minVersionString))
199  {
200  if (!PackageVersion.TryParse(minVersionString, out version))
201  {
202  return false;
203  }
204  versionSpec.MinVersion = version;
205  }
206 
207  // Same deal for max
208  if (!string.IsNullOrWhiteSpace(maxVersionString))
209  {
210  if (!PackageVersion.TryParse(maxVersionString, out version))
211  {
212  return false;
213  }
214  versionSpec.MaxVersion = version;
215  }
216 
217  // Successful parse!
218  result = versionSpec;
219  return true;
220  }
221 
222  /// <summary>
223  /// Display a pretty version of the dependency.
224  /// </summary>
225  /// <returns>A pretty version of the dependency.</returns>
226  public string ToPrettyPrint()
227  {
228  if (MinVersion != null && IsMinInclusive && MaxVersion == null && !IsMaxInclusive)
229  {
230  return string.Format(CultureInfo.InvariantCulture, "(>= {0})", MinVersion);
231  }
232 
233  if (MinVersion != null && MaxVersion != null && MinVersion == MaxVersion && IsMinInclusive && IsMaxInclusive)
234  {
235  return string.Format(CultureInfo.InvariantCulture, "(= {0})", MinVersion);
236  }
237 
238  var versionBuilder = new StringBuilder();
239  if (MinVersion != null)
240  {
241  if (IsMinInclusive)
242  {
243  versionBuilder.AppendFormat("(>= ");
244  }
245  else
246  {
247  versionBuilder.Append("(> ");
248  }
249  versionBuilder.Append(MinVersion);
250  }
251 
252  if (MaxVersion != null)
253  {
254  versionBuilder.Append(versionBuilder.Length == 0 ? "(" : " && ");
255 
256  if (IsMaxInclusive)
257  {
258  versionBuilder.AppendFormat("<= ");
259  }
260  else
261  {
262  versionBuilder.Append("< ");
263  }
264  versionBuilder.Append(MaxVersion);
265  }
266 
267  if (versionBuilder.Length > 0)
268  {
269  versionBuilder.Append(")");
270  }
271 
272  return versionBuilder.ToString();
273  }
274 
275  /// <inheritdoc/>
276  public override string ToString()
277  {
278  if (MinVersion != null && IsMinInclusive && MaxVersion == null && !IsMaxInclusive)
279  {
280  return MinVersion.ToString();
281  }
282 
283  if (MinVersion != null && MaxVersion != null && MinVersion == MaxVersion && IsMinInclusive && IsMaxInclusive)
284  {
285  return "[" + MinVersion + "]";
286  }
287 
288  var versionBuilder = new StringBuilder();
289  versionBuilder.Append(IsMinInclusive ? '[' : '(');
290  versionBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}, {1}", MinVersion, MaxVersion);
291  versionBuilder.Append(IsMaxInclusive ? ']' : ')');
292 
293  return versionBuilder.ToString();
294  }
295 
296  internal static PackageVersionRange FromVersionSpec(NuGet.IVersionSpec spec)
297  {
298  if (spec == null)
299  {
300  return null;
301  }
302 
303  return new PackageVersionRange()
304  {
305  MinVersion = PackageVersion.FromSemanticVersion(spec.MinVersion),
306  IsMinInclusive = spec.IsMinInclusive,
307  MaxVersion = PackageVersion.FromSemanticVersion(spec.MaxVersion),
308  IsMaxInclusive = spec.IsMaxInclusive
309  };
310  }
311  }
312 }
string ToPrettyPrint()
Display a pretty version of the dependency.
bool IsMinInclusive
Gets or sets a value indicating whether the min version is inclusive.
static bool TryParse(string value, out PackageVersionRange result)
Tries to parse a version dependency.
PackageVersionRange()
Initializes a new instance of the PackageVersionRange class.
static bool TryParse(string version, out PackageVersion value)
Parses a version string using loose semantic versioning rules that allows 2-4 version components foll...
Version Version
Gets the normalized version portion.
PackageVersionRange(PackageVersion version)
Initializes a new instance of the PackageVersionRange class.
PackageVersionRange(PackageVersion minVersion, bool minVersionInclusive)
Initializes a new instance of the PackageVersionRange class.
A hybrid implementation of SemVer that supports semantic versioning as described at http://semver...
static PackageVersionRange GetSafeRange(PackageVersion version)
The safe range is defined as the highest build and revision for a given major and minor version ...
A dependency to a range of version.