Author: assaf
Date: Wed Jan 30 21:54:24 2008
New Revision: 617010

URL: http://svn.apache.org/viewvc?rev=617010&view=rev
Log:
Added missing specs, documentation for Javac/Scalac

Added:
    incubator/buildr/trunk/spec/java_compilers_spec.rb
      - copied, changed from r616185, 
incubator/buildr/trunk/spec/java_compilers.rb
    incubator/buildr/trunk/spec/java_test_frameworks_spec.rb
      - copied unchanged from r616131, 
incubator/buildr/trunk/spec/java_test_frameworks.rb
    incubator/buildr/trunk/spec/scala_compilers_spec.rb
      - copied, changed from r616131, 
incubator/buildr/trunk/spec/scala_compilers.rb
Removed:
    incubator/buildr/trunk/spec/java_compilers.rb
    incubator/buildr/trunk/spec/java_test_frameworks.rb
    incubator/buildr/trunk/spec/scala_compilers.rb
Modified:
    incubator/buildr/trunk/CHANGELOG
    incubator/buildr/trunk/doc/pages/building.textile
    incubator/buildr/trunk/lib/core/application.rb
    incubator/buildr/trunk/lib/core/compile.rb
    incubator/buildr/trunk/lib/core/project.rb
    incubator/buildr/trunk/lib/java/compilers.rb
    incubator/buildr/trunk/spec/compile_spec.rb

Modified: incubator/buildr/trunk/CHANGELOG
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/CHANGELOG?rev=617010&r1=617009&r2=617010&view=diff
==============================================================================
--- incubator/buildr/trunk/CHANGELOG (original)
+++ incubator/buildr/trunk/CHANGELOG Wed Jan 30 21:54:24 2008
@@ -24,7 +24,7 @@
 * Fixed: Error when downloading a file from a server which answers with a 
response with no content length.
 
 1.2.10 (2007-11-26)
-* Changed: Resources sets permission on copied files to make them 
read/write-able.
+* Changed: Resources sets permission on copied files to make them 
read/write-able (Shane Witbeck).
 * Changed: Artifact download no longer generates destination directory if not 
downloaded (Antoine).
 * Fixed: EOL in MANIFEST.MF.
 * Fixed: Bunch of typos, courtesy of Merlyn Albery-Speyer and Soemirno 
Kartosoewito.

Modified: incubator/buildr/trunk/doc/pages/building.textile
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/doc/pages/building.textile?rev=617010&r1=617009&r2=617010&view=diff
==============================================================================
--- incubator/buildr/trunk/doc/pages/building.textile (original)
+++ incubator/buildr/trunk/doc/pages/building.textile Wed Jan 30 21:54:24 2008
@@ -186,6 +186,71 @@
 }}}
 
 
