Commit 07035581 authored by Martin v. Löwis's avatar Martin v. Löwis

Issue #19106: Touch generated files to be 1s newer than their youngest source.

parent e9e8ea4c
...@@ -10,6 +10,7 @@ In addition to the dependency syntax, #-comments are supported. ...@@ -10,6 +10,7 @@ In addition to the dependency syntax, #-comments are supported.
from __future__ import with_statement from __future__ import with_statement
import errno import errno
import os import os
import time
def parse_config(repo): def parse_config(repo):
try: try:
...@@ -36,13 +37,17 @@ def parse_config(repo): ...@@ -36,13 +37,17 @@ def parse_config(repo):
return result return result
def check_rule(ui, repo, modified, output, inputs): def check_rule(ui, repo, modified, output, inputs):
"""Verify that the output is newer than any of the inputs.
Return (status, stamp), where status is True if the update succeeded,
and stamp is the newest time stamp assigned to any file (might be in
the future)."""
f_output = repo.wjoin(output) f_output = repo.wjoin(output)
try: try:
o_time = os.stat(f_output).st_mtime o_time = os.stat(f_output).st_mtime
except OSError: except OSError:
ui.warn("Generated file %s does not exist\n" % output) ui.warn("Generated file %s does not exist\n" % output)
return False return False, 0
need_touch = False youngest = 0 # youngest dependency
backdate = None backdate = None
backdate_source = None backdate_source = None
for i in inputs: for i in inputs:
...@@ -51,31 +56,34 @@ def check_rule(ui, repo, modified, output, inputs): ...@@ -51,31 +56,34 @@ def check_rule(ui, repo, modified, output, inputs):
i_time = os.stat(f_i).st_mtime i_time = os.stat(f_i).st_mtime
except OSError: except OSError:
ui.warn(".hgtouch input file %s does not exist\n" % i) ui.warn(".hgtouch input file %s does not exist\n" % i)
return False return False, 0
if i in modified: if i in modified:
# input is modified. Need to backdate at least to i_time # input is modified. Need to backdate at least to i_time
if backdate is None or backdate > i_time: if backdate is None or backdate > i_time:
backdate = i_time backdate = i_time
backdate_source = i backdate_source = i
continue continue
if o_time <= i_time: youngest = max(i_time, youngest)
# generated file is older, touch
need_touch = True
if backdate is not None: if backdate is not None:
ui.warn("Input %s for file %s locally modified\n" % (backdate_source, output)) ui.warn("Input %s for file %s locally modified\n" % (backdate_source, output))
# set to 1s before oldest modified input # set to 1s before oldest modified input
backdate -= 1 backdate -= 1
os.utime(f_output, (backdate, backdate)) os.utime(f_output, (backdate, backdate))
return False return False, 0
if need_touch: if youngest >= o_time:
ui.note("Touching %s\n" % output) ui.note("Touching %s\n" % output)
os.utime(f_output, None) youngest += 1
return True os.utime(f_output, (youngest, youngest))
return True, youngest
else:
# Nothing to update
return True, 0
def do_touch(ui, repo): def do_touch(ui, repo):
modified = repo.status()[0] modified = repo.status()[0]
dependencies = parse_config(repo) dependencies = parse_config(repo)
success = True success = True
tstamp = 0 # newest time stamp assigned
# try processing all rules in topological order # try processing all rules in topological order
hold_back = {} hold_back = {}
while dependencies: while dependencies:
...@@ -85,10 +93,17 @@ def do_touch(ui, repo): ...@@ -85,10 +93,17 @@ def do_touch(ui, repo):
if i in dependencies: if i in dependencies:
hold_back[output] = inputs hold_back[output] = inputs
continue continue
success = check_rule(ui, repo, modified, output, inputs) _success, _tstamp = check_rule(ui, repo, modified, output, inputs)
sucess = success and _success
tstamp = max(tstamp, _tstamp)
# put back held back rules # put back held back rules
dependencies.update(hold_back) dependencies.update(hold_back)
hold_back = {} hold_back = {}
now = time.time()
if tstamp > now:
# wait until real time has passed the newest time stamp, to
# avoid having files dated in the future
time.sleep(tstamp-now)
if hold_back: if hold_back:
ui.warn("Cyclic dependency involving %s\n" % (' '.join(hold_back.keys()))) ui.warn("Cyclic dependency involving %s\n" % (' '.join(hold_back.keys())))
return False return False
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment