1: class NuGetLatest
2: attr_reader :path
3:
4: def initialize(package_name, packages_dir = Dir.pwd)
5: @package_name = package_name
6:
7: raise "#{packages_dir} is not a directory" unless File.directory? packages_dir
8:
9: Dir.chdir packages_dir do
10: candidates = Dir["#{package_name}*"]
11: raise "No package '#{package_name}' was found in #{packages_dir}" unless candidates.any?
12:
13: latest = find_latest_version candidates
14: @path = File.join packages_dir, latest
15: end
16: end
17:
18: def to_s
19: @path
20: end
21:
22: def +(other)
23: to_s + other
24: end
25:
26: private
27: def find_latest_version(candidates)
28: return candidates.first if candidates.length == 1
29:
30: latest = candidates.map { |path|
31: version = path.sub /^#{@package_name}./, ''
32: version = parse_version version
33:
34: {
35: :version => version,
36: :path => path
37: }
38: }.max { |left, right| left[:version] <=> right[:version] }
39:
40: latest[:path]
41: end
42:
43: def parse_version(version_string)
44: major, minor, patch, revision, special = version_string.match(/^(\d+)\.(\d+)\.(\d+)\.?(\d+)?-?(.+)?$/).captures
45: SemVer.new(major.to_i, minor.to_i, patch.to_i, revision.to_i, special)
46: end
47:
48: # Borrowed from the SemVer gem and enhanced to support .NET's 4-digit versioning system.
49: class SemVer
50: attr_accessor :major, :minor, :patch, :revision, :special
51:
52: def initialize(major = 0, minor = 0, patch = 0, revision = 0, special = '')
53: major.kind_of? Integer or raise "invalid major: #{major}"
54: minor.kind_of? Integer or raise "invalid minor: #{minor}"
55: patch.kind_of? Integer or raise "invalid patch: #{patch}"
56: revision.kind_of? Integer or raise "invalid revision: #{revision}"
57:
58: unless special.nil? or special.empty?
59: special =~ /[A-Za-z][0-9A-Za-z-]+/ or raise "invalid special: #{special}"
60: end
61:
62: @major, @minor, @patch, @revision, @special = major, minor, patch, revision, special
63: end
64:
65: def <=>(other)
66: maj = @major.to_i <=> other.major.to_i
67: return maj unless maj == 0
68:
69: min = @minor.to_i <=> other.minor.to_i
70: return min unless min == 0
71:
72: pat = @patch.to_i <=> other.patch.to_i
73: return pat unless pat == 0
74:
75: rev = @revision.to_i <=> other.revision.to_i
76: return rev unless rev == 0
77:
78: spe = @special <=> other.special
79: return spe unless spe == 0
80:
81: 0
82: end
83:
84: include Comparable
85: end
86: end
87:
88: module Conversions
89: def NuGetLatest(package_name, packages_dir)
90: NuGetLatest.new(package_name, packages_dir)
91: end
92: end
93:
94: include Conversions