rake 0.8.7 → 0.9.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.
Files changed (124) hide show
  1. data/.gemtest +0 -0
  2. data/CHANGES +77 -9
  3. data/{README → README.rdoc} +14 -10
  4. data/Rakefile +129 -118
  5. data/TODO +1 -1
  6. data/doc/command_line_usage.rdoc +18 -6
  7. data/doc/glossary.rdoc +2 -2
  8. data/doc/jamis.rb +2 -2
  9. data/doc/proto_rake.rdoc +22 -22
  10. data/doc/rake.1.gz +0 -0
  11. data/doc/rakefile.rdoc +55 -32
  12. data/doc/rational.rdoc +6 -6
  13. data/doc/release_notes/rake-0.4.15.rdoc +1 -1
  14. data/doc/release_notes/rake-0.5.0.rdoc +1 -1
  15. data/doc/release_notes/rake-0.7.0.rdoc +1 -1
  16. data/doc/release_notes/rake-0.7.2.rdoc +3 -3
  17. data/doc/release_notes/rake-0.7.3.rdoc +2 -2
  18. data/doc/release_notes/rake-0.8.0.rdoc +1 -1
  19. data/doc/release_notes/rake-0.8.2.rdoc +3 -3
  20. data/doc/release_notes/rake-0.8.3.rdoc +2 -2
  21. data/doc/release_notes/rake-0.8.4.rdoc +1 -1
  22. data/doc/release_notes/rake-0.8.5.rdoc +1 -1
  23. data/doc/release_notes/rake-0.8.6.rdoc +1 -1
  24. data/doc/release_notes/rake-0.8.7.rdoc +1 -1
  25. data/doc/release_notes/rake-0.9.0.rdoc +112 -0
  26. data/install.rb +14 -12
  27. data/lib/rake/alt_system.rb +7 -6
  28. data/lib/rake/application.rb +589 -0
  29. data/lib/rake/classic_namespace.rb +1 -0
  30. data/lib/rake/clean.rb +2 -4
  31. data/lib/rake/cloneable.rb +25 -0
  32. data/lib/rake/contrib/compositepublisher.rb +2 -5
  33. data/lib/rake/contrib/ftptools.rb +5 -8
  34. data/lib/rake/contrib/publisher.rb +2 -8
  35. data/lib/rake/contrib/rubyforgepublisher.rb +2 -4
  36. data/lib/rake/contrib/sshpublisher.rb +4 -6
  37. data/lib/rake/contrib/sys.rb +7 -25
  38. data/lib/rake/default_loader.rb +10 -0
  39. data/lib/rake/dsl.rb +2 -0
  40. data/lib/rake/dsl_definition.rb +143 -0
  41. data/lib/rake/early_time.rb +18 -0
  42. data/lib/rake/ext/core.rb +27 -0
  43. data/lib/rake/ext/module.rb +39 -0
  44. data/lib/rake/ext/string.rb +167 -0
  45. data/lib/rake/ext/time.rb +14 -0
  46. data/lib/rake/file_creation_task.rb +24 -0
  47. data/lib/rake/file_list.rb +403 -0
  48. data/lib/rake/file_task.rb +47 -0
  49. data/lib/rake/file_utils.rb +112 -0
  50. data/lib/rake/file_utils_ext.rb +142 -0
  51. data/lib/rake/gempackagetask.rb +6 -90
  52. data/lib/rake/invocation_chain.rb +51 -0
  53. data/lib/rake/invocation_exception_mixin.rb +16 -0
  54. data/lib/rake/loaders/makefile.rb +13 -15
  55. data/lib/rake/multi_task.rb +16 -0
  56. data/lib/rake/name_space.rb +25 -0
  57. data/lib/rake/packagetask.rb +13 -12
  58. data/lib/rake/pathmap.rb +1 -0
  59. data/lib/rake/pseudo_status.rb +24 -0
  60. data/lib/rake/rake_module.rb +29 -0
  61. data/lib/rake/rake_test_loader.rb +10 -2
  62. data/lib/rake/rdoctask.rb +211 -190
  63. data/lib/rake/ruby182_test_unit_fix.rb +9 -7
  64. data/lib/rake/rule_recursion_overflow_error.rb +20 -0
  65. data/lib/rake/runtest.rb +4 -6
  66. data/lib/rake/task.rb +327 -0
  67. data/lib/rake/task_argument_error.rb +7 -0
  68. data/lib/rake/task_arguments.rb +74 -0
  69. data/lib/rake/task_manager.rb +307 -0
  70. data/lib/rake/tasklib.rb +1 -2
  71. data/lib/rake/testtask.rb +57 -27
  72. data/lib/rake/version.rb +10 -0
  73. data/lib/rake/win32.rb +4 -4
  74. data/lib/rake.rb +29 -2470
  75. data/test/contrib/test_sys.rb +8 -31
  76. data/test/data/access/Rakefile +33 -0
  77. data/test/data/comments/Rakefile +18 -0
  78. data/test/data/default/Rakefile +1 -1
  79. data/test/data/deprecated_import/Rakefile +1 -0
  80. data/test/data/dryrun/Rakefile +1 -1
  81. data/test/data/file_creation_task/Rakefile +1 -1
  82. data/test/data/namespace/Rakefile +9 -0
  83. data/test/data/rakelib/test1.rb +1 -0
  84. data/test/data/verbose/Rakefile +34 -0
  85. data/test/{filecreation.rb → file_creation.rb} +11 -7
  86. data/test/functional/functional_test.rb +25 -0
  87. data/test/{session_functional.rb → functional/session_based_tests.rb} +141 -23
  88. data/test/in_environment.rb +7 -5
  89. data/test/{test_application.rb → lib/application_test.rb} +331 -143
  90. data/test/{test_clean.rb → lib/clean_test.rb} +1 -0
  91. data/test/{test_definitions.rb → lib/definitions_test.rb} +3 -3
  92. data/test/lib/dsl_test.rb +52 -0
  93. data/test/{test_earlytime.rb → lib/earlytime_test.rb} +1 -2
  94. data/test/{test_extension.rb → lib/extension_test.rb} +2 -2
  95. data/test/{test_file_creation_task.rb → lib/file_creation_task_test.rb} +1 -1
  96. data/test/{test_file_task.rb → lib/file_task_test.rb} +4 -4
  97. data/test/{test_filelist.rb → lib/filelist_test.rb} +38 -24
  98. data/test/{test_fileutils.rb → lib/fileutils_test.rb} +27 -22
  99. data/test/{test_multitask.rb → lib/multitask_test.rb} +14 -6
  100. data/test/lib/package_task_test.rb +82 -0
  101. data/test/{test_pathmap.rb → lib/pathmap_test.rb} +3 -2
  102. data/test/{test_rake.rb → lib/rake_test.rb} +1 -1
  103. data/test/{test_rdoc_task.rb → lib/rdoc_task_test.rb} +19 -23
  104. data/test/{test_require.rb → lib/require_test.rb} +8 -2
  105. data/test/{test_rules.rb → lib/rules_test.rb} +2 -3
  106. data/test/{test_task_arguments.rb → lib/task_arguments_test.rb} +5 -5
  107. data/test/{test_task_manager.rb → lib/task_manager_test.rb} +15 -5
  108. data/test/{test_tasks.rb → lib/task_test.rb} +84 -21
  109. data/test/{test_test_task.rb → lib/test_task_test.rb} +3 -3
  110. data/test/lib/testtask_test.rb +49 -0
  111. data/test/{test_top_level_functions.rb → lib/top_level_functions_test.rb} +5 -3
  112. data/test/{test_win32.rb → lib/win32_test.rb} +19 -0
  113. data/test/rake_test_setup.rb +5 -9
  114. data/test/ruby_version_test.rb +3 -0
  115. data/test/test_helper.rb +19 -0
  116. metadata +108 -49
  117. data/test/functional.rb +0 -15
  118. data/test/test_package_task.rb +0 -118
  119. /data/test/{test_ftp.rb → lib/ftp_test.rb} +0 -0
  120. /data/test/{test_invocation_chain.rb → lib/invocation_chain_test.rb} +0 -0
  121. /data/test/{test_makefile_loader.rb → lib/makefile_loader_test.rb} +0 -0
  122. /data/test/{test_namespace.rb → lib/namespace_test.rb} +0 -0
  123. /data/test/{test_pseudo_status.rb → lib/pseudo_status_test.rb} +0 -0
  124. /data/test/{test_tasklib.rb → lib/tasklib_test.rb} +0 -0
@@ -1,5 +1,3 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  # = Tools for FTP uploading.
4
2
  #
5
3
  # This file is still under development and is not released for general
@@ -25,7 +23,7 @@ module Rake # :nodoc:
25
23
 
26
24
  def initialize(path, entry)
27
25
  @path = path
28
- @mode, line, @owner, @group, size, d1, d2, d3, @name = entry.split(' ')
26
+ @mode, _, @owner, @group, size, d1, d2, d3, @name = entry.split(' ')
29
27
  @size = size.to_i
30
28
  @time = determine_time(d1, d2, d3)
31
29
  end
@@ -59,7 +57,6 @@ module Rake # :nodoc:
59
57
  def determine_time(d1, d2, d3)
60
58
  now = self.class.time.now
61
59
  if /:/ =~ d3
62
- h, m = d3.split(':')
63
60
  result = Time.parse("#{d1} #{d2} #{now.year} #{d3}")
64
61
  if result > now
65
62
  result = Time.parse("#{d1} #{d2} #{now.year-1} #{d3}")
@@ -102,7 +99,7 @@ module Rake # :nodoc:
102
99
  end
103
100
  end
104
101
 
105
- # Create an FTP uploader targetting the directory +path+ on +host+
102
+ # Create an FTP uploader targeting the directory +path+ on +host+
106
103
  # using the given account and password. +path+ will be the root
