# HG changeset patch # User Matt Mackall # Date 1443240647 18000 # Node ID 0224d22ef5d815c86d7ebce6644f056c406acbfd # Parent a672cc61ab1de50d931f215d89fafc22906ba356# Parent f31ddc9bfa5f8f28cd899e907a0a9edb072b3e9a merge with stable diff -r f31ddc9bfa5f -r 0224d22ef5d8 Makefile --- a/Makefile Fri Sep 25 13:30:49 2015 -0700 +++ b/Makefile Fri Sep 25 23:10:47 2015 -0500 @@ -157,14 +157,12 @@ N=`cd dist && echo mercurial-*.mpkg | sed 's,\.mpkg$$,,'` && hdiutil create -srcfolder dist/$$N.mpkg/ -scrub -volname "$$N" -ov packages/osx/$$N.dmg rm -rf dist/mercurial-*.mpkg -debian-jessie: - mkdir -p packages/debian-jessie - contrib/builddeb - mv debbuild/*.deb packages/debian-jessie - rm -rf debbuild +deb: + mkdir -p packages/debian-unknown + contrib/builddeb --release unknown docker-debian-jessie: - mkdir -p packages/debian/jessie + mkdir -p packages/debian-jessie contrib/dockerdeb jessie fedora20: diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/builddeb --- a/contrib/builddeb Fri Sep 25 13:30:49 2015 -0700 +++ b/contrib/builddeb Fri Sep 25 23:10:47 2015 -0500 @@ -7,13 +7,23 @@ . $(dirname $0)/packagelib.sh BUILD=1 -DEBBUILDDIR="$PWD/debbuild" +CLEANUP=1 +DEBVERSION=jessie while [ "$1" ]; do case "$1" in - --prepare ) + --release ) + shift + DEBVERSION="$1" + shift + ;; + --cleanup ) shift BUILD= ;; + --build ) + shift + CLEANUP= + ;; --debbuilddir ) shift DEBBUILDDIR="$1" @@ -26,10 +36,9 @@ esac done -set -u +trap "if [ '$CLEANUP' ] ; then rm -r '$PWD/debian' ; fi" EXIT -rm -rf $DEBBUILDDIR -mkdir -p $DEBBUILDDIR +set -u if [ ! -d .hg ]; then echo 'You are not inside a Mercurial repository!' 1>&2 @@ -38,25 +47,38 @@ gethgversion -cp -r $PWD/contrib/debian $DEBBUILDDIR/DEBIAN -chmod -R 0755 $DEBBUILDDIR/DEBIAN - -control=$DEBBUILDDIR/DEBIAN/control - -# This looks like sed -i, but sed -i behaves just differently enough -# between BSD and GNU sed that I gave up and did the dumb thing. -sed "s/__VERSION__/$version/" < $control > $control.tmp -mv $control.tmp $control +control=debian/control +changelog=debian/changelog if [ "$BUILD" ]; then - dpkg-deb --build $DEBBUILDDIR - mv $DEBBUILDDIR.deb $DEBBUILDDIR/mercurial-$version-$release.deb - if [ $? = 0 ]; then - echo - echo "Built packages for $version-$release:" - find $DEBBUILDDIR/ -type f -newer $control + if [ -d debian ] ; then + echo "Error! debian control directory already exists!" + exit 1 fi -else - echo "Prepared sources for $version-$release $control are in $DEBBUILDDIR - use like:" - echo "dpkg-deb --build $DEBBUILDDIR" + + cp -r $PWD/contrib/debian debian + chmod -R 0755 debian + + # This looks like sed -i, but sed -i behaves just differently enough + # between BSD and GNU sed that I gave up and did the dumb thing. + sed "s/__VERSION__/$version/" < $changelog > $changelog.tmp + date=$(date --rfc-2822) + sed "s/__DATE__/$date/" < $changelog.tmp > $changelog + rm $changelog.tmp + + debuild -us -uc -b + if [ $? != 0 ]; then + echo 'debuild failed!' + exit 1 + fi + fi +if [ "$CLEANUP" ] ; then + echo + OUTPUTDIR=${OUTPUTDIR:=packages/debian-$DEBVERSION} + find ../mercurial*.deb ../mercurial_*.build ../mercurial_*.changes \ + -type f -newer $control -print0 | \ + xargs -Inarf -0 mv narf "$OUTPUTDIR" + echo "Built packages for $version-$release:" + find "$OUTPUTDIR" -type f -newer $control -name '*.deb' +fi diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/buildrpm --- a/contrib/buildrpm Fri Sep 25 13:30:49 2015 -0700 +++ b/contrib/buildrpm Fri Sep 25 23:10:47 2015 -0500 @@ -56,6 +56,7 @@ RPMPYTHONVER=%{nil} fi +mkdir -p $RPMBUILDDIR/SOURCES $HG archive -t tgz $RPMBUILDDIR/SOURCES/mercurial-$version-$release.tar.gz if [ "$PYTHONVER" ]; then ( @@ -79,6 +80,7 @@ ) fi +mkdir -p $RPMBUILDDIR/SPECS rpmspec=$RPMBUILDDIR/SPECS/mercurial.spec sed -e "s,^Version:.*,Version: $version," \ diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/check-code.py --- a/contrib/check-code.py Fri Sep 25 13:30:49 2015 -0700 +++ b/contrib/check-code.py Fri Sep 25 23:10:47 2015 -0500 @@ -291,6 +291,8 @@ (r'os\.path\.join\(.*, *(""|\'\')\)', "use pathutil.normasprefix(path) instead of os.path.join(path, '')"), (r'\s0[0-7]+\b', 'legacy octal syntax; use "0o" prefix instead of "0"'), + # XXX only catch mutable arguments on the first line of the definition + (r'def.*[( ]\w+=\{\}', "don't use mutable default arguments"), ], # warnings [ diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/debian/cacerts.rc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/debian/cacerts.rc Fri Sep 25 23:10:47 2015 -0500 @@ -0,0 +1,5 @@ +# This config file points Mercurial at the system-wide certificate +# store from the ca-certificates package. + +[web] +cacerts = /etc/ssl/certs/ca-certificates.crt diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/debian/changelog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/debian/changelog Fri Sep 25 23:10:47 2015 -0500 @@ -0,0 +1,5 @@ +mercurial (__VERSION__) unstable; urgency=medium + + * Automated build performed by upstream. + + -- Mercurial Devel __DATE__ diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/debian/compat --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/debian/compat Fri Sep 25 23:10:47 2015 -0500 @@ -0,0 +1,1 @@ +9 diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/debian/control --- a/contrib/debian/control Fri Sep 25 13:30:49 2015 -0700 +++ b/contrib/debian/control Fri Sep 25 23:10:47 2015 -0500 @@ -1,9 +1,47 @@ -Package: mercurial -Version: __VERSION__ +Source: mercurial Section: vcs Priority: optional +Maintainer: Mercurial Developers +Build-Depends: + debhelper (>= 7), + dh-python, + python-all +Standards-Version: 3.9.4 +X-Python-Version: >= 2.6 + +Package: mercurial +Depends: + python, + ${shlibs:Depends}, + ${misc:Depends}, + ${python:Depends}, + mercurial-common (= ${source:Version}) +Architecture: any +Description: fast, easy to use, distributed revision control tool. + Mercurial is a fast, lightweight Source Control Management system designed + for efficient handling of very large distributed projects. + . + Its features include: + * O(1) delta-compressed file storage and retrieval scheme + * Complete cross-indexing of files and changesets for efficient exploration + of project history + * Robust SHA1-based integrity checking and append-only storage model + * Decentralized development model with arbitrary merging between trees + * Easy-to-use command-line interface + * Integrated stand-alone web interface + * Small Python codebase + +Package: mercurial-common Architecture: all -Depends: python -Conflicts: mercurial-common -Maintainer: Mercurial Developers -Description: Mercurial (probably nightly) package built by upstream. +Depends: + ${misc:Depends}, + ${python:Depends}, +Recommends: mercurial (= ${source:Version}), ca-certificates +Breaks: mercurial (<< ${source:Version}) +Replaces: mercurial (<< 2.6.3) +Description: easy-to-use, scalable distributed version control system (common files) + Mercurial is a fast, lightweight Source Control Management system designed + for efficient handling of very large distributed projects. + . + This package contains the architecture independent components of Mercurial, + and is generally useless without the mercurial package. diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/debian/copyright --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/debian/copyright Fri Sep 25 23:10:47 2015 -0500 @@ -0,0 +1,27 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: mercurial +Source: http://www.selenic.com/mercurial/ + +Files: * +Copyright: 2005-2015, Matt Mackall and others. +License: GPL-2+ + This program is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + . + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU General Public License for more + details. + . + You should have received a copy of the GNU General Public + License along with this package; if not, write to the Free + Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301 USA + . + On Debian systems, the full text of the GNU General Public + License version 2 can be found in the file + `/usr/share/common-licenses/GPL-2'. diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/debian/hgkpath.rc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/debian/hgkpath.rc Fri Sep 25 23:10:47 2015 -0500 @@ -0,0 +1,2 @@ +[hgk] +path = /usr/share/mercurial/hgk diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/debian/rules --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/debian/rules Fri Sep 25 23:10:47 2015 -0500 @@ -0,0 +1,36 @@ +#!/usr/bin/make -f +# Uncomment this to turn on verbose mode. +# export DH_VERBOSE=1 + +CPUS=$(shell cat /proc/cpuinfo | grep -E ^processor | wc -l) + +%: + dh $@ --with python2 + +override_dh_auto_test: + http_proxy='' dh_auto_test -- TESTFLAGS="-j$(CPUS)" + +override_dh_python2: + dh_python2 + find debian/mercurial/usr/share -type d -empty -delete + +override_dh_install: + python$(PYVERS) setup.py install --root $(CURDIR)/debian/mercurial --install-layout=deb + # remove arch-independent python stuff + find $(CURDIR)/debian/mercurial/usr/lib \ + ! -name '*.so' ! -type d -delete , \ + -type d -empty -delete + python$(PYVERS) setup.py install --root $(CURDIR)/debian/mercurial-common --install-layout=deb + make install-doc PREFIX=$(CURDIR)/debian/mercurial-common/usr + # remove arch-dependent python stuff + find $(CURDIR)/debian/mercurial-common/usr/lib \ + -name '*.so' ! -type d -delete , \ + -type d -empty -delete + cp contrib/hg-ssh $(CURDIR)/debian/mercurial-common/usr/bin + mkdir -p $(CURDIR)/debian/mercurial-common/usr/share/mercurial + cp contrib/hgk $(CURDIR)/debian/mercurial-common/usr/share/mercurial + mkdir -p $(CURDIR)/debian/mercurial-common/etc/mercurial/hgrc.d/ + cp contrib/debian/*.rc $(CURDIR)/debian/mercurial-common/etc/mercurial/hgrc.d/ + mkdir -p $(CURDIR)/debian/mercurial-common/usr/share/bash-completion/completions + cp contrib/bash_completion $(CURDIR)/debian/mercurial-common/usr/share/bash-completion/completions/mercurial + rm $(CURDIR)/debian/mercurial-common/usr/bin/hg diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/dockerdeb --- a/contrib/dockerdeb Fri Sep 25 13:30:49 2015 -0700 +++ b/contrib/dockerdeb Fri Sep 25 23:10:47 2015 -0500 @@ -8,32 +8,27 @@ checkdocker +DEBPLATFORM="$1" PLATFORM="debian-$1" shift # extra params are passed to build process +OUTPUTDIR=${OUTPUTDIR:=$ROOTDIR/packages/$PLATFORM} + initcontainer $PLATFORM -DEBBUILDDIR=$ROOTDIR/packages/$PLATFORM -contrib/builddeb --debbuilddir $DEBBUILDDIR/staged --prepare +# debuild only appears to be able to save built debs etc to .., so we +# have to share the .. of the current directory with the docker +# container and hope it's writable. Whee. +dn=$(basename $PWD) -DSHARED=/mnt/shared/ if [ $(uname) = "Darwin" ] ; then - $DOCKER run -u $DBUILDUSER --rm -v $DEBBUILDDIR:$DSHARED -v $PWD:/mnt/hg $CONTAINER \ - sh -c "cd /mnt/hg && make clean && make local" + $DOCKER run -u $DBUILDUSER --rm -v $PWD/..:/mnt $CONTAINER \ + sh -c "cd /mnt/$dn && make clean && make local" fi -$DOCKER run -u $DBUILDUSER --rm -v $DEBBUILDDIR:$DSHARED -v $PWD:/mnt/hg $CONTAINER \ - sh -c "cd /mnt/hg && make PREFIX=$DSHARED/staged/usr install" -$DOCKER run -u $DBUILDUSER --rm -v $DEBBUILDDIR:$DSHARED $CONTAINER \ - dpkg-deb --build $DSHARED/staged +$DOCKER run -u $DBUILDUSER --rm -v $PWD/..:/mnt $CONTAINER \ + sh -c "cd /mnt/$dn && DEB_BUILD_OPTIONS='${DEB_BUILD_OPTIONS:=}' contrib/builddeb --build --release $DEBPLATFORM" +contrib/builddeb --cleanup --release $DEBPLATFORM if [ $(uname) = "Darwin" ] ; then - $DOCKER run -u $DBUILDUSER --rm -v $DEBBUILDDIR:$DSHARED -v $PWD:/mnt/hg $CONTAINER \ - sh -c "cd /mnt/hg && make clean" + $DOCKER run -u $DBUILDUSER --rm -v $PWD/..:/mnt $CONTAINER \ + sh -c "cd /mnt/$dn && make clean" fi - -gethgversion - -rm -r $DEBBUILDDIR/staged -mv $DEBBUILDDIR/staged.deb $DEBBUILDDIR/mercurial-$version-$release.deb - -echo -echo "Build complete - results can be found in $DEBBUILDDIR" diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/import-checker.py --- a/contrib/import-checker.py Fri Sep 25 13:30:49 2015 -0700 +++ b/contrib/import-checker.py Fri Sep 25 23:10:47 2015 -0500 @@ -164,7 +164,7 @@ for m in ['msvcrt', '_winreg']: yield m # These get missed too - for m in 'ctypes', 'email': + for m in 'ctypes', 'email', 'multiprocessing': yield m yield 'builtins' # python3 only for m in 'fcntl', 'grp', 'pwd', 'termios': # Unix only @@ -200,8 +200,7 @@ for name in files: if name == '__init__.py': continue - if not (name.endswith('.py') or name.endswith('.so') - or name.endswith('.pyd')): + if not name.endswith(('.py', '.so', '.pyc', '.pyo', '.pyd')): continue full_path = os.path.join(top, name) rel_path = full_path[len(libpath) + 1:] diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/revsetbenchmarks.py --- a/contrib/revsetbenchmarks.py Fri Sep 25 13:30:49 2015 -0700 +++ b/contrib/revsetbenchmarks.py Fri Sep 25 23:10:47 2015 -0500 @@ -33,6 +33,8 @@ """update the repo to a revision""" try: check_call(['hg', 'update', '--quiet', '--check', str(rev)]) + check_output(['make', 'local'], + stderr=None) # suppress output except for error/warning except CalledProcessError as exc: print >> sys.stderr, 'update to revision %s failed, aborting' % rev sys.exit(exc.returncode) diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/showstack.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/showstack.py Fri Sep 25 23:10:47 2015 -0500 @@ -0,0 +1,17 @@ +# showstack.py - extension to dump a Python stack trace on signal +# +# binds to both SIGQUIT (Ctrl-\) and SIGINFO (Ctrl-T on BSDs) + +import sys, signal, traceback + +def sigshow(*args): + sys.stderr.write("\n") + traceback.print_stack(args[1], limit=10, file=sys.stderr) + sys.stderr.write("----\n") + +def extsetup(ui): + signal.signal(signal.SIGQUIT, sigshow) + try: + signal.signal(signal.SIGINFO, sigshow) + except AttributeError: + pass diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/vagrant/Vagrantfile --- a/contrib/vagrant/Vagrantfile Fri Sep 25 13:30:49 2015 -0700 +++ b/contrib/vagrant/Vagrantfile Fri Sep 25 23:10:47 2015 -0500 @@ -1,9 +1,8 @@ # -*- mode: ruby -*- Vagrant.configure('2') do |config| - # Debian 7.4 32-bit i386 without configuration management software - config.vm.box = "puppetlabs/debian-7.4-32-nocm" - #config.vm.box = "pnd/debian-wheezy32-basebox" + # Debian 8.1 x86_64 without configuration management software + config.vm.box = "debian/jessie64" config.vm.hostname = "tests" config.vm.define "tests" do |conf| diff -r f31ddc9bfa5f -r 0224d22ef5d8 contrib/vim/patchreview.txt --- a/contrib/vim/patchreview.txt Fri Sep 25 13:30:49 2015 -0700 +++ b/contrib/vim/patchreview.txt Fri Sep 25 23:10:47 2015 -0500 @@ -30,7 +30,7 @@ software development projects. This plugin provides that missing functionality. -It also improves on |:diffpatch|'s behaviour of creating the patched files in +It also improves on |:diffpatch|'s behavior of creating the patched files in the same directory as original file which can lead to project workspace pollution. diff -r f31ddc9bfa5f -r 0224d22ef5d8 doc/check-seclevel.py --- a/doc/check-seclevel.py Fri Sep 25 13:30:49 2015 -0700 +++ b/doc/check-seclevel.py Fri Sep 25 23:10:47 2015 -0500 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# checkseclevel - checking section title levels in each online help documents +# checkseclevel - checking section title levels in each online help document import sys, os import optparse diff -r f31ddc9bfa5f -r 0224d22ef5d8 doc/hgmanpage.py --- a/doc/hgmanpage.py Fri Sep 25 13:30:49 2015 -0700 +++ b/doc/hgmanpage.py Fri Sep 25 23:10:47 2015 -0500 @@ -18,11 +18,11 @@ 7 miscellaneous 8 system administration -Man pages are written *troff*, a text file formatting system. +Man pages are written in *troff*, a text file formatting system. See http://www.tldp.org/HOWTO/Man-Page for a start. -Man pages have no subsection only parts. +Man pages have no subsections only parts. Standard parts NAME , @@ -317,7 +317,7 @@ self._cnt = 0 self._indent = 2 if style == 'arabic': - # indentation depends on number of childrens + # indentation depends on number of children # and start value. self._indent = len(str(len(node.children))) self._indent += len(str(self._cnt)) + 1 diff -r f31ddc9bfa5f -r 0224d22ef5d8 hgext/blackbox.py --- a/hgext/blackbox.py Fri Sep 25 13:30:49 2015 -0700 +++ b/hgext/blackbox.py Fri Sep 25 23:10:47 2015 -0500 @@ -107,9 +107,11 @@ if blackbox: date = util.datestr(None, '%Y/%m/%d %H:%M:%S') user = util.getuser() + pid = str(os.getpid()) formattedmsg = msg[0] % msg[1:] try: - blackbox.write('%s %s> %s' % (date, user, formattedmsg)) + blackbox.write('%s %s (%s)> %s' % + (date, user, pid, formattedmsg)) except IOError as err: self.debug('warning: cannot write to blackbox.log: %s\n' % err.strerror) diff -r f31ddc9bfa5f -r 0224d22ef5d8 hgext/convert/__init__.py --- a/hgext/convert/__init__.py Fri Sep 25 13:30:49 2015 -0700 +++ b/hgext/convert/__init__.py Fri Sep 25 23:10:47 2015 -0500 @@ -316,6 +316,9 @@ ``convert.git.remoteprefix`` as a prefix followed by a /. The default is 'remote'. + :convert.git.skipsubmodules: does not convert root level .gitmodules files + or files with 160000 mode indicating a submodule. Default is False. + Perforce Source ############### diff -r f31ddc9bfa5f -r 0224d22ef5d8 hgext/convert/common.py --- a/hgext/convert/common.py Fri Sep 25 13:30:49 2015 -0700 +++ b/hgext/convert/common.py Fri Sep 25 23:10:47 2015 -0500 @@ -82,6 +82,13 @@ def after(self): pass + def targetfilebelongstosource(self, targetfilename): + """Returns true if the given targetfile belongs to the source repo. This + is useful when only a subdirectory of the target belongs to the source + repo.""" + # For normal full repo converts, this is always True. + return True + def setrevmap(self, revmap): """set the map of already-converted revisions""" pass diff -r f31ddc9bfa5f -r 0224d22ef5d8 hgext/convert/convcmd.py --- a/hgext/convert/convcmd.py Fri Sep 25 13:30:49 2015 -0700 +++ b/hgext/convert/convcmd.py Fri Sep 25 23:10:47 2015 -0500 @@ -120,6 +120,9 @@ item=file, total=self.filecount) return self.source.getfile(file, rev) + def targetfilebelongstosource(self, targetfilename): + return self.source.targetfilebelongstosource(targetfilename) + def lookuprev(self, rev): return self.source.lookuprev(rev) diff -r f31ddc9bfa5f -r 0224d22ef5d8 hgext/convert/filemap.py --- a/hgext/convert/filemap.py Fri Sep 25 13:30:49 2015 -0700 +++ b/hgext/convert/filemap.py Fri Sep 25 23:10:47 2015 -0500 @@ -42,6 +42,7 @@ self.include = {} self.exclude = {} self.rename = {} + self.targetprefixes = None if path: if self.parse(path): raise util.Abort(_('errors in filemap')) @@ -100,6 +101,30 @@ pass return '', name, '' + def istargetfile(self, filename): + """Return true if the given target filename is covered as a destination + of the filemap. This is useful for identifying what parts of the target + repo belong to the source repo and what parts don't.""" + if self.targetprefixes is None: + self.targetprefixes = set() + for before, after in self.rename.iteritems(): + self.targetprefixes.add(after) + + # If "." is a target, then all target files are considered from the + # source. + if not self.targetprefixes or '.' in self.targetprefixes: + return True + + filename = normalize(filename) + for pre, suf in rpairs(filename): + # This check is imperfect since it doesn't account for the + # include/exclude list, but it should work in filemaps that don't + # apply include/exclude to the same source directories they are + # renaming. + if pre in self.targetprefixes: + return True + return False + def __call__(self, name): if self.include: inc = self.lookup(name, self.include)[0] @@ -410,6 +435,9 @@ return files, ncopies, ncleanp2 + def targetfilebelongstosource(self, targetfilename): + return self.filemapper.istargetfile(targetfilename) + def getfile(self, name, rev): realname, realrev = rev return self.base.getfile(realname, realrev) diff -r f31ddc9bfa5f -r 0224d22ef5d8 hgext/convert/git.py --- a/hgext/convert/git.py Fri Sep 25 13:30:49 2015 -0700 +++ b/hgext/convert/git.py Fri Sep 25 23:10:47 2015 -0500 @@ -224,6 +224,8 @@ lcount = len(difftree) i = 0 + skipsubmodules = self.ui.configbool('convert', 'git.skipsubmodules', + False) def add(entry, f, isdest): seen.add(f) h = entry[3] @@ -232,6 +234,9 @@ renamesource = (not isdest and entry[4][0] == 'R') if f == '.gitmodules': + if skipsubmodules: + return + subexists[0] = True if entry[4] == 'D' or renamesource: subdeleted[0] = True @@ -239,7 +244,8 @@ else: changes.append(('.hgsub', '')) elif entry[1] == '160000' or entry[0] == ':160000': - subexists[0] = True + if not skipsubmodules: + subexists[0] = True else: if renamesource: h = hex(nullid) @@ -377,28 +383,31 @@ def getbookmarks(self): bookmarks = {} - # Interesting references in git are prefixed - prefix = 'refs/heads/' - prefixlen = len(prefix) + # Handle local and remote branches + remoteprefix = self.ui.config('convert', 'git.remoteprefix', 'remote') + reftypes = [ + # (git prefix, hg prefix) + ('refs/remotes/origin/', remoteprefix + '/'), + ('refs/heads/', '') + ] - # factor two commands - remoteprefix = self.ui.config('convert', 'git.remoteprefix', 'remote') - gitcmd = { remoteprefix + '/': 'git ls-remote --heads origin', - '': 'git show-ref'} + exclude = set([ + 'refs/remotes/origin/HEAD', + ]) - # Origin heads - for reftype in gitcmd: - try: - fh = self.gitopen(gitcmd[reftype], err=subprocess.PIPE) - for line in fh: - line = line.strip() - rev, name = line.split(None, 1) - if not name.startswith(prefix): + try: + fh = self.gitopen('git show-ref', err=subprocess.PIPE) + for line in fh: + line = line.strip() + rev, name = line.split(None, 1) + # Process each type of branch + for gitprefix, hgprefix in reftypes: + if not name.startswith(gitprefix) or name in exclude: continue - name = '%s%s' % (reftype, name[prefixlen:]) + name = '%s%s' % (hgprefix, name[len(gitprefix):]) bookmarks[name] = rev - except Exception: - pass + except Exception: + pass return bookmarks diff -r f31ddc9bfa5f -r 0224d22ef5d8 hgext/convert/hg.py --- a/hgext/convert/hg.py Fri Sep 25 13:30:49 2015 -0700 +++ b/hgext/convert/hg.py Fri Sep 25 23:10:47 2015 -0500 @@ -23,6 +23,7 @@ from mercurial.node import bin, hex, nullid from mercurial import hg, util, context, bookmarks, error, scmutil, exchange from mercurial import phases +from mercurial import merge as mergemod from common import NoRepo, commit, converter_source, converter_sink, mapfile @@ -176,14 +177,58 @@ return fp.getvalue() + def _calculatemergedfiles(self, source, p1ctx, p2ctx): + """Calculates the files from p2 that we need to pull in when merging p1 + and p2, given that the merge is coming from the given source. + + This prevents us from losing files that only exist in the target p2 and + that don't come from the source repo (like if you're merging multiple + repositories together). + """ + anc = [p1ctx.ancestor(p2ctx)] + # Calculate what files are coming from p2 + actions, diverge, rename = mergemod.calculateupdates( + self.repo, p1ctx, p2ctx, anc, + True, # branchmerge + True, # force + False, # partial + False, # acceptremote + False, # followcopies + ) + + for file, (action, info, msg) in actions.iteritems(): + if source.targetfilebelongstosource(file): + # If the file belongs to the source repo, ignore the p2 + # since it will be covered by the existing fileset. + continue + + # If the file requires actual merging, abort. We don't have enough + # context to resolve merges correctly. + if action in ['m', 'dm', 'cd', 'dc']: + raise util.Abort(_("unable to convert merge commit " + "since target parents do not merge cleanly (file " + "%s, parents %s and %s)") % (file, p1ctx, + p2ctx)) + elif action == 'k': + # 'keep' means nothing changed from p1 + continue + else: + # Any other change means we want to take the p2 version + yield file + def putcommit(self, files, copies, parents, commit, source, revmap, full, cleanp2): files = dict(files) def getfilectx(repo, memctx, f): - if p2ctx and f in cleanp2 and f not in copies: + if p2ctx and f in p2files and f not in copies: self.ui.debug('reusing %s from p2\n' % f) - return p2ctx[f] + try: + return p2ctx[f] + except error.ManifestLookupError: + # If the file doesn't exist in p2, then we're syncing a + # delete, so just return None. + return None try: v = files[f] except KeyError: @@ -255,6 +300,7 @@ while parents: p1 = p2 p2 = parents.pop(0) + p1ctx = self.repo[p1] p2ctx = None if p2 != nullid: p2ctx = self.repo[p2] @@ -262,6 +308,13 @@ if full: fileset.update(self.repo[p1]) fileset.update(self.repo[p2]) + + if p2ctx: + p2files = set(cleanp2) + for file in self._calculatemergedfiles(source, p1ctx, p2ctx): + p2files.add(file) + fileset.add(file) + ctx = context.memctx(self.repo, (p1, p2), text, fileset, getfilectx, commit.author, commit.date, extra) @@ -378,9 +431,6 @@ class mercurial_source(converter_source): def __init__(self, ui, path, revs=None): converter_source.__init__(self, ui, path, revs) - if revs and len(revs) > 1: - raise util.Abort(_("mercurial source does not support specifying " - "multiple revisions")) self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False) self.ignored = set() self.saverev = ui.configbool('convert', 'hg.saverev', False) @@ -415,7 +465,7 @@ else: self.keep = util.always if revs: - self._heads = [self.repo[revs[0]].node()] + self._heads = [self.repo[r].node() for r in revs] else: self._heads = self.repo.heads() else: diff -r f31ddc9bfa5f -r 0224d22ef5d8 hgext/eol.py --- a/hgext/eol.py Fri Sep 25 13:30:49 2015 -0700 +++ b/hgext/eol.py Fri Sep 25 23:10:47 2015 -0500 @@ -23,7 +23,7 @@ ``native`` is an alias for checking out in the platform's default line ending: ``LF`` on Unix (including Mac OS X) and ``CRLF`` on Windows. Note that ``BIN`` (do nothing to line endings) is Mercurial's -default behaviour; it is only needed if you need to override a later, +default behavior; it is only needed if you need to override a later, more general pattern. The optional ``[repository]`` section specifies the line endings to diff -r f31ddc9bfa5f -r 0224d22ef5d8 hgext/extdiff.py --- a/hgext/extdiff.py Fri Sep 25 13:30:49 2015 -0700 +++ b/hgext/extdiff.py Fri Sep 25 23:10:47 2015 -0500 @@ -146,72 +146,94 @@ subrepos=opts.get('subrepos') matcher = scmutil.match(repo[node2], pats, opts) - mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher, - listsubrepos=subrepos)[:3]) - if do3way: - mod_b, add_b, rem_b = map(set, repo.status(node1b, node2, matcher, - listsubrepos=subrepos)[:3]) + + if opts.get('patch'): + if subrepos: + raise util.Abort(_('--patch cannot be used with --subrepos')) + if node2 is None: + raise util.Abort(_('--patch requires two revisions')) else: - mod_b, add_b, rem_b = set(), set(), set() - modadd = mod_a | add_a | mod_b | add_b - common = modadd | rem_a | rem_b - if not common: - return 0 + mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher, + listsubrepos=subrepos)[:3]) + if do3way: + mod_b, add_b, rem_b = map(set, + repo.status(node1b, node2, matcher, + listsubrepos=subrepos)[:3]) + else: + mod_b, add_b, rem_b = set(), set(), set() + modadd = mod_a | add_a | mod_b | add_b + common = modadd | rem_a | rem_b + if not common: + return 0 tmproot = tempfile.mkdtemp(prefix='extdiff.') try: - # Always make a copy of node1a (and node1b, if applicable) - dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a) - dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot, subrepos)[0] - rev1a = '@%d' % repo[node1a].rev() - if do3way: - dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b) - dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot, + if not opts.get('patch'): + # Always make a copy of node1a (and node1b, if applicable) + dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a) + dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot, subrepos)[0] - rev1b = '@%d' % repo[node1b].rev() - else: - dir1b = None - rev1b = '' + rev1a = '@%d' % repo[node1a].rev() + if do3way: + dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b) + dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot, + subrepos)[0] + rev1b = '@%d' % repo[node1b].rev() + else: + dir1b = None + rev1b = '' - fns_and_mtime = [] + fns_and_mtime = [] - # If node2 in not the wc or there is >1 change, copy it - dir2root = '' - rev2 = '' - if node2: - dir2 = snapshot(ui, repo, modadd, node2, tmproot, subrepos)[0] - rev2 = '@%d' % repo[node2].rev() - elif len(common) > 1: - #we only actually need to get the files to copy back to - #the working dir in this case (because the other cases - #are: diffing 2 revisions or single file -- in which case - #the file is already directly passed to the diff tool). - dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot, - subrepos) - else: - # This lets the diff tool open the changed file directly - dir2 = '' - dir2root = repo.root + # If node2 in not the wc or there is >1 change, copy it + dir2root = '' + rev2 = '' + if node2: + dir2 = snapshot(ui, repo, modadd, node2, tmproot, subrepos)[0] + rev2 = '@%d' % repo[node2].rev() + elif len(common) > 1: + #we only actually need to get the files to copy back to + #the working dir in this case (because the other cases + #are: diffing 2 revisions or single file -- in which case + #the file is already directly passed to the diff tool). + dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot, + subrepos) + else: + # This lets the diff tool open the changed file directly + dir2 = '' + dir2root = repo.root + + label1a = rev1a + label1b = rev1b + label2 = rev2 - label1a = rev1a - label1b = rev1b - label2 = rev2 - - # If only one change, diff the files instead of the directories - # Handle bogus modifies correctly by checking if the files exist - if len(common) == 1: - common_file = util.localpath(common.pop()) - dir1a = os.path.join(tmproot, dir1a, common_file) - label1a = common_file + rev1a - if not os.path.isfile(dir1a): - dir1a = os.devnull - if do3way: - dir1b = os.path.join(tmproot, dir1b, common_file) - label1b = common_file + rev1b - if not os.path.isfile(dir1b): - dir1b = os.devnull - dir2 = os.path.join(dir2root, dir2, common_file) - label2 = common_file + rev2 + # If only one change, diff the files instead of the directories + # Handle bogus modifies correctly by checking if the files exist + if len(common) == 1: + common_file = util.localpath(common.pop()) + dir1a = os.path.join(tmproot, dir1a, common_file) + label1a = common_file + rev1a + if not os.path.isfile(dir1a): + dir1a = os.devnull + if do3way: + dir1b = os.path.join(tmproot, dir1b, common_file) + label1b = common_file + rev1b + if not os.path.isfile(dir1b): + dir1b = os.devnull + dir2 = os.path.join(dir2root, dir2, common_file) + label2 = common_file + rev2 + else: + template = 'hg-%h.patch' + cmdutil.export(repo, [repo[node1a].rev(), repo[node2].rev()], + template=repo.vfs.reljoin(tmproot, template), + match=matcher) + label1a = cmdutil.makefilename(repo, template, node1a) + label2 = cmdutil.makefilename(repo, template, node2) + dir1a = repo.vfs.reljoin(tmproot, label1a) + dir2 = repo.vfs.reljoin(tmproot, label2) + dir1b = None + label1b = None + fns_and_mtime = [] # Function to quote file/dir names in the argument string. # When not operating in 3-way mode, an empty string is @@ -255,6 +277,7 @@ _('pass option to comparison program'), _('OPT')), ('r', 'rev', [], _('revision'), _('REV')), ('c', 'change', '', _('change made by revision'), _('REV')), + ('', 'patch', None, _('compare patches for two revisions')) ] + commands.walkopts + commands.subrepoopts, _('hg extdiff [OPT]... [FILE]...'), inferrepo=True) diff -r f31ddc9bfa5f -r 0224d22ef5d8 hgext/highlight/__init__.py --- a/hgext/highlight/__init__.py Fri Sep 25 13:30:49 2015 -0700 +++ b/hgext/highlight/__init__.py Fri Sep 25 23:10:47 2015 -0500 @@ -13,23 +13,28 @@ It depends on the Pygments syntax highlighting library: http://pygments.org/ -There is a single configuration option:: +There are two configuration options:: [web] - pygments_style =