+h3. Java
+
+The Java compiler looks for source files in the project's @src/main/java@
+directory, and defaults to compiling them into the @target/classes@ directory.
+It looks for test cases in the project's @src/test/java@ and defaults to
+compile them into the @target/test/classes@ directory.
+
+If you point the @compile@ task at any other source directory, it will use the
+Java compiler if any of these directories contains files with the extension
[EMAIL PROTECTED]@.
+
+When using the Java compiler, if you don't specify the packaging type, it
+defaults to JAR.  If you don't specify the test framework, it defaults to
+JUnit.
+
+The Java compiler supports the following options:
+
+* @:debug@ -- Generates bytecode with debugging information.  You can also
+override this by setting the environment variable @debug@ to @[EMAIL PROTECTED]
+* @:deprecation@ -- If true, shows deprecation messages.  False by default.
+* @:lint@ -- Defaults to false.  Set this option to true to use all lint
+options, or specify a specific lint option (e.g. @:lint=>'cast'@).
+* @:other@ -- Array of options passed to the compiler (e.g.
+@:other=>'-implicit:none'@).
+* @:source@ -- Source code compatibility (e.g. '1.5').
+* @:target@ -- Bytecode compatibility (e.g. '1.4').
+* @:warnings@ -- Issue warnings when compiling.  True when running in verbose
+mode.
+
+
+h3. Scala
+
+Before using the Scala compiler, you must first set the environment variable
[EMAIL PROTECTED]@.
+
+The Scala compiler looks for source files in the project's @src/main/scala@
+directory, and defaults to compiling them into the @target/classes@ directory.
+It looks for test cases in the project's @src/test/scala@ and defaults to
+compile them into the @target/test/classes@ directory.
+
+If you point the @compile@ task at any other source directory, it will use the
+Scala compiler if any of these directories contains files with the extension
[EMAIL PROTECTED]@.
+
+When using the Scala compiler, if you don't specify the packaging type, it
+defaults to JAR.
+
+The Scala compiler supports the following options:
+
+* @:debug@ -- Generates bytecode with debugging information.  You can also
+override this by setting the environment variable @debug@ to @[EMAIL PROTECTED]
+* @:deprecation@ -- If true, shows deprecation messages.  False by default.
+* @:optimise@ -- Generates faster bytecode by applying optimisations to the 
program.
+* @:other@ -- Array of options passed to the compiler (e.g.
+@:other=>'-Xprint-types'@).
+* @:source@ -- Source code compatibility (e.g. '1.5').
+* @:target@ -- Bytecode compatibility (e.g. '1.4').
+* @:warnings@ -- Issue warnings when compiling.  True when running in verbose
+mode.
+
+By default Buildr uses FSC, the Fast Offline Compiler.  You can switch to use
+the Scala native compiler by setting the environment variable @USE_FSC@ to
[EMAIL PROTECTED]@.
+
+
 h2. Resources
 
 The @compile@ task comes bundled with a @resources@ task.  It copies files from

Modified: incubator/buildr/trunk/lib/core/application.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/core/application.rb?rev=617010&r1=617009&r2=617010&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/core/application.rb (original)
+++ incubator/buildr/trunk/lib/core/application.rb Wed Jan 30 21:54:24 2008
@@ -58,7 +58,7 @@
           real << ("%ih" % (times.real / 3600)) if times.real >= 3600
           real << ("%im" % ((times.real / 60) % 60)) if times.real >= 60
           real << ("%.3fs" % (times.real % 60))
-          puts "Completed in #{real.join} seconds"
+          puts "Completed in #{real.join}"
         end
       end
 

Modified: incubator/buildr/trunk/lib/core/compile.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/core/compile.rb?rev=617010&r1=617009&r2=617010&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/core/compile.rb (original)
+++ incubator/buildr/trunk/lib/core/compile.rb Wed Jan 30 21:54:24 2008
@@ -88,7 +88,8 @@
 
       # Construct a new compiler with the specified options.  Note that 
options may
       # change before the compiler is run.
-      def initialize(options)
+      def initialize(project, options)
+        @project = project
         @options = options
       end
 
@@ -329,7 +330,7 @@
       cls = Compiler.select(name) or raise ArgumentError, "No #{name} compiler 
available. Did you install it?"
       return self if cls === @compiler
       raise "#{compiler} compiler already selected for this project" if 
@compiler
-      @compiler = cls.new(options)
+      @compiler = cls.new(project, options)
       from Array(cls.sources).map { |path| @project.path_to(:source, @usage, 
path) }.
         select { |path| File.exist?(path) } if sources.empty?
       into @project.path_to(:target, @usage, cls.target) unless target

Modified: incubator/buildr/trunk/lib/core/project.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/core/project.rb?rev=617010&r1=617009&r2=617010&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/core/project.rb (original)
+++ incubator/buildr/trunk/lib/core/project.rb Wed Jan 30 21:54:24 2008
@@ -641,6 +641,10 @@
       methods.each { |method| method.call(project) }
     end
 
+    def add_callback(callback)
+      @callbacks[:after_define] << callback.method(:after_define) if 
callback.respond_to?(:after_define)
+    end
+
   end
 
 
