doubleshot 0.1.0-java → 0.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/Doubleshot +21 -10
  2. data/README.textile +13 -5
  3. data/bin/doubleshot +9 -1
  4. data/ext/java/Aether.java +199 -0
  5. data/ext/java/ManualWagonProvider.java +24 -0
  6. data/ext/java/SimpleRepositoryListener.java +77 -0
  7. data/lib/doubleshot.rb +155 -9
  8. data/lib/doubleshot/cli.rb +2 -1
  9. data/lib/doubleshot/cli/options.rb +3 -1
  10. data/lib/doubleshot/commands/build.rb +47 -9
  11. data/lib/doubleshot/commands/gem.rb +30 -9
  12. data/lib/doubleshot/commands/init.rb +41 -10
  13. data/lib/doubleshot/commands/install.rb +4 -4
  14. data/lib/doubleshot/commands/jar.rb +60 -2
  15. data/lib/doubleshot/commands/pom.rb +29 -0
  16. data/lib/doubleshot/commands/test.rb +85 -32
  17. data/lib/doubleshot/compiler.rb +20 -17
  18. data/lib/doubleshot/compiler/classpath.rb +46 -0
  19. data/lib/doubleshot/configuration.rb +158 -8
  20. data/lib/doubleshot/dependencies/dependency.rb +16 -15
  21. data/lib/doubleshot/dependencies/dependency_list.rb +20 -5
  22. data/lib/doubleshot/dependencies/gem_dependency.rb +35 -0
  23. data/lib/doubleshot/dependencies/gem_dependency_list.rb +1 -1
  24. data/lib/doubleshot/dependencies/jar_dependency.rb +64 -1
  25. data/lib/doubleshot/dependencies/jar_dependency_list.rb +1 -1
  26. data/lib/doubleshot/jar.rb +13 -2
  27. data/lib/doubleshot/lockfile.rb +108 -0
  28. data/lib/doubleshot/pom.rb +42 -0
  29. data/lib/doubleshot/readonly_collection.rb +6 -2
  30. data/lib/doubleshot/resolver.rb +22 -0
  31. data/lib/doubleshot/resolver/jar_resolver.rb +36 -0
  32. data/lib/doubleshot/setup.rb +1 -47
  33. data/lib/ruby/blank.rb +3 -3
  34. data/lib/ruby/pathname.rb +8 -4
  35. data/lib/ruby/time.rb +1 -2
  36. data/target/doubleshot.jar +0 -0
  37. data/test/compiler/classpath_spec.rb +74 -0
  38. data/test/compiler_spec.rb +89 -10
  39. data/test/configuration/source_locations_spec.rb +2 -2
  40. data/test/configuration_spec.rb +115 -17
  41. data/test/dependencies/dependency_list_spec.rb +26 -4
  42. data/test/dependencies/dependency_spec.rb +19 -18
  43. data/test/dependencies/gem_dependency_list_spec.rb +0 -0
  44. data/test/dependencies/gem_dependency_spec.rb +54 -0
  45. data/test/dependencies/jar_dependency_list_spec.rb +0 -0
  46. data/test/dependencies/jar_dependency_spec.rb +62 -1
  47. data/test/dependencies_spec.rb +4 -4
  48. data/test/doubleshot_spec.rb +34 -2
  49. data/test/helper.rb +36 -1
  50. data/test/lockfile_spec.rb +236 -0
  51. data/test/pom_spec.rb +66 -0
  52. data/test/readonly_collection_spec.rb +10 -3
  53. data/test/resolver/jar_resolver_spec.rb +34 -0
  54. data/test/resolver_spec.rb +25 -0
  55. metadata +28 -28
  56. data/ext/java/Empty.java +0 -0
@@ -3,6 +3,41 @@ require "doubleshot/dependencies/dependency"
3
3
  class Doubleshot
4
4
  class Dependencies
5
5
  class GemDependency < Dependency
6
+
7
+ def initialize(name)
8
+ super
9
+ @requirements = Set.new
10
+ end
11
+
12
+ def requirements
13
+ ReadonlyCollection.new(@requirements)
14
+ end
15
+
16
+ def add_requirement(requirement)
17
+ requirement = Gem::Requirement.new(requirement)
18
+ @requirements << requirement
19
+ requirement
20
+ end
21
+
22
+ def ==(other)
23
+ eql?(other) && requirements == other.requirements
24
+ end
25
+
26
+ def to_s(long_form = false)
27
+ if long_form && !@requirements.empty?
28
+ "#{name} (#{@requirements.sort.map(&:to_s).join(", ")})"
29
+ else
30
+ @name
31
+ end
32
+ end
33
+
34
+ # def gemspec
35
+ # end
36
+
37
+ # def dependencies
38
+ # #gemspec.runtime_dependencies
39
+ # end
40
+
6
41
  end
