如何阻止 rake 将文件依赖项视为可能的任务名称?

How do I stop rake from treating a file dependency as a possible task name?

短版:

我有一个问题:我需要一个 rake 任务的文件依赖与另一个 rake 任务的名称匹配,所以 rake 不依赖文件,而是尝试依赖具有匹配名称的任务。

我如何告诉 rake 只匹配文件的依赖项?还有其他出路吗?

长版:

我正在尝试在我的 Rails 应用程序中创建一个 rake 任务,以压缩我关心的所有文件。而已。简单。

我也很欣赏 rake 中的正常依赖性测试:如果没有文件更改并且 zip 文件已经存在,则不要执行任何操作。

问题是我想包含在 zip 文件中的文件之一(因此被视为任务依赖项)是 test 目录,但 rake test 恰好是一个现有的耙子任务。如果我这样说:

# FILES_TO_INCLUDE being a Rake::FileList...
file 'output.zip' => FILES_TO_INCLUDE.to_a do
  ...
end

rake 最终也是 运行 rake test

由于我一直在添加文件,并且由于 Rails 不时更改内置的 rake 任务,所以我永远无法确定 rake 任务和文件之间不会发生冲突名字。

我该怎么做才能避免这个问题?有没有我遗漏的更好的 rake 用法?

我观察到同样的行为。 FileTask,由 rake DSL 中的 file 方法定义,继承自主 Rake Task class 并且,实际上,调用依赖项(或者用 Rake 的语言 prerequisities) 对于 Tasks 和 FileTasks 似乎是一样的,也就是说,如果一个文件名已经被定义为 rake 任务,则该任务是 运行。

我想到的唯一解决方案是将路径部分添加到FILES_TO_INCLUDE中的文件中。它可以像 "./" 前缀一样简单。

所以,我会试试这个:

file 'output.zip' => FILES_TO_INCLUDE.map { |file| "./#{file}" } do
  ...
end

这种方法似乎对我有效。

此外,对于您的特定情况(创建一些其他文件的 zip 文件),您实际上可以使用 Rake 中已有的现成解决方案,PackageTask:

Rake::PackageTask.new("rake", "1.2.3") do |p|
  p.need_zip = true
  p.package_files.include("lib/**/*.rb")
end

这将在 pkg(可配置)子目录中创建一个 rake-1.2.3.zip 存档。您可能还需要在文件前加上一些目录规范。

我的第一个解决方法是避免使用可能是文件名的符号名称。
例如。在您的情况下:task :do_testsdirectory 'test'
缺点:如果不总是非常小心就无法工作。

第二个是对符号任务使用特殊语法::@name
PRO: 好记,不用写太多。

现在我正在试验一种技巧,自动执行 :@name - 事情。

    class Object; def rakesym
      self
    end end
    class Symbol; def rakesym
      self.to_s.sub(/\A@?/,'@').to_sym
    end end
    module Rake::DSL
      # transform symbol-tasks and -deps to :@XXXX
      #
      # args is always an array
      # [ t ]
      # [ t, p0 ]       ---> t[p0]
      # [ t, p0,p1 ]    ---> t[p0,p1]
      # [ {t => deps } ]
      # [ t, { [prms] => deps } ]
      # [ t, p0 => deps ]    ---> ERROR
      # [ t, p0,p1 => deps ] ---> ERROR
      # [ t, {[] => deps}
      # [ t, {[params] => deps} ]
      #
      # deps can be a single value or an array:
      #    deps:==   d0 | [] | [d0] | [ d0,d1,.. ]
      def hack_args( *args )
        STDOUT.puts "=== args before: #{args.inspect}"

        args[0] = args[0].rakesym
        if (args[0].is_a? Hash) && (args[0].size == 1)
          t,deps = args[0].first
          args[0] = { t.rakesym => deps }
        end
        if (args[-1].is_a? Hash) && (args[-1].size == 1)
          x, deps = args[-1].first
          deps.map!{|d| d.rakesym } if deps.is_a? Array
          args[-1][x] = deps.rakesym
        end
        STDOUT.puts "=== args after: #{args.inspect}"
        return args
      end

      alias task_o task
      def task(*args, &block )
        task_o( *hack_args(*args), &block )
      end

      # ... same for 'file', 'file_create' and 'directory'

    end # module Rake::DSL

现在这给出了两个不同的任务:

   desc "create html/ directory"
   directory 'html'
   desc "compile HTML docs"
   task :html => HTML_FILES

我可以从 shell 调用:

> rake -D
rake html
    create html/ directory

rake @html
    compile HTML docs

还有待办事项:

  • 处理名称空间。
  • 修补 defaul_task_name