107
104
  # path of the uploader.
108
105
  def initialize(path, host, account, password)
@@ -121,7 +118,7 @@ module Rake # :nodoc:
121
118
  current_dir = File.join(route)
122
119
  if @created[current_dir].nil?
123
120
  @created[current_dir] = true
124
- puts "Creating Directory #{current_dir}" if @verbose
121
+ $stderr.puts "Creating Directory #{current_dir}" if @verbose
125
122
  @ftp.mkdir(current_dir) rescue nil
126
123
  end
127
124
  end
@@ -134,7 +131,7 @@ module Rake # :nodoc:
134
131
  upload(fn)
135
132
  end
136
133
  end
137
-
134
+
138
135
  # Close the uploader.
139
136
  def close
140
137
  @ftp.close
@@ -144,7 +141,7 @@ module Rake # :nodoc:
144
141
 
145
142
  # Upload a single file to the uploader's root path.
146
143
  def upload(file)
147
- puts "Uploading #{file}" if @verbose
144
+ $stderr.puts "Uploading #{file}" if @verbose
148
145
  dir = File.dirname(file)
149
146
  makedirs(dir)
150
147
  @ftp.putbinaryfile(file, file) unless File.directory?(file)
@@ -1,19 +1,13 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Copyright 2003, 2004, 2005, 2006, 2007, 2008 by Jim Weirich (jim@weirichhouse.org)
1
+ # Copyright 2003-2010 by Jim Weirich (jim.weirich@gmail.com)
4
2
  # All rights reserved.
5
3
 
6
- # Permission is granted for use, copying, modification, distribution,
7
- # and distribution of modified versions of this work as long as the
8
- # above copyright notice is included.
9
-
10
4
  # Configuration information about an upload host system.
11
5
  # * name :: Name of host system.
12
6
  # * webdir :: Base directory for the web information for the
