naturalsorter 2.0.5 → 2.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +25 -31
- data/lib/natcmp.rb +2 -2
- data/lib/naturalsorter.rb +45 -59
- data/lib/naturalsorter/version.rb +1 -1
- data/lib/version_tag_recognizer.rb +33 -56
- data/lib/versioncmp.rb +40 -45
- data/spec/naturalsorter_spec.rb +53 -49
- metadata +2 -2
data/README.markdown
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# NaturalSorter
|
2
2
|
|
3
|
-
[![
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/naturalsorter.png)](http://badge.fury.io/rb/naturalsorter)
|
4
4
|
[![Dependency Status](http://www.versioneye.com/package/naturalsorter/badge.png)](http://www.versioneye.com/package/naturalsorter)
|
5
|
+
[![Build Status](https://travis-ci.org/versioneye/naturalsorter.png)](https://travis-ci.org/versioneye/naturalsorter)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/versioneye/naturalsorter.png)](https://codeclimate.com/github/versioneye/naturalsorter)
|
5
7
|
|
6
8
|
|
7
9
|
## The Mission
|
@@ -14,47 +16,39 @@ If you are sorting this in ruby with ".sort" you will get this result
|
|
14
16
|
|
15
17
|
`["init20", "init200", "init30"]`
|
16
18
|
|
17
|
-
Because the default sort method does not recognize the numbers in the string. The NaturalSorter will return this result.
|
19
|
+
Because the default sort method does not recognize the numbers in the string. The NaturalSorter will return this result.
|
18
20
|
|
19
21
|
`["init20", "init30", "init200"]`
|
20
22
|
|
21
23
|
## Version Sorting
|
22
|
-
This fork contains some special algorithms to sort version numbers in a natural order. This project is used at <https://www.versioneye.com> to show versions of selected open source projects.
|
24
|
+
This fork contains some special algorithms to sort version numbers in a natural order. This project is used at <https://www.versioneye.com> to show versions of selected open source projects.
|
23
25
|
|
24
26
|
|
25
27
|
## API
|
26
28
|
|
27
|
-
This 2 methods are sorting a simple array of Strings. The name of the methods and the parameters are self explained.
|
28
|
-
|
29
|
-
`Naturalsorter::Sorter.sort(array, caseinsesitive)`
|
30
|
-
|
31
|
-
`Naturalsorter::Sorter.sort_desc(array, caseinsesitive)`
|
32
|
-
|
33
|
-
And this here is for more advanced sorting. Where you can put in a array of objects and the method which should called on every object for comparison.
|
34
|
-
|
35
|
-
`Naturalsorter::Sorter.sort_by_method(array, method, caseinsesitive)`
|
29
|
+
This 2 methods are sorting a simple array of Strings. The name of the methods and the parameters are self explained.
|
36
30
|
|
37
|
-
`Naturalsorter::Sorter.
|
31
|
+
`Naturalsorter::Sorter.sort(array, caseinsesitive = false, asc = true)`
|
38
32
|
|
39
|
-
|
33
|
+
And this here is for more advanced sorting. Where you can put in a array of objects and the method which should called on every object for comparison.
|
40
34
|
|
41
|
-
`Naturalsorter::Sorter.
|
35
|
+
`Naturalsorter::Sorter.sort_by_method(array, method, caseinsesitive = false, asc = true)`
|
42
36
|
|
43
|
-
|
37
|
+
This methods are based on a different algo. Spezially optimizied for sorting version strings.
|
44
38
|
|
45
|
-
|
39
|
+
`Naturalsorter::Sorter.sort_version(array, asc = true)`
|
46
40
|
|
47
|
-
|
41
|
+
This here is again for an array with objects. Spezially optimizied for sorting version strings.
|
48
42
|
|
49
|
-
`Naturalsorter::Sorter.
|
43
|
+
`Naturalsorter::Sorter.sort_version_by_method(array, method, asc = true )`
|
50
44
|
|
51
45
|
Get the newest version from the both given.
|
52
46
|
|
53
|
-
`Naturalsorter::Sorter.get_newest_version(first, second)`
|
47
|
+
`Naturalsorter::Sorter.get_newest_version(first, second)`
|
54
48
|
|
55
49
|
Is a bigger than b?
|
56
50
|
|
57
|
-
`Naturalsorter::Sorter.bigger?(a, b)`
|
51
|
+
`Naturalsorter::Sorter.bigger?(a, b)`
|
58
52
|
|
59
53
|
Is a bigger than b or equal?
|
60
54
|
|
@@ -68,19 +62,19 @@ Is a smaller than b or equal?
|
|
68
62
|
|
69
63
|
`Naturalsorter::Sorter.smaller_or_equal?(a, b)`
|
70
64
|
|
71
|
-
This is for the Ruby GEM notaiton '~>'. For example '~>1.1' fits '1.2' and '1.9' and '1.14'. But not 2.0.
|
72
|
-
The parameter version would be for example '~>1.1' and the parameter newest_version would be the
|
73
|
-
current newest version of the GEM, for example "2.0". The method will return false in this case
|
74
|
-
because '~>1.1' doesn't fit anymore the newest version.
|
65
|
+
This is for the Ruby GEM notaiton '~>'. For example '~>1.1' fits '1.2' and '1.9' and '1.14'. But not 2.0.
|
66
|
+
The parameter version would be for example '~>1.1' and the parameter newest_version would be the
|
67
|
+
current newest version of the GEM, for example "2.0". The method will return false in this case
|
68
|
+
because '~>1.1' doesn't fit anymore the newest version.
|
75
69
|
|
76
|
-
`Naturalsorter::Sorter.is_version_current?(version, newest_version)`
|
70
|
+
`Naturalsorter::Sorter.is_version_current?(version, newest_version)`
|
77
71
|
|
78
72
|
|
79
|
-
## Installation
|
73
|
+
## Installation
|
80
74
|
|
81
75
|
You should add this line to your Gemfile
|
82
76
|
|
83
|
-
`gem 'naturalsorter', '2.0.
|
77
|
+
`gem 'naturalsorter', '2.0.6'`
|
84
78
|
|
85
79
|
and run this command in your app root directory
|
86
80
|
|
@@ -88,13 +82,13 @@ and run this command in your app root directory
|
|
88
82
|
|
89
83
|
## How To Use - Examples
|
90
84
|
|
91
|
-
After the installation you can use it like this:
|
85
|
+
After the installation you can use it like this:
|
92
86
|
|
93
87
|
`Naturalsorter::Sorter.sort(["a400", "a5", "a1"], true)`
|
94
88
|
|
95
89
|
it will return the array ["a1", "a5", "a400"]. The second paramter is for "caseinsesitive".
|
96
90
|
|
97
|
-
If you have more advanced objects you want to sort, you should use the second method. Assume you have a Class User with 3 attributes: "firstname", "lastname", "age" and you want to sort an array of class Users by "firstname".
|
91
|
+
If you have more advanced objects you want to sort, you should use the second method. Assume you have a Class User with 3 attributes: "firstname", "lastname", "age" and you want to sort an array of class Users by "firstname".
|
98
92
|
|
99
93
|
`Naturalsorter::Sorter.sort_by_method(users, "firstname", true)`
|
100
94
|
|
@@ -109,5 +103,5 @@ will return the array ["1.1", "1.2", "1.10"]
|
|
109
103
|
|
110
104
|
## Alan Davies
|
111
105
|
|
112
|
-
The first 4 methods in this librarie are internal based on the natcmp implementation from Alan Davies. All glorry to him for his awesome work.
|
106
|
+
The first 4 methods in this librarie are internal based on the natcmp implementation from Alan Davies. All glorry to him for his awesome work.
|
113
107
|
|
data/lib/natcmp.rb
CHANGED
@@ -61,10 +61,10 @@ def self.natcmp(str1, str2, caseInsensitive=false)
|
|
61
61
|
|
62
62
|
case (num1 <=> num2)
|
63
63
|
when -1 then return -1
|
64
|
-
when
|
64
|
+
when 1 then return 1
|
65
65
|
end
|
66
66
|
when -1 then return -1
|
67
|
-
when
|
67
|
+
when 1 then return 1
|
68
68
|
end # case
|
69
69
|
|
70
70
|
end # while
|
data/lib/naturalsorter.rb
CHANGED
@@ -29,95 +29,81 @@ module Naturalsorter
|
|
29
29
|
|
30
30
|
class Sorter
|
31
31
|
|
32
|
-
|
33
|
-
def self.sort(array, caseinsesitive)
|
32
|
+
def self.sort(array, caseinsesitive = false , asc = true )
|
34
33
|
return array if (array.nil? || array.empty?)
|
35
|
-
|
34
|
+
if asc
|
35
|
+
return array.sort { |a, b| Natcmp.natcmp(a, b, caseinsesitive) }
|
36
|
+
else
|
37
|
+
return array.sort { |a, b| Natcmp.natcmp(b, a, caseinsesitive) }
|
38
|
+
end
|
36
39
|
end
|
37
40
|
|
38
|
-
def self.sort_desc(array, caseinsesitive)
|
39
|
-
return array if (array.nil? || array.empty?)
|
40
|
-
array.sort { |a, b| Natcmp.natcmp(b, a, caseinsesitive) }
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
41
|
# 'Natural order' sort for an array of objects.
|
45
|
-
def self.sort_by_method(array, method, caseinsesitive)
|
46
|
-
return array if (array.nil? || array.empty?)
|
47
|
-
|
48
|
-
|
42
|
+
def self.sort_by_method(array, method, caseinsesitive = false, asc = true)
|
43
|
+
return array if (array.nil? || array.empty? || array.length == 1)
|
44
|
+
if asc
|
45
|
+
array.sort { |a,b| Natcmp.natcmp( a.send(method), b.send(method), caseinsesitive) }
|
46
|
+
else
|
47
|
+
array.sort { |a, b| Natcmp.natcmp(b.send(method), a.send(method), caseinsesitive) }
|
48
|
+
end
|
49
49
|
end
|
50
50
|
|
51
|
-
def self.sort_by_method_desc(array, method, caseinsesitive)
|
52
|
-
return array if (array.nil? || array.empty?)
|
53
|
-
return array if array.length == 1
|
54
|
-
array.sort { |a, b| Natcmp.natcmp(b.send(method), a.send(method), caseinsesitive) }
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
def self.sort_version(array)
|
59
|
-
return array if (array.nil? || array.empty?)
|
60
|
-
array.sort { |a,b| Versioncmp.compare( a, b ) }
|
61
|
-
end
|
62
51
|
|
63
|
-
def self.
|
64
|
-
return array if (array.nil? || array.empty?)
|
65
|
-
|
52
|
+
def self.sort_version(array, asc = true)
|
53
|
+
return array if (array.nil? || array.empty? || array.length == 1)
|
54
|
+
if asc
|
55
|
+
array.sort { |a,b| Versioncmp.compare( a, b ) }
|
56
|
+
else
|
57
|
+
array.sort { |a,b| Versioncmp.compare( b, a ) }
|
58
|
+
end
|
66
59
|
end
|
67
60
|
|
68
61
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
62
|
+
def self.sort_version_by_method(array, method, asc = true )
|
63
|
+
return array if (array.nil? || array.empty? || array.length == 1 )
|
64
|
+
if asc
|
65
|
+
array.sort { |a,b| Versioncmp.compare(a.send(method), b.send(method)) }
|
66
|
+
else
|
67
|
+
array.sort { |a,b| Versioncmp.compare(b.send(method), a.send(method)) }
|
68
|
+
end
|
74
69
|
end
|
75
|
-
|
76
|
-
def self.sort_version_by_method_desc(array, method)
|
77
|
-
return array if (array.nil? || array.empty?)
|
78
|
-
return array if array.length == 1
|
79
|
-
array.sort { |a,b| Versioncmp.compare(b.send(method), a.send(method)) }
|
80
|
-
end
|
81
|
-
|
82
|
-
|
70
|
+
|
83
71
|
|
84
72
|
def self.get_newest_version(first, second)
|
85
73
|
array = [first, second]
|
86
74
|
array = array.sort { |a,b| Versioncmp.compare( a, b ) }
|
87
75
|
array.last
|
88
76
|
end
|
77
|
+
|
78
|
+
def self.get_newest(a, b)
|
79
|
+
Versioncmp.replace_leading_vs a, b
|
80
|
+
Sorter.get_newest_version(a, b)
|
81
|
+
end
|
89
82
|
|
90
83
|
def self.bigger?(a, b)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
84
|
+
return false if a.eql?( b )
|
85
|
+
newest = self.get_newest a, b
|
86
|
+
newest.eql?( a )
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.smaller?(a, b)
|
90
|
+
return false if b.eql?( a )
|
91
|
+
newest = self.get_newest a, b
|
92
|
+
newest.eql?( b )
|
96
93
|
end
|
97
94
|
|
98
95
|
def self.bigger_or_equal?(a, b)
|
99
|
-
Versioncmp.replace_leading_v( a )
|
100
|
-
Versioncmp.replace_leading_v( b )
|
101
96
|
return true if a.eql?(b)
|
102
|
-
newest =
|
97
|
+
newest = self.get_newest a, b
|
103
98
|
newest.eql?(a)
|
104
99
|
end
|
105
100
|
|
106
|
-
def self.smaller?(a, b)
|
107
|
-
Versioncmp.replace_leading_v( a )
|
108
|
-
Versioncmp.replace_leading_v( b )
|
109
|
-
return false if a.eql?(b)
|
110
|
-
newest = Sorter.get_newest_version(a, b)
|
111
|
-
newest.eql?(b)
|
112
|
-
end
|
113
|
-
|
114
101
|
def self.smaller_or_equal?(a, b)
|
115
|
-
Versioncmp.replace_leading_v( a )
|
116
|
-
Versioncmp.replace_leading_v( b )
|
117
102
|
return true if a.eql?(b)
|
118
|
-
newest =
|
103
|
+
newest = self.get_newest a, b
|
119
104
|
newest.eql?(b)
|
120
105
|
end
|
106
|
+
|
121
107
|
|
122
108
|
|
123
109
|
# This is for the GEM notaiton ~>
|
@@ -28,10 +28,14 @@ class VersionTagRecognizer
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.tagged? value
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
self.
|
31
|
+
return true if self.alpha?(value)
|
32
|
+
return true if self.beta?(value)
|
33
|
+
return true if self.dev?(value)
|
34
|
+
return true if self.rc?(value)
|
35
|
+
return true if self.snapshot?(value)
|
36
|
+
return true if self.pre?(value)
|
37
|
+
return true if self.jbossorg?(value)
|
38
|
+
return false
|
35
39
|
end
|
36
40
|
|
37
41
|
def self.remove_tag value
|
@@ -54,53 +58,25 @@ class VersionTagRecognizer
|
|
54
58
|
end
|
55
59
|
|
56
60
|
def self.remove_minimum_stability val
|
57
|
-
if val.match(/@.*$/)
|
58
|
-
val.gsub!(/@.*$/, "")
|
59
|
-
end
|
61
|
+
val.gsub!(/@.*$/, "") if val.match(/@.*$/)
|
60
62
|
end
|
61
63
|
|
62
64
|
def self.does_it_fit_stability?( version_number, stability )
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
if self.stable?( version_number ) ||
|
79
|
-
self.rc?( version_number ) ||
|
80
|
-
self.beta?( version_number )
|
81
|
-
return true
|
82
|
-
end
|
83
|
-
elsif stability.casecmp( A_STABILITY_ALPHA ) == 0
|
84
|
-
if self.stable?( version_number ) ||
|
85
|
-
self.rc?( version_number ) ||
|
86
|
-
self.beta?( version_number ) ||
|
87
|
-
self.alpha?( version_number )
|
88
|
-
return true
|
89
|
-
end
|
90
|
-
elsif stability.casecmp( A_STABILITY_SNAPSHOT ) == 0
|
91
|
-
if self.stable?( version_number ) ||
|
92
|
-
self.rc?( version_number ) ||
|
93
|
-
self.pre?( version_number ) ||
|
94
|
-
self.beta?( version_number ) ||
|
95
|
-
self.alpha?( version_number ) ||
|
96
|
-
self.snapshot?( version_number )
|
97
|
-
return true
|
98
|
-
end
|
99
|
-
elsif stability.casecmp( A_STABILITY_DEV ) == 0
|
100
|
-
return true
|
101
|
-
else
|
102
|
-
return false
|
103
|
-
end
|
65
|
+
stable = self.stable?( version_number )
|
66
|
+
pre = stable || self.pre?( version_number )
|
67
|
+
rc = stable || self.rc?( version_number )
|
68
|
+
beta = rc || self.beta?( version_number )
|
69
|
+
alpha = beta || self.alpha?( version_number )
|
70
|
+
snapshot = alpha || self.pre?( version_number ) || self.snapshot?( version_number )
|
71
|
+
|
72
|
+
return true if (stability.casecmp( A_STABILITY_STABLE ) == 0) && stable
|
73
|
+
return true if (stability.casecmp( A_STABILITY_PRE ) == 0) && pre
|
74
|
+
return true if (stability.casecmp( A_STABILITY_RC ) == 0) && rc
|
75
|
+
return true if (stability.casecmp( A_STABILITY_BETA ) == 0) && beta
|
76
|
+
return true if (stability.casecmp( A_STABILITY_ALPHA ) == 0) && alpha
|
77
|
+
return true if (stability.casecmp( A_STABILITY_SNAPSHOT ) == 0) && snapshot
|
78
|
+
return true if (stability.casecmp( A_STABILITY_DEV ) == 0)
|
79
|
+
return false
|
104
80
|
end
|
105
81
|
|
106
82
|
def self.stability_tag_for( version )
|
@@ -131,14 +107,15 @@ class VersionTagRecognizer
|
|
131
107
|
end
|
132
108
|
|
133
109
|
def self.stable? value
|
134
|
-
if value.match(/.+RELEASE.*/i)
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
!self.
|
141
|
-
!self.
|
110
|
+
return true if value.match(/.+RELEASE.*/i)
|
111
|
+
return true if value.match(/.+BUILD.*/i)
|
112
|
+
return true if value.match(/.+FINAL.*/i)
|
113
|
+
return true if value.match(/.+SP.*/i)
|
114
|
+
return true if value.match(/.+GA.*/i)
|
115
|
+
|
116
|
+
!self.alpha?(value) and !self.beta?(value) and
|
117
|
+
!self.dev?(value) and !self.pre?(value) and
|
118
|
+
!self.rc?(value) and !value.match(/.+SEC.*/i) and
|
142
119
|
!self.snapshot?(value) and !value.match(/.+M.+/i)
|
143
120
|
end
|
144
121
|
|
data/lib/versioncmp.rb
CHANGED
@@ -29,17 +29,12 @@ class Versioncmp
|
|
29
29
|
#
|
30
30
|
def self.compare(a_val, b_val)
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
end
|
32
|
+
a_empty = a_val.nil? || a_val.empty?
|
33
|
+
b_empty = b_val.nil? || b_val.empty?
|
35
34
|
|
36
|
-
if
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
if a_val.nil? && b_val.nil?
|
41
|
-
return -1
|
42
|
-
end
|
35
|
+
return 0 if a_empty && b_empty
|
36
|
+
return 1 if (a_empty == false) && b_empty
|
37
|
+
return -1 if (b_empty == false) && a_empty
|
43
38
|
|
44
39
|
a = pre_process a_val
|
45
40
|
b = pre_process b_val
|
@@ -48,14 +43,14 @@ class Versioncmp
|
|
48
43
|
offset2 = 0;
|
49
44
|
|
50
45
|
for i in 0..100
|
51
|
-
break if offset1 >= a.length() || offset2 >= b.length()
|
46
|
+
break if offset1 >= a.length() || offset2 >= b.length()
|
52
47
|
|
53
48
|
part1 = Versioncmp.get_a_piece_of_the_cake(offset1, a);
|
54
49
|
part2 = Versioncmp.get_a_piece_of_the_cake(offset2, b);
|
55
|
-
|
50
|
+
|
56
51
|
return -1 if Versioncmp.timestamp?(part1) && part2.length() < 8
|
57
52
|
return 1 if Versioncmp.timestamp?(part2) && part1.length() < 8
|
58
|
-
|
53
|
+
|
59
54
|
offset1 += part1.length() + 1;
|
60
55
|
offset2 += part2.length() + 1;
|
61
56
|
|
@@ -64,10 +59,10 @@ class Versioncmp
|
|
64
59
|
bi = part2.to_i;
|
65
60
|
result = Versioncmp.compare_int(ai, bi);
|
66
61
|
return result if result != 0
|
67
|
-
next
|
62
|
+
next
|
68
63
|
elsif ( !part1.match(/^[0-9]+$/) && !part2.match(/^[0-9]+$/) )
|
69
64
|
result = double_scope_checker(a, b)
|
70
|
-
return result if result != 0
|
65
|
+
return result if result != 0
|
71
66
|
result = Versioncmp.compare_string(part1, part2)
|
72
67
|
return result if (result != 0)
|
73
68
|
next
|
@@ -78,12 +73,12 @@ class Versioncmp
|
|
78
73
|
return -1;
|
79
74
|
end
|
80
75
|
end
|
81
|
-
result = Versioncmp.check_for_tags(a, b)
|
76
|
+
result = Versioncmp.check_for_tags(a, b)
|
82
77
|
return result
|
83
78
|
end
|
84
|
-
|
79
|
+
|
85
80
|
# Tags are RC, alpha, beta, dev and so on.
|
86
|
-
#
|
81
|
+
#
|
87
82
|
def self.check_for_tags(a, b)
|
88
83
|
big = String.new(a)
|
89
84
|
small = String.new(b)
|
@@ -97,24 +92,24 @@ class Versioncmp
|
|
97
92
|
return Versioncmp.compare_string_length(a, b)
|
98
93
|
end
|
99
94
|
end
|
100
|
-
self.compare_string_length_odd(a, b)
|
95
|
+
self.compare_string_length_odd(a, b)
|
101
96
|
end
|
102
97
|
|
103
98
|
def self.double_scope_checker(a, b)
|
104
99
|
if VersionTagRecognizer.tagged?(a) && VersionTagRecognizer.tagged?(b)
|
105
|
-
a_without_scope
|
100
|
+
a_without_scope = VersionTagRecognizer.remove_tag a
|
106
101
|
b_without_scope = VersionTagRecognizer.remove_tag b
|
107
102
|
if a_without_scope.eql? b_without_scope
|
108
103
|
return VersionTagRecognizer.compare_tags(a, b)
|
109
104
|
end
|
110
105
|
end
|
111
|
-
0
|
106
|
+
0
|
112
107
|
end
|
113
|
-
|
108
|
+
|
114
109
|
def self.get_a_piece_of_the_cake(offset, cake)
|
115
110
|
for z in 0..100
|
116
111
|
offsetz = offset + z
|
117
|
-
break if offsetz > cake.length()
|
112
|
+
break if offsetz > cake.length()
|
118
113
|
p = cake[ offset..offset + z ]
|
119
114
|
if ( p.match(/^\w+\.$/) != nil )
|
120
115
|
break
|
@@ -126,21 +121,21 @@ class Versioncmp
|
|
126
121
|
piece = cake[offset..offset + z ]
|
127
122
|
return piece
|
128
123
|
end
|
129
|
-
|
124
|
+
|
130
125
|
def self.timestamp?(part)
|
131
126
|
return part.length() == 8 && part.match(/^[0-9]+$/) != nil
|
132
127
|
end
|
133
128
|
|
134
|
-
def self.pre_process val
|
129
|
+
def self.pre_process val
|
135
130
|
a = replace_x_dev val
|
136
|
-
replace_leading_v a
|
131
|
+
replace_leading_v a
|
137
132
|
replace_99_does_not_exist a
|
138
|
-
replace_timestamps a
|
139
|
-
VersionTagRecognizer.remove_minimum_stability a
|
140
|
-
a
|
133
|
+
replace_timestamps a
|
134
|
+
VersionTagRecognizer.remove_minimum_stability a
|
135
|
+
a
|
141
136
|
end
|
142
137
|
|
143
|
-
def self.replace_99_does_not_exist val
|
138
|
+
def self.replace_99_does_not_exist val
|
144
139
|
if val.eql?("99.0-does-not-exist")
|
145
140
|
val.gsub!("99.0-does-not-exist", "0.0.0")
|
146
141
|
end
|
@@ -148,17 +143,17 @@ class Versioncmp
|
|
148
143
|
|
149
144
|
# Some glory Java Devs used the timestamp as version string
|
150
145
|
# http://www.versioneye.com/package/commons-beanutils--commons-beanutils
|
151
|
-
# Ganz grosses Kino
|
146
|
+
# Ganz grosses Kino !
|
152
147
|
#
|
153
148
|
def self.replace_timestamps val
|
154
149
|
if val.match(/^[0-9]{8}$/)
|
155
150
|
val.gsub!(/^[0-9]{8}$/, "0.0.0")
|
156
|
-
elsif val.match(/^[0-9]{8}.[0-9]{6}$/)
|
151
|
+
elsif val.match(/^[0-9]{8}.[0-9]{6}$/)
|
157
152
|
val.gsub!(/^[0-9]{8}.[0-9]{6}$/, "0.0.0")
|
158
153
|
end
|
159
154
|
end
|
160
155
|
|
161
|
-
def self.replace_x_dev val
|
156
|
+
def self.replace_x_dev val
|
162
157
|
new_val = String.new(val)
|
163
158
|
if val.eql?("dev-master")
|
164
159
|
new_val = "9999999"
|
@@ -170,16 +165,17 @@ class Versioncmp
|
|
170
165
|
new_val
|
171
166
|
end
|
172
167
|
|
173
|
-
def self.replace_leading_v val
|
174
|
-
if val.match(/^v[0-9]+/)
|
175
|
-
val.gsub!(/^v/, "")
|
176
|
-
end
|
168
|
+
def self.replace_leading_v val
|
169
|
+
val.gsub!(/^v/, "") if val.match(/^v[0-9]+/)
|
177
170
|
end
|
178
171
|
|
179
|
-
|
172
|
+
def self.replace_leading_vs a, b
|
173
|
+
self.replace_leading_v a
|
174
|
+
self.replace_leading_v b
|
175
|
+
end
|
180
176
|
|
181
177
|
def self.check_jquery_versioning(part1, part2)
|
182
|
-
# --- START ---- special case for awesome jquery shitty verison numbers
|
178
|
+
# --- START ---- special case for awesome jquery shitty verison numbers
|
183
179
|
if ( part1.match(/^[0-9]+[a-zA-Z]+[0-9]+$/) != nil && part2.match(/^[0-9]+$/) != nil )
|
184
180
|
part1_1 = part1.match(/^[0-9]+/)
|
185
181
|
result = Versioncmp.compare_int(part1_1[0], part2)
|
@@ -199,7 +195,7 @@ class Versioncmp
|
|
199
195
|
end
|
200
196
|
|
201
197
|
return nil
|
202
|
-
# --- END ---- special case for awesome jquery shitty verison numbers
|
198
|
+
# --- END ---- special case for awesome jquery shitty verison numbers
|
203
199
|
end
|
204
200
|
|
205
201
|
def self.compare_int(ai, bi)
|
@@ -207,20 +203,19 @@ class Versioncmp
|
|
207
203
|
return 0 if (ai == bi)
|
208
204
|
return 1
|
209
205
|
end
|
210
|
-
|
206
|
+
|
211
207
|
def self.compare_string(a, b)
|
212
208
|
return 0 if a.eql? b
|
213
|
-
return
|
214
|
-
return 1
|
209
|
+
return Natcmp.natcmp(a, b)
|
215
210
|
end
|
216
211
|
|
217
|
-
def self.compare_string_length(a, b)
|
212
|
+
def self.compare_string_length(a, b)
|
218
213
|
return 0 if a.length() == b.length()
|
219
214
|
return 1 if a.length() < b.length()
|
220
215
|
return -1
|
221
216
|
end
|
222
217
|
|
223
|
-
def self.compare_string_length_odd(a, b)
|
218
|
+
def self.compare_string_length_odd(a, b)
|
224
219
|
return 1 if a.length > b.length
|
225
220
|
return -1 if a.length < b.length
|
226
221
|
return 0
|
data/spec/naturalsorter_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require "naturalsorter"
|
2
2
|
|
3
3
|
describe Naturalsorter::Sorter do
|
4
|
-
|
4
|
+
|
5
5
|
describe "sort" do
|
6
6
|
it "cba is abc" do
|
7
7
|
Naturalsorter::Sorter.sort(["c", "b", "a"], true).should eql(["a", "b", "c"])
|
@@ -12,13 +12,13 @@ describe Naturalsorter::Sorter do
|
|
12
12
|
end
|
13
13
|
describe "sort_desc" do
|
14
14
|
it "cba is abc" do
|
15
|
-
Naturalsorter::Sorter.
|
15
|
+
Naturalsorter::Sorter.sort(["c", "b", "a"], true, false).should eql(["c", "b", "a"])
|
16
16
|
end
|
17
17
|
it "c400b5a1 is a1b5c400" do
|
18
|
-
Naturalsorter::Sorter.
|
18
|
+
Naturalsorter::Sorter.sort(["a5", "a400", "a1"], true, false).should eql(["a400", "a5", "a1"])
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
describe "sort_by_method" do
|
23
23
|
it "c400b5a1 is a1b5c400" do
|
24
24
|
Naturalsorter::Sorter.sort_by_method(["a400", "a5", "a1"], "to_s", true).should eql(["a1", "a5", "a400"])
|
@@ -26,11 +26,11 @@ describe Naturalsorter::Sorter do
|
|
26
26
|
end
|
27
27
|
describe "sort_by_method_desc" do
|
28
28
|
it "a5 a400 a1 is a400 a5 a1" do
|
29
|
-
Naturalsorter::Sorter.
|
29
|
+
Naturalsorter::Sorter.sort_by_method(["a5", "a400", "a1"], "to_s", true, false).should eql(["a400", "a5", "a1"])
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
33
|
-
|
32
|
+
|
33
|
+
|
34
34
|
describe "sort_version" do
|
35
35
|
|
36
36
|
it "1.1 is 1.1" do
|
@@ -40,23 +40,23 @@ describe Naturalsorter::Sorter do
|
|
40
40
|
it "1.1 is bigger than 20030211.134440" do
|
41
41
|
Naturalsorter::Sorter.sort_version(["1.1", "20030211.134440"]).should eql(["20030211.134440", "1.1"])
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
it "1.1, 1.0 is 1.0, 1.1" do
|
45
45
|
Naturalsorter::Sorter.sort_version(["1.1", "1.0"]).should eql(["1.0", "1.1"])
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
it "1.0, 1.1 is 1.0, 1.1" do
|
49
49
|
Naturalsorter::Sorter.sort_version(["1.0", "1.1"]).should eql(["1.0", "1.1"])
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
it "4.5, 1.0 is 1.0, 4.5" do
|
53
53
|
Naturalsorter::Sorter.sort_version(["4.5", "1.0"]).should eql(["1.0", "4.5"])
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
it "1.0, 4.5 is 1.0, 4.5" do
|
57
57
|
Naturalsorter::Sorter.sort_version(["1.0", "4.5"]).should eql(["1.0", "4.5"])
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
it "1.2, 1.1 is 1.1, 1.2" do
|
61
61
|
Naturalsorter::Sorter.sort_version(["0.4", "0.1", "1.1", "1.2", "1.0"]).should eql(["0.1", "0.4", "1.0", "1.1", "1.2"])
|
62
62
|
end
|
@@ -66,15 +66,15 @@ describe Naturalsorter::Sorter do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
it "1.2, 1.1 is 1.1, 1.2" do
|
69
|
-
Naturalsorter::Sorter.
|
69
|
+
Naturalsorter::Sorter.sort_version(["0.4", "0.1", "1.1", "1.2", "1.0", "1.0.RC1"], false).should eql(["1.2", "1.1", "1.0", "1.0.RC1", "0.4", "0.1"])
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
it "1.2, 1.1 is 1.1, 1.2" do
|
73
|
-
Naturalsorter::Sorter.
|
73
|
+
Naturalsorter::Sorter.sort_version(["0.4", "0.1", "1.1", "1.1.1", "1.2", "1.2.1", "1.0", "1.0.RC1"], false).should eql(["1.2.1", "1.2", "1.1.1", "1.1", "1.0", "1.0.RC1", "0.4", "0.1"])
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
it "sorts this to the end 20040121.140929" do
|
77
|
-
Naturalsorter::Sorter.
|
77
|
+
Naturalsorter::Sorter.sort_version(["0.4", "0.1", "20040121.140929", "1.1.1", "1.2", "1.2.1", "1.0", "1.0.RC1"], false).should eql(["1.2.1", "1.2", "1.1.1", "1.0", "1.0.RC1", "0.4", "0.1", "20040121.140929"])
|
78
78
|
end
|
79
79
|
|
80
80
|
it "1.2, 1.1 is 1.1, 1.2" do
|
@@ -89,37 +89,41 @@ describe Naturalsorter::Sorter do
|
|
89
89
|
Naturalsorter::Sorter.sort_version(["1.1.RC1", "1.1", "1.0"]).should eql(["1.0", "1.1.RC1", "1.1"])
|
90
90
|
end
|
91
91
|
|
92
|
+
it "sorts 2.1.0-beta11 higher than 2.1.0-beta9" do
|
93
|
+
Naturalsorter::Sorter.sort_version(["2.1.0-beta11", "2.1.0-beta9"]).should eql(["2.1.0-beta9", "2.1.0-beta11"])
|
94
|
+
end
|
95
|
+
|
92
96
|
end
|
93
|
-
|
94
|
-
describe "is_version_current?" do
|
95
|
-
it "returns true" do
|
97
|
+
|
98
|
+
describe "is_version_current?" do
|
99
|
+
it "returns true" do
|
96
100
|
Naturalsorter::Sorter.is_version_current?("1.1.1", "1.1.9").should be_true
|
97
101
|
end
|
98
|
-
it "returns true" do
|
102
|
+
it "returns true" do
|
99
103
|
Naturalsorter::Sorter.is_version_current?("1.1.1", "1.1.2").should be_true
|
100
104
|
end
|
101
|
-
it "returns true" do
|
105
|
+
it "returns true" do
|
102
106
|
Naturalsorter::Sorter.is_version_current?("1.1.1", "1.1.12").should be_true
|
103
107
|
end
|
104
|
-
it "returns false" do
|
108
|
+
it "returns false" do
|
105
109
|
Naturalsorter::Sorter.is_version_current?("1.1.1", "1.2.0").should be_false
|
106
110
|
end
|
107
|
-
it "returns false" do
|
111
|
+
it "returns false" do
|
108
112
|
Naturalsorter::Sorter.is_version_current?("1.1.1", "1.2").should be_false
|
109
113
|
end
|
110
|
-
it "returns false" do
|
114
|
+
it "returns false" do
|
111
115
|
Naturalsorter::Sorter.is_version_current?("1.1.1", "2.0").should be_false
|
112
116
|
end
|
113
|
-
it "returns false" do
|
117
|
+
it "returns false" do
|
114
118
|
Naturalsorter::Sorter.is_version_current?("1.1.1", "2").should be_false
|
115
119
|
end
|
116
|
-
it "returns false" do
|
120
|
+
it "returns false" do
|
117
121
|
Naturalsorter::Sorter.is_version_current?("1.1", "2.0").should be_false
|
118
122
|
end
|
119
123
|
end
|
120
|
-
|
121
|
-
describe "get_newest_version" do
|
122
|
-
|
124
|
+
|
125
|
+
describe "get_newest_version" do
|
126
|
+
|
123
127
|
it "returns 2.0" do
|
124
128
|
Naturalsorter::Sorter.get_newest_version("1.1", "2.0").should eql("2.0")
|
125
129
|
end
|
@@ -153,11 +157,11 @@ describe Naturalsorter::Sorter do
|
|
153
157
|
it "returns still 1.11.1" do
|
154
158
|
Naturalsorter::Sorter.get_newest_version("1.10.x-dev", "1.11.1").should eql("1.11.1")
|
155
159
|
end
|
156
|
-
|
160
|
+
|
157
161
|
end
|
158
|
-
|
159
|
-
describe "bigger?" do
|
160
|
-
|
162
|
+
|
163
|
+
describe "bigger?" do
|
164
|
+
|
161
165
|
it "returns true" do
|
162
166
|
Naturalsorter::Sorter.bigger?("1.1", "1.0").should be_true
|
163
167
|
end
|
@@ -179,11 +183,11 @@ describe Naturalsorter::Sorter do
|
|
179
183
|
it "returns false" do
|
180
184
|
Naturalsorter::Sorter.bigger?("2.20", "3.0").should be_false
|
181
185
|
end
|
182
|
-
|
186
|
+
|
183
187
|
end
|
184
|
-
|
185
|
-
describe "bigger_or_equal?" do
|
186
|
-
|
188
|
+
|
189
|
+
describe "bigger_or_equal?" do
|
190
|
+
|
187
191
|
it "returns true" do
|
188
192
|
Naturalsorter::Sorter.bigger_or_equal?("1.1", "1.0").should be_true
|
189
193
|
end
|
@@ -205,11 +209,11 @@ describe Naturalsorter::Sorter do
|
|
205
209
|
it "returns false" do
|
206
210
|
Naturalsorter::Sorter.bigger_or_equal?("2.20", "3.0").should be_false
|
207
211
|
end
|
208
|
-
|
212
|
+
|
209
213
|
end
|
210
|
-
|
211
|
-
describe "smaller?" do
|
212
|
-
|
214
|
+
|
215
|
+
describe "smaller?" do
|
216
|
+
|
213
217
|
it "returns false" do
|
214
218
|
Naturalsorter::Sorter.smaller?("1.1", "1.0").should be_false
|
215
219
|
end
|
@@ -225,11 +229,11 @@ describe Naturalsorter::Sorter do
|
|
225
229
|
it "returns true" do
|
226
230
|
Naturalsorter::Sorter.smaller?("2.20", "3.0").should be_true
|
227
231
|
end
|
228
|
-
|
232
|
+
|
229
233
|
end
|
230
|
-
|
231
|
-
describe "smaller_or_equal?" do
|
232
|
-
|
234
|
+
|
235
|
+
describe "smaller_or_equal?" do
|
236
|
+
|
233
237
|
it "returns false" do
|
234
238
|
Naturalsorter::Sorter.smaller_or_equal?("1.1", "1.0").should be_false
|
235
239
|
end
|
@@ -248,7 +252,7 @@ describe Naturalsorter::Sorter do
|
|
248
252
|
it "returns true" do
|
249
253
|
Naturalsorter::Sorter.smaller_or_equal?("2.20", "v3.0").should be_true
|
250
254
|
end
|
251
|
-
|
255
|
+
|
252
256
|
end
|
253
|
-
|
254
|
-
end
|
257
|
+
|
258
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: naturalsorter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-06-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|