[PATCH] eol: hook should consider all changegroup heads (issue2666)

Antoine Pitrou solipsis at pitrou.net
Tue Mar 1 02:46:30 CST 2011


# HG changeset patch
# User Antoine Pitrou <solipsis at pitrou.net>
# Date 1298968929 -3600
# Branch stable
# Node ID b9101359e4b0b0e218cb4508518d909dd86fb266
# Parent  4f5f54314720a20f58ce6167937496368b889330
eol: hook should consider all changegroup heads (issue2666)

If the eol hook only considers the tipmost changeset in the
changegroup, it is possible to first check in a file with a
bogus line ending, then create another head from a previous
changeset, and push the whole bunch without eol noticing.
By considering all heads in the changegroup, we fix this issue.

diff --git a/hgext/eol.py b/hgext/eol.py
--- a/hgext/eol.py
+++ b/hgext/eol.py
@@ -128,26 +128,39 @@
 }
 
 
+def checkfile(ui, repo, node, file):
+    """check that a file in the given node has expected EOLs"""
+    for pattern, target in ui.configitems('encode'):
+        if match.match(repo.root, '', [pattern])(file):
+            data = node[file].data()
+            if ((target == "to-lf" and "\r\n" in data) or
+                (target == "to-crlf" and singlelf.search(data))):
+                return target
+            # Ignore other rules for this file
+            break
+
 def hook(ui, repo, node, hooktype, **kwargs):
     """verify that files have expected EOLs"""
+    start = repo[node].rev()
     files = set()
-    for rev in xrange(repo[node].rev(), len(repo)):
+    heads = set([start])
+    for rev in xrange(start, len(repo)):
+        for p in repo.changelog.parentrevs(rev):
+            heads.discard(p)
+        heads.add(rev)
         files.update(repo[rev].files())
-    tip = repo['tip']
-    for f in files:
-        if f not in tip:
-            continue
-        for pattern, target in ui.configitems('encode'):
-            if match.match(repo.root, '', [pattern])(f):
-                data = tip[f].data()
-                if target == "to-lf" and "\r\n" in data:
-                    raise util.Abort(_("%s should not have CRLF line endings")
-                                     % f)
-                elif target == "to-crlf" and singlelf.search(data):
-                    raise util.Abort(_("%s should not have LF line endings")
-                                     % f)
-                # Ignore other rules for this file
-                break
+    for head in heads:
+        ctx = repo[head]
+        for f in files:
+            if f not in ctx:
+                continue
+            target = checkfile(ui, repo, ctx, f)
+            if target == "to-lf":
+                raise util.Abort(_("%s should not have CRLF line endings")
+                                 % f)
+            elif target == "to-crlf":
+                raise util.Abort(_("%s should not have LF line endings")
+                                 % f)
 
 
 def preupdate(ui, repo, hooktype, parent1, parent2):
diff --git a/tests/test-eol-hook.t b/tests/test-eol-hook.t
--- a/tests/test-eol-hook.t
+++ b/tests/test-eol-hook.t
@@ -88,3 +88,50 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 1 files
+
+  $ printf "first\r\nsecond" > b.txt
+  $ hg add b.txt
+  $ hg commit -m 'CRLF b.txt'
+  $ hg push ../main
+  pushing to ../main
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  error: pretxnchangegroup hook failed: b.txt should not have CRLF line endings
+  transaction abort!
+  rollback completed
+  abort: b.txt should not have CRLF line endings
+  [255]
+
+  $ hg up -r -2
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ printf "some\nother\nfile" > c.txt
+  $ hg add c.txt
+  $ hg commit -m "LF c.txt, b.txt doesn't exist here"
+  created new head
+  $ hg push -f ../main
+  pushing to ../main
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files (+1 heads)
+  error: pretxnchangegroup hook failed: b.txt should not have CRLF line endings
+  transaction abort!
+  rollback completed
+  abort: b.txt should not have CRLF line endings
+  [255]
+
+  $ hg up -r -2
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ printf "first\nsecond" > b.txt
+  $ hg commit -m 'LF b.txt (fixed)'
+  $ hg push -f ../main
+  pushing to ../main
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 3 changesets with 3 changes to 2 files (+1 heads)


More information about the Mercurial-devel mailing list