summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.hgtouch12
-rw-r--r--Makefile.pre.in6
-rw-r--r--Misc/NEWS6
-rw-r--r--Tools/hg/hgtouch.py99
4 files changed, 122 insertions, 1 deletions
diff --git a/.hgtouch b/.hgtouch
new file mode 100644
index 0000000..ad936fa
--- /dev/null
+++ b/.hgtouch
@@ -0,0 +1,12 @@
+# -*- Makefile -*-
+# Define dependencies of generated files that are checked into hg.
+# The syntax of this file uses make rule dependencies, without actions
+
+Python/importlib.h: Lib/importlib/_bootstrap.py Python/freeze_importlib.py
+
+Include/ast.h: Parser/Python.asdl Parser/asdl.py Parser/asdl_c.py
+Python/Python-ast.c: Include/ast.h
+
+Python/opcode_targets.h: Python/makeopcodetargets.py Lib/opcode.py
+
+Objects/typeslots.inc: Include/typeslots.h Objects/typeslots.py \ No newline at end of file
diff --git a/Makefile.pre.in b/Makefile.pre.in
index e6b37f8..38ffa34 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1337,6 +1337,10 @@ TAGS::
etags Include/*.h; \
for i in $(SRCDIRS); do etags -a $$i/*.[ch]; done
+# Touch generated files
+touch:
+ hg --config extensions.touch=Tools/hg/hgtouch.py touch -v
+
# Sanitation targets -- clean leaves libraries, executables and tags
# files, which clobber removes as well
pycremoval:
@@ -1445,7 +1449,7 @@ Python/thread.o: @THREADHEADERS@
.PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure
.PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools
.PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber distclean
-.PHONY: smelly funny patchcheck
+.PHONY: smelly funny patchcheck touch
.PHONY: gdbhooks
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff --git a/Misc/NEWS b/Misc/NEWS
index 21cead0..c4da5b0 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -176,6 +176,12 @@ Library
- Issue #14493: Use gvfs-open or xdg-open in webbrowser.
+Build
+-----
+
+- "make touch" will now touch generated files that are checked into Mercurial,
+ after a "hg update" which failed to bring the timestamps into the right order.
+
Tests
-----
diff --git a/Tools/hg/hgtouch.py b/Tools/hg/hgtouch.py
new file mode 100644
index 0000000..c7fde10
--- /dev/null
+++ b/Tools/hg/hgtouch.py
@@ -0,0 +1,99 @@
+"""Bring time stamps of generated checked-in files into the right order
+
+A versioned configuration file .hgtouch specifies generated files, in the
+syntax of make rules.
+
+ output: input1 input2
+
+In addition to the dependency syntax, #-comments are supported.
+"""
+import os
+
+def parse_config(repo):
+ configfile = repo.wjoin(".hgtouch")
+ if not os.path.exists(configfile):
+ return {}
+ result = {}
+ with open(configfile) as f:
+ for line in f:
+ # strip comments
+ line = line.split('#')[0].strip()
+ if ':' not in line:
+ continue
+ outputs, inputs = line.split(':', 1)
+ outputs = outputs.split()
+ inputs = inputs.split()
+ for o in outputs:
+ try:
+ result[o].extend(inputs)
+ except KeyError:
+ result[o] = inputs
+ return result
+
+def check_rule(ui, repo, modified, output, inputs):
+ f_output = repo.wjoin(output)
+ try:
+ o_time = os.stat(f_output).st_mtime
+ except OSError:
+ ui.warn("Generated file %s does not exist\n" % output)
+ return False
+ need_touch = False
+ backdate = None
+ backdate_source = None
+ for i in inputs:
+ f_i = repo.wjoin(i)
+ try:
+ i_time = os.stat(f_i).st_mtime
+ except OSError:
+ ui.warn(".hgtouch input file %s does not exist\n" % i)
+ return False
+ if i in modified:
+ # input is modified. Need to backdate at least to i_time
+ if backdate is None or backdate > i_time:
+ backdate = i_time
+ backdate_source = i
+ continue
+ if o_time <= i_time:
+ # generated file is older, touch
+ need_touch = True
+ if backdate is not None:
+ ui.warn("Input %s for file %s locally modified\n" % (backdate_source, output))
+ # set to 1s before oldest modified input
+ backdate -= 1
+ os.utime(f_output, (backdate, backdate))
+ return False
+ if need_touch:
+ ui.note("Touching %s\n" % output)
+ os.utime(f_output, None)
+ return True
+
+def do_touch(ui, repo):
+ modified = repo.status()[0]
+ dependencies = parse_config(repo)
+ success = True
+ # try processing all rules in topological order
+ hold_back = {}
+ while dependencies:
+ output, inputs = dependencies.popitem()
+ # check whether any of the inputs is generated
+ for i in inputs:
+ if i in dependencies:
+ hold_back[output] = inputs
+ continue
+ success = check_rule(ui, repo, modified, output, inputs)
+ # put back held back rules
+ dependencies.update(hold_back)
+ hold_back = {}
+ if hold_back:
+ ui.warn("Cyclic dependency involving %s\n" % (' '.join(hold_back.keys())))
+ return False
+ return success
+
+def touch(ui, repo):
+ "touch generated files that are older than their sources after an update."
+ do_touch(ui, repo)
+
+cmdtable = {
+ "touch": (touch, [],
+ "touch generated files according to the .hgtouch configuration")
+}