gjp 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +2 -2
- data/bin/gjp +8 -4
- data/lib/gjp.rb +1 -0
- data/lib/gjp/cli.rb +60 -43
- data/lib/gjp/get_pom.rb +78 -59
- data/lib/gjp/get_source.rb +72 -68
- data/lib/gjp/get_source_address.rb +37 -32
- data/lib/gjp/logger.rb +10 -17
- data/lib/gjp/pom.rb +28 -24
- data/lib/gjp/version.rb +1 -1
- data/lib/gjp/version_matcher.rb +77 -79
- data/spec/lib/get_pom_spec.rb +5 -5
- data/spec/lib/get_source_address_spec.rb +3 -3
- data/spec/lib/get_source_spec.rb +3 -3
- data/spec/lib/pom_spec.rb +28 -20
- data/spec/lib/version_matcher_spec.rb +22 -28
- data/spec/spec_helper.rb +5 -1
- metadata +2 -2
data/README.md
CHANGED
|
@@ -15,8 +15,8 @@ Easiest install is via RubyGems:
|
|
|
15
15
|
## Usage
|
|
16
16
|
|
|
17
17
|
Currently available tools:
|
|
18
|
-
* `gjp get-pom
|
|
19
|
-
* `gjp get-source-address POM` will attempt to find the SCM Internet address of a pom.xml (from the file itself or through api.github.com);
|
|
18
|
+
* `gjp get-pom NAME` will attempt to find a pom. `NAME` can be a jar file on your disk, a project directory, or simply a `name-version` string. `gjp` will get the pom either from the package itself or through search.maven.org using heuristic searching;
|
|
19
|
+
* `gjp get-source-address POM` will attempt to find the SCM Internet address of a pom.xml at the `POM` filename or URI (from the file itself or through api.github.com);
|
|
20
20
|
* `gjp get-source POM ADDRESS` downloads the source of a pom.xml's project from its SCM at ADDRESS;
|
|
21
21
|
|
|
22
22
|
## Source
|
data/bin/gjp
CHANGED
|
@@ -15,11 +15,15 @@
|
|
|
15
15
|
# http://www.gnu.org/licenses/lgpl-2.1.html
|
|
16
16
|
#
|
|
17
17
|
|
|
18
|
+
if File.exist?(File.join(File.dirname(__FILE__), "..", ".git"))
|
|
19
|
+
$: << File.join(File.dirname(__FILE__), "..", "lib")
|
|
20
|
+
end
|
|
21
|
+
|
|
18
22
|
begin
|
|
19
|
-
require
|
|
23
|
+
require "gjp"
|
|
20
24
|
rescue LoadError
|
|
21
|
-
require
|
|
22
|
-
require
|
|
25
|
+
require "rubygems"
|
|
26
|
+
require "gjp"
|
|
23
27
|
end
|
|
24
28
|
|
|
25
|
-
MainCommand.run
|
|
29
|
+
Gjp::MainCommand.run
|
data/lib/gjp.rb
CHANGED
data/lib/gjp/cli.rb
CHANGED
|
@@ -1,51 +1,68 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
|
-
|
|
2
|
+
require "gjp/logger"
|
|
3
3
|
require "clamp"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
5
|
+
# Initialize global logger
|
|
6
|
+
Gjp.logger = ::Logger.new(STDERR)
|
|
7
|
+
Gjp.logger.datetime_format = "%Y-%m-%d %H:%M "
|
|
8
|
+
Gjp.logger.level = ::Logger::INFO
|
|
9
|
+
Gjp.logger.formatter = proc do |severity, datetime, progname, msg|
|
|
10
|
+
"#{severity.chars.first}: #{msg}\n"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module Gjp
|
|
14
|
+
class MainCommand < Clamp::Command
|
|
15
|
+
subcommand "get-pom", "Retrieves a pom corresponding to a filename" do
|
|
16
|
+
parameter "NAME", "a jar file path, a project directory path or a non-existing filename in the `project-version` form"
|
|
17
|
+
option ["-v", "--verbose"], :flag, "verbose output"
|
|
18
|
+
option ["--very-verbose"], :flag, "very verbose output"
|
|
19
|
+
option ["--very-very-verbose"], :flag, "very very verbose output"
|
|
20
|
+
|
|
21
|
+
def configure_log_level(v, vv, vvv)
|
|
22
|
+
if vvv
|
|
23
|
+
Gjp.logger.level = Logger::DEBUG
|
|
24
|
+
elsif vv
|
|
25
|
+
Gjp.logger.level = Logger::INFO
|
|
26
|
+
elsif v
|
|
27
|
+
Gjp.logger.level = Logger::WARN
|
|
28
|
+
else
|
|
29
|
+
Gjp.logger.level = Logger::ERROR
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def very_very_verbose=(flag)
|
|
34
|
+
configure_log_level(verbose?, very_verbose?, flag)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def very_verbose=(flag)
|
|
38
|
+
configure_log_level(verbose?, flag, very_very_verbose?)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def verbose=(flag)
|
|
42
|
+
configure_log_level(flag, very_verbose?, very_very_verbose?)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def execute
|
|
46
|
+
puts Gjp::PomGetter.get_pom(name)
|
|
22
47
|
end
|
|
23
48
|
end
|
|
24
|
-
|
|
49
|
+
|
|
50
|
+
subcommand "get-source-address", "Retrieves a project's SCM Internet address" do
|
|
51
|
+
parameter "POM", "project's pom file path"
|
|
52
|
+
|
|
53
|
+
def execute
|
|
54
|
+
puts Gjp::SourceAddressGetter.get_source_address(pom)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
25
57
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
subcommand "get-source", "Retrieves a project's source code directory" do
|
|
39
|
-
parameter "ADDRESS", "project's SCM Internet address"
|
|
40
|
-
parameter "POM", "project's pom file path"
|
|
41
|
-
parameter "[DIRECTORY]", "directory in which to save the source code", :default => "."
|
|
42
|
-
option ["-v", "--verbose"], :flag, "verbose output"
|
|
43
|
-
option ["--very-verbose"], :flag, "very verbose output"
|
|
44
|
-
option ["--very-very-verbose"], :flag, "very very verbose output"
|
|
45
|
-
|
|
46
|
-
def execute
|
|
47
|
-
init_logger
|
|
48
|
-
puts SourceGetter.get_source(address, pom, directory)
|
|
49
|
-
end
|
|
58
|
+
subcommand "get-source", "Retrieves a project's source code directory" do
|
|
59
|
+
parameter "ADDRESS", "project's SCM Internet address"
|
|
60
|
+
parameter "POM", "project's pom file path"
|
|
61
|
+
parameter "[DIRECTORY]", "directory in which to save the source code", :default => "."
|
|
62
|
+
|
|
63
|
+
def execute
|
|
64
|
+
puts Gjp::SourceGetter.get_source(address, pom, directory)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
50
67
|
end
|
|
51
68
|
end
|
data/lib/gjp/get_pom.rb
CHANGED
|
@@ -8,81 +8,100 @@ require "pathname"
|
|
|
8
8
|
|
|
9
9
|
require "gjp/version_matcher"
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
module Gjp
|
|
12
|
+
# implements the get-pom subcommand
|
|
13
|
+
class PomGetter
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
def self.log
|
|
16
|
+
Gjp.logger
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# returns the pom corresponding to a filename
|
|
20
|
+
def self.get_pom(filename)
|
|
21
|
+
(get_pom_from_dir(filename) or get_pom_from_jar(filename) or get_pom_from_sha1(filename) or get_pom_from_heuristic(filename))
|
|
22
|
+
end
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
# returns the pom in a project directory
|
|
25
|
+
def self.get_pom_from_dir(dir)
|
|
26
|
+
if File.directory?(dir)
|
|
27
|
+
pom_path = File.join(dir, "pom.xml")
|
|
28
|
+
if File.file?(pom_path)
|
|
29
|
+
log.info("pom.xml found in #{dir}/pom.xml")
|
|
25
30
|
return File.read(pom_path)
|
|
31
|
+
end
|
|
26
32
|
end
|
|
27
33
|
end
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
|
|
35
|
+
# returns a pom embedded in a jar file
|
|
36
|
+
def self.get_pom_from_jar(file)
|
|
37
|
+
begin
|
|
38
|
+
Zip::ZipFile.foreach(file) do |entry|
|
|
39
|
+
if entry.name =~ /\/pom.xml$/
|
|
40
|
+
log.info("pom.xml found in #{file}##{entry.name}")
|
|
41
|
+
return entry.get_input_stream.read
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
rescue Zip::ZipError
|
|
45
|
+
log.info "#{file} does not seem to be a valid jar archive, skipping"
|
|
46
|
+
rescue TypeError
|
|
47
|
+
log.info "#{file} seems to be a valid jar archive but is corrupt, skipping"
|
|
36
48
|
end
|
|
49
|
+
return nil
|
|
37
50
|
end
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
|
|
52
|
+
# returns a pom from search.maven.org with a jar sha1 search
|
|
53
|
+
def self.get_pom_from_sha1(file)
|
|
54
|
+
begin
|
|
55
|
+
if File.file?(file)
|
|
56
|
+
sha1 = Digest::SHA1.hexdigest File.read(file)
|
|
57
|
+
results = repository_search({:q => "1:\"#{sha1}\""}).select {|result| result["ec"].include?(".pom")}
|
|
58
|
+
result = results.first
|
|
59
|
+
if result != nil
|
|
60
|
+
log.info("pom.xml for #{file} found on search.maven.org for sha1 #{sha1} (#{result["g"]}:#{result["a"]}:#{result["v"]})")
|
|
61
|
+
return repository_download(result)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
return nil
|
|
65
|
+
rescue RestClient::ResourceNotFound
|
|
66
|
+
$stderr.puts "Got an error while looking for #{file}'s SHA1 in search.maven.org"
|
|
67
|
+
end
|
|
49
68
|
end
|
|
50
|
-
end
|
|
51
69
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
70
|
+
# returns a pom from search.maven.org with a heuristic name search
|
|
71
|
+
def self.get_pom_from_heuristic(filename)
|
|
72
|
+
begin
|
|
73
|
+
filename = Pathname.new(filename).basename.to_s.sub(/.jar$/, "")
|
|
74
|
+
my_artifact_id, my_version = VersionMatcher.split_version(filename)
|
|
57
75
|
|
|
58
|
-
|
|
59
|
-
|
|
76
|
+
result = repository_search({:q => my_artifact_id}).first
|
|
77
|
+
if result != nil
|
|
60
78
|
results = repository_search({:q => "g:\"#{result["g"]}\" AND a:\"#{result["a"]}\"", :core => "gav"})
|
|
61
79
|
their_versions = results.map {|doc| doc["v"]}
|
|
62
80
|
best_matched_version = if my_version != nil then VersionMatcher.best_match(my_version, their_versions) else their_versions.max end
|
|
63
81
|
best_matched_result = (results.select{|result| result["v"] == best_matched_version}).first
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
82
|
+
|
|
83
|
+
log.warn("pom.xml for #{filename} found on search.maven.org with heuristic search (#{best_matched_result["g"]}:#{best_matched_result["a"]}:#{best_matched_result["v"]})")
|
|
84
|
+
|
|
67
85
|
return repository_download(best_matched_result)
|
|
86
|
+
end
|
|
87
|
+
rescue RestClient::ResourceNotFound
|
|
88
|
+
$stderr.puts "Got an error while looking for #{filename} in search.maven.org"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# returns a JSON result from search.maven.com
|
|
93
|
+
def self.repository_search(params)
|
|
94
|
+
response = RestClient.get "http://search.maven.org/solrsearch/select", {:params => params.merge({"rows" => "100", "wt" => "json"})}
|
|
95
|
+
json = JSON.parse(response.to_s)
|
|
96
|
+
return json["response"]["docs"]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# downloads a POM from a search.maven.com search result
|
|
100
|
+
def self.repository_download(result)
|
|
101
|
+
if result != nil
|
|
102
|
+
path = "#{result["g"].gsub(".", "/")}/#{result["a"]}/#{result["v"]}/#{result["a"]}-#{result["v"]}.pom"
|
|
103
|
+
return (RestClient.get "http://search.maven.org/remotecontent", {:params => {:filepath => path}}).to_s
|
|
68
104
|
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# returns a JSON result from search.maven.com
|
|
73
|
-
def self.repository_search(params)
|
|
74
|
-
response = RestClient.get "http://search.maven.org/solrsearch/select", {:params => params.merge({"rows" => "100", "wt" => "json"})}
|
|
75
|
-
json = JSON.parse(response.to_s)
|
|
76
|
-
return json["response"]["docs"]
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# downloads a POM from a search.maven.com search result
|
|
80
|
-
def self.repository_download(result)
|
|
81
|
-
if result != nil
|
|
82
|
-
path = "#{result["g"].gsub(".", "/")}/#{result["a"]}/#{result["v"]}/#{result["a"]}-#{result["v"]}.pom"
|
|
83
|
-
return (RestClient.get "http://search.maven.org/remotecontent", {:params => {:filepath => path}}).to_s
|
|
84
105
|
end
|
|
85
106
|
end
|
|
86
|
-
|
|
87
107
|
end
|
|
88
|
-
|
data/lib/gjp/get_source.rb
CHANGED
|
@@ -2,80 +2,84 @@
|
|
|
2
2
|
|
|
3
3
|
require "rest_client"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
module Gjp
|
|
6
|
+
# implements the get-source subcommand
|
|
7
|
+
class SourceGetter
|
|
8
|
+
def self.log
|
|
9
|
+
Gjp.logger
|
|
10
|
+
end
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
# downloads a project's source into a specified directory
|
|
13
|
+
def self.get_source(address, pomfile, directory)
|
|
14
|
+
log.info("downloading: #{address} in #{directory}, pomfile: #{pomfile}")
|
|
15
|
+
|
|
16
|
+
dummy, prefix, scm_address = address.split(/^([^:]+):(.*)$/)
|
|
17
|
+
log.info("prefix: #{prefix}, scm_address: #{scm_address}")
|
|
18
|
+
|
|
19
|
+
get_source_from_scm(prefix, scm_address, pomfile, directory)
|
|
20
|
+
end
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
22
|
+
# checks code out from an scm
|
|
23
|
+
def self.get_source_from_scm(prefix, scm_address, pomfile, directory)
|
|
24
|
+
pom = Pom.new(pomfile)
|
|
25
|
+
dir = File.join(directory, "#{pom.group_id}:#{pom.artifact_id}:#{pom.version}")
|
|
26
|
+
begin
|
|
27
|
+
Dir::mkdir(dir)
|
|
28
|
+
rescue Errno::EEXIST
|
|
29
|
+
log.warn("Source directory exists, leaving...")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if prefix == "git"
|
|
33
|
+
get_source_from_git(scm_address, dir, pom.version)
|
|
34
|
+
elsif prefix == "svn"
|
|
35
|
+
get_source_from_svn(scm_address, dir, pom.version)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
# checks code out of git
|
|
40
|
+
def self.get_source_from_git(scm_address, dir, version)
|
|
41
|
+
`git clone #{scm_address} #{dir}`
|
|
42
|
+
|
|
43
|
+
Dir.chdir(dir) do
|
|
44
|
+
tags = `git tag`.split("\n")
|
|
45
|
+
|
|
46
|
+
if tags.any?
|
|
47
|
+
best_tag = get_best_tag(tags, version)
|
|
48
|
+
log.info("checking out tag: #{best_tag}")
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
`git checkout #{best_tag}`
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
# checks code out of svn
|
|
56
|
+
def self.get_source_from_svn(scm_address, dir, version)
|
|
57
|
+
`svn checkout #{scm_address} #{dir}`
|
|
58
|
+
|
|
59
|
+
Dir.chdir(dir) do
|
|
60
|
+
tags = `svn ls "^/tags"`.split("\n")
|
|
61
|
+
|
|
62
|
+
if tags.any?
|
|
63
|
+
best_tag = get_best_tag(tags, version)
|
|
64
|
+
log.info("checking out tag: #{best_tag}")
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
`svn checkout #{scm_address}/tags/#{best_tag}`
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
66
70
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
# return the (heuristically) most similar tag to the specified version
|
|
72
|
+
def self.get_best_tag(tags, version)
|
|
73
|
+
versions_to_tags =Hash[
|
|
74
|
+
*tags.map do |tag|
|
|
75
|
+
[VersionMatcher.split_version(tag)[1], tag]
|
|
76
|
+
end.flatten
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
log.info("found the following versions and tags: #{versions_to_tags}")
|
|
76
80
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
best_version = VersionMatcher.best_match(version, versions_to_tags.keys)
|
|
82
|
+
versions_to_tags[best_version]
|
|
83
|
+
end
|
|
84
|
+
end
|
|
80
85
|
end
|
|
81
|
-
|
|
@@ -4,45 +4,50 @@ require "rest_client"
|
|
|
4
4
|
require "json"
|
|
5
5
|
require "open-uri"
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
module Gjp
|
|
8
|
+
# implements the get-source-address subcommand
|
|
9
|
+
class SourceAddressGetter
|
|
10
|
+
def self.log
|
|
11
|
+
Gjp.logger
|
|
12
|
+
end
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
# returns the pom corresponding to a file or directory, if it can be found
|
|
15
|
+
def self.get_source_address(file)
|
|
16
|
+
log.info("looking for source address for: #{file}")
|
|
17
|
+
(get_source_address_from_pom(file) or get_source_address_from_github(file))
|
|
18
|
+
end
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
# returns an scm address in a pom file
|
|
21
|
+
def self.get_source_address_from_pom(file)
|
|
22
|
+
pom = Pom.new(file)
|
|
23
|
+
result = pom.connection_address
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
if result != nil
|
|
26
|
+
log.info("address found in pom")
|
|
27
|
+
result
|
|
28
|
+
end
|
|
24
29
|
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# returns an scm address looking for it on github
|
|
28
|
-
def self.get_source_address_from_github(file)
|
|
29
|
-
pom = Pom.new(file)
|
|
30
|
-
|
|
31
|
-
result = (github_search(pom.artifact_id) or github_search(pom.artifact_id.split("-").first) or github_search(pom.group_id))
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
# returns an scm address looking for it on github
|
|
32
|
+
def self.get_source_address_from_github(file)
|
|
33
|
+
pom = Pom.new(file)
|
|
34
|
+
|
|
35
|
+
result = (github_search(pom.artifact_id) or github_search(pom.artifact_id.split("-").first) or github_search(pom.group_id))
|
|
36
|
+
|
|
37
|
+
if result != nil
|
|
38
|
+
log.info("address found on Github: #{result}")
|
|
39
|
+
result
|
|
40
|
+
end
|
|
36
41
|
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# returns a Giuthub repo address based on the keyword
|
|
40
|
-
def self.github_search(keyword)
|
|
41
|
-
if keyword != "" and keyword != nil
|
|
42
|
-
response = RestClient.get "https://api.github.com/legacy/repos/search/" + CGI::escape(keyword), :user_agent => "gjp/" + Gjp::VERSION, :language => "java", :sort => "forks"
|
|
43
|
-
json = JSON.parse(response.to_s)
|
|
44
42
|
|
|
45
|
-
|
|
43
|
+
# returns a Giuthub repo address based on the keyword
|
|
44
|
+
def self.github_search(keyword)
|
|
45
|
+
if keyword != "" and keyword != nil
|
|
46
|
+
response = RestClient.get "https://api.github.com/legacy/repos/search/" + CGI::escape(keyword), :user_agent => "gjp/" + Gjp::VERSION, :language => "java", :sort => "forks"
|
|
47
|
+
json = JSON.parse(response.to_s)
|
|
48
|
+
|
|
49
|
+
(json["repositories"].map {|repository| "git:" + repository["url"]}).first
|
|
50
|
+
end
|
|
46
51
|
end
|
|
47
52
|
end
|
|
48
53
|
end
|
data/lib/gjp/logger.rb
CHANGED
|
@@ -2,23 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
require "logger"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if very_very_verbose?
|
|
9
|
-
Logger::DEBUG
|
|
10
|
-
elsif very_verbose?
|
|
11
|
-
Logger::INFO
|
|
12
|
-
elsif verbose?
|
|
13
|
-
Logger::WARN
|
|
14
|
-
else
|
|
15
|
-
Logger::ERROR
|
|
16
|
-
end
|
|
17
|
-
else
|
|
18
|
-
level
|
|
5
|
+
module Gjp
|
|
6
|
+
def self.logger=(logger)
|
|
7
|
+
@logger = logger
|
|
19
8
|
end
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
|
|
10
|
+
def self.logger
|
|
11
|
+
@logger ||= Logger.new('/dev/null')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def logger
|
|
15
|
+
Gjp.logger
|
|
23
16
|
end
|
|
24
17
|
end
|
data/lib/gjp/pom.rb
CHANGED
|
@@ -1,30 +1,34 @@
|
|
|
1
|
-
# encoding: UTF-8
|
|
1
|
+
# encoding: UTF-8
|
|
2
2
|
|
|
3
3
|
require "nokogiri"
|
|
4
|
+
require "open-uri"
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
connection_nodes.
|
|
6
|
+
module Gjp
|
|
7
|
+
# encapsulates a pom.xml file
|
|
8
|
+
class Pom
|
|
9
|
+
def initialize(filename)
|
|
10
|
+
@doc = Nokogiri::XML(open(filename).read)
|
|
11
|
+
@doc.remove_namespaces!
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def connection_address
|
|
15
|
+
connection_nodes = @doc.xpath("//scm/connection/text()")
|
|
16
|
+
if connection_nodes.any?
|
|
17
|
+
connection_nodes.first.to_s.sub(/^scm:/, "")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def group_id
|
|
22
|
+
@doc.xpath("project/groupId/text()").to_s
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def artifact_id
|
|
26
|
+
@doc.xpath("project/artifactId/text()").to_s
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def version
|
|
30
|
+
@doc.xpath("project/version/text()").to_s
|
|
16
31
|
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def group_id
|
|
20
|
-
@doc.xpath("project/groupId/text()").to_s
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def artifact_id
|
|
24
|
-
@doc.xpath("project/artifactId/text()").to_s
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def version
|
|
28
|
-
@doc.xpath("project/version/text()").to_s
|
|
29
32
|
end
|
|
30
33
|
end
|
|
34
|
+
|
data/lib/gjp/version.rb
CHANGED
data/lib/gjp/version_matcher.rb
CHANGED
|
@@ -2,93 +2,92 @@
|
|
|
2
2
|
|
|
3
3
|
require "text"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def self.extract_version(full_name)
|
|
12
|
-
full_name.sub /^[^0-9]+/, ""
|
|
13
|
-
end
|
|
5
|
+
module Gjp
|
|
6
|
+
# heuristically matches version strings
|
|
7
|
+
class VersionMatcher
|
|
8
|
+
def self.log
|
|
9
|
+
Gjp.logger
|
|
10
|
+
end
|
|
14
11
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
12
|
+
# heuristically splits a full name into an artifact name and version string
|
|
13
|
+
# assumes that version strings begin with a numeric character and are separated
|
|
14
|
+
# by a ., -, _, ~ or space
|
|
15
|
+
# returns a [name, version] pair
|
|
16
|
+
def self.split_version(full_name)
|
|
17
|
+
matches = full_name.match(/(.*?)(?:[\.\-\_ ~,]?([0-9].*))?$/)
|
|
18
|
+
if matches != nil and matches.length > 1
|
|
19
|
+
[matches[1], matches[2]]
|
|
20
|
+
else
|
|
21
|
+
[full_string, nil]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
27
24
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
my_chunks = my_version.split /[\.\-\_ ~,]/
|
|
39
|
-
their_chunks_hash = Hash[
|
|
40
|
-
their_versions.map do |their_version|
|
|
41
|
-
their_chunks_for_version = their_version.split /[\.\-\_ ~,]/
|
|
42
|
-
their_chunks_for_version += [nil]*[my_chunks.length - their_chunks_for_version.length, 0].max
|
|
43
|
-
[their_version, their_chunks_for_version]
|
|
44
|
-
end
|
|
45
|
-
]
|
|
25
|
+
# returns the "best match" between a version number and a set of available version numbers
|
|
26
|
+
# using a heuristic criterion. Idea:
|
|
27
|
+
# - split the version number in chunks divided by ., - etc.
|
|
28
|
+
# - every chunk with same index is "compared", differences make up a score
|
|
29
|
+
# - "comparison" is a subtraction if the chunk is an integer, a string distance measure otherwise
|
|
30
|
+
# - score weighs differently on chunk index (first chunks are most important)
|
|
31
|
+
# - lowest score wins
|
|
32
|
+
def self.best_match(my_version, their_versions)
|
|
33
|
+
log.debug("version comparison: #{my_version} vs #{their_versions.join(', ')}")
|
|
46
34
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
35
|
+
my_chunks = my_version.split /[\.\-\_ ~,]/
|
|
36
|
+
their_chunks_hash = Hash[
|
|
37
|
+
their_versions.map do |their_version|
|
|
38
|
+
their_chunks_for_version = their_version.split /[\.\-\_ ~,]/
|
|
39
|
+
their_chunks_for_version += [nil]*[my_chunks.length - their_chunks_for_version.length, 0].max
|
|
40
|
+
[their_version, their_chunks_for_version]
|
|
41
|
+
end
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
max_chunks_length = ([my_chunks.length] + their_chunks_hash.values.map {|chunk| chunk.length}).max
|
|
45
|
+
|
|
46
|
+
scoreboard = []
|
|
47
|
+
their_versions.each do |their_version|
|
|
48
|
+
their_chunks = their_chunks_hash[their_version]
|
|
49
|
+
score = 0
|
|
50
|
+
their_chunks.each_with_index do |their_chunk, i|
|
|
51
|
+
score_multiplier = 100**(max_chunks_length -i -1)
|
|
52
|
+
my_chunk = my_chunks[i]
|
|
53
|
+
score += chunk_distance(my_chunk, their_chunk) * score_multiplier
|
|
54
|
+
end
|
|
55
|
+
scoreboard << {:version => their_version, :score => score}
|
|
57
56
|
end
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
scoreboard = scoreboard.sort_by {|element| element[:score]}
|
|
57
|
+
|
|
58
|
+
scoreboard = scoreboard.sort_by {|element| element[:score]}
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
log.debug("scoreboard: ")
|
|
61
|
+
scoreboard.each_with_index do |element, i|
|
|
62
|
+
log.debug(" #{i+1}. #{element[:version]} (score: #{element[:score]})")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
winner = scoreboard.first
|
|
66
|
+
|
|
67
|
+
if winner != nil
|
|
68
|
+
return winner[:version]
|
|
69
|
+
end
|
|
66
70
|
end
|
|
67
71
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
their_chunk = "0"
|
|
85
|
-
end
|
|
86
|
-
if my_chunk.is_i? and their_chunk.is_i?
|
|
87
|
-
return [(my_chunk.to_i - their_chunk.to_i).abs, 99].min
|
|
88
|
-
else
|
|
89
|
-
return [Text::Levenshtein.distance(my_chunk.upcase, their_chunk.upcase), 99].min
|
|
72
|
+
# returns a score representing the distance between two version chunks
|
|
73
|
+
# for integers, the score is the difference between their values
|
|
74
|
+
# for strings, the score is the Levenshtein distance
|
|
75
|
+
# in any case score is normalized between 0 (identical) and 99 (very different/uncomparable)
|
|
76
|
+
def self.chunk_distance(my_chunk, their_chunk)
|
|
77
|
+
if my_chunk == nil
|
|
78
|
+
my_chunk = "0"
|
|
79
|
+
end
|
|
80
|
+
if their_chunk == nil
|
|
81
|
+
their_chunk = "0"
|
|
82
|
+
end
|
|
83
|
+
if my_chunk.is_i? and their_chunk.is_i?
|
|
84
|
+
return [(my_chunk.to_i - their_chunk.to_i).abs, 99].min
|
|
85
|
+
else
|
|
86
|
+
return [Text::Levenshtein.distance(my_chunk.upcase, their_chunk.upcase), 99].min
|
|
87
|
+
end
|
|
90
88
|
end
|
|
91
89
|
end
|
|
90
|
+
|
|
92
91
|
end
|
|
93
92
|
|
|
94
93
|
class String
|
|
@@ -96,4 +95,3 @@ class String
|
|
|
96
95
|
!!(self =~ /^[0-9]+$/)
|
|
97
96
|
end
|
|
98
97
|
end
|
|
99
|
-
|
data/spec/lib/get_pom_spec.rb
CHANGED
|
@@ -2,33 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
|
-
describe PomGetter do
|
|
5
|
+
describe Gjp::PomGetter do
|
|
6
6
|
describe ".get_pom" do
|
|
7
7
|
it "gets the pom from a directory" do
|
|
8
8
|
dir_path = File.join("spec", "data", "commons-logging")
|
|
9
9
|
pom_path = File.join(dir_path, "pom.xml")
|
|
10
|
-
PomGetter.get_pom(dir_path).should eq(File.read(pom_path))
|
|
10
|
+
Gjp::PomGetter.get_pom(dir_path).should eq(File.read(pom_path))
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
it "gets the pom from a jar" do
|
|
14
14
|
dir_path = File.join("spec", "data", "commons-logging")
|
|
15
15
|
pom_path = File.join(dir_path, "pom.xml")
|
|
16
16
|
jar_path = File.join(dir_path, "commons-logging-1.1.1.jar")
|
|
17
|
-
PomGetter.get_pom(jar_path).should eq(File.read(pom_path))
|
|
17
|
+
Gjp::PomGetter.get_pom(jar_path).should eq(File.read(pom_path))
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
it "gets the pom from sha1" do
|
|
21
21
|
dir_path = File.join("spec", "data", "antlr")
|
|
22
22
|
pom_path = File.join(dir_path, "pom.xml")
|
|
23
23
|
jar_path = File.join(dir_path, "antlr-2.7.2.jar")
|
|
24
|
-
PomGetter.get_pom(jar_path).should eq(File.read(pom_path))
|
|
24
|
+
Gjp::PomGetter.get_pom(jar_path).should eq(File.read(pom_path))
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
it "gets the pom from a heuristic" do
|
|
28
28
|
dir_path = File.join("spec", "data", "nailgun")
|
|
29
29
|
pom_path = File.join(dir_path, "pom.xml")
|
|
30
30
|
jar_path = File.join(dir_path, "nailgun-0.7.1.jar")
|
|
31
|
-
PomGetter.get_pom(jar_path).should eq(File.read(pom_path))
|
|
31
|
+
Gjp::PomGetter.get_pom(jar_path).should eq(File.read(pom_path))
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
end
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
|
-
describe SourceAddressGetter do
|
|
5
|
+
describe Gjp::SourceAddressGetter do
|
|
6
6
|
describe ".get_source_address" do
|
|
7
7
|
it "gets the source address from a pom file" do
|
|
8
8
|
pom_path = File.join("spec", "data", "commons-logging", "pom.xml")
|
|
9
|
-
SourceAddressGetter.get_source_address(pom_path).should eq "svn:http://svn.apache.org/repos/asf/commons/proper/logging/tags/commons-logging-1.1.1"
|
|
9
|
+
Gjp::SourceAddressGetter.get_source_address(pom_path).should eq "svn:http://svn.apache.org/repos/asf/commons/proper/logging/tags/commons-logging-1.1.1"
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
it "gets the source address from Github" do
|
|
13
13
|
pom_path = File.join("spec", "data", "antlr", "pom.xml")
|
|
14
|
-
SourceAddressGetter.get_source_address(pom_path).should eq "git:https://github.com/antlr/antlr4"
|
|
14
|
+
Gjp::SourceAddressGetter.get_source_address(pom_path).should eq "git:https://github.com/antlr/antlr4"
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
end
|
data/spec/lib/get_source_spec.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require "spec_helper"
|
|
4
4
|
require "fileutils"
|
|
5
5
|
|
|
6
|
-
describe SourceGetter do
|
|
6
|
+
describe Gjp::SourceGetter do
|
|
7
7
|
describe ".get_source_from_git" do
|
|
8
8
|
it "gets the sources from a git repo" do
|
|
9
9
|
dir_path = File.join("spec", "data", "nailgun")
|
|
@@ -13,7 +13,7 @@ describe SourceGetter do
|
|
|
13
13
|
|
|
14
14
|
FileUtils.rm_rf(repo_path)
|
|
15
15
|
|
|
16
|
-
SourceGetter.get_source("git:git@github.com:martylamb/nailgun.git", pom_path, dir_path)
|
|
16
|
+
Gjp::SourceGetter.get_source("git:git@github.com:martylamb/nailgun.git", pom_path, dir_path)
|
|
17
17
|
|
|
18
18
|
File.open(file_path).readline.should eq "nailgun\n"
|
|
19
19
|
end
|
|
@@ -28,7 +28,7 @@ describe SourceGetter do
|
|
|
28
28
|
|
|
29
29
|
FileUtils.rm_rf(repo_path)
|
|
30
30
|
|
|
31
|
-
SourceGetter.get_source("svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_3_14/apps", pom_path, dir_path)
|
|
31
|
+
Gjp::SourceGetter.get_source("svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_3_14/apps", pom_path, dir_path)
|
|
32
32
|
|
|
33
33
|
File.open(file_path).readline.should eq "README.txt - showcase\n"
|
|
34
34
|
end
|
data/spec/lib/pom_spec.rb
CHANGED
|
@@ -2,30 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
|
-
describe Pom do
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
describe Gjp::Pom do
|
|
6
|
+
[ File.join("spec", "data", "commons-logging", "pom.xml"),
|
|
7
|
+
'http://search.maven.org/remotecontent?filepath=commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.pom'].each do |loc|
|
|
8
|
+
|
|
9
|
+
let(:pom) { Gjp::Pom.new(loc) }
|
|
10
|
+
|
|
11
|
+
describe "#connection_address" do
|
|
12
|
+
it "reads the SCM connection address" do
|
|
13
|
+
pom.connection_address.should eq "svn:http://svn.apache.org/repos/asf/commons/proper/logging/tags/commons-logging-1.1.1"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "reads the SCM connection address from a remote repository" do
|
|
17
|
+
pom.connection_address.should eq "svn:http://svn.apache.org/repos/asf/commons/proper/logging/tags/commons-logging-1.1.1"
|
|
18
|
+
end
|
|
11
19
|
end
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
|
|
21
|
+
describe "#group_id" do
|
|
22
|
+
it "reads the group id" do
|
|
23
|
+
pom.group_id.should eq "commons-logging"
|
|
24
|
+
end
|
|
17
25
|
end
|
|
18
|
-
end
|
|
19
26
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
describe "#artifact_id" do
|
|
28
|
+
it "reads the artifact id" do
|
|
29
|
+
pom.artifact_id.should eq "commons-logging"
|
|
30
|
+
end
|
|
23
31
|
end
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
|
|
33
|
+
describe "#version" do
|
|
34
|
+
it "reads the version" do
|
|
35
|
+
pom.version.should eq "1.1.1"
|
|
36
|
+
end
|
|
29
37
|
end
|
|
30
38
|
end
|
|
31
39
|
end
|
|
@@ -2,63 +2,57 @@
|
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
|
-
describe VersionMatcher do
|
|
5
|
+
describe Gjp::VersionMatcher do
|
|
6
6
|
|
|
7
7
|
it "splits full names into names and version numbers" do
|
|
8
|
-
VersionMatcher.split_version("moio-3.2beta1").should eq(["moio", "3.2beta1"])
|
|
9
|
-
VersionMatcher.split_version("3.2beta1").should eq(["
|
|
10
|
-
VersionMatcher.split_version("v3.2beta1").should eq(["v", "3.2beta1"])
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
it "extracts version numbers" do
|
|
14
|
-
VersionMatcher.extract_version("moio-3.2beta1").should eq("3.2beta1")
|
|
15
|
-
VersionMatcher.extract_version("3.2beta1").should eq("3.2beta1")
|
|
16
|
-
VersionMatcher.extract_version("v3.2beta1").should eq("3.2beta1")
|
|
8
|
+
Gjp::VersionMatcher.split_version("moio-3.2beta1").should eq(["moio", "3.2beta1"])
|
|
9
|
+
Gjp::VersionMatcher.split_version("3.2beta1").should eq(["", "3.2beta1"])
|
|
10
|
+
Gjp::VersionMatcher.split_version("v3.2beta1").should eq(["v", "3.2beta1"])
|
|
17
11
|
end
|
|
18
12
|
|
|
19
13
|
it "computes chunk distances" do
|
|
20
|
-
VersionMatcher.chunk_distance(nil, "1").should eq(1)
|
|
21
|
-
VersionMatcher.chunk_distance("alpha", nil).should eq(5)
|
|
14
|
+
Gjp::VersionMatcher.chunk_distance(nil, "1").should eq(1)
|
|
15
|
+
Gjp::VersionMatcher.chunk_distance("alpha", nil).should eq(5)
|
|
22
16
|
|
|
23
|
-
VersionMatcher.chunk_distance("1", "1").should eq(0)
|
|
24
|
-
VersionMatcher.chunk_distance("1", "9").should eq(8)
|
|
25
|
-
VersionMatcher.chunk_distance("1", "999").should eq(99)
|
|
17
|
+
Gjp::VersionMatcher.chunk_distance("1", "1").should eq(0)
|
|
18
|
+
Gjp::VersionMatcher.chunk_distance("1", "9").should eq(8)
|
|
19
|
+
Gjp::VersionMatcher.chunk_distance("1", "999").should eq(99)
|
|
26
20
|
|
|
27
|
-
VersionMatcher.chunk_distance("snap", "SNAP").should eq(0)
|
|
28
|
-
VersionMatcher.chunk_distance("snap", "snippete").should eq(5)
|
|
29
|
-
VersionMatcher.chunk_distance("snap", "l"*999).should eq(99)
|
|
21
|
+
Gjp::VersionMatcher.chunk_distance("snap", "SNAP").should eq(0)
|
|
22
|
+
Gjp::VersionMatcher.chunk_distance("snap", "snippete").should eq(5)
|
|
23
|
+
Gjp::VersionMatcher.chunk_distance("snap", "l"*999).should eq(99)
|
|
30
24
|
|
|
31
|
-
VersionMatcher.chunk_distance("1", "SNAP").should eq(4)
|
|
25
|
+
Gjp::VersionMatcher.chunk_distance("1", "SNAP").should eq(4)
|
|
32
26
|
|
|
33
|
-
VersionMatcher.chunk_distance("0", "10").should eq(10)
|
|
34
|
-
VersionMatcher.chunk_distance("0", "9").should eq(9)
|
|
27
|
+
Gjp::VersionMatcher.chunk_distance("0", "10").should eq(10)
|
|
28
|
+
Gjp::VersionMatcher.chunk_distance("0", "9").should eq(9)
|
|
35
29
|
end
|
|
36
30
|
|
|
37
31
|
it "finds the best match" do
|
|
38
32
|
my_version = "1.0"
|
|
39
33
|
available_versions = ["1.0", "1", "2.0", "1.0.1", "4.5.6.7.8"]
|
|
40
|
-
VersionMatcher.best_match(my_version, available_versions).should eq("1.0")
|
|
34
|
+
Gjp::VersionMatcher.best_match(my_version, available_versions).should eq("1.0")
|
|
41
35
|
|
|
42
36
|
available_versions = ["3.0", "2.0", "1.0.1"]
|
|
43
|
-
VersionMatcher.best_match(my_version, available_versions).should eq("1.0.1")
|
|
37
|
+
Gjp::VersionMatcher.best_match(my_version, available_versions).should eq("1.0.1")
|
|
44
38
|
|
|
45
39
|
available_versions = ["1.snap", "2.0", "4.0.1"]
|
|
46
|
-
VersionMatcher.best_match(my_version, available_versions).should eq("1.snap")
|
|
40
|
+
Gjp::VersionMatcher.best_match(my_version, available_versions).should eq("1.snap")
|
|
47
41
|
|
|
48
42
|
available_versions = ["1.10", "1.9", "2.0", "3.0.1"]
|
|
49
|
-
VersionMatcher.best_match(my_version, available_versions).should eq("1.9")
|
|
43
|
+
Gjp::VersionMatcher.best_match(my_version, available_versions).should eq("1.9")
|
|
50
44
|
|
|
51
45
|
my_version = "1.snap"
|
|
52
46
|
available_versions = ["1.snap", "1"]
|
|
53
|
-
VersionMatcher.best_match(my_version, available_versions).should eq("1.snap")
|
|
47
|
+
Gjp::VersionMatcher.best_match(my_version, available_versions).should eq("1.snap")
|
|
54
48
|
|
|
55
49
|
my_version = "1.very-very_very_longish"
|
|
56
50
|
available_versions = ["1.snap", "1"]
|
|
57
|
-
VersionMatcher.best_match(my_version, available_versions).should eq("1.snap")
|
|
51
|
+
Gjp::VersionMatcher.best_match(my_version, available_versions).should eq("1.snap")
|
|
58
52
|
|
|
59
53
|
my_version = "1.snap"
|
|
60
54
|
available_versions = []
|
|
61
|
-
VersionMatcher.best_match(my_version, available_versions).should be_nil
|
|
55
|
+
Gjp::VersionMatcher.best_match(my_version, available_versions).should be_nil
|
|
62
56
|
end
|
|
63
57
|
end
|
|
64
58
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gjp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2013-06-
|
|
12
|
+
date: 2013-06-12 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rake
|