1 : #include "names.hh"
2 : #include "util.hh"
3 :
4 :
5 : namespace nix {
6 :
7 :
8 3 : DrvName::DrvName()
9 : {
10 3 : name = "";
11 3 : }
12 :
13 :
14 : /* Parse a derivation name. The `name' part of a derivation name is
15 : everything up to but not including the first dash *not* followed by
16 : a letter. The `version' part is the rest (excluding the separating
17 : dash). E.g., `apache-httpd-2.0.48' is parsed to (`apache-httpd',
18 : '2.0.48'). */
19 480 : DrvName::DrvName(const string & s) : hits(0)
20 : {
21 480 : name = fullName = s;
22 1836 : for (unsigned int i = 0; i < s.size(); ++i) {
23 : /* !!! isalpha/isdigit are affected by the locale. */
24 1722 : if (s[i] == '-' && i + 1 < s.size() && !isalpha(s[i + 1])) {
25 366 : name = string(s, 0, i);
26 366 : version = string(s, i + 1);
27 366 : break;
28 : }
29 : }
30 480 : }
31 :
32 :
33 245 : bool DrvName::matches(DrvName & n)
34 : {
35 245 : if (name != "*" && name != n.name) return false;
36 197 : if (version != "" && version != n.version) return false;
37 170 : return true;
38 : }
39 :
40 :
41 : static string nextComponent(string::const_iterator & p,
42 230 : const string::const_iterator end)
43 : {
44 : /* Skip any dots and dashes (component separators). */
45 230 : while (p != end && (*p == '.' || *p == '-')) ++p;
46 :
47 230 : if (p == end) return "";
48 :
49 : /* If the first character is a digit, consume the longest sequence
50 : of digits. Otherwise, consume the longest sequence of
51 : non-digit, non-separator characters. */
52 214 : string s;
53 214 : if (isdigit(*p))
54 179 : while (p != end && isdigit(*p)) s += *p++;
55 : else
56 155 : while (p != end && (!isdigit(*p) && *p != '.' && *p != '-'))
57 85 : s += *p++;
58 :
59 214 : return s;
60 : }
61 :
62 :
63 216 : static bool componentsLT(const string & c1, const string & c2)
64 : {
65 : int n1, n2;
66 216 : bool c1Num = string2Int(c1, n1), c2Num = string2Int(c2, n2);
67 :
68 216 : if (c1Num && c2Num) return n1 < n2;
69 49 : else if (c1 == "" && c2Num) return true;
70 44 : else if (c1 == "pre" && c2 != "pre") return true;
71 29 : else if (c2 == "pre") return false;
72 : /* Assume that `2.3a' < `2.3.1'. */
73 10 : else if (c2Num) return true;
74 8 : else if (c1Num) return false;
75 3 : else return c1 < c2;
76 : }
77 :
78 :
79 47 : int compareVersions(const string & v1, const string & v2)
80 : {
81 47 : string::const_iterator p1 = v1.begin();
82 47 : string::const_iterator p2 = v2.begin();
83 :
84 166 : while (p1 != v1.end() || p2 != v2.end()) {
85 115 : string c1 = nextComponent(p1, v1.end());
86 115 : string c2 = nextComponent(p2, v2.end());
87 158 : if (componentsLT(c1, c2)) return -1;
88 101 : else if (componentsLT(c2, c1)) return 1;
89 : }
90 :
91 4 : return 0;
92 : }
93 :
94 :
95 103 : DrvNames drvNamesFromArgs(const Strings & opArgs)
96 : {
97 103 : DrvNames result;
98 312 : for (Strings::const_iterator i = opArgs.begin();
99 : i != opArgs.end(); ++i)
100 106 : result.push_back(DrvName(*i));
101 0 : return result;
102 : }
103 :
104 :
105 : }
|