7
42
  end
8
43
  end
@@ -4,7 +4,7 @@ require "doubleshot/dependencies/gem_dependency"
4
4
  class Doubleshot
5
5
  class Dependencies
6
6
  class GemDependencyList < DependencyList
7
-
7
+ DEPENDENCY_CLASS = GemDependency
8
8
  end
9
9
  end
10
10
  end
@@ -3,6 +3,69 @@ require "doubleshot/dependencies/dependency"
3
3
  class Doubleshot
4
4
  class Dependencies
5
5
  class JarDependency < Dependency
6
+
7
+ PACKAGE_TYPES = [ "pom", "jar", "maven-plugin", "ejb", "war", "ear", "rar", "par", "bundle" ]
8
+
9
+ attr_reader :group, :artifact, :packaging, :classifier, :version, :path
10
+
11
+ def initialize(maven_coordinate)
12
+ # This is Maven's default package type, if unspecified.
13
+ @packaging = "jar"
14
+
15
+ maven_coordinate_parts = maven_coordinate.split(":")
16
+ @group = maven_coordinate_parts.shift
17
+ @artifact = maven_coordinate_parts.shift
18
+
19
+ if version = maven_coordinate_parts.pop
20
+ if !PACKAGE_TYPES.include?(version)
21
+ self.version = version
22
+ else
23
+ raise ArgumentError.new("Expected last coordinate part to be a Version but was a Package Type: #{maven_coordinate}")
24
+ end
25
+ end
26
+
27
+ if packaging = maven_coordinate_parts.shift
28
+ self.packaging = packaging
29
+ end
30
+
31
+ if classifier = maven_coordinate_parts.shift
32
+ @classifier = classifier
33
+ end
34
+
35
+ @name = "#{@group}:#{@artifact}:#{@packaging}#{":#{@classifier}" if @classifier}:#{@version}"
36
+
37
+ if [ @group, @artifact, @packaging, @version ].any? &:blank?
38
+ raise ArgumentError.new("Invalid coordinate: #{@name}")
39
+ end
40
+ end
41
+
42
+ def to_s(long_form = false)
43
+ @name
44
+ end
45
+
46
+ def path=(path)
47
+ @path = Pathname(path.to_s)
48
+ end
49
+
50
+ private
51
+
52
+ def packaging=(value = "jar")
53
+ if PACKAGE_TYPES.include?(value.downcase)
54
+ @packaging = value.downcase
55
+ else
56
+ raise ArgumentError.new("Invalid Packaging Type: #{value.inspect}")
57
+ end
58
+ end
59
+
60
+ def version=(value)
61
+ if !value.blank?
62
+ @version = value
63
+ else
64
+ raise ArgumentError.new("Version must not be blank")
65
+ end
66
+ # compare version against rules specified here: http://www.sonatype.com/books/mvnref-book/reference/pom-relationships-sect-pom-syntax.html#pom-relationships-sect-version-build-numbers
67
+ # http://stackoverflow.com/questions/30571/how-do-i-tell-maven-to-use-the-latest-version-of-a-dependency
68
+ end
6
69
  end
7
70
  end
8
- end
71
+ end
@@ -4,7 +4,7 @@ require "doubleshot/dependencies/jar_dependency"
4
4
  class Doubleshot
5
5
  class Dependencies
6
6
  class JarDependencyList < DependencyList
7
-
7
+ DEPENDENCY_CLASS = JarDependency
8
8
  end
9
9
  end
10
10
  end
@@ -37,7 +37,14 @@ target = Pathname "target"
37
37
 
38
38
  target.mkdir unless target.exist?
39
39
 
40
- ant.path id: "classpath" do
40
+ ant.path id: "classpath" do
41
+ fileset dir: "target"
42
+ ["ext/java"].each do |jar|
43
+ fileset dir: Pathname(jar).dirname
44
+ end
45
+ end
46
+
47
+ ant.path id: "classpath" do
41
48
  fileset dir: target.to_s
42
49
  JBUNDLER_CLASSPATH.each do |jar|
43
50
  fileset dir: Pathname(jar).dirname
@@ -48,4 +55,8 @@ ant.javac srcdir: source.to_s, destdir: target.to_s, debug: "yes", includeantrun
48
55
 
49
56
  $CLASSPATH << target.to_s
50
57
 