@@ -730,9 +734,9 @@
       def extended(base) #:nodoc:
         # When extending project, add instance and call before_define.
         if Project === base
-          callbacks = self.callbacks.new
-          callbacks.before_define if callbacks.respond_to?(:before_define)
-          base.callbacks << callbacks
+          callbacks = self.send(:callbacks).new
+          callbacks.before_define(base) if 
callbacks.respond_to?(:before_define)
+          base.send :add_callback, callbacks
         end
       end
 

Modified: incubator/buildr/trunk/lib/java/compilers.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/java/compilers.rb?rev=617010&r1=617009&r2=617010&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/java/compilers.rb (original)
+++ incubator/buildr/trunk/lib/java/compilers.rb Wed Jan 30 21:54:24 2008
@@ -27,7 +27,7 @@
 
       specify :language=>:java, :target=>'classes', :target_ext=>'class', 
:packaging=>:jar
 
-      def initialize(options) #:nodoc:
+      def initialize(project, options) #:nodoc:
         super
         options[:debug] = Buildr.options.debug if options[:debug].nil?
         options[:warnings] = verbose if options[:warnings].nil?
@@ -38,8 +38,8 @@
       def compile(sources, target, dependencies) #:nodoc:
         check_options options, OPTIONS
         cmd_args = []
-        #tools = File.expand_path('lib/tools.jar', ENV['JAVA_HOME']) if 
ENV['JAVA_HOME']
-        #dependencies << tools if tools && File.exist?(tools)
+        tools = File.expand_path('lib/tools.jar', ENV['JAVA_HOME']) if 
ENV['JAVA_HOME']
+        dependencies << tools if tools && File.exist?(tools)
         cmd_args << '-cp' << dependencies.join(File::PATH_SEPARATOR) unless 
dependencies.empty?
         source_paths = sources.select { |source| File.directory?(source) }
         cmd_args << '-sourcepath' << source_paths.join(File::PATH_SEPARATOR) 
unless source_paths.empty?
@@ -108,7 +108,7 @@
 
       specify :language=>:scala, :target=>'classes', :target_ext=>'class', 
:packaging=>:jar
 
-      def initialize(options) #:nodoc:
+      def initialize(project, options) #:nodoc:
         super
         options[:debug] = Buildr.options.debug if options[:debug].nil?
         options[:warnings] = verbose if options[:warnings].nil?
@@ -210,7 +210,7 @@
       # Includes additional source files and directories when generating the 
documentation
       # and returns self. When specifying a directory, includes all .java 
files in that directory.
       def include(*files)
-        @files.include *files
+        @files.include *files.flatten.compact
         self
       end
 

Modified: incubator/buildr/trunk/spec/compile_spec.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/spec/compile_spec.rb?rev=617010&r1=617009&r2=617010&view=diff
==============================================================================
--- incubator/buildr/trunk/spec/compile_spec.rb (original)
+++ incubator/buildr/trunk/spec/compile_spec.rb Wed Jan 30 21:54:24 2008
@@ -513,137 +513,3 @@
 
   it 'should use current profile for filtering'
 end
