[Python-checkins] cpython: Issue #14642: Add "hg touch" extension, and "make touch" target.

martin.v.loewis python-checkins at python.org
Fri Apr 27 16:10:18 CEST 2012


http://hg.python.org/cpython/rev/b3d3f3238c13
changeset:   76574:b3d3f3238c13
user:        Martin v. Loewis <martin at v.loewis.de>
date:        Fri Apr 27 16:10:21 2012 +0200
summary:
  Issue #14642: Add "hg touch" extension, and "make touch" target.

files:
  .hgtouch            |  12 ++++
  Makefile.pre.in     |   6 +-
  Misc/NEWS           |   6 ++
  Tools/hg/hgtouch.py |  99 +++++++++++++++++++++++++++++++++
  4 files changed, 122 insertions(+), 1 deletions(-)


diff --git a/.hgtouch b/.hgtouch
new file mode 100644
--- /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
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1337,6 +1337,10 @@
 	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 @@
 .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
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -176,6 +176,12 @@
 
 - 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
--- /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")
+}

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list