##// END OF EJS Templates
Added signature for changeset a92b9f8e11ba
Added signature for changeset a92b9f8e11ba

File last commit:

r35168:671aba34 default
r35184:fff9ffa2 stable
Show More
hg.py
655 lines | 23.5 KiB | text/x-python | PythonLexer
Martin Geisler
convert: add copyright and license headers to back-ends
r8250 # hg.py - hg backend for convert extension
#
# Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
#
# This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Brendan Cully
Split convert extension into common and repository type modules
r4536
Bryan O'Sullivan
convert: some tidyups, doc improvements, and test fixes...
r5556 # Notes for hg->hg conversion:
#
# * Old versions of Mercurial didn't trim the whitespace from the ends
# of commit messages, but new versions do. Changesets created by
# those older versions, then converted, may thus have different
# hashes for changesets that are otherwise identical.
#
Patrick Mezard
convert/hg: update documentation
r8596 # * Using "--config convert.hg.saverev=true" will make the source
# identifier to be stored in the converted revision. This will cause
# the converted revision to have a different identity than the
# source.
timeless
convert: hg use absolute_import
r28370 from __future__ import absolute_import
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
timeless
convert: hg use absolute_import
r28370 import os
import re
import time
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
Yuya Nishihara
py3: move up symbol imports to enforce import-checker rules...
r29205 from mercurial.i18n import _
timeless
convert: hg use absolute_import
r28370 from mercurial import (
bookmarks,
context,
error,
exchange,
hg,
lock as lockmod,
merge as mergemod,
node as nodemod,
phases,
scmutil,
util,
)
timeless
pycompat: switch to util.stringio for py3 compat
r28861 stringio = util.stringio
timeless
convert: hg use absolute_import
r28370 from . import common
mapfile = common.mapfile
NoRepo = common.NoRepo
Brendan Cully
Split convert extension into common and repository type modules
r4536
Mads Kiilerich
convert: replace revision references in messages if they are >= short hashes...
r23972 sha1re = re.compile(r'\b[0-9a-f]{12,40}\b')
Sean Farley
convert: replace old sha1s in the description...
r20372
timeless
convert: hg use absolute_import
r28370 class mercurial_sink(common.converter_sink):
Brendan Cully
convert: split converter into convertsource and convertsink
r4763 def __init__(self, ui, path):
timeless
convert: hg use absolute_import
r28370 common.converter_sink.__init__(self, ui, path)
Boris Feld
configitems: register the 'convert.hg.usebranchnames' config
r34171 self.branchnames = ui.configbool('convert', 'hg.usebranchnames')
Boris Feld
configitems: register the 'convert.hg.clonebranches' config
r34164 self.clonebranches = ui.configbool('convert', 'hg.clonebranches')
Boris Feld
configitems: register the 'convert.hg.tagsbranch' config
r34170 self.tagsbranch = ui.config('convert', 'hg.tagsbranch')
Brendan Cully
convert: hg: optionally create branches as clones...
r5173 self.lastbranch = None
Bryan O'Sullivan
convert: refactor sink initialisation, to remove hardcoding of hg...
r5441 if os.path.isdir(path) and len(os.listdir(path)) > 0:
try:
self.repo = hg.repository(self.ui, path)
Patrick Mezard
convert: mercurial sink must be local
r5918 if not self.repo.local():
Martin Geisler
convert: write "repository" instead of "repo"...
r10938 raise NoRepo(_('%s is not a local Mercurial repository')
% path)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.RepoError as err:
Matt Mackall
ui: print_exc() -> traceback()
r8206 ui.traceback()
Bryan O'Sullivan
convert: refactor sink initialisation, to remove hardcoding of hg...
r5441 raise NoRepo(err.args[0])
else:
try:
ui.status(_('initializing destination %s repository\n') % path)
self.repo = hg.repository(self.ui, path, create=True)
Patrick Mezard
convert: mercurial sink must be local
r5918 if not self.repo.local():
Martin Geisler
convert: write "repository" instead of "repo"...
r10938 raise NoRepo(_('%s is not a local Mercurial repository')
% path)
Bryan O'Sullivan
convert: refactor sink initialisation, to remove hardcoding of hg...
r5441 self.created.append(path)
Peter Arrenbrecht
cleanup: drop unused assignments
r7875 except error.RepoError:
Matt Mackall
ui: print_exc() -> traceback()
r8206 ui.traceback()
Martin Geisler
convert: mark strings for translation
r10939 raise NoRepo(_("could not create hg repository %s as sink")
Martin Geisler
convert: write "repository" instead of "repo"...
r10938 % path)
Bryan O'Sullivan
convert: acquire/release locks periodically
r5014 self.lock = None
self.wlock = None
Alexis S. L. Carvalho
convert: add a mode where mercurial_sink skips empty revisions....
r5378 self.filemapmode = False
Matt Harbison
convert: support incremental conversion with hg subrepos...
r25558 self.subrevmaps = {}
Bryan O'Sullivan
convert: acquire/release locks periodically
r5014
def before(self):
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('run hg sink pre-conversion action\n')
Alexis S. L. Carvalho
convert: fix locking order
r5052 self.wlock = self.repo.wlock()
Bryan O'Sullivan
convert: acquire/release locks periodically
r5014 self.lock = self.repo.lock()
def after(self):
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('run hg sink post-conversion action\n')
Matt Mackall
convert: make hg sink cleanup safer
r10086 if self.lock:
self.lock.release()
if self.wlock:
self.wlock.release()
Brendan Cully
Split convert extension into common and repository type modules
r4536
Bryan O'Sullivan
convert: rename mapfile to revmapfile, so we can map more than just revs
r5011 def revmapfile(self):
Pierre-Yves David
convert: directly use repo.vfs.join...
r31327 return self.repo.vfs.join("shamap")
Brendan Cully
Split convert extension into common and repository type modules
r4536
Edouard Gomez
convert extension: Add support for username mapping...
r4589 def authorfile(self):
Pierre-Yves David
convert: directly use repo.vfs.join...
r31327 return self.repo.vfs.join("authormap")
Edouard Gomez
convert extension: Add support for username mapping...
r4589
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 def setbranch(self, branch, pbranches):
if not self.clonebranches:
Brendan Cully
convert: hg: optionally create branches as clones...
r5173 return
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 setbranch = (branch != self.lastbranch)
Brendan Cully
convert: hg: optionally create branches as clones...
r5173 self.lastbranch = branch
if not branch:
branch = 'default'
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if pbranches:
pbranch = pbranches[0][1]
else:
pbranch = 'default'
Brendan Cully
convert: hg: optionally create branches as clones...
r5173
branchpath = os.path.join(self.path, branch)
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 if setbranch:
self.after()
try:
self.repo = hg.repository(self.ui, branchpath)
Brodie Rao
cleanup: replace naked excepts with except Exception: ...
r16689 except Exception:
Brendan Cully
convert: hg: optionally create branches as clones...
r5173 self.repo = hg.repository(self.ui, branchpath, create=True)
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 self.before()
# pbranches may bring revisions from other branches (merge parents)
# Make sure we have them, or pull them.
missings = {}
for b in pbranches:
try:
self.repo.lookup(b[0])
Brodie Rao
cleanup: replace naked excepts with except Exception: ...
r16689 except Exception:
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 missings.setdefault(b[1], []).append(b[0])
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 if missings:
self.after()
Mads Kiilerich
convert: process missing branches in sorted order
r18373 for pbranch, heads in sorted(missings.iteritems()):
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 pbranchpath = os.path.join(self.path, pbranch)
Matt Mackall
hg: change various repository() users to use peer() where appropriate...
r14556 prepo = hg.peer(self.ui, {}, pbranchpath)
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
Pierre-Yves David
convert-hg: use localrepo.pull...
r22698 exchange.pull(self.repo, prepo,
[prepo.lookup(h) for h in heads])
Patrick Mezard
convert: hg.clonebranches must pull missing parents (issue941)
r5934 self.before()
Brendan Cully
convert: hg: optionally create branches as clones...
r5173
Mads Kiilerich
convert: backout b75a04502ced and 9616b03113ce - tagmap...
r21076 def _rewritetags(self, source, revmap, data):
timeless
pycompat: switch to util.stringio for py3 compat
r28861 fp = stringio()
Patrick Mezard
convert: rewrite tags when converting from hg to hg
r8693 for line in data.splitlines():
s = line.split(' ', 1)
if len(s) != 2:
continue
revid = revmap.get(source.lookuprev(s[0]))
if not revid:
timeless
convert: hg use absolute_import
r28370 if s[0] == nodemod.nullhex:
Matt Mackall
convert: properly pass null ids through .hgtags (issue4678)...
r25305 revid = s[0]
else:
continue
Mads Kiilerich
convert: backout b75a04502ced and 9616b03113ce - tagmap...
r21076 fp.write('%s %s\n' % (revid, s[1]))
Patrick Mezard
convert: rewrite tags when converting from hg to hg
r8693 return fp.getvalue()
Matt Harbison
convert: support incremental conversion with hg subrepos...
r25558 def _rewritesubstate(self, source, data):
timeless
pycompat: switch to util.stringio for py3 compat
r28861 fp = stringio()
Matt Harbison
convert: support incremental conversion with hg subrepos...
r25558 for line in data.splitlines():
s = line.split(' ', 1)
if len(s) != 2:
continue
revid = s[0]
subpath = s[1]
timeless
convert: hg use absolute_import
r28370 if revid != nodemod.nullhex:
Matt Harbison
convert: support incremental conversion with hg subrepos...
r25558 revmap = self.subrevmaps.get(subpath)
if revmap is None:
revmap = mapfile(self.ui,
self.repo.wjoin(subpath, '.hg/shamap'))
self.subrevmaps[subpath] = revmap
# It is reasonable that one or more of the subrepos don't
# need to be converted, in which case they can be cloned
# into place instead of converted. Therefore, only warn
# once.
msg = _('no ".hgsubstate" updates will be made for "%s"\n')
if len(revmap) == 0:
sub = self.repo.wvfs.reljoin(subpath, '.hg')
if self.repo.wvfs.exists(sub):
self.ui.warn(msg % subpath)
newid = revmap.get(revid)
if not newid:
if len(revmap) > 0:
self.ui.warn(_("%s is missing from %s/.hg/shamap\n") %
(revid, subpath))
else:
revid = newid
fp.write('%s %s\n' % (revid, subpath))
return fp.getvalue()
Durham Goode
convert: fix convert dropping p2 contents during filemap merge...
r26037 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, # 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']:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("unable to convert merge commit "
Durham Goode
convert: fix convert dropping p2 contents during filemap merge...
r26037 "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
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395 def putcommit(self, files, copies, parents, commit, source, revmap, full,
cleanp2):
Patrick Mezard
convert: hg sink commits without working dir
r6717 files = dict(files)
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395
Patrick Mezard
convert: hg sink commits without working dir
r6717 def getfilectx(repo, memctx, f):
Durham Goode
convert: fix convert dropping p2 contents during filemap merge...
r26037 if p2ctx and f in p2files and f not in copies:
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395 self.ui.debug('reusing %s from p2\n' % f)
Durham Goode
convert: fix syncing deletes from p2 merge commit...
r26078 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
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 try:
v = files[f]
except KeyError:
return None
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 data, mode = source.getfile(f, v)
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 if data is None:
return None
Patrick Mezard
convert: rewrite tags when converting from hg to hg
r8693 if f == '.hgtags':
Mads Kiilerich
convert: backout b75a04502ced and 9616b03113ce - tagmap...
r21076 data = self._rewritetags(source, revmap, data)
Matt Harbison
convert: support incremental conversion with hg subrepos...
r25558 if f == '.hgsubstate':
data = self._rewritesubstate(source, data)
Sean Farley
memfilectx: call super.__init__ instead of duplicating code...
r21689 return context.memfilectx(self.repo, f, data, 'l' in mode,
'x' in mode, copies.get(f))
Patrick Mezard
convert: hg sink commits without working dir
r6717
Brendan Cully
Split convert extension into common and repository type modules
r4536 pl = []
for p in parents:
Patrick Mezard
convert: hg sink commits without working dir
r6717 if p not in pl:
Brendan Cully
Split convert extension into common and repository type modules
r4536 pl.append(p)
parents = pl
Alexis S. L. Carvalho
convert: add a mode where mercurial_sink skips empty revisions....
r5378 nparents = len(parents)
if self.filemapmode and nparents == 1:
timeless
convert: hg use absolute_import
r28370 m1node = self.repo.changelog.read(nodemod.bin(parents[0]))[0]
Alexis S. L. Carvalho
convert: add a mode where mercurial_sink skips empty revisions....
r5378 parent = parents[0]
Brendan Cully
Split convert extension into common and repository type modules
r4536
Matt Mackall
many, many trivial check-code fixups
r10282 if len(parents) < 2:
timeless
convert: hg use absolute_import
r28370 parents.append(nodemod.nullid)
Matt Mackall
many, many trivial check-code fixups
r10282 if len(parents) < 2:
timeless
convert: hg use absolute_import
r28370 parents.append(nodemod.nullid)
Brendan Cully
Split convert extension into common and repository type modules
r4536 p2 = parents.pop(0)
text = commit.desc
Sean Farley
convert: replace old sha1s in the description...
r20372
sha1s = re.findall(sha1re, text)
for sha1 in sha1s:
oldrev = source.lookuprev(sha1)
newrev = revmap.get(oldrev)
if newrev is not None:
text = text.replace(sha1, newrev[:len(sha1)])
Bryan O'Sullivan
convert: make contents of "extra" dict available from sources, for sinks....
r5439 extra = commit.extra.copy()
Matt Harbison
convert: update the transplant, rebase and graft references in 'extra'...
r21765
Durham Goode
convert: add config for recording the source name...
r25750 sourcename = self.repo.ui.config('convert', 'hg.sourcename')
if sourcename:
extra['convert_source'] = sourcename
Matt Harbison
convert: update 'intermediate-source' in the destination's extras dictionary
r25589 for label in ('source', 'transplant_source', 'rebase_source',
'intermediate-source'):
Matt Harbison
convert: update the transplant, rebase and graft references in 'extra'...
r21765 node = extra.get(label)
if node is None:
continue
# Only transplant stores its reference in binary
if label == 'transplant_source':
timeless
convert: hg use absolute_import
r28370 node = nodemod.hex(node)
Matt Harbison
convert: update the transplant, rebase and graft references in 'extra'...
r21765
newrev = revmap.get(node)
if newrev is not None:
if label == 'transplant_source':
timeless
convert: hg use absolute_import
r28370 newrev = nodemod.bin(newrev)
Matt Harbison
convert: update the transplant, rebase and graft references in 'extra'...
r21765
extra[label] = newrev
Bryan O'Sullivan
convert: add config option to turn off use of branch names
r5038 if self.branchnames and commit.branch:
Brendan Cully
convert: record the source revision in the changelog
r4873 extra['branch'] = commit.branch
Matt Harbison
convert: always track the hg source revision in the internal commit object...
r25570 if commit.rev and commit.saverev:
Brendan Cully
convert: record the source revision in the changelog
r4873 extra['convert_revision'] = commit.rev
Thomas Arendsen Hein
removed trailing whitespace
r4957
Brendan Cully
Split convert extension into common and repository type modules
r4536 while parents:
p1 = p2
p2 = parents.pop(0)
Durham Goode
convert: fix convert dropping p2 contents during filemap merge...
r26037 p1ctx = self.repo[p1]
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395 p2ctx = None
timeless
convert: hg use absolute_import
r28370 if p2 != nodemod.nullid:
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395 p2ctx = self.repo[p2]
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 fileset = set(files)
if full:
Mads Kiilerich
convert: don't use multi-argument set.update...
r22360 fileset.update(self.repo[p1])
fileset.update(self.repo[p2])
Durham Goode
convert: fix convert dropping p2 contents during filemap merge...
r26037
if p2ctx:
p2files = set(cleanp2)
for file in self._calculatemergedfiles(source, p1ctx, p2ctx):
p2files.add(file)
fileset.add(file)
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 ctx = context.memctx(self.repo, (p1, p2), text, fileset,
Matt Mackall
many, many trivial check-code fixups
r10282 getfilectx, commit.author, commit.date, extra)
Matt Harbison
convert: apply the appropriate phases to the destination (issue4165)...
r25571
# We won't know if the conversion changes the node until after the
# commit, so copy the source's phase for now.
self.repo.ui.setconfig('phases', 'new-commit',
phases.phasenames[commit.phase], 'convert')
Bryan O'Sullivan
with: use context manager for transaction in mercurial_sink
r27863 with self.repo.transaction("convert") as tr:
timeless
convert: hg use absolute_import
r28370 node = nodemod.hex(self.repo.commitctx(ctx))
Matt Harbison
convert: apply the appropriate phases to the destination (issue4165)...
r25571
# If the node value has changed, but the phase is lower than
# draft, set it back to draft since it hasn't been exposed
# anywhere.
if commit.rev != node:
ctx = self.repo[node]
if ctx.phase() < phases.draft:
Boris Feld
convert: use the new 'phase.registernew' function
r33455 phases.registernew(self.repo, tr, phases.draft,
[ctx.node()])
Matt Harbison
convert: apply the appropriate phases to the destination (issue4165)...
r25571
Brendan Cully
Split convert extension into common and repository type modules
r4536 text = "(octopus merge fixup)\n"
Durham Goode
convert: fix bug with converting the same commit twice...
r25697 p2 = node
Brendan Cully
Split convert extension into common and repository type modules
r4536
Alexis S. L. Carvalho
convert: add a mode where mercurial_sink skips empty revisions....
r5378 if self.filemapmode and nparents == 1:
Durham Goode
manifest: remove last uses of repo.manifest...
r30375 man = self.repo.manifestlog._revlog
timeless
convert: hg use absolute_import
r28370 mnode = self.repo.changelog.read(nodemod.bin(p2))[0]
Matt Mackall
convert: handle closed branch heads in hg-hg conversion (issue2185)
r11673 closed = 'close' in commit.extra
if not closed and not man.cmp(m1node, man.revision(mnode)):
Patrick Mezard
convert: better feedback when filtering out empty revisions...
r8611 self.ui.status(_("filtering out empty revision\n"))
Matt Mackall
convert: fix crazy rollback call, broken by recent rollback safety checks...
r15193 self.repo.rollback(force=True)
Alexis S. L. Carvalho
convert: add a mode where mercurial_sink skips empty revisions....
r5378 return parent
Brendan Cully
Split convert extension into common and repository type modules
r4536 return p2
def puttags(self, tags):
Peter Arrenbrecht
cleanup: whitespace cleanup
r7877 try:
parentctx = self.repo[self.tagsbranch]
tagparent = parentctx.node()
except error.RepoError:
parentctx = None
timeless
convert: hg use absolute_import
r28370 tagparent = nodemod.nullid
Brendan Cully
Split convert extension into common and repository type modules
r4536
Sean Farley
convert: compare tags from all heads instead of just one...
r20376 oldlines = set()
for branch, heads in self.repo.branchmap().iteritems():
for h in heads:
if '.hgtags' in self.repo[h]:
oldlines.update(
set(self.repo[h]['.hgtags'].data().splitlines(True)))
oldlines = sorted(list(oldlines))
Brendan Cully
Split convert extension into common and repository type modules
r4536
Matt Mackall
replace util.sort with sorted built-in...
r8209 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
Peter Arrenbrecht
cleanup: whitespace cleanup
r7877 if newlines == oldlines:
Patrick Mezard
convert: fix history topology when using hg.tagsbranch...
r9431 return None, None
Sean Farley
convert: avoid updating tags when there is nothing new...
r20377
# if the old and new tags match, then there is nothing to update
oldtags = set()
newtags = set()
for line in oldlines:
s = line.strip().split(' ', 1)
if len(s) != 2:
continue
oldtags.add(s[1])
for line in newlines:
s = line.strip().split(' ', 1)
if len(s) != 2:
continue
if s[1] not in oldtags:
newtags.add(s[1].strip())
if not newtags:
return None, None
Peter Arrenbrecht
cleanup: whitespace cleanup
r7877 data = "".join(newlines)
def getfilectx(repo, memctx, f):
Sean Farley
memfilectx: call super.__init__ instead of duplicating code...
r21689 return context.memfilectx(repo, f, data, False, False, None)
Patrick Mezard
convert: hg sink commits without working dir
r6717
Peter Arrenbrecht
cleanup: whitespace cleanup
r7877 self.ui.status(_("updating tags\n"))
date = "%s 0" % int(time.mktime(time.gmtime()))
extra = {'branch': self.tagsbranch}
ctx = context.memctx(self.repo, (tagparent, None), "update tags",
[".hgtags"], getfilectx, "convert-repo", date,
extra)
Durham Goode
convert: fix bug with converting the same commit twice...
r25697 node = self.repo.commitctx(ctx)
timeless
convert: hg use absolute_import
r28370 return nodemod.hex(node), nodemod.hex(tagparent)
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
Alexis S. L. Carvalho
convert: add a mode where mercurial_sink skips empty revisions....
r5378 def setfilemapmode(self, active):
self.filemapmode = active
Edouard Gomez
convert: add bookmark support to the hg sink
r13746 def putbookmarks(self, updatedbookmark):
if not len(updatedbookmark):
return
Laurent Charignon
convert: use repo._bookmarks.recordchange instead of repo._bookmarks.write...
r26974 wlock = lock = tr = None
try:
wlock = self.repo.wlock()
lock = self.repo.lock()
tr = self.repo.transaction('bookmark')
Laurent Charignon
convert: indentation change to make the next patch more legible...
r26973 self.ui.status(_("updating bookmarks\n"))
destmarks = self.repo._bookmarks
Boris Feld
bookmark: use 'applychanges' in the convert extension
r33487 changes = [(bookmark, nodemod.bin(updatedbookmark[bookmark]))
for bookmark in updatedbookmark]
destmarks.applychanges(self.repo, tr, changes)
Laurent Charignon
convert: use repo._bookmarks.recordchange instead of repo._bookmarks.write...
r26974 tr.close()
finally:
lockmod.release(lock, wlock, tr)
Edouard Gomez
convert: add bookmark support to the hg sink
r13746
Mads Kiilerich
convert: introduce hascommitfrommap sink method...
r21635 def hascommitfrommap(self, rev):
# the exact semantics of clonebranches is unclear so we can't say no
return rev in self.repo or self.clonebranches
Mads Kiilerich
convert: rename sink hascommit to hascommitforsplicemap...
r21634 def hascommitforsplicemap(self, rev):
Brodie Rao
cleanup: "not x in y" -> "x not in y"
r16686 if rev not in self.repo and self.clonebranches:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('revision %s not found in destination '
Patrick Mezard
convert: use splicemap entries when sorting revisions (issue1748)...
r16106 'repository (lookups with clonebranches=true '
'are not implemented)') % rev)
return rev in self.repo
Edouard Gomez
convert: add bookmark support to the hg sink
r13746
timeless
convert: hg use absolute_import
r28370 class mercurial_source(common.converter_source):
Durham Goode
convert: add support for specifying multiple revs...
r25748 def __init__(self, ui, path, revs=None):
timeless
convert: hg use absolute_import
r28370 common.converter_source.__init__(self, ui, path, revs)
Boris Feld
configitems: register the 'convert.hg.ignoreerrors' config
r34165 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors')
Benoit Boissinot
convert: use set instead of dict
r8456 self.ignored = set()
Boris Feld
configitems: register the 'convert.hg.saverev' config
r34167 self.saverev = ui.configbool('convert', 'hg.saverev')
Bryan O'Sullivan
convert: fail properly if we can't read a source hg repository
r5358 try:
self.repo = hg.repository(self.ui, path)
Bryan O'Sullivan
convert: report errors more meaningfully if run with --traceback
r5437 # try to provoke an exception if this isn't really a hg
# repo, but some other bogus compatible-looking url
Alexis S. L. Carvalho
convert: make sure mercurial_source has a local hg repo
r5522 if not self.repo.local():
Brodie Rao
cleanup: "raise SomeException()" -> "raise SomeException"
r16687 raise error.RepoError
Matt Mackall
error: move repo errors...
r7637 except error.RepoError:
Matt Mackall
ui: print_exc() -> traceback()
r8206 ui.traceback()
Martin Geisler
convert: mark strings for translation
r10939 raise NoRepo(_("%s is not a local Mercurial repository") % path)
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 self.lastrev = None
self.lastctx = None
Mads Kiilerich
convert: refactor hg getchanges and caching
r22299 self._changescache = None, None
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554 self.convertfp = None
Patrick Mezard
convert: implement startrev for hg source
r6885 # Restrict converted revisions to startrev descendants
startnode = ui.config('convert', 'hg.startrev')
Mads Kiilerich
convert: introduce hg.revs to replace hg.startrev and --rev with a revset...
r19891 hgrevs = ui.config('convert', 'hg.revs')
if hgrevs is None:
if startnode is not None:
try:
startnode = self.repo.lookup(startnode)
except error.RepoError:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('%s is not a valid start revision')
Mads Kiilerich
convert: introduce hg.revs to replace hg.startrev and --rev with a revset...
r19891 % startnode)
startrev = self.repo.changelog.rev(startnode)
children = {startnode: 1}
for r in self.repo.changelog.descendants([startrev]):
children[self.repo.changelog.node(r)] = 1
self.keep = children.__contains__
else:
self.keep = util.always
Durham Goode
convert: add support for specifying multiple revs...
r25748 if revs:
Durham Goode
convert: remove restriction on multiple --rev in hg source...
r26154 self._heads = [self.repo[r].node() for r in revs]
Mads Kiilerich
convert: introduce hg.revs to replace hg.startrev and --rev with a revset...
r19891 else:
self._heads = self.repo.heads()
Patrick Mezard
convert: implement startrev for hg source
r6885 else:
Durham Goode
convert: add support for specifying multiple revs...
r25748 if revs or startnode is not None:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('hg.revs cannot be combined with '
Mads Kiilerich
convert: introduce hg.revs to replace hg.startrev and --rev with a revset...
r19891 'hg.startrev or --rev'))
nodes = set()
parents = set()
for r in scmutil.revrange(self.repo, [hgrevs]):
ctx = self.repo[r]
nodes.add(ctx.node())
parents.update(p.node() for p in ctx.parents())
self.keep = nodes.__contains__
self._heads = nodes - parents
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
Martin von Zweigbergk
convert: use _ prefix for private methods in hg sink...
r27717 def _changectx(self, rev):
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 if self.lastrev != rev:
Matt Mackall
use repo[changeid] to get a changectx
r6747 self.lastctx = self.repo[rev]
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 self.lastrev = rev
return self.lastctx
Martin von Zweigbergk
convert: use _ prefix for private methods in hg sink...
r27717 def _parents(self, ctx):
Patrick Mezard
convert/hg: make parents() return changectx, not nodes
r9531 return [p for p in ctx.parents() if p and self.keep(p.node())]
Patrick Mezard
convert: implement startrev for hg source
r6885
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 def getheads(self):
timeless
convert: hg use absolute_import
r28370 return [nodemod.hex(h) for h in self._heads if self.keep(h)]
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
def getfile(self, name, rev):
try:
Martin von Zweigbergk
convert: use _ prefix for private methods in hg sink...
r27717 fctx = self._changectx(rev)[name]
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 return fctx.data(), fctx.flags()
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 except error.LookupError:
return None, None
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
Martin von Zweigbergk
convert: replace cache of (m,a,r) by (ma,r)...
r27718 def _changedfiles(self, ctx1, ctx2):
Martin von Zweigbergk
convert: use manifest.diff() instead of ctx.status()...
r27719 ma, r = [], []
maappend = ma.append
rappend = r.append
d = ctx1.manifest().diff(ctx2.manifest())
for f, ((node1, flag1), (node2, flag2)) in d.iteritems():
if node2 is None:
rappend(f)
else:
maappend(f)
return ma, r
Martin von Zweigbergk
convert: replace cache of (m,a,r) by (ma,r)...
r27718
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 def getchanges(self, rev, full):
Martin von Zweigbergk
convert: use _ prefix for private methods in hg sink...
r27717 ctx = self._changectx(rev)
parents = self._parents(ctx)
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 if full or not parents:
Mads Kiilerich
convert: refactor hg getchanges and caching
r22299 files = copyfiles = ctx.manifest()
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 if parents:
Mads Kiilerich
convert: refactor hg getchanges and caching
r22299 if self._changescache[0] == rev:
Martin von Zweigbergk
convert: replace cache of (m,a,r) by (ma,r)...
r27718 ma, r = self._changescache[1]
Mads Kiilerich
convert: refactor hg getchanges and caching
r22299 else:
Martin von Zweigbergk
convert: replace cache of (m,a,r) by (ma,r)...
r27718 ma, r = self._changedfiles(parents[0], ctx)
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 if not full:
Martin von Zweigbergk
convert: replace cache of (m,a,r) by (ma,r)...
r27718 files = ma + r
copyfiles = ma
Martin von Zweigbergk
convert: use _ prefix for private methods in hg sink...
r27717 # _getcopies() is also run for roots and before filtering so missing
Mads Kiilerich
convert: refactor hg getchanges and caching
r22299 # revlogs are detected early
Martin von Zweigbergk
convert: use _ prefix for private methods in hg sink...
r27717 copies = self._getcopies(ctx, parents, copyfiles)
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395 cleanp2 = set()
if len(parents) == 2:
Martin von Zweigbergk
convert: use manifest.diff() instead of ctx.status()...
r27719 d = parents[1].manifest().diff(ctx.manifest(), clean=True)
for f, value in d.iteritems():
if value is None:
cleanp2.add(f)
Mads Kiilerich
convert: refactor hg getchanges and caching
r22299 changes = [(f, rev) for f in files if f not in self.ignored]
changes.sort()
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395 return changes, copies, cleanp2
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
Martin von Zweigbergk
convert: use _ prefix for private methods in hg sink...
r27717 def _getcopies(self, ctx, parents, files):
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 copies = {}
Alexis S. L. Carvalho
convert: mercurial_source: also search for copies in modified files...
r5280 for name in files:
Patrick Mezard
convert: ignore hg source errors with hg.ignoreerrors (issue 1357)...
r7231 if name in self.ignored:
continue
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 try:
Mads Kiilerich
convert: fix bad conversion of copies when hg.startrev is specified...
r19457 copysource, _copynode = ctx.filectx(name).renamed()
if copysource in self.ignored:
Patrick Mezard
convert: ignore hg source errors with hg.ignoreerrors (issue 1357)...
r7231 continue
Patrick Mezard
convert/hg: handle bogus copy records (issue1843)
r9532 # Ignore copy sources not in parent revisions
found = False
for p in parents:
if copysource in p:
found = True
break
if not found:
continue
Patrick Mezard
convert: ignore hg source errors with hg.ignoreerrors (issue 1357)...
r7231 copies[name] = copysource
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 except TypeError:
pass
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.LookupError as e:
Patrick Mezard
convert: ignore hg source errors with hg.ignoreerrors (issue 1357)...
r7231 if not self.ignoreerrors:
raise
Benoit Boissinot
convert: use set instead of dict
r8456 self.ignored.add(name)
Patrick Mezard
convert: ignore hg source errors with hg.ignoreerrors (issue 1357)...
r7231 self.ui.warn(_('ignoring: %s\n') % e)
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 return copies
Thomas Arendsen Hein
Remove trailing spaces, fix indentation
r5143
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013 def getcommit(self, rev):
Martin von Zweigbergk
convert: use _ prefix for private methods in hg sink...
r27717 ctx = self._changectx(rev)
Mads Kiilerich
convert: keep converted hg parents that are outside convert.hg.revs (BC)...
r28900 _parents = self._parents(ctx)
parents = [p.hex() for p in _parents]
optparents = [p.hex() for p in ctx.parents() if p and p not in _parents]
Matt Harbison
convert: always track the hg source revision in the internal commit object...
r25570 crev = rev
timeless
convert: hg use absolute_import
r28370 return common.commit(author=ctx.user(),
date=util.datestr(ctx.date(),
'%Y-%m-%d %H:%M:%S %1%2'),
desc=ctx.description(),
rev=crev,
parents=parents,
Mads Kiilerich
convert: keep converted hg parents that are outside convert.hg.revs (BC)...
r28900 optparents=optparents,
timeless
convert: hg use absolute_import
r28370 branch=ctx.branch(),
extra=ctx.extra(),
sortkey=ctx.rev(),
saverev=self.saverev,
phase=ctx.phase())
Bryan O'Sullivan
convert: Support Mercurial as a source, as well as a sink
r5013
def gettags(self):
Mads Kiilerich
convert: mercurial source: convert global tags only - not local tags...
r21498 # This will get written to .hgtags, filter non global tags out.
tags = [t for t in self.repo.tagslist()
if self.repo.tagtype(t[0]) == 'global']
timeless
convert: hg use absolute_import
r28370 return dict([(name, nodemod.hex(node)) for name, node in tags
Patrick Mezard
convert: implement startrev for hg source
r6885 if self.keep(node)])
Alexis S. L. Carvalho
mercurial_source: add --filemap support
r5379
def getchangedfiles(self, rev, i):
Martin von Zweigbergk
convert: use _ prefix for private methods in hg sink...
r27717 ctx = self._changectx(rev)
parents = self._parents(ctx)
Patrick Mezard
convert: implement startrev for hg source
r6885 if not parents and i is None:
i = 0
Martin von Zweigbergk
convert: replace cache of (m,a,r) by (ma,r)...
r27718 ma, r = ctx.manifest().keys(), []
Patrick Mezard
convert: implement startrev for hg source
r6885 else:
i = i or 0
Martin von Zweigbergk
convert: replace cache of (m,a,r) by (ma,r)...
r27718 ma, r = self._changedfiles(parents[i], ctx)
ma, r = [[f for f in l if f not in self.ignored] for l in (ma, r)]
Alexis S. L. Carvalho
mercurial_source: add --filemap support
r5379
if i == 0:
Martin von Zweigbergk
convert: replace cache of (m,a,r) by (ma,r)...
r27718 self._changescache = (rev, (ma, r))
Alexis S. L. Carvalho
mercurial_source: add --filemap support
r5379
Martin von Zweigbergk
convert: replace cache of (m,a,r) by (ma,r)...
r27718 return ma + r
Alexis S. L. Carvalho
mercurial_source: add --filemap support
r5379
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554 def converted(self, rev, destrev):
if self.convertfp is None:
Pierre-Yves David
convert: directly use repo.vfs.join...
r31327 self.convertfp = open(self.repo.vfs.join('shamap'), 'a')
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554 self.convertfp.write('%s %s\n' % (destrev, rev))
self.convertfp.flush()
Patrick Mezard
test-convert: test before() and after() conversion actions
r5805
def before(self):
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('run hg source pre-conversion action\n')
Patrick Mezard
test-convert: test before() and after() conversion actions
r5805
def after(self):
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('run hg source post-conversion action\n')
Patrick Mezard
convert: fail fast if source does not support --sourcesort
r8691
def hasnativeorder(self):
return True
Patrick Mezard
convert: rewrite tags when converting from hg to hg
r8693
Constantine Linnick
convert: add closesort algorithm to mercurial sources...
r18819 def hasnativeclose(self):
return True
Patrick Mezard
convert: rewrite tags when converting from hg to hg
r8693 def lookuprev(self, rev):
try:
timeless
convert: hg use absolute_import
r28370 return nodemod.hex(self.repo.lookup(rev))
Matt Harbison
convert: handle LookupError in mercurial_source.lookuprev()...
r23926 except (error.RepoError, error.LookupError):
Patrick Mezard
convert: rewrite tags when converting from hg to hg
r8693 return None
Edouard Gomez
convert: add bookmark support to hg source
r13757
def getbookmarks(self):
return bookmarks.listbookmarks(self.repo)
Ben Goswami
splicemap: improve error handling when source is hg (issue2084)...
r19120
Sean Farley
convert: add mapname parameter to checkrevformat...
r20373 def checkrevformat(self, revstr, mapname='splicemap'):
Ben Goswami
splicemap: improve error handling when source is hg (issue2084)...
r19120 """ Mercurial, revision string is a 40 byte hex """
Sean Farley
convert: add mapname parameter to checkrevformat...
r20373 self.checkhexformat(revstr, mapname)