Class: Doubleshot

Inherits:
Object show all
Defined in:
lib/doubleshot.rb,
lib/doubleshot/cli.rb,
lib/doubleshot/pom.rb,
lib/doubleshot/compiler.rb,
lib/doubleshot/lockfile.rb,
lib/doubleshot/resolver.rb,
lib/doubleshot/cli/options.rb,
lib/doubleshot/dependencies.rb,
lib/doubleshot/configuration.rb,
lib/doubleshot/compiler/classpath.rb,
lib/doubleshot/readonly_collection.rb,
lib/doubleshot/resolver/gem_resolver.rb,
lib/doubleshot/resolver/jar_resolver.rb,
lib/doubleshot/dependencies/dependency.rb,
lib/doubleshot/dependencies/gem_dependency.rb,
lib/doubleshot/dependencies/jar_dependency.rb,
lib/doubleshot/resolver/gem_resolver/graph.rb,
lib/doubleshot/dependencies/dependency_list.rb,
lib/doubleshot/resolver/gem_resolver/demand.rb,
lib/doubleshot/resolver/gem_resolver/errors.rb,
lib/doubleshot/resolver/gem_resolver/solver.rb,
lib/doubleshot/resolver/gem_resolver/source.rb,
lib/doubleshot/configuration/source_locations.rb,
lib/doubleshot/resolver/gem_resolver/artifact.rb,
lib/doubleshot/dependencies/gem_dependency_list.rb,
lib/doubleshot/dependencies/jar_dependency_list.rb,
lib/doubleshot/resolver/gem_resolver/dependency.rb,
lib/doubleshot/resolver/gem_resolver/gem_source.rb,
lib/doubleshot/resolver/gem_resolver/solver/variable_row.rb,
lib/doubleshot/resolver/gem_resolver/solver/constraint_row.rb,
lib/doubleshot/resolver/gem_resolver/solver/variable_table.rb,
lib/doubleshot/resolver/gem_resolver/solver/constraint_table.rb

Defined Under Namespace

Classes: CLI, Compiler, Configuration, Dependencies, Lockfile, Pom, ReadonlyCollection, Resolver

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize {|@config| ... } ⇒ Doubleshot

Returns a new instance of Doubleshot.

Yields:



30
31
32
33
34
35
# File 'lib/doubleshot.rb', line 30

def initialize
  @classpath = Set.new
  @config = Doubleshot::Configuration.new
  @lockfile = Doubleshot::Lockfile.new
  yield @config if block_given?
end

Instance Attribute Details

#classpathObject (readonly)

Returns the value of attribute classpath.



28
29
30
# File 'lib/doubleshot.rb', line 28

def classpath
  @classpath
end

#configObject (readonly)

Returns the value of attribute config.



26
27
28
# File 'lib/doubleshot.rb', line 26

def config
  @config
end

#lockfileObject (readonly)

Returns the value of attribute lockfile.



27
28
29
# File 'lib/doubleshot.rb', line 27

def lockfile
  @lockfile
end

#pathObject

Returns the value of attribute path.



25
26
27
# File 'lib/doubleshot.rb', line 25

def path
  @path
end

Class Method Details

.currentObject



41
42
43
# File 'lib/doubleshot.rb', line 41

def self.current
  @current ||= load
end

.load(path = "Doubleshot") ⇒ Object



45
46
47
48
49
50
# File 'lib/doubleshot.rb', line 45

def self.load(path = "Doubleshot")
  path = Pathname(path)
  doubleshot = eval(path.read)
  doubleshot.path = path
  doubleshot
end

Instance Method Details

#bootstrap!Object



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/doubleshot.rb', line 240

def bootstrap!
  if !@config.target.exist? || !lockfile.exist? || !classpath_cache.exist? || Pathname("pom.xml").mtime > classpath_cache.mtime
    # Dependencies classpath:
    paths = `mvn dependency:build-classpath`.split(/\bDependencies classpath\b/).last.split($/).grep(/\.jar\b/).map { |line| line.split(":") }.flatten
    coordinates = `mvn dependency:list`.split(/\bfiles have been resolved\b/).last.split($/).grep(/\bcompile$/).map do |line|
      line.split.last.sub /\:compile$/, ""
    end

    resolved = Hash[*coordinates.zip(paths).flatten]

    resolved.each_pair do |coordinate, path|
      require path
      self.classpath << path
      jar = Dependencies::JarDependency.new(coordinate)
      jar.path = path
      lockfile.add jar
      # puts "Added coordinate: #{coordinate.inspect} as #{jar.to_s.inspect}"
    end

    lockfile.flush!

    classpath_cache.open("w+") do |file|
      file << resolved.to_yaml
    end
  else
    # TODO: This is problematic since Maven and Aether resolve different dependencies...
    setup!
  end
  
  self
end

#build!(conditional = true) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/doubleshot.rb', line 95

def build!(conditional = true)
  if !conditional && @config.target.exist?
    @config.target.rmtree
  end

  return unless @config.source.java.exist?

  compiler = Doubleshot::Compiler.new(@config.source.java, @config.target)

  lockfile.jars.each do |jar|
    compiler.classpath << jar.path
  end

  if !conditional || compiler.pending?
    puts "Compiling..."
    compiler.build! true
  else
    puts "Conditional build: No source changes."
  end
  
  self
end

#build_gemspecObject



37
38
39
# File 'lib/doubleshot.rb', line 37

