文件更新了吗?Ruby中的问题

文件更新了吗?Ruby中的问题,ruby,linux,file-io,filesystems,rake,Ruby,Linux,File Io,Filesystems,Rake,我用最新的?方法来确定文件是否必须重新编译/重新链接/重新生成等。有时,我使用的构建框架在这些步骤中非常快,以至于输出文件和必备文件具有完全相同的文件修改时间戳。这会导致生成框架不必要地重新编译/重新链接文件 我像这样比较建筑的时间戳- compile_file(file) unless uptodate?(file, %W(#{dependencies})) 我查了最新的消息来源?看起来像这样- def uptodate?(new, old_list, options = nil) ra

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

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

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微秒)。

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

在生成文件的步骤中,添加逻辑以将生成文件的时间提前一秒(如果该时间等于其依赖时间)。是的,这是一次黑客攻击,但在这种情况下可能是你能做的最好的

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


除了以上任何一项,你可以选择最新的猴子补丁?或者只创建您自己的错误,当时间戳相等时,不进行构建。

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

在生成文件的步骤中,添加逻辑以将生成文件的时间提前一秒(如果该时间等于其依赖时间)。是的,这是一次黑客攻击,但在这种情况下可能是你能做的最好的

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


除了以上任何一项,你可以选择最新的猴子补丁?或者只是创建自己的错误,当时间戳相等时不构建。

看起来Ruby的
文件
对象不支持文件修改时间戳的亚秒解析,即使底层文件系统支持。一种解决方案是使用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::Update?
返回false时,我们才会执行此操作。

看起来Ruby的
file
对象不支持文件修改时间戳的亚秒解析,即使底层文件系统支持。一种解决方案是使用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::Update?
返回false时,我们才会执行此魔术。

这段代码很奇怪,如果人们提供选项时会出错,为什么要接受选项呢?我不理解这个问题,如果构建框架是如此之快,那么如果偶尔重新编译一个文件,又有什么关系呢?除非你说它在同一个构建过程中多次重新编译同一个文件。如果是这样的话,那么考虑到一个更好的工具。例如,它是为此目的而构建的,并通过依赖关系来处理此问题,因此不会有这样的问题。@Joshuache说,代码是Ruby中FileUtils模块的一部分(也就是说,它不是由我编写的!)。我正在使用Rake,但我怀疑即使我指定了文件依赖项,它也会以同样的方式运行(我猜它在内部使用了Update?)。我不希望构建框架不必要地重新编译/重新链接/运行单元测试,因为当您进行TDD时,它确实很重要!伙计,不管怎么说,stdlib O.O中有一些奇怪的代码,区别在于(如果我正确理解你在做什么的话)Rake只检查该文件一次,例如,它只编译一次,这是因为Rake任务不像方法,而是像依赖项。文件a依赖于c,文件b依赖于c。如果您同时编译a和b,那么c将为a编译一次,因此c的依赖关系得到满足。很抱歉,延迟回复@joshuacheck。我了解了文件依赖关系在Rake中的工作方式。我放弃了它,因为我的耙子变得乱七八糟,无法维护。据我所知,Rake文件依赖关系在内部被重新评估,就像我(明确地)通过比较文件修改时间戳所做的那样。这段代码很奇怪,如果人们提供选项时会出错,为什么要接受这些选项呢?我不理解这个问题,如果构建框架是如此之快,那么如果偶尔重新编译一个文件,又有什么关系呢?除非你说它在同一个构建过程中多次重新编译同一个文件。如果是这样的话,那么考虑到一个更好的工具。例如,它是为此目的而构建的,并通过依赖关系来处理此问题,因此不会有这样的问题。@Joshuache说,代码是Ruby中FileUtils模块的一部分(也就是说,它不是由我编写的!)。我正在使用Rake,但我怀疑即使我指定了文件依赖项,它也会以同样的方式运行(我猜它在内部使用了Update?)。我不希望构建框架不必要地重新编译/重新链接/运行单元测试,因为当您进行TDD时,它确实很重要!伙计,不管怎么说,stdlib O.O中有一些奇怪的代码,区别在于(如果我正确理解你在做什么的话)Rake只会检查该文件一次,例如,它只会编译一次,这是因为Rake任务不像方法,而是像dependent