51
- ant.jar jarfile: "example.jar", basedir: target.to_s
58
+ ant.jar jarfile: "example.jar", basedir: target.to_s do
59
+ @config.runtime.jars.each do |jar|
60
+ ant.zipgroupfileset dir: jar.path.dirname, includes: jar.path.to_s
61
+ end
62
+ end
@@ -0,0 +1,108 @@
1
+ class Doubleshot
2
+ class Lockfile
3
+
4
+ class UnlockedDependencyError < StandardError
5
+ def initialize(dependency)
6
+ super "Dependency #{dependency.to_s.inspect} is unlocked!"
7
+ end
8
+ end
9
+
10
+ class UnknownDependencyTypeError < NotImplementedError
11
+ def initialize(dependency)
12
+ super "Handling for this dependency is not implemented: #{dependency.inspect}"
13
+ end
14
+ end
15
+
16
+ attr_reader :path
17
+
18
+ def initialize(path = "Doubleshot.lock")
19
+ @path = Pathname(path.to_s)
20
+ @gems = Dependencies::GemDependencyList.new
21
+ @jars = Dependencies::JarDependencyList.new
22
+ end
23
+
24
+ def delete
25
+ @path.delete
26
+ end
27
+
28
+ def exist?
29
+ @path.exist?
30
+ end
31
+
32
+ def mtime
33
+ @path.mtime
34
+ end
35
+
36
+ def gems
37
+ load
38
+ ReadonlyCollection.new @gems
39
+ end
40
+
41
+ def jars
42
+ load
43
+ ReadonlyCollection.new @jars
44
+ end
45
+
46
+ def empty?
47
+ @gems.empty? && @jars.empty?
48
+ end
49
+
50
+ def add(dependency)
51
+ if dependency.class == Dependencies::Dependency
52
+ raise ArgumentError.new("+dependency+ must be a concrete type (JarDependency or GemDependency).")
53
+ elsif dependency.class < Dependencies::Dependency
54
+ if dependency.locked?
55
+ case dependency
56
+ when Dependencies::JarDependency then @jars.add(dependency)
57
+ when Dependencies::GemDependency then @gems.add(dependency)
58
+ else raise UnknownDependencyTypeError.new(dependency)
59
+ end
60
+ else
61
+ raise UnlockedDependencyError.new(dependency)
62
+ end
63
+ else
64
+ raise ArgumentError.new("+dependency+ must be a type of Doubleshot::Dependencies::Dependency.")
65
+ end
66
+
67
+ self
68
+ end
69
+
70
+ def load
71
+ unless @loaded
72
+ (data["JARS"] || []).each do |buildr_string|
73
+ @jars.add Dependencies::JarDependency.new(buildr_string)
74
+ end
75
+
76
+ # TODO: add gems to this method
77
+ # (data["GEMS"] || []).each do |gem_string|
78
+ # @gems.add Dependencies::GemDependency.new(gem_string)
79
+ # end
80
+ end
81
+
82
+ @loaded = true
83
+ end
84
+
85
+ def flush!
86
+ output = { "JARS" => [], "GEMS" => [] }
87
+
88
+ jars.each do |jar|
89
+ output["JARS"] << jar.to_s(true)
90
+ end
91
+
92
+ gems.each do |gem|
93
+ output["GEMS"] << gem.to_s(true)
94
+ end
95
+
96
+ @path.open("w+") do |file|
97
+ file << output.to_yaml
98
+ end
99
+ end
100
+
101
+ private
102
+
103
+ def data
104
+ @data ||= (@path.exist? ? YAML.load(@path.read) : {})
105
+ end
106
+
107
+ end # class Lockfile
108
+ end # class Doubleshot
@@ -0,0 +1,42 @@
1
+ class Doubleshot
2
+ class Pom
3
+ def initialize(config)
4
+ @config = config
5
+ end
6
+
7
+ def to_s
8
+ jars = @config.runtime.jars + @config.development.jars
9
+
10
+ <<-EOS.margin
11
+ <?xml version="1.0"?>
12
+ <project xmlns="http://maven.apache.org/POM/4.0.0"
13
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
14
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
15
+ <modelVersion>4.0.0</modelVersion>
16
+ <groupId>#{@config.group}</groupId>
17
+ <artifactId>#{@config.project}</artifactId>
18
+ <version>#{@config.version}</version>
19
+ <packaging>pom</packaging>
20
+ <name>#{@config.project}</name>
21
+ #{
22
+ unless jars.empty?
23
+ "<dependencies>\n " +
24
+ jars.map do |jar|
25
+ <<-JAR.strip
26
+ <dependency>
27
+ <groupId>#{jar.group}</groupId>
28
+ <artifactId>#{jar.artifact}</artifactId>
29
+ <type>#{jar.packaging}</type>
30
+ #{
31
+ "<classifier>#{jar.classifier}</classifier>" unless jar.classifier.blank?
32
+ }<version>#{jar.version}</version>
33
+ </dependency>
34
+ JAR
35
+ end.join("\n ") +
36
+ "\n </dependencies>\n"
37
+ end
38
+ } </project>
39
+ EOS
40
+ end
41
+ end
42
+ end
@@ -22,11 +22,15 @@ class Doubleshot
22
22
  def empty?
