# HG changeset patch # User Matt Mackall # Date 1285891798 18000 # Node ID 10dcfba4f16d42f2fd80faf91818a0d6607591da # Parent e356c5c21b15e6798270c3d4335d47a19abd2888# Parent bb324910e40aa330e222eba733f5675c8059a090 merge with i18n diff -r e356c5c21b15 -r 10dcfba4f16d doc/hgrc.5.txt --- a/doc/hgrc.5.txt Thu Sep 30 14:07:57 2010 -0300 +++ b/doc/hgrc.5.txt Thu Sep 30 19:09:58 2010 -0500 @@ -951,8 +951,9 @@ third-party tools like email notification hooks can construct URLs. Example: ``http://hgserver/repos/``. ``cacerts`` - Path to file containing a list of PEM encoded certificate authorities - that may be used to verify an SSL server's identity. The form must be + Path to file containing a list of PEM encoded certificate authority + certificates. If specified on the client, then it will verify the identity + of remote HTTPS servers with these certificates. The form must be as follows:: -----BEGIN CERTIFICATE----- @@ -962,8 +963,8 @@ ... (certificate in base64 PEM encoding) ... -----END CERTIFICATE----- - This feature is only supported when using Python 2.6. If you wish to - use it with earlier versions of Python, install the backported + This feature is only supported when using Python 2.6 or later. If you wish + to use it with earlier versions of Python, install the backported version of the ssl library that is available from ``http://pypi.python.org``. diff -r e356c5c21b15 -r 10dcfba4f16d mercurial/help/urls.txt --- a/mercurial/help/urls.txt Thu Sep 30 14:07:57 2010 -0300 +++ b/mercurial/help/urls.txt Thu Sep 30 19:09:58 2010 -0500 @@ -18,6 +18,9 @@ possible if the feature is explicitly enabled on the remote Mercurial server. +Note that the security of HTTPS URLs depends on proper configuration of +web.cacerts. + Some notes about using SSH with Mercurial: - SSH requires an accessible shell account on the destination machine diff -r e356c5c21b15 -r 10dcfba4f16d mercurial/patch.py --- a/mercurial/patch.py Thu Sep 30 14:07:57 2010 -0300 +++ b/mercurial/patch.py Thu Sep 30 19:09:58 2010 -0500 @@ -1184,7 +1184,9 @@ gp.path = pathstrip(gp.path, strip - 1)[1] if gp.oldpath: gp.oldpath = pathstrip(gp.oldpath, strip - 1)[1] - if gp.op in ('COPY', 'RENAME'): + # Binary patches really overwrite target files, copying them + # will just make it fails with "target file exists" + if gp.op in ('COPY', 'RENAME') and not gp.binary: copyfn(gp.oldpath, gp.path, cwd) changed[gp.path] = gp else: @@ -1567,6 +1569,9 @@ header.append('new file mode %s\n' % mode) elif ctx2.flags(f): losedatafn(f) + # In theory, if tn was copied or renamed we should check + # if the source is binary too but the copy record already + # forces git mode. if util.binary(tn): if opts.git: dodiff = 'binary' @@ -1586,7 +1591,7 @@ else: header.append('deleted file mode %s\n' % gitmode[man1.flags(f)]) - elif not to: + elif not to or util.binary(to): # regular diffs cannot represent empty file deletion losedatafn(f) else: diff -r e356c5c21b15 -r 10dcfba4f16d mercurial/url.py --- a/mercurial/url.py Thu Sep 30 14:07:57 2010 -0300 +++ b/mercurial/url.py Thu Sep 30 19:09:58 2010 -0500 @@ -7,7 +7,7 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -import urllib, urllib2, urlparse, httplib, os, re, socket, cStringIO +import urllib, urllib2, urlparse, httplib, os, re, socket, cStringIO, time from i18n import _ import keepalive, util @@ -469,6 +469,31 @@ _generic_start_transaction(self, h, req) return keepalive.HTTPHandler._start_transaction(self, h, req) +def _verifycert(cert, hostname): + '''Verify that cert (in socket.getpeercert() format) matches hostname and is + valid at this time. CRLs and subjectAltName are not handled. + + Returns error message if any problems are found and None on success. + ''' + if not cert: + return _('no certificate received') + notafter = cert.get('notAfter') + if notafter and time.time() > ssl.cert_time_to_seconds(notafter): + return _('certificate expired %s') % notafter + notbefore = cert.get('notBefore') + if notbefore and time.time() < ssl.cert_time_to_seconds(notbefore): + return _('certificate not valid before %s') % notbefore + dnsname = hostname.lower() + for s in cert.get('subject', []): + key, value = s[0] + if key == 'commonName': + certname = value.lower() + if (certname == dnsname or + '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]): + return None + return _('certificate is for %s') % certname + return _('no commonName found in certificate') + if has_https: class BetterHTTPS(httplib.HTTPSConnection): send = keepalive.safesend @@ -484,7 +509,11 @@ self.sock = _ssl_wrap_socket(sock, self.key_file, self.cert_file, cert_reqs=CERT_REQUIRED, ca_certs=cacerts) - self.ui.debug(_('server identity verification succeeded\n')) + msg = _verifycert(self.sock.getpeercert(), self.host) + if msg: + raise util.Abort('%s certificate error: %s' % (self.host, msg)) + self.ui.debug(_('%s certificate successfully verified\n') % + self.host) else: httplib.HTTPSConnection.connect(self) diff -r e356c5c21b15 -r 10dcfba4f16d tests/test-diff-upgrade --- a/tests/test-diff-upgrade Thu Sep 30 14:07:57 2010 -0300 +++ b/tests/test-diff-upgrade Thu Sep 30 19:09:58 2010 -0500 @@ -20,6 +20,7 @@ chmod +x unsetexec echo binary > binary python -c "file('rmbinary', 'wb').write('\0')" +python -c "file('bintoregular', 'wb').write('\0')" hg ci -Am addfiles echo regular >> regular echo newregular >> newregular @@ -28,6 +29,7 @@ rm rmregular echo exec >> exec echo newexec > newexec +echo bintoregular > bintoregular chmod +x newexec rm rmexec chmod +x setexec @@ -43,10 +45,11 @@ echo '% git=no: git diff for single regular file' hg autodiff --git=yes regular -echo '% git=auto: regular diff for regular files and removals' -hg autodiff --git=auto regular newregular rmregular rmbinary rmexec +echo '% git=auto: regular diff for regular files and non-binary removals' +hg autodiff --git=auto regular newregular rmregular rmexec -for f in exec newexec setexec unsetexec binary newbinary newempty rmempty; do +for f in exec newexec setexec unsetexec binary newbinary newempty rmempty \ + rmbinary bintoregular; do echo '% git=auto: git diff for' $f hg autodiff --git=auto $f done diff -r e356c5c21b15 -r 10dcfba4f16d tests/test-diff-upgrade.out --- a/tests/test-diff-upgrade.out Thu Sep 30 14:07:57 2010 -0300 +++ b/tests/test-diff-upgrade.out Thu Sep 30 19:09:58 2010 -0500 @@ -1,5 +1,6 @@ % make a combination of new, changed and deleted file adding binary +adding bintoregular adding exec adding regular adding rmbinary @@ -17,40 +18,42 @@ removing rmexec removing rmregular % git=no: regular diff for all files -diff -r b3f053cd7c7f binary +diff -r a66d19b9302d binary Binary file binary has changed -diff -r b3f053cd7c7f exec +diff -r a66d19b9302d bintoregular +Binary file bintoregular has changed +diff -r a66d19b9302d exec --- a/exec +++ b/exec @@ -1,1 +1,2 @@ exec +exec -diff -r b3f053cd7c7f newbinary +diff -r a66d19b9302d newbinary Binary file newbinary has changed -diff -r b3f053cd7c7f newexec +diff -r a66d19b9302d newexec --- /dev/null +++ b/newexec @@ -0,0 +1,1 @@ +newexec -diff -r b3f053cd7c7f newregular +diff -r a66d19b9302d newregular --- /dev/null +++ b/newregular @@ -0,0 +1,1 @@ +newregular -diff -r b3f053cd7c7f regular +diff -r a66d19b9302d regular --- a/regular +++ b/regular @@ -1,1 +1,2 @@ regular +regular -diff -r b3f053cd7c7f rmbinary +diff -r a66d19b9302d rmbinary Binary file rmbinary has changed -diff -r b3f053cd7c7f rmexec +diff -r a66d19b9302d rmexec --- a/rmexec +++ /dev/null @@ -1,1 +0,0 @@ -rmexec -diff -r b3f053cd7c7f rmregular +diff -r a66d19b9302d rmregular --- a/rmregular +++ /dev/null @@ -1,1 +0,0 @@ @@ -62,32 +65,30 @@ @@ -1,1 +1,2 @@ regular +regular -% git=auto: regular diff for regular files and removals -diff -r b3f053cd7c7f newregular +% git=auto: regular diff for regular files and non-binary removals +diff -r a66d19b9302d newregular --- /dev/null +++ b/newregular @@ -0,0 +1,1 @@ +newregular -diff -r b3f053cd7c7f regular +diff -r a66d19b9302d regular --- a/regular +++ b/regular @@ -1,1 +1,2 @@ regular +regular -diff -r b3f053cd7c7f rmbinary -Binary file rmbinary has changed -diff -r b3f053cd7c7f rmexec +diff -r a66d19b9302d rmexec --- a/rmexec +++ /dev/null @@ -1,1 +0,0 @@ -rmexec -diff -r b3f053cd7c7f rmregular +diff -r a66d19b9302d rmregular --- a/rmregular +++ /dev/null @@ -1,1 +0,0 @@ -rmregular % git=auto: git diff for exec -diff -r b3f053cd7c7f exec +diff -r a66d19b9302d exec --- a/exec +++ b/exec @@ -1,1 +1,2 @@ @@ -129,56 +130,71 @@ % git=auto: git diff for rmempty diff --git a/rmempty b/rmempty deleted file mode 100644 +% git=auto: git diff for rmbinary +diff --git a/rmbinary b/rmbinary +deleted file mode 100644 +Binary file rmbinary has changed +% git=auto: git diff for bintoregular +diff --git a/bintoregular b/bintoregular +index f76dd238ade08917e6712764a16a22005a50573d..9c42f2b6427d8bf034b7bc23986152dc01bfd3ab +GIT binary patch +literal 13 +Uc$`bh%qz(+N=+}#Ni5<5043uE82|tP + % git=warn: regular diff with data loss warnings -diff -r b3f053cd7c7f binary +diff -r a66d19b9302d binary Binary file binary has changed -diff -r b3f053cd7c7f exec +diff -r a66d19b9302d bintoregular +Binary file bintoregular has changed +diff -r a66d19b9302d exec --- a/exec +++ b/exec @@ -1,1 +1,2 @@ exec +exec -diff -r b3f053cd7c7f newbinary +diff -r a66d19b9302d newbinary Binary file newbinary has changed -diff -r b3f053cd7c7f newexec +diff -r a66d19b9302d newexec --- /dev/null +++ b/newexec @@ -0,0 +1,1 @@ +newexec -diff -r b3f053cd7c7f newregular +diff -r a66d19b9302d newregular --- /dev/null +++ b/newregular @@ -0,0 +1,1 @@ +newregular -diff -r b3f053cd7c7f regular +diff -r a66d19b9302d regular --- a/regular +++ b/regular @@ -1,1 +1,2 @@ regular +regular -diff -r b3f053cd7c7f rmbinary +diff -r a66d19b9302d rmbinary Binary file rmbinary has changed -diff -r b3f053cd7c7f rmexec +diff -r a66d19b9302d rmexec --- a/rmexec +++ /dev/null @@ -1,1 +0,0 @@ -rmexec -diff -r b3f053cd7c7f rmregular +diff -r a66d19b9302d rmregular --- a/rmregular +++ /dev/null @@ -1,1 +0,0 @@ -rmregular data lost for: binary +data lost for: bintoregular data lost for: newbinary data lost for: newempty data lost for: newexec +data lost for: rmbinary data lost for: rmempty data lost for: setexec data lost for: unsetexec % git=abort: fail on execute bit change abort: losing data for setexec % git=abort: succeed on regular file -diff -r b3f053cd7c7f regular +diff -r a66d19b9302d regular --- a/regular +++ b/regular @@ -1,1 +1,2 @@ diff -r e356c5c21b15 -r 10dcfba4f16d tests/test-doctest.py --- a/tests/test-doctest.py Thu Sep 30 14:07:57 2010 -0300 +++ b/tests/test-doctest.py Thu Sep 30 19:09:58 2010 -0500 @@ -5,18 +5,13 @@ import doctest import mercurial.changelog -# test doctest from changelog - doctest.testmod(mercurial.changelog) -import mercurial.httprepo -doctest.testmod(mercurial.httprepo) - -import mercurial.util -doctest.testmod(mercurial.util) - import mercurial.dagparser doctest.testmod(mercurial.dagparser, optionflags=doctest.NORMALIZE_WHITESPACE) +import mercurial.url +doctest.testmod(mercurial.url) + import hgext.convert.cvsps doctest.testmod(hgext.convert.cvsps) diff -r e356c5c21b15 -r 10dcfba4f16d tests/test-git-import --- a/tests/test-git-import Thu Sep 30 14:07:57 2010 -0300 +++ b/tests/test-git-import Thu Sep 30 19:09:58 2010 -0500 @@ -1,5 +1,7 @@ #!/bin/sh +. $TESTDIR/helpers.sh + hg init a cd a @@ -226,5 +228,20 @@ copy to foo3 EOF hg tip -q +cat foo3 -cat foo3 +echo % move text file and patch as binary +echo a > text2 +hg ci -Am0 +hg import -d "1000000 0" -m rename-as-binary - <<"EOF" +diff --git a/text2 b/binary2 +rename from text2 +rename to binary2 +index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757 +GIT binary patch +literal 5 +Mc$`b*O5$Pw00T?_*Z=?k + +EOF +cat binary2 | repr +hg st --copies --change . \ No newline at end of file diff -r e356c5c21b15 -r 10dcfba4f16d tests/test-git-import.out --- a/tests/test-git-import.out Thu Sep 30 14:07:57 2010 -0300 +++ b/tests/test-git-import.out Thu Sep 30 19:09:58 2010 -0500 @@ -80,3 +80,10 @@ applying patch from stdin 14:c4cd9cdeaa74 foo +% move text file and patch as binary +adding text2 +applying patch from stdin +'a\nb\n\x00' +A binary2 + text2 +R text2 diff -r e356c5c21b15 -r 10dcfba4f16d tests/test-url.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-url.py Thu Sep 30 19:09:58 2010 -0500 @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +def check(a, b): + if a != b: + print (a, b) + +from mercurial.url import _verifycert + +# Test non-wildcard certificates +check(_verifycert({'subject': ((('commonName', 'example.com'),),)}, 'example.com'), + None) +check(_verifycert({'subject': ((('commonName', 'example.com'),),)}, 'www.example.com'), + 'certificate is for example.com') +check(_verifycert({'subject': ((('commonName', 'www.example.com'),),)}, 'example.com'), + 'certificate is for www.example.com') + +# Test wildcard certificates +check(_verifycert({'subject': ((('commonName', '*.example.com'),),)}, 'www.example.com'), + None) +check(_verifycert({'subject': ((('commonName', '*.example.com'),),)}, 'example.com'), + 'certificate is for *.example.com') +check(_verifycert({'subject': ((('commonName', '*.example.com'),),)}, 'w.w.example.com'), + 'certificate is for *.example.com') + +# Avoid some pitfalls +check(_verifycert({'subject': ((('commonName', '*.foo'),),)}, 'foo'), + 'certificate is for *.foo') +check(_verifycert({'subject': ((('commonName', '*o'),),)}, 'foo'), + 'certificate is for *o') + +import time +lastyear = time.gmtime().tm_year - 1 +nextyear = time.gmtime().tm_year + 1 +check(_verifycert({'notAfter': 'May 9 00:00:00 %s GMT' % lastyear}, 'example.com'), + 'certificate expired May 9 00:00:00 %s GMT' % lastyear) +check(_verifycert({'notBefore': 'May 9 00:00:00 %s GMT' % nextyear}, 'example.com'), + 'certificate not valid before May 9 00:00:00 %s GMT' % nextyear) +check(_verifycert({'notAfter': 'Sep 29 15:29:48 %s GMT' % nextyear, 'subject': ()}, 'example.com'), + 'no commonName found in certificate') +check(_verifycert(None, 'example.com'), + 'no certificate received')