13
7
  # application. The application name (APP) is appended to
14
8
  # this directory before using.
15
9
  # * pkgdir :: Directory on the host system where packages can be
16
- # placed.
10
+ # placed.
17
11
  HostInfo = Struct.new(:name, :webdir, :pkgdir)
18
12
 
19
13
  # Manage several publishers as a single entity.
@@ -1,12 +1,10 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  require 'rake/contrib/sshpublisher'
4
2
 
5
3
  module Rake
6
4
 
7
5
  class RubyForgePublisher < SshDirPublisher
8
6
  attr_reader :project, :proj_id, :user
9
-
7
+
10
8
  def initialize(projname, user)
11
9
  super(
12
10
  "#{user}@rubyforge.org",
@@ -14,5 +12,5 @@ module Rake
14
12
  "html")
15
13
  end
16
14
  end
17
-
15
+
18
16
  end
@@ -1,5 +1,3 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  require 'rake/contrib/compositepublisher'
4
2
 
5
3
  module Rake
@@ -12,12 +10,12 @@ module Rake
12
10
  @remote_dir = remote_dir
13
11
  @local_dir = local_dir
14
12
  end
15
-
13
+
16
14
  def upload
17
15
  sh %{scp -rq #{@local_dir}/* #{@host}:#{@remote_dir}}
18
16
  end
19
17
  end
20
-
18
+
21
19
  # Publish an entire directory to a fresh remote directory using SSH.
22
20
  class SshFreshDirPublisher < SshDirPublisher
23
21
  def upload
@@ -26,7 +24,7 @@ module Rake
26
24
  super
27
25
  end
28
26
  end
29
-
27
+
30
28
  # Publish a list of files to an existing remote directory.
31
29
  class SshFilePublisher
32
30
  # Create a publisher using the give host information.
@@ -36,7 +34,7 @@ module Rake
36
34
  @local_dir = local_dir
37
35
  @files = files
38
36
  end
39
-
37
+
40
38
  # Upload the local directory to the remote directory.
41
39
  def upload
42
40
  @files.each do |fn|
@@ -1,26 +1,8 @@
1
- #!/usr/bin/env ruby
1
+ warn 'Sys has been deprecated in favor of FileUtils'
2
2
 
3
3
  #--
4
- # Copyright 2003, 2004, 2005, 2006, 2007, 2008 by Jim Weirich (jim@weirichhouse.org)
5
- #
6
- # Permission is hereby granted, free of charge, to any person obtaining
7
- # a copy of this software and associated documentation files (the
8
- # "Software"), to deal in the Software without restriction, including
9
- # without limitation the rights to use, copy, modify, merge, publish,
10
- # distribute, sublicense, and/or sell copies of the Software, and to
11
- # permit persons to whom the Software is furnished to do so, subject to
12
- # the following conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be
15
- # included in all copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4
+ # Copyright 2003-2010 by Jim Weirich (jim.weirich@gmail.com)
5
+ # All rights reserved.
24
6
  #++
25
7
  #
26
8
  begin
@@ -40,7 +22,7 @@ require 'rbconfig'
40
22
  # in Ruby 1.8.
41
23
  #
42
24
  module Sys
43
- RUBY = Config::CONFIG['ruby_install_name']
25
+ RUBY = RbConfig::CONFIG['ruby_install_name']
44
26
 
45
27
  # Install all the files matching +wildcard+ into the +dest_dir+
46
28
  # directory. The permission mode is set to +mode+.
@@ -60,7 +42,7 @@ module Sys
60
42
  def ruby(*args)
61
43
  run "#{RUBY} #{args.join(' ')}"
62
44
  end
63
-
45
+
64
46
  # Copy a single file from +file_name+ to +dest_file+.
65
47
  def copy(file_name, dest_file)
66
48
  log "Copying file #{file_name} to #{dest_file}"
@@ -160,10 +142,10 @@ module Sys
160
142
  return split_all(head) + [tail]
161
143
  end
162
144
 
163
- # Write a message to standard out if $verbose is enabled.
145
+ # Write a message to standard error if $verbose is enabled.
164
146
  def log(msg)
165
147
  print " " if $trace && $verbose
166
- puts msg if $verbose
148
+ $stderr.puts msg if $verbose
167
149
  end
168
150
 
169
151
  # Perform a block with $verbose disabled.
@@ -0,0 +1,10 @@
1
+ module Rake
2
+
3
+ # Default Rakefile loader used by +import+.
4
+ class DefaultLoader
5
+ def load(fn)
6
+ Rake.load_rakefile(File.expand_path(fn))
7
+ end
8
+ end
9
+
10
+ end
data/lib/rake/dsl.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'rake'
2
+ include Rake::DSL
@@ -0,0 +1,143 @@
1
+ # Rake DSL functions.
2
+ require 'rake/file_utils_ext'
3
+
4
+ module Rake
5
+ module DSL
6
+
7
+ # Include the FileUtils file manipulation functions in the top
8
+ # level module, but mark them private so that they don't
9
+ # unintentionally define methods on other objects.
10
+
11
+ include FileUtilsExt
12
+ private(*FileUtils.instance_methods(false))
13
+ private(*FileUtilsExt.instance_methods(false))
14
+
15
+ # Declare a basic task.
16
+ #
17
+ # Example:
18
+ # task :clobber => [:clean] do
19
+ # rm_rf "html"
20
+ # end
21
+ #
22
+ def task(*args, &block)
23
+ Rake::Task.define_task(*args, &block)
24
+ end
25
+
26
+
27
+ # Declare a file task.
28
+ #
29
+ # Example:
30
+ # file "config.cfg" => ["config.template"] do
31
+ # open("config.cfg", "w") do |outfile|
32
+ # open("config.template") do |infile|
33
+ # while line = infile.gets
34
+ # outfile.puts line
35
+ # end
36
+ # end
37
+ # end
38
+ # end
39
+ #
40
+ def file(*args, &block)
41
+ Rake::FileTask.define_task(*args, &block)
42
+ end
43
+
44
+ # Declare a file creation task.
45
+ # (Mainly used for the directory command).
46
+ def file_create(args, &block)
47
+ Rake::FileCreationTask.define_task(args, &block)
48
+ end
49
+
50
+ # Declare a set of files tasks to create the given directories on
51
+ # demand.
52
+ #
53
+ # Example:
54
+ # directory "testdata/doc"
55
+ #
56
+ def directory(dir)
57
+ Rake.each_dir_parent(dir) do |d|
58
+ file_create d do |t|
59
+ mkdir_p t.name if ! File.exist?(t.name)
60
+ end
61
+ end
62
+ end
63
+
64
+ # Declare a task that performs its prerequisites in
65
+ # parallel. Multitasks does *not* guarantee that its prerequisites
66
+ # will execute in any given order (which is obvious when you think
67
+ # about it)
68
+ #
69
+ # Example:
70
+ # multitask :deploy => [:deploy_gem, :deploy_rdoc]
71
+ #
72
+ def multitask(args, &block)
73
+ Rake::MultiTask.define_task(args, &block)
74
+ end
75
+
76
+ # Create a new rake namespace and use it for evaluating the given
77
+ # block. Returns a NameSpace object that can be used to lookup
78
+ # tasks defined in the namespace.
79
+ #
80
+ # E.g.
81
+ #
82
+ # ns = namespace "nested" do
83
+ # task :run
84
+ # end
85
+ # task_run = ns[:run] # find :run in the given namespace.
86
+ #
87
+ def namespace(name=nil, &block)
88
+ name = name.to_s if name.kind_of?(Symbol)
89
+ name = name.to_str if name.respond_to?(:to_str)
90
+ unless name.kind_of?(String) || name.nil?
91
+ raise ArgumentError, "Expected a String or Symbol for a namespace name"
92
+ end
93
+ Rake.application.in_namespace(name, &block)
94
+ end
95
+
96
+ # Declare a rule for auto-tasks.
97
+ #
98
+ # Example:
99
+ # rule '.o' => '.c' do |t|
100
+ # sh %{cc -o #{t.name} #{t.source}}
101
+ # end
102
+ #
103
+ def rule(*args, &block)
104
+ Rake::Task.create_rule(*args, &block)
105
+ end
106
+
107
+ # Describe the next rake task.
108
+ #
109
+ # Example:
110
+ # desc "Run the Unit Tests"
111
+ # task :test => [:build]
112
+ # runtests
113
+ # end
114
+ #
115
+ def desc(description)
116
+ Rake.application.last_description = description
117
+ end
118
+
119
+ # Import the partial Rakefiles +fn+. Imported files are loaded
120
+ # _after_ the current file is completely loaded. This allows the
121
+ # import statement to appear anywhere in the importing file, and yet
122
+ # allowing the imported files to depend on objects defined in the
123
+ # importing file.
124
+ #
125
+ # A common use of the import statement is to include files
126
+ # containing dependency declarations.
127
+ #
128
+ # See also the --rakelibdir command line option.
129
+ #
130
+ # Example:
131
+ # import ".depend", "my_rules"
132
+ #
133
+ def import(*fns)
134
+ fns.each do |fn|
135
+ Rake.application.add_import(fn)
136
+ end
137
+ end
138
+ end
139
+
140
+ extend FileUtilsExt
141
+ end
142
+
143
+ self.extend Rake::DSL
@@ -0,0 +1,18 @@
1
+ module Rake
2
+
3
+ # EarlyTime is a fake timestamp that occurs _before_ any other time value.
4
+ class EarlyTime
5
+ include Comparable
6
+ include Singleton
7
+
8
+ def <=>(other)
9
+ -1
10
+ end
11
+
12
+ def to_s
13
+ "<EARLY TIME>"
14
+ end
15
+ end
16
+
17
+ EARLY = EarlyTime.instance
18
+ end
@@ -0,0 +1,27 @@
1
+ ######################################################################
2
+ # Core extension library
3
+ #
4
+ class Module
5
+ # Check for an existing method in the current class before extending. IF
6
+ # the method already exists, then a warning is printed and the extension is
7
+ # not added. Otherwise the block is yielded and any definitions in the
8
+ # block will take effect.
9
+ #
10
+ # Usage:
11
+ #
12
+ # class String
13
+ # rake_extension("xyz") do
14
+ # def xyz
15
+ # ...
16
+ # end
17
+ # end
18
+ # end
19
+ #
20
+ def rake_extension(method)
21
+ if method_defined?(method)
22
+ $stderr.puts "WARNING: Possible conflict with Rake extension: #{self}##{method} already exists"
23
+ else
24
+ yield
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,39 @@
1
+ require 'rake/ext/core'
2
+ require 'rake/task'
3
+ require 'rake/file_task'
4
+ require 'rake/file_creation_task'
5
+ require 'rake/application'
6
+ require 'rake/task_manager'
7
+
8
+ ######################################################################
9
+ # Rake extensions to Module.
10
+ #
11
+ class Module
12
+
13
+ # Rename the original handler to make it available.
14
+ alias :rake_original_const_missing :const_missing
15
+
16
+ # Check for deprecated uses of top level (i.e. in Object) uses of
17
+ # Rake class names. If someone tries to reference the constant
18
+ # name, display a warning and return the proper object. Using the
19
+ # --classic-namespace command line option will define these
20
+ # constants in Object and avoid this handler.
21
+ def const_missing(const_name)
22
+ case const_name
23
+ when :Task
24
+ Rake.application.const_warning(const_name)
25
+ Rake::Task
26
+ when :FileTask
27
+ Rake.application.const_warning(const_name)
28
+ Rake::FileTask
29
+ when :FileCreationTask
30
+ Rake.application.const_warning(const_name)
31
+ Rake::FileCreationTask
32
+ when :RakeApp
33
+ Rake.application.const_warning(const_name)
34
+ Rake::Application
35
+ else
36
+ rake_original_const_missing(const_name)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,167 @@
1
+ require 'rake/ext/core'
2
+
3
+ ######################################################################
4
+ # Rake extension methods for String.
5
+ #
6
+ class String
7
+ rake_extension("ext") do
8
+ # Replace the file extension with +newext+. If there is no extension on
9
+ # the string, append the new extension to the end. If the new extension
10
+ # is not given, or is the empty string, remove any existing extension.
11
+ #
12
+ # +ext+ is a user added method for the String class.
13
+ def ext(newext='')
14
+ return self.dup if ['.', '..'].include? self
15
+ if newext != ''
16
+ newext = (newext =~ /^\./) ? newext : ("." + newext)
17
+ end
18
+ self.chomp(File.extname(self)) << newext
19
+ end
20
+ end
21
+
22
+ rake_extension("pathmap") do
23
+ # Explode a path into individual components. Used by +pathmap+.
24
+ def pathmap_explode
25
+ head, tail = File.split(self)
26
+ return [self] if head == self
27
+ return [tail] if head == '.' || tail == '/'
28
+ return [head, tail] if head == '/'
29
+ return head.pathmap_explode + [tail]
30
+ end
31
+ protected :pathmap_explode
32
+
33
+ # Extract a partial path from the path. Include +n+ directories from the
34
+ # front end (left hand side) if +n+ is positive. Include |+n+|
35
+ # directories from the back end (right hand side) if +n+ is negative.
36
+ def pathmap_partial(n)
37
+ dirs = File.dirname(self).pathmap_explode
38
+ partial_dirs =
39
+ if n > 0
40
+ dirs[0...n]
41
+ elsif n < 0
42
+ dirs.reverse[0...-n].reverse
43
+ else
44
+ "."
45
+ end
46
+ File.join(partial_dirs)
47
+ end
48
+ protected :pathmap_partial
49
+
50
+ # Preform the pathmap replacement operations on the given path. The
51
+ # patterns take the form 'pat1,rep1;pat2,rep2...'.
52
+ def pathmap_replace(patterns, &block)
53
+ result = self
54
+ patterns.split(';').each do |pair|
55
+ pattern, replacement = pair.split(',')
56
+ pattern = Regexp.new(pattern)
57
+ if replacement == '*' && block_given?
58
+ result = result.sub(pattern, &block)
59
+ elsif replacement
60
+ result = result.sub(pattern, replacement)
61
+ else
62
+ result = result.sub(pattern, '')
63
+ end
64
+ end
65
+ result
66
+ end
67
+ protected :pathmap_replace
68
+
69
+ # Map the path according to the given specification. The specification
70
+ # controls the details of the mapping. The following special patterns are
71
+ # recognized:
72
+ #
73
+ # * <b>%p</b> -- The complete path.
74
+ # * <b>%f</b> -- The base file name of the path, with its file extension,
75
+ # but without any directories.
76
+ # * <b>%n</b> -- The file name of the path without its file extension.
77
+ # * <b>%d</b> -- The directory list of the path.
78
+ # * <b>%x</b> -- The file extension of the path. An empty string if there
79
+ # is no extension.
80
+ # * <b>%X</b> -- Everything *but* the file extension.
81
+ # * <b>%s</b> -- The alternate file separator if defined, otherwise use
82
+ # the standard file separator.
83
+ # * <b>%%</b> -- A percent sign.
84
+ #
85
+ # The %d specifier can also have a numeric prefix (e.g. '%2d'). If the
86
+ # number is positive, only return (up to) +n+ directories in the path,
87
+ # starting from the left hand side. If +n+ is negative, return (up to)
88
+ # |+n+| directories from the right hand side of the path.
89
+ #
90
+ # Examples:
91
+ #
92
+ # 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b'
93
+ # 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d'
94
+ #
95
+ # Also the %d, %p, %f, %n, %x, and %X operators can take a
96
+ # pattern/replacement argument to perform simple string substitutions on a
97
+ # particular part of the path. The pattern and replacement are separated
98
+ # by a comma and are enclosed by curly braces. The replacement spec comes
99
+ # after the % character but before the operator letter. (e.g.
100
+ # "%{old,new}d"). Multiple replacement specs should be separated by
101
+ # semi-colons (e.g. "%{old,new;src,bin}d").
102
+ #
103
+ # Regular expressions may be used for the pattern, and back refs may be
104
+ # used in the replacement text. Curly braces, commas and semi-colons are
105
+ # excluded from both the pattern and replacement text (let's keep parsing
106
+ # reasonable).
107
+ #
108
+ # For example:
109
+ #
110
+ # "src/org/onestepback/proj/A.java".pathmap("%{^src,bin}X.class")
111
+ #
112
+ # returns:
113
+ #
114
+ # "bin/org/onestepback/proj/A.class"
115
+ #
116
+ # If the replacement text is '*', then a block may be provided to perform
117
+ # some arbitrary calculation for the replacement.
118
+ #
119
+ # For example:
120
+ #
121
+ # "/path/to/file.TXT".pathmap("%X%{.*,*}x") { |ext|
122
+ # ext.downcase
123
+ # }
124
+ #
125
+ # Returns:
126
+ #
127
+ # "/path/to/file.txt"
128
+ #
129
+ def pathmap(spec=nil, &block)
130
+ return self if spec.nil?
131
+ result = ''
132
+ spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag|
133
+ case frag
134
+ when '%f'
135
+ result << File.basename(self)
136
+ when '%n'
137
+ result << File.basename(self).ext
138
+ when '%d'
139
+ result << File.dirname(self)
140
+ when '%x'
141
+ result << File.extname(self)
142
+ when '%X'
143
+ result << self.ext
144
+ when '%p'
145
+ result << self
146
+ when '%s'
147
+ result << (File::ALT_SEPARATOR || File::SEPARATOR)
148
+ when '%-'
149
+ # do nothing
150
+ when '%%'
151
+ result << "%"
152
+ when /%(-?\d+)d/
153
+ result << pathmap_partial($1.to_i)
154
+ when /^%\{([^}]*)\}(\d*[dpfnxX])/
155
+ patterns, operator = $1, $2
156
+ result << pathmap('%' + operator).pathmap_replace(patterns, &block)
157
+ when /^%/
158
+ fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'"
159
+ else
160
+ result << frag
161
+ end
162
+ end
163
+ result
164
+ end
165
+ end
166
+ end # class String
167
+
@@ -0,0 +1,14 @@
1
+ # ###########################################################################
2
+ # Extensions to time to allow comparisons with an early time class.
3
+ #
4
+ class Time
5
+ alias rake_original_time_compare :<=>
6
+ def <=>(other)
7
+ if Rake::EarlyTime === other
8
+ - other.<=>(self)
9
+ else
10
+ rake_original_time_compare(other)
11
+ end
12
+ end
13
+ end # class Time
14
+
@@ -0,0 +1,24 @@
1
+ require 'rake/file_task'
2
+ require 'rake/early_time'
3
+
4
+ module Rake
5
+
6
+ # A FileCreationTask is a file task that when used as a dependency will be
7
+ # needed if and only if the file has not been created. Once created, it is
8
+ # not re-triggered if any of its dependencies are newer, nor does trigger
9
+ # any rebuilds of tasks that depend on it whenever it is updated.
10
+ #
11
+ class FileCreationTask < FileTask
12
+ # Is this file task needed? Yes if it doesn't exist.
13
+ def needed?
14
+ ! File.exist?(name)
15
+ end
16
+
17
+ # Time stamp for file creation task. This time stamp is earlier
18
+ # than any other time stamp.
19
+ def timestamp
20
+ Rake::EARLY
21
+ end
22
+ end
23
+
24
+ end