-
-
-describe Project, '#javadoc' do
-  before { @task_name = 'javadoc' }
-  it_should_behave_like 'accessor task'
-
-  def sources
-    @sources ||= (1..3).map { |i| "Test#{i}" }.
-      each { |name| write "src/main/java/foo/#{name}.java", "package foo; 
public class #{name}{}" }.
-      map { |name| "src/main/java/foo/#{name}.java" }
-  end
-
-  it 'should set target directory to target/javadoc' do
-    define('foo').javadoc.target.to_s.should point_to_path('target/javadoc')
-  end
-
-  it 'should create file task for target directory' do
-    define('foo')
-    project('foo').javadoc.should_receive(:invoke_prerequisites)
-    project('foo').file('target/javadoc').invoke
-  end
-
-  it 'should respond to into() and return self' do
-    task = nil
-    define('foo') { task = javadoc.into('docs') }
-    task.should be(project('foo').javadoc)
-  end
-
-  it 'should respond to into() and change target directory' do
-    define('foo') { javadoc.into('docs') }
-    project('foo').javadoc.should_receive(:invoke_prerequisites)
-    file('docs').invoke
-  end
-
-  it 'should respond to from() and return self' do
-    task = nil
-    define('foo') { task = javadoc.from('srcs') }
-    task.should be(project('foo').javadoc)
-  end
-
-  it 'should respond to from() and add sources' do
-    define('foo') { javadoc.from 'srcs' }
-    project('foo').javadoc.source_files.should include('srcs')
-  end
-
-  it 'should respond to from() and add file task' do
-    define('foo') { javadoc.from file('srcs') }
-    project('foo').javadoc.source_files.first.should point_to_path('srcs')
-  end
-
-  it 'should respond to from() and add project\'s sources and dependencies' do
-    write 'bar/src/main/java/Test.java'
-    define 'foo' do
-      define('bar') { compile.with 'group:id:jar:1.0' }
-      javadoc.from project('foo:bar')
-    end
-    project('foo').javadoc.source_files.first.should 
point_to_path('bar/src/main/java/Test.java')
-    project('foo').javadoc.classpath.map(&:to_spec).should 
include('group:id:jar:1.0')
-  end
-
-  it 'should generate javadocs from project' do
-    sources
-    define 'foo'
-    project('foo').javadoc.source_files.sort.should == sources.sort.map { |f| 
File.expand_path(f) }
-  end
-
-  it 'should include compile dependencies' do
-    define('foo') { compile.with 'group:id:jar:1.0' }
-    project('foo').javadoc.classpath.map(&:to_spec).should 
include('group:id:jar:1.0')
-  end
-
-  it 'should respond to include() and return self' do
-    define('foo') { javadoc.include('srcs').should be(javadoc) }
-  end
-
-  it 'should respond to include() and add files' do
-    define('foo').javadoc.include sources.first
-    project('foo').javadoc.source_files.sort.should == [sources.first]
-  end
-
-  it 'should respond to exclude() and return self' do
-    define('foo') { javadoc.exclude('srcs').should be(javadoc) }
-  end
-
-  it 'should respond to exclude() and ignore files' do
-    sources
-    define('foo').javadoc.exclude sources.first
-    project('foo').javadoc.source_files.sort.should == sources[1..-1].map { 
|f| File.expand_path(f) }
-  end
-
-  it 'should respond to using() and return self' do
-    define('foo') { javadoc.using(:windowtitle=>'Fooing').should be(javadoc) }
-  end
-
-  it 'should respond to using() and accept options' do
-    define('foo') { javadoc.using :windowtitle=>'Fooing' }
-    project('foo').javadoc.options[:windowtitle].should eql('Fooing')
-  end
-
-  it 'should pick -windowtitle from project name' do
-    define('foo') { define 'bar' }
-    project('foo').javadoc.options[:windowtitle].should eql('foo')
-    project('foo:bar').javadoc.options[:windowtitle].should eql('foo:bar')
-  end
-
-  it 'should pick -windowtitle from project description' do
-    desc 'My App'
-    define('foo').javadoc.options[:windowtitle].should eql('My App')
-  end
-
-  it 'should produce documentation' do
-    sources
-    define('foo').javadoc.invoke
-    (1..3).map { |i| "target/javadoc/foo/Test#{i}.html" }.each { |f| 
file(f).should exist }
-  end
-
-  it 'should fail on error' do
-    write 'Test.java', 'class Test {}'
-    define('foo') { javadoc.include 'Test.java' }
-    lambda { project('foo').javadoc.invoke }.should raise_error(RuntimeError, 
/Failed to generate Javadocs/)
-  end
-
-  it 'should be local task' do
-    define('foo') { define('bar') }
-    project('foo:bar').javadoc.should_receive(:invoke_prerequisites)
-    in_original_dir(project('foo:bar').base_dir) { task('javadoc').invoke }
-  end
-
-  it 'should not recurse' do
-    define('foo') { define 'bar' }
-    project('foo:bar').javadoc.should_not_receive(:invoke_prerequisites)
-    project('foo').javadoc.invoke
-  end
-end

Copied: incubator/buildr/trunk/spec/java_compilers_spec.rb (from r616185, 
incubator/buildr/trunk/spec/java_compilers.rb)
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/spec/java_compilers_spec.rb?p2=incubator/buildr/trunk/spec/java_compilers_spec.rb&p1=incubator/buildr/trunk/spec/java_compilers.rb&r1=616185&r2=617010&rev=617010&view=diff
==============================================================================
--- incubator/buildr/trunk/spec/java_compilers.rb (original)
+++ incubator/buildr/trunk/spec/java_compilers_spec.rb Wed Jan 30 21:54:24 2008
@@ -59,7 +59,7 @@
   end
 
   def javac_args
-    Compiler::Javac.new(compile_task.options).send(:javac_args)
+    compile_task.instance_eval { @compiler }.send(:javac_args)
   end
 
   it 'should set warnings option to false by default' do
@@ -212,3 +212,198 @@
     ENV.delete "DEBUG"
   end
 end
+
+
+describe Project, '#javadoc' do
+  def sources
+    @sources ||= (1..3).map { |i| "Test#{i}" }.
+      each { |name| write "src/main/java/foo/#{name}.java", "package foo; 
public class #{name}{}" }.
+      map { |name| "src/main/java/foo/#{name}.java" }
+  end
+
+  it 'should return the project\'s Javadoc task' do
+    define('foo') { compile.using(:javac) }
+    project('foo').javadoc.name.should eql('foo:javadoc')
+  end
+
+  it 'should return a Javadoc task' do
+    define('foo') { compile.using(:javac) }
+    project('foo').javadoc.should be_kind_of(Javadoc::JavadocTask)
+  end
+
+  it 'should set target directory to target/javadoc' do
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.target.to_s.should point_to_path('target/javadoc')
+    end
+  end
+
+  it 'should create file task for target directory' do
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.should_receive(:invoke_prerequisites)
+    end
+    project('foo').file('target/javadoc').invoke
+  end
+
+  it 'should respond to into() and return self' do
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.into('docs').should be(javadoc)
+    end
+  end
+
+  it 'should respond to into() and change target directory' do
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.into('docs')
+      javadoc.should_receive(:invoke_prerequisites)
+    end
+    file('docs').invoke
+  end
+
+  it 'should respond to from() and return self' do
+    task = nil
+    define('foo') { task = javadoc.from('srcs') }
+    task.should be(project('foo').javadoc)
+  end
+
+  it 'should respond to from() and add sources' do
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.from('srcs').should be(javadoc)
+    end
+  end
+
+  it 'should respond to from() and add file task' do
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.from('srcs').should be(javadoc)
+    end
+    project('foo').javadoc.source_files.first.should point_to_path('srcs')
+  end
+
+  it 'should respond to from() and add project\'s sources and dependencies' do
+    write 'bar/src/main/java/Test.java'
+    define 'foo' do
+      compile.using(:javac)
+      define('bar') { compile.using(:javac).with 'group:id:jar:1.0' }
+      javadoc.from project('foo:bar')
+    end
+    project('foo').javadoc.source_files.first.should 
point_to_path('bar/src/main/java/Test.java')
+    project('foo').javadoc.classpath.map(&:to_spec).should 
include('group:id:jar:1.0')
+  end
+
+  it 'should generate javadocs from project' do
+    sources
+    define('foo') { compile.using(:javac) }
+    project('foo').javadoc.source_files.sort.should == sources.sort.map { |f| 
File.expand_path(f) }
+  end
+
+  it 'should include compile dependencies' do
+    define('foo') { compile.using(:javac).with 'group:id:jar:1.0' }
+    project('foo').javadoc.classpath.map(&:to_spec).should 
include('group:id:jar:1.0')
+  end
+
+  it 'should respond to include() and return self' do
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.include('srcs').should be(javadoc)
+    end
+  end
+
+  it 'should respond to include() and add files' do
+    included = sources.first
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.include included
+    end
+    project('foo').javadoc.source_files.should include(included)
+  end
+
+  it 'should respond to exclude() and return self' do
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.exclude('srcs').should be(javadoc)
+    end
+  end
+
+  it 'should respond to exclude() and ignore files' do
+    excluded = sources.first
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.exclude excluded
+    end
+    sources
+    project('foo').javadoc.source_files.sort.should == sources[1..-1].map { 
|f| File.expand_path(f) }
+  end
+
+  it 'should respond to using() and return self' do
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.using(:windowtitle=>'Fooing').should be(javadoc)
+    end
+  end
+
+  it 'should respond to using() and accept options' do
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.using :windowtitle=>'Fooing'
+    end
+    project('foo').javadoc.options[:windowtitle].should eql('Fooing')
+  end
+
+  it 'should pick -windowtitle from project name' do
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.options[:windowtitle].should eql('foo')
+
+      define 'bar' do
+        compile.using(:javac)
+        javadoc.options[:windowtitle].should eql('foo:bar')
+      end
+    end
+  end
+
+  it 'should pick -windowtitle from project description' do
+    desc 'My App'
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.options[:windowtitle].should eql('My App')
+    end
+  end
+
+  it 'should produce documentation' do
+    sources
+    define('foo') { compile.using(:javac) }
+    project('foo').javadoc.invoke
+    (1..3).map { |i| "target/javadoc/foo/Test#{i}.html" }.each { |f| 
file(f).should exist }
+  end
+
+  it 'should fail on error' do
+    write 'Test.java', 'class Test {}'
+    define 'foo' do
+      compile.using(:javac)
+      javadoc.include 'Test.java'
+    end
+    lambda { project('foo').javadoc.invoke }.should raise_error(RuntimeError, 
/Failed to generate Javadocs/)
+  end
+
+  it 'should be local task' do
+    define 'foo' do
+      define('bar') { compile.using(:javac) }
+    end
+    project('foo:bar').javadoc.should_receive(:invoke_prerequisites)
+    in_original_dir(project('foo:bar').base_dir) { task('javadoc').invoke }
+  end
+
+  it 'should not recurse' do
+    define 'foo' do
+      compile.using(:javac)
+      define('bar') { compile.using(:javac) }
+    end
+    project('foo:bar').javadoc.should_not_receive(:invoke_prerequisites)
+    project('foo').javadoc.invoke
+  end
+end
+

Copied: incubator/buildr/trunk/spec/scala_compilers_spec.rb (from r616131, 
incubator/buildr/trunk/spec/scala_compilers.rb)
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/spec/scala_compilers_spec.rb?p2=incubator/buildr/trunk/spec/scala_compilers_spec.rb&p1=incubator/buildr/trunk/spec/scala_compilers.rb&r1=616131&r2=617010&rev=617010&view=diff
==============================================================================
--- incubator/buildr/trunk/spec/scala_compilers.rb (original)
+++ incubator/buildr/trunk/spec/scala_compilers_spec.rb Wed Jan 30 21:54:24 2008
@@ -38,7 +38,8 @@
       package(:jar)
     end
     write 'src/test/DependencyTest.scala', 'class DependencyTest { var d: 
Dependency = _ }'
-    lambda { 
define('foo').compile.from('src/test').with(project('dependency')).invoke 
}.should run_task('foo:compile')
+    define('foo').compile.from('src/test').with(project('dependency')).invoke
+    file('target/classes/DependencyTest.class').should exist
   end
 end
 
@@ -49,7 +50,7 @@
   end
 
   def scalac_args
-    Compiler::Scalac.new(compile_task.options).send(:scalac_args)
+    compile_task.instance_eval { @compiler }.send(:scalac_args)
   end
 
   it 'should set warnings option to false by default' do


Reply via email to