@@ -20,8 +20,50 @@ intersect(a::VersionInterval, b::VersionInterval) = VersionInterval(max(a.lower,
20
20
== (a:: VersionInterval , b:: VersionInterval ) = a. lower == b. lower && a. upper == b. upper
21
21
hash (i:: VersionInterval , h:: UInt ) = hash ((i. lower, i. upper), h + (0x0f870a92db508386 % UInt))
22
22
23
+ function normalize! (ivals:: Vector{VersionInterval} )
24
+ # VersionSet internal normalization:
25
+ # removes empty intervals and fuses intervals without gaps
26
+ # e.g.:
27
+ # [0.0.0,1.0.0) ∪ [1.0.0,1.5.0) ∪ [1.6.0,1.6.0) ∪ [2.0.0,∞)
28
+ # becomes:
29
+ # [0.0.0,1.5.0) ∪ [2.0.0,∞)
30
+ # (still assumes that lower bounds are sorted, and intervals do
31
+ # not overlap)
32
+ l = length (ivals)
33
+ l == 0 && return ivals
34
+
35
+ lo, up, k0 = ivals[1 ]. lower, ivals[1 ]. upper, 1
36
+ fusing = false
37
+ for k = 2 : l
38
+ lo1, up1 = ivals[k]. lower, ivals[k]. upper
39
+ if lo1 == up
40
+ up = up1
41
+ fusing = true
42
+ continue
43
+ end
44
+ if lo < up
45
+ # The only purpose of the "fusing" check is to avoid
46
+ # extra allocations
47
+ ivals[k0] = fusing ? VersionInterval (lo, up) : ivals[k- 1 ]
48
+ k0 += 1
49
+ end
50
+ fusing = false
51
+ lo, up = lo1, up1
52
+ end
53
+ if lo < up
54
+ ivals[k0] = fusing ? VersionInterval (lo, up) : ivals[l]
55
+ k0 += 1
56
+ end
57
+ resize! (ivals, k0 - 1 )
58
+ return ivals
59
+ end
60
+
23
61
struct VersionSet
24
62
intervals:: Vector{VersionInterval}
63
+ VersionSet (intervals:: Vector{VersionInterval} ) = new (normalize! (intervals))
64
+ # copy is defined inside the struct block to call `new` directly
65
+ # without going through `normalize!`
66
+ Base. copy (vset:: VersionSet ) = new (copy (vset. intervals))
25
67
end
26
68
function VersionSet (versions:: Vector{VersionNumber} )
27
69
intervals = VersionInterval[]
@@ -37,54 +79,25 @@ function VersionSet(versions::Vector{VersionNumber})
37
79
end
38
80
VersionSet (versions:: VersionNumber... ) = VersionSet (VersionNumber[versions... ])
39
81
40
- const empty_versionset = VersionSet ([ v " 0.0 " , v " 0.0 " ])
82
+ const empty_versionset = VersionSet (VersionInterval[ ])
41
83
42
- function normalize! (A:: VersionSet )
43
- # removes empty intervals and fuses intervals without gaps
44
- # e.g.:
45
- # [0.0.0,1.0.0) ∪ [1.0.0,1.5.0) ∪ [1.6.0,1.6.0) ∪ [2.0.0,∞)
46
- # becomes:
47
- # [0.0.0,1.5.0) ∪ [2.0.0,∞)
48
- # (still assumes that intervals are properly sorted)
49
- ivals = A. intervals
50
- l = length (ivals)
51
- for k = l: - 1 : 1
52
- isempty (ivals[k]) && (splice! (ivals, k); l -= 1 )
53
- end
54
- l > 1 || return A
55
- lo, up, k0 = ivals[l]. lower, ivals[l]. upper, l
56
- fuse = false
57
- for k = (l- 1 ): - 1 : 1
58
- lo1, up1 = ivals[k]. lower, ivals[k]. upper
59
- if up1 == lo
60
- fuse = true
61
- lo = lo1
62
- continue
63
- end
64
- fuse && splice! (ivals, (k+ 1 ): k0, (VersionInterval (lo, up),))
65
- fuse = false
66
- lo, up = lo1, up1
67
- k0 = k
68
- end
69
- fuse && splice! (ivals, 1 : k0, (VersionInterval (lo, up),))
70
- return A
71
- end
72
-
73
- show (io:: IO , s:: VersionSet ) = join (io, s. intervals, " ∪ " )
84
+ # Windows console doesn't like Unicode
85
+ const _empty_symbol = @static is_windows () ? " empty" : " ∅"
86
+ const _union_symbol = @static is_windows () ? " or " : " ∪ "
87
+ show (io:: IO , s:: VersionSet ) = isempty (s) ? print (io, _empty_symbol) :
88
+ join (io, s. intervals, _union_symbol)
74
89
isempty (s:: VersionSet ) = all (isempty, s. intervals)
75
90
in (v:: VersionNumber , s:: VersionSet ) = any (i-> in (v,i), s. intervals)
76
91
function intersect (A:: VersionSet , B:: VersionSet )
77
- (isempty (A) || isempty (B)) && return normalize! ( copy (empty_versionset) )
92
+ (isempty (A) || isempty (B)) && return copy (empty_versionset)
78
93
ivals = [intersect (a,b) for a in A. intervals for b in B. intervals]
79
- filter! (i-> ! isempty (i), ivals)
80
94
sort! (ivals, by= i-> i. lower)
81
95
VersionSet (ivals)
82
96
end
83
- copy (A:: VersionSet ) = VersionSet (copy (A. intervals))
84
97
85
98
union (A:: VersionSet , B:: VersionSet ) = union! (copy (A), B)
86
99
function union! (A:: VersionSet , B:: VersionSet )
87
- A == B && return normalize! (A)
100
+ A == B && return A
88
101
ivals = A. intervals
89
102
for intB in B. intervals
90
103
lB, uB = intB. lower, intB. upper
@@ -105,7 +118,8 @@ function union!(A::VersionSet, B::VersionSet)
105
118
end
106
119
end
107
120
end
108
- return normalize! (VersionSet (ivals))
121
+ normalize! (ivals)
122
+ return A
109
123
end
110
124
111
125
== (A:: VersionSet , B:: VersionSet ) = A. intervals == B. intervals
@@ -223,11 +237,7 @@ function _show(io::IO, ritem::ResolveBacktraceItem, indent::String, seen::Set{Re
223
237
end
224
238
print (io, " required by package $(w[1 ]) , " )
225
239
if isa (w[2 ]. versionreq, VersionSet)
226
- if ! isempty (w[2 ]. versionreq)
227
- println (io, " whose allowed version range is $(w[2 ]. versionreq) :" )
228
- else
229
- println (io, " whose allowed version range is empty:" )
230
- end
240
+ println (io, " whose allowed version range is $(w[2 ]. versionreq) :" )
231
241
else
232
242
println (io, " whose only allowed version is $(w[2 ]. versionreq) :" )
233
243
end
0 commit comments