23
23
  entries.empty?
24
24
  end
25
-
25
+
26
26
  def eql?(other)
27
27
  other.is_a?(self.class) && entries == other.entries
28
28
  end
29
29
  alias :== :eql?
30
+
31
+ def +(other)
32
+ ReadonlyCollection.new(entries + other.entries)
33
+ end
30
34
  end
31
35
 
32
- end
36
+ end
@@ -0,0 +1,22 @@
1
+ require "uri"
2
+
3
+ class Doubleshot
4
+ class Resolver
5
+ def initialize(*repositories)
6
+ @repositories = repositories.map do |repository|
7
+ URI.parse repository.to_s
8
+ end
9
+ raise ArgumentError.new("no repositories specified") if @repositories.empty?
10
+ end
11
+
12
+ def fetch(dependencies)
13
+ raise NotImplementedError.new
14
+ end
15
+
16
+ def repositories
17
+ ReadonlyCollection.new(@repositories)
18
+ end
19
+ end
20
+ end
21
+
22
+ require "doubleshot/resolver/jar_resolver"
@@ -0,0 +1,36 @@
1
+ java_import "org.sam.doubleshot.Aether"
2
+
3
+ class Doubleshot
4
+ class Resolver
5
+ class JarResolver < Resolver
6
+ DEFAULT_REPOSITORY = "http://repo1.maven.org/maven2"
7
+
8
+ def initialize(*repositories)
9
+ super
10
+ # Change the second argument to "true" to get verbose output.
11
+ @aether = Aether.new(Pathname("~/.m2").expand_path.to_s, false, false)
12
+ @repositories.each do |repository|
13
+ @aether.add_repository repository.host, repository.to_s
14
+ end
15
+ end
16
+
17
+ def resolve!(dependencies)
18
+ dependencies.each do |dependency|
19
+ @aether.add_artifact dependency.to_s
20
+ end
21
+
22
+ @aether.resolve
23
+ classpath_map = @aether.classpath_map
24
+
25
+ @aether.resolved_coordinates.each do |coordinate|
26
+ dependencies.add Dependencies::JarDependency.new coordinate
27
+ end
28
+
29
+ dependencies.each do |dependency|
30
+ dependency.path = classpath_map[dependency.to_s]
31
+ end
32
+ dependencies
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,49 +1,3 @@
1
1
  require_relative "../doubleshot"
2
2
 
3
- gemfile = Pathname "Gemfile"
4
- gemfile_lock = Pathname "Gemfile.lock"
5
-
6
- install_gems = -> do
7
- require "bundler"
8
- require "bundler/cli"
9
- Bundler::CLI.new.install
10
- end
11
-
12
- if gemfile.exist?
13
- begin
14
- install_gems.call if !gemfile_lock.exist? || gemfile.mtime > gemfile_lock.mtime
15
- require "bundler/setup"
16
- end
17
- end
18
-
19
- install_jars = -> do
20
- require "jbundler/cli"
21
- JBundler::Cli.new.install
22
- end
23
-
24
- jarfile = Pathname "Jarfile"
25
- jarfile_lock = Pathname "Jarfile.lock"
26
-
27
- if jarfile.exist?
28
- require "bundler" unless Object::const_defined?("Bundler")
29
- require "jbundler"
30
- install_jars.call if !jarfile_lock.exist? || jarfile.mtime > jarfile_lock.mtime
31
- end
32
-
33
- require "ant"
34
-
35
- source = Pathname "ext/java"
36
- target = Pathname "target"
37
-
38
- target.mkdir unless target.exist?
39
-
40
- ant.path id: "classpath" do
41
- fileset dir: target.to_s
42
- JBUNDLER_CLASSPATH.each do |jar|
43
- fileset dir: Pathname(jar).dirname
44
- end
45
- end
46
-
47
- ant.javac srcdir: source.to_s, destdir: target.to_s, debug: "yes", includeantruntime: "no", classpathref: "classpath"
48
-
49
- $CLASSPATH << target.to_s
3
+ Doubleshot::current.setup!
data/lib/ruby/blank.rb CHANGED
@@ -9,10 +9,10 @@
9
9
  # distribute, sublicense, and/or sell copies of the Software, and to
10
10
  # permit persons to whom the Software is furnished to do so, subject to
11
11
  # the following conditions:
12
- #
12
+ #
13
13
  # The above copyright notice and this permission notice shall be
14
14
  # included in all copies or substantial portions of the Software.
15
- #
15
+ #
16
16
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
17
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
18
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -129,4 +129,4 @@ class Numeric #:nodoc:
129
129
  def blank?
130
130
  false
131
131
  end
132
- end
132
+ end