gjp 0.9.0 → 0.10.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 +1 -0
- data/lib/gjp/cli.rb +2 -1
- data/lib/gjp/jar_table.rb +87 -58
- data/lib/gjp/version.rb +1 -1
- data/spec/lib/jar_table_spec.rb +8 -15
- metadata +2 -2
data/README.md
CHANGED
@@ -19,6 +19,7 @@ Currently available tools:
|
|
19
19
|
* `gjp get-parent-pom POM` will attempt to download a pom's parent from search.maven.org, where `POM` is a filename or URI;
|
20
20
|
* `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. `POM` can either be a filename or a URI;
|
21
21
|
* `gjp get-source POM ADDRESS` downloads the source of a pom.xml's project from its SCM at ADDRESS;
|
22
|
+
* `gjp scaffold-jar-table DIRECTORY` looks for jars in the project's DIRECTORY and classifies them as build-time dependencies (b), run-time dependencies (r) or products (p);
|
22
23
|
|
23
24
|
## Source
|
24
25
|
|
data/lib/gjp/cli.rb
CHANGED
@@ -77,9 +77,10 @@ module Gjp
|
|
77
77
|
|
78
78
|
subcommand "scaffold-jar-table", "Creates a heuristic version of a project's jar table" do
|
79
79
|
parameter "[DIRECTORY]", "project directory", :default => "."
|
80
|
+
option ["--include-all"], :flag, "include tests and samples in produced jars", :default => false
|
80
81
|
|
81
82
|
def execute
|
82
|
-
puts Gjp::JarTable.new(directory).to_s
|
83
|
+
puts Gjp::JarTable.new(directory, include_all?).to_s
|
83
84
|
end
|
84
85
|
end
|
85
86
|
end
|
data/lib/gjp/jar_table.rb
CHANGED
@@ -7,19 +7,26 @@ module Gjp
|
|
7
7
|
# assumes the project is in a directory with jar files
|
8
8
|
# in its (possibly nested) subdirectories
|
9
9
|
class JarTable
|
10
|
-
def
|
10
|
+
def log
|
11
11
|
Gjp.logger
|
12
12
|
end
|
13
13
|
|
14
|
-
attr_reader :
|
14
|
+
attr_reader :rows, :runtime_required_packages, :source_defined_packages
|
15
15
|
|
16
16
|
# builds a JarTable from a directory (paths relative to the current directory)
|
17
|
-
def initialize(dir)
|
18
|
-
|
17
|
+
def initialize(dir, include_all)
|
18
|
+
jars = get_jars(dir)
|
19
|
+
sources = get_sources(dir)
|
20
|
+
statements = get_statements(sources)
|
21
|
+
@runtime_required_packages = get_runtime_required_packages(statements)
|
22
|
+
@source_defined_packages = get_source_defined_packages(statements)
|
23
|
+
|
24
|
+
log.debug "Runtime required packages are:\n#{@runtime_required_packages.join("\n")}"
|
25
|
+
log.debug "Source defined packages are:\n#{@source_defined_packages.join("\n")}"
|
19
26
|
|
20
27
|
@rows = Hash[
|
21
28
|
jars.map do |jar|
|
22
|
-
[jar, get_type(jar)]
|
29
|
+
[jar, get_type(jar, include_all)]
|
23
30
|
end
|
24
31
|
]
|
25
32
|
end
|
@@ -29,66 +36,24 @@ module Gjp
|
|
29
36
|
"#b - jar is required for building the project"
|
30
37
|
"#r - jar is required runtime by the project"
|
31
38
|
"#p - jar is produced by the project"
|
39
|
+
"#i - jar is ignored"
|
32
40
|
@rows.map do |key, value|
|
33
41
|
"#{value.to_s[0]} #{key}"
|
34
42
|
end.sort
|
35
43
|
end
|
36
44
|
|
37
45
|
# jar files in the project's directory
|
38
|
-
def
|
39
|
-
Dir["#{
|
40
|
-
end
|
41
|
-
|
42
|
-
# returns packages defined in a jar file
|
43
|
-
def jar_defined_packages(jar)
|
44
|
-
result = []
|
45
|
-
begin
|
46
|
-
Zip::ZipFile.foreach(jar) do |entry|
|
47
|
-
if entry.name =~ /^(.+)\/.+?\.class$/
|
48
|
-
result << $1.gsub("/", ".")
|
49
|
-
end
|
50
|
-
end
|
51
|
-
rescue Zip::ZipError
|
52
|
-
log.info "#{file} does not seem to be a valid jar archive, skipping"
|
53
|
-
rescue TypeError
|
54
|
-
log.info "#{file} seems to be a valid jar archive but is corrupt, skipping"
|
55
|
-
end
|
56
|
-
|
57
|
-
return result.sort.uniq
|
58
|
-
end
|
59
|
-
|
60
|
-
# returns :produced if the jar was produced from the project's sources, and
|
61
|
-
# :required or :build_required if it is needed at runtime or build time
|
62
|
-
# (heuristically)
|
63
|
-
def get_type(jar)
|
64
|
-
if source_defined?(jar)
|
65
|
-
:produced
|
66
|
-
elsif runtime_required?(jar)
|
67
|
-
:required
|
68
|
-
else
|
69
|
-
:build_required
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# returns true if a jar is produced from source code in the project's directory
|
74
|
-
def source_defined?(jar)
|
75
|
-
jar_defined_packages(jar).all? { |package| source_defined_packages.include?(package) }
|
76
|
-
end
|
77
|
-
|
78
|
-
# returns true if a jar is required runtime, false if it is only needed
|
79
|
-
# at compile time. Current implementation is heuristic (looks for "import" statements
|
80
|
-
# in java code)
|
81
|
-
def runtime_required?(jar)
|
82
|
-
jar_defined_packages(jar).any? { |package| source_required_packages.include?(package) }
|
46
|
+
def get_jars(dir)
|
47
|
+
Dir["#{dir}/**/*.jar"]
|
83
48
|
end
|
84
49
|
|
85
50
|
# java source files in the project's directory
|
86
|
-
def
|
87
|
-
Dir["#{
|
51
|
+
def get_sources(dir)
|
52
|
+
Dir["#{dir}/**/*.java"]
|
88
53
|
end
|
89
54
|
|
90
55
|
# java statements in java source files
|
91
|
-
def
|
56
|
+
def get_statements(sources)
|
92
57
|
sources.map do |source|
|
93
58
|
File.readlines(source)
|
94
59
|
.map { |line| line.split(";") }
|
@@ -98,22 +63,86 @@ module Gjp
|
|
98
63
|
end
|
99
64
|
|
100
65
|
# heuristically determined package names that the sources require
|
101
|
-
def
|
102
|
-
|
66
|
+
def get_runtime_required_packages(statements)
|
67
|
+
get_statement_fragments_from(statements, /^import[ \t]+(?:static[ \t]+)?(.+)\..+?$/)
|
103
68
|
end
|
104
69
|
|
105
70
|
# heuristically determined package names that the sources define
|
106
|
-
def
|
107
|
-
|
71
|
+
def get_source_defined_packages(statements)
|
72
|
+
get_statement_fragments_from(statements, /^package[ \t]+(.+)$/)
|
108
73
|
end
|
109
74
|
|
110
75
|
# matches a regex against all source statements
|
111
|
-
def
|
76
|
+
def get_statement_fragments_from(statements, regex)
|
112
77
|
statements.map do |statement|
|
113
78
|
if statement =~ regex
|
114
79
|
$1
|
115
80
|
end
|
116
81
|
end.select {|package| package != nil}.flatten.sort.uniq
|
117
82
|
end
|
83
|
+
|
84
|
+
|
85
|
+
# returns :produced if the jar was produced from the project's sources, and
|
86
|
+
# :required or :build_required if it is needed at runtime or build time
|
87
|
+
# (heuristically)
|
88
|
+
def get_type(jar, include_all)
|
89
|
+
if not include_all and (jar =~ /(test)|(sample)/)
|
90
|
+
:ignored
|
91
|
+
else
|
92
|
+
jar_defined_packages = get_jar_defined_packages(jar)
|
93
|
+
|
94
|
+
if source_defined?(jar, jar_defined_packages)
|
95
|
+
:produced
|
96
|
+
elsif runtime_required?(jar, jar_defined_packages)
|
97
|
+
:required
|
98
|
+
else
|
99
|
+
:build_required
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# returns true if a jar is produced from source code in the project's directory
|
105
|
+
def source_defined?(jar, jar_defined_packages)
|
106
|
+
log.debug "Determining if #{jar} is defined in the sources"
|
107
|
+
log.debug "#{jar} contains:\n#{jar_defined_packages.join("\n")}"
|
108
|
+
|
109
|
+
result = jar_defined_packages.all? { |package| @source_defined_packages.include?(package) }
|
110
|
+
|
111
|
+
log.debug "result is:#{result}"
|
112
|
+
|
113
|
+
return result
|
114
|
+
end
|
115
|
+
|
116
|
+
# returns true if a jar is required runtime, false if it is only needed
|
117
|
+
# at compile time. Current implementation is heuristic (looks for "import" statements
|
118
|
+
# in java code)
|
119
|
+
def runtime_required?(jar, jar_defined_packages)
|
120
|
+
log.debug "Determining if #{jar} is required at runtime"
|
121
|
+
log.debug "#{jar} contains:\n#{jar_defined_packages.join("\n")}"
|
122
|
+
|
123
|
+
result = jar_defined_packages.any? { |package| @runtime_required_packages.include?(package) }
|
124
|
+
|
125
|
+
log.debug "result is:#{result}"
|
126
|
+
|
127
|
+
return result
|
128
|
+
end
|
129
|
+
|
130
|
+
# returns packages defined in a jar file
|
131
|
+
def get_jar_defined_packages(jar)
|
132
|
+
result = []
|
133
|
+
begin
|
134
|
+
Zip::ZipFile.foreach(jar) do |entry|
|
135
|
+
if entry.name =~ /^(.+)\/.+?\.class$/
|
136
|
+
result << $1.gsub("/", ".")
|
137
|
+
end
|
138
|
+
end
|
139
|
+
rescue Zip::ZipError
|
140
|
+
log.info "#{jar} does not seem to be a valid jar archive, skipping"
|
141
|
+
rescue TypeError
|
142
|
+
log.info "#{jar} seems to be a valid jar archive but is corrupt, skipping"
|
143
|
+
end
|
144
|
+
|
145
|
+
return result.sort.uniq
|
146
|
+
end
|
118
147
|
end
|
119
148
|
end
|
data/lib/gjp/version.rb
CHANGED
data/spec/lib/jar_table_spec.rb
CHANGED
@@ -4,11 +4,11 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Gjp::JarTable do
|
6
6
|
let(:dir) { File.join("spec", "data", "ant-super-simple-code") }
|
7
|
-
let(:jar_table) { Gjp::JarTable.new(dir) }
|
7
|
+
let(:jar_table) { Gjp::JarTable.new(dir, true) }
|
8
8
|
|
9
|
-
describe "#
|
9
|
+
describe "#get_jars" do
|
10
10
|
it "finds jar paths in a directory" do
|
11
|
-
jar_table.
|
11
|
+
jar_table.get_jars(dir).should include(
|
12
12
|
File.join(dir, "dist", "antsimple-20130618.jar"),
|
13
13
|
File.join(dir, "lib", "junit-4.11.jar"),
|
14
14
|
File.join(dir, "lib", "log4j-1.2.13.jar")
|
@@ -16,9 +16,9 @@ describe Gjp::JarTable do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
describe "#
|
19
|
+
describe "#get_jar_defined_packages" do
|
20
20
|
it "finds the package names part of a jar file" do
|
21
|
-
jar_table.
|
21
|
+
jar_table.get_jar_defined_packages(File.join(dir, "lib", "junit-4.11.jar")).should include(
|
22
22
|
"junit.framework",
|
23
23
|
"junit.extensions",
|
24
24
|
"org.junit.runner",
|
@@ -27,16 +27,9 @@ describe Gjp::JarTable do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
describe "#runtime_required?" do
|
31
|
-
it "heuristically determines if a jar file is needed runtime" do
|
32
|
-
jar_table.runtime_required?(File.join(dir, "lib", "junit-4.11.jar")).should be_false
|
33
|
-
jar_table.runtime_required?(File.join(dir, "lib", "log4j-1.2.13.jar")).should be_true
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
30
|
describe "#sources" do
|
38
31
|
it "finds source paths in a directory" do
|
39
|
-
jar_table.
|
32
|
+
jar_table.get_sources(dir).should include(
|
40
33
|
File.join(dir, "src", "mypackage", "HW.java")
|
41
34
|
)
|
42
35
|
end
|
@@ -48,9 +41,9 @@ describe Gjp::JarTable do
|
|
48
41
|
end
|
49
42
|
end
|
50
43
|
|
51
|
-
describe "#
|
44
|
+
describe "#runtime_required_packages" do
|
52
45
|
it "finds the package names required by this project's sources" do
|
53
|
-
jar_table.
|
46
|
+
jar_table.runtime_required_packages.should include("org.apache.log4j")
|
54
47
|
end
|
55
48
|
end
|
56
49
|
|
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.10.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-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|