def build_gemspec
  @config.gemspec.to_ruby
end

#classpath_cacheObject

def load_jars!



236
237
238
# File 'lib/doubleshot.rb', line 236

def classpath_cache
  @classpath_cache ||= Pathname(".classpath.cache")
end

#load_gems!Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/doubleshot.rb', line 118

def load_gems!
  if lockfile.gems.empty?
    dependencies = @config.runtime.gems + @config.development.gems

    puts "Dependencies not locked. Resolving the following:"
    dependencies.each do |dependency|
      puts "  #{dependency.name}: #{dependency.requirements.map(&:to_s).join(", ")}"
    end

    unless dependencies.empty?
      resolver = Resolver::GemResolver.new *@config.gem_repositories
      puts "Using repositories: #{@config.gem_repositories.map(&:to_s).join(",")}"

      resolver.resolve! dependencies

      puts "Resolved dependencies:"
      dependencies.each do |dependency|
        puts "  #{dependency.name}: #{dependency.version}"
      end

      require "rubygems/dependency_installer"
      Gem::sources = @config.gem_repositories.entries
      installer = Gem::DependencyInstaller.new domain: :both
      dependencies.each do |dependency|
        begin
          puts "Activating: #{dependency.name} #{dependency.version}"
          gem dependency.name, dependency.version
        rescue LoadError
          puts "Gem not installed! Installing: #{dependency.name} #{dependency.version}"
          installer.install dependency.name, dependency.version
          gem dependency.name, dependency.version
        end
        lockfile.add dependency
      end

      dependencies.each { |dependency| lockfile.add dependency }
      lockfile.flush!
    end
  else
    missing_dependencies = []
    lockfile.gems.each do |dependency|
      begin
        gem dependency.name, dependency.version
      rescue LoadError
        missing_dependencies << dependency
      end
    end

    unless missing_dependencies.empty?
      # TODO: Figure out how to use #gem_repositories here
      require "rubygems/dependency_installer"
      Gem::sources = @config.gem_repositories.entries
      installer = Gem::DependencyInstaller.new domain: :both

      missing_dependencies.each do |dependency|
        installer.install dependency.name, dependency.version
        gem dependency.name, dependency.version
      end
    end
  end
end

#load_jars!Object



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/doubleshot.rb', line 180

def load_jars!
  if classpath_cache.exist?
    # We survived the cleanup checks, go ahead and just load
    # the cached version of your JARs.
    cached_paths = YAML::load(classpath_cache)

    lockfile.jars.each do |jar|
      jar.path = cached_paths[jar.to_s]
      begin
        require jar.path
        self.classpath << jar.path
      rescue LoadError
        warn "Could not load: #{jar.to_s.inspect}"
        raise
      end
    end
  else
    # No classpath_cache exists, we must resolve the paths
    # to our dependencies, then store the results in
    # classpath_cache for future processes to use.
    jars = @config.runtime.jars + @config.development.jars
    unless jars.empty?

      resolver = Resolver::JarResolver.new(*@config.mvn_repositories)

      if lockfile.exist? && !lockfile.jars.empty?
        jars = Dependencies::JarDependencyList.new
        lockfile.jars.each do |jar|
          jars.add jar
        end
      end

      resolver.resolve! jars

      jars.each { |jar| lockfile.add jar }
      lockfile.flush!

      cache = {}
      jars.each do |jar|
        cache[jar.to_s] = jar.path.to_s
        begin
          require jar.path
          self.classpath << jar.path
        rescue LoadError
          warn "Could not load: #{jar.to_s.inspect}"
          raise
        end
      end

      classpath_cache.open("w+") do |file|
        file << cache.to_yaml
      end
    end # unless jars.empty?
  end # if classpath_cache.exist?
end

#setup!Object

This modifies the current environment. Do not run this unless you really know what you’re doing (modifying global shared state). The recommended way to call this, and ensure it’s only called once for your current configuration, is to:

require "doubleshot/setup"


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/doubleshot.rb', line 58

def setup!
  # This will add your compiled sources to $CLASSPATH so
  # you can reference your Java classes in Ruby.
  $CLASSPATH << @config.target.to_url if @config.target.exist?

  # BEGIN: Cleanup tasks
  #
  # Delete +lockfile+ and +classpath_file+ if the
  # Doubleshot file has been modified since they were written.
  #
  # SCENARIO: You will run into this if you've added a new dependency
  # (or made any other change) to your Doubleshot configuration file.
  if path && path.exist? && lockfile.exist? && path.mtime > lockfile.mtime
    lockfile.delete
    classpath_cache.delete if classpath_cache.exist?
  end

  # If the above is not true, your Doubleshot file hasn't
  # been modified, but you may have updated the +lockfile+,
  # in which case we need to check if the classpath_cache is
  # still current, or needs to be flushed.
  #
  # SCENARIO: You will typically run into this if you've cloned
  # a Doubleshotted project, where the Doubleshot file and Lockfile
  # have been committed to the repository, but you have not ever
  # started the project on your local machine.
  if lockfile.exist? && classpath_cache.exist? && lockfile.mtime > classpath_cache.mtime
    classpath_cache.delete
  end
  # END: Cleanup tasks

  load_gems! unless @config.runtime.gems.empty? && @config.development.gems.empty?
  load_jars! unless @config.runtime.jars.empty? && @config.development.jars.empty?
  
  self
end