[PATCH] add standard hook to reject text files with CRLF
Jesse Glick
jesse.glick at sun.com
Wed Dec 19 12:55:27 CST 2007
> # HG changeset patch
> # User Jesse Glick <jesse.glick at sun.com>
> # Date 1198089898 18000
> # Node ID ff5aadbd4939f419554d6d43eb8e821735a21184
> # Parent 9d6ad26fab10e06768858ed1a74eff80207cb0f5
> Issue 882: add standard hook to reject text files with CRLF.
> While the win32text extension does LF <-> CRLF conversion, and will issue a
> warning in case a file already in the repository uses CRLF, it provides no
> mechanism for verifying that incoming changes use LF. In a large development
> team with some Windows users, it is virtually guaranteed that someone will
> forget to set up the encode filter correctly and accidentally check in a file
> using CRLF, which can cause warnings for other Windows users when they next
> fetch changes. Since this is a general problem it is desirable to have a
> pre-commit (or -push) hook available to reject such accidents earlier rather
> than trying to fix them up after the fact.
>
> diff --git a/hgext/win32text.py b/hgext/win32text.py
> --- a/hgext/win32text.py
> +++ b/hgext/win32text.py
> @@ -1,5 +1,6 @@ from mercurial import util, ui
> from mercurial import util, ui
> from mercurial.i18n import gettext as _
> +from mercurial.node import *
> import re
>
> # regexp for single LF without CR preceding.
> @@ -43,3 +44,40 @@ util.filtertable.update({
> 'cleverdecode:': cleverdecode,
> 'cleverencode:': cleverencode,
> })
> +
> +def forbidcrlf(ui, repo, hooktype, node, **kwargs):
> + '''Prevent text files containing CRLF from being committed or pushed.
> +
> + Usage:
> + [hooks]
> + pretxncommit.crlf = python:hgext.win32text.forbidcrlf
> + pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf'''
> + halt = False
> + for rev in xrange(repo.changelog.rev(bin(node)), repo.changelog.count()):
> + c = repo.changectx(rev)
> + for f in c.files():
> + if f not in c:
> + continue
> + data = c[f].data()
> + if '\0' not in data and '\r\n' in data:
> + if not halt:
> + ui.warn(_('Attempt to commit or push text file(s) '
> + 'using CRLF line endings\n'))
> + ui.warn(_('in %s: %s\n') % (short(c.node()), f))
> + halt = True
> + if halt and hooktype == 'pretxnchangegroup':
> + ui.warn(_('\nTo prevent this mistake in your local repository,\n'
> + 'add to Mercurial.ini or .hg/hgrc:\n'
> + '\n'
> + '[hooks]\n'
> + 'pretxncommit.crlf = python:hgext.win32text.forbidcrlf\n'
> + '\n'
> + 'and also consider adding:\n'
> + '\n'
> + '[extensions]\n'
> + 'hgext.win32text =\n'
> + '[encode]\n'
> + '** = cleverencode:\n'
> + '[decode]\n'
> + '** = cleverdecode:\n'))
> + return halt
> diff --git a/tests/test-win32text b/tests/test-win32text
> new file mode 100644
> --- /dev/null
> +++ b/tests/test-win32text
> @@ -0,0 +1,56 @@
> +#!/bin/sh
> +
> +hg init
> +echo '[hooks]' >> .hg/hgrc
> +echo 'pretxncommit.crlf = python:hgext.win32text.forbidcrlf' >> .hg/hgrc
> +echo 'pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf' >> .hg/hgrc
> +cat .hg/hgrc
> +echo
> +
> +echo hello > f
> +hg add f
> +hg ci -m 1 -d'0 0'
> +echo
> +
> +unix2dos f
> +hg ci -m 2 -d'0 0'
> +hg revert -a
> +echo
> +
> +mkdir d
> +echo hello > d/f2
> +unix2dos d/f2
> +hg add d/f2
> +hg ci -m 3 -d'0 0'
> +hg revert -a
> +rm d/f2
> +echo
> +
> +hg rem f
> +hg ci -m 4 -d'0 0'
> +echo
> +
> +printf 'hello\x00\x0D\x0A' > bin
> +hg add bin
> +hg ci -m 5 -d'0 0'
> +hg log -v
> +echo
> +
> +hg clone . dupe
> +echo
> +for x in a b c d; do echo content > dupe/$x; done
> +hg -R dupe add
> +unix2dos dupe/b dupe/c dupe/d
> +hg -R dupe ci -m a -d'0 0' dupe/a
> +hg -R dupe ci -m b/c -d'0 0' dupe/[bc]
> +hg -R dupe ci -m d -d'0 0' dupe/d
> +hg -R dupe log -v
> +echo
> +
> +hg pull dupe
> +echo
> +
> +hg log -v
> +echo
> +
> +# XXX missing tests for encode/decode hooks
> diff --git a/tests/test-win32text.out b/tests/test-win32text.out
> new file mode 100644
> --- /dev/null
> +++ b/tests/test-win32text.out
> @@ -0,0 +1,157 @@
> +[hooks]
> +pretxncommit.crlf = python:hgext.win32text.forbidcrlf
> +pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf
> +
> +
> +Attempt to commit or push text file(s) using CRLF line endings
> +in b1aa5cde7ff4: f
> +transaction abort!
> +rollback completed
> +abort: pretxncommit.crlf hook failed
> +reverting f
> +
> +Attempt to commit or push text file(s) using CRLF line endings
> +in 88b17af74937: d/f2
> +transaction abort!
> +rollback completed
> +abort: pretxncommit.crlf hook failed
> +forgetting d/f2
> +
> +
> +changeset: 2:a55cab36df04
> +tag: tip
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: bin
> +description:
> +5
> +
> +
> +changeset: 1:c72a7d1d0907
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: f
> +description:
> +4
> +
> +
> +changeset: 0:fcf06d5c4e1d
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: f
> +description:
> +1
> +
> +
> +
> +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +
> +adding dupe/a
> +adding dupe/b
> +adding dupe/c
> +adding dupe/d
> +changeset: 5:81c49ee61396
> +tag: tip
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: d
> +description:
> +d
> +
> +
> +changeset: 4:02184785bcac
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: b c
> +description:
> +b/c
> +
> +
> +changeset: 3:36e70ffe2c3d
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: a
> +description:
> +a
> +
> +
> +changeset: 2:a55cab36df04
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: bin
> +description:
> +5
> +
> +
> +changeset: 1:c72a7d1d0907
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: f
> +description:
> +4
> +
> +
> +changeset: 0:fcf06d5c4e1d
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: f
> +description:
> +1
> +
> +
> +
> +pulling from dupe
> +searching for changes
> +adding changesets
> +adding manifests
> +adding file changes
> +added 3 changesets with 4 changes to 4 files
> +Attempt to commit or push text file(s) using CRLF line endings
> +in 02184785bcac: b
> +in 02184785bcac: c
> +in 81c49ee61396: d
> +
> +To prevent this mistake in your local repository,
> +add to Mercurial.ini or .hg/hgrc:
> +
> +[hooks]
> +pretxncommit.crlf = python:hgext.win32text.forbidcrlf
> +
> +and also consider adding:
> +
> +[extensions]
> +hgext.win32text =
> +[encode]
> +** = cleverencode:
> +[decode]
> +** = cleverdecode:
> +transaction abort!
> +rollback completed
> +abort: pretxnchangegroup.crlf hook failed
> +
> +changeset: 2:a55cab36df04
> +tag: tip
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: bin
> +description:
> +5
> +
> +
> +changeset: 1:c72a7d1d0907
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: f
> +description:
> +4
> +
> +
> +changeset: 0:fcf06d5c4e1d
> +user: test
> +date: Thu Jan 01 00:00:00 1970 +0000
> +files: f
> +description:
> +1
> +
> +
> +
More information about the Mercurial-devel
mailing list