0

我用的是最新的?Ruby 中的方法来确定是否必须重新编译/重新链接/重新生成文件等。有时我使用的构建框架在这些步骤中非常快,以至于输出文件和先决条件文件具有完全相同的文件修改时间戳. 这会导致构建框架不必要地重新编译/重新链接文件。

我比较像这样构建的时间戳 -

compile_file(file) unless uptodate?(file, %W(#{dependencies}))

我查找了最新的来源?从这里开始,它看起来像这样 -

def uptodate?(new, old_list, options = nil)
  raise ArgumentError, 'uptodate? does not accept any option' if options
  return false unless File.exist?(new)
  new_time = File.mtime(new)
  old_list.each do |old|
    if File.exist?(old)
      return false unless new_time > File.mtime(old)
    end
  end
  true
end

正如所怀疑的,如果时间戳相等,它会返回 false。解决这个问题的最优雅的方法是什么?我曾尝试在 Linux 和 Windows 上运行该框架,但我遇到了同样的问题。从我在这里阅读的内容来看,这不太可能是文件系统特定的文件修改时间分辨率问题(因为 ext4 的分辨率为 1 微秒)。

4

2 回答 2

2

看起来 Ruby 的File对象不支持文件修改时间戳的亚秒级分辨率,即使底层文件系统支持。一种解决方案是ls --full-time使用 Ruby 解析并解析结果DateTime,它确实支持几分之一秒:

module FileUtilsPlus
  def self.uptodate?(new, old_list, options = nil)
    return true if FileUtils.uptodate?(new, old_list, options)
    return false unless File.exist?(new)
    new_time = filemtime(new)
    old_list.each do |old|
      if File.exist?(old)
        return false unless new_time > filemtime(old)
      end
    end
  end

  def self.filemtime(path)
    DateTime.parse(`ls --full-time foo | awk '{ print $6 " " $7 }'`)
  end
end

请注意,这将比 Ruby 的本机文件操作要慢得多,所以我们只会在FileUtils::uptodate?返回 false 时使用这个魔法。

于 2012-08-17T04:21:10.843 回答
1

uptodate?似乎是正确的。如果时间戳相等,则文件可能是最新的,也可能不是。因此,它在安全方面犯了错误并宣布它已过时。

在构建文件的步骤中,添加逻辑以将构建文件的时间提前一秒(如果它等于其依赖项的时间)。是的,这是一个 hack,但在这种情况下可能是你能做的最好的。

一些文件系统(ext4 等)可以存储具有亚秒级分辨率的时间戳,可能值得一看。

除非上述任何一项,您都可以更新猴子补丁?或者只是在时间戳相等时创建自己的错误而不是构建。

于 2012-08-17T04:17:56.033 回答