##// END OF EJS Templates
tags: implement persistent tag caching (issue548)....
tags: implement persistent tag caching (issue548). - rename findglobaltags() to findglobaltags1() (so the "no cache" implementation is still there if we need it) - add findglobaltags2() and make findglobaltags() an alias for it (disabling tag caching is a one-line patch) - factor out tagcache class with methods readcache() and writecache(); the expensive part of tag finding (iterate over heads and find .hgtags filenode) is now in tagcache.readcache()

File last commit:

r9151:f528d1a9 default
r9151:f528d1a9 default
Show More
localrepo.py
2144 lines | 80.3 KiB | text/x-python | PythonLexer
mpm@selenic.com
Break apart hg.py...
r1089 # localrepo.py - read/write repository class for mercurial
#
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
mpm@selenic.com
Break apart hg.py...
r1089 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.
mpm@selenic.com
Break apart hg.py...
r1089
Joel Rosdahl
Expand import * to allow Pyflakes to find problems
r6211 from node import bin, hex, nullid, nullrev, short
Matt Mackall
Simplify i18n imports
r3891 from i18n import _
Matt Mackall
commit: recurse into subrepositories
r8813 import repo, changegroup, subrepo
Simon Heimberg
separate import lines from mercurial and general python modules
r8312 import changelog, dirstate, filelog, manifest, context
Peter Arrenbrecht
drop unused imports
r8390 import lock, transaction, store, encoding
Simon Heimberg
separate import lines from mercurial and general python modules
r8312 import util, extensions, hook, error
Matt Mackall
match: remove files arg from repo.status and friends
r6603 import match as match_
Stefano Tortarolo
make commit fail when committing unresolved files
r6888 import merge as merge_
Greg Ward
Factor tags module out of localrepo (issue548)....
r9149 import tags as tags_
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 from lock import release
Henri Wiechers
cleanup: removed unused imports
r8731 import weakref, stat, errno, os, time, inspect
Matt Mackall
localrepo: use propertycache
r8260 propertycache = util.propertycache
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109
Vadim Gelfer
add support for streaming clone....
r2612 class localrepository(repo.repository):
Henrik Stuart
named branches: server branchmap wire protocol support (issue736)...
r8562 capabilities = set(('lookup', 'changegroupsubset', 'branchmap'))
Matt Mackall
repo: add internal support for sharing store directories...
r8799 supported = set('revlogv1 store fncache shared'.split())
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439
Matt Mackall
ui: replace parentui mechanism with repo.baseui
r8189 def __init__(self, baseui, path=None, create=0):
Vadim Gelfer
add support for streaming clone....
r2612 repo.repository.__init__(self)
Benoit Boissinot
move code around
r3850 self.root = os.path.realpath(path)
Alexis S. L. Carvalho
Save an absolute path in repo.path...
r4170 self.path = os.path.join(self.root, ".hg")
Benoit Boissinot
move code around
r3850 self.origroot = path
self.opener = util.opener(self.path)
self.wopener = util.opener(self.root)
Matt Mackall
repo: set up ui and extensions earlier
r8797 self.baseui = baseui
self.ui = baseui.copy()
try:
self.ui.readconfig(self.join("hgrc"), self.root)
extensions.loadall(self.ui)
except IOError:
pass
mpm@selenic.com
Break apart hg.py...
r1089
Benoit Boissinot
localrepo: move the repo creation code, fail if the repo exists
r3035 if not os.path.isdir(self.path):
if create:
if not os.path.exists(path):
os.mkdir(path)
os.mkdir(self.path)
Alexis S. L. Carvalho
small fixes for the parent patch...
r4166 requirements = ["revlogv1"]
Matt Mackall
repo: set up ui and extensions earlier
r8797 if self.ui.configbool('format', 'usestore', True):
Matt Mackall
Allow disabling store format to work with absurdly long filenames
r4163 os.mkdir(os.path.join(self.path, "store"))
Alexis S. L. Carvalho
small fixes for the parent patch...
r4166 requirements.append("store")
Matt Mackall
repo: set up ui and extensions earlier
r8797 if self.ui.configbool('format', 'usefncache', True):
Adrian Buehlmann
add format.usefncache config option (default is true)...
r7234 requirements.append("fncache")
Alexis S. L. Carvalho
small fixes for the parent patch...
r4166 # create an invalid changelog
self.opener("00changelog.i", "a").write(
'\0\0\0\2' # represents revlogv2
' dummy changelog to prevent using the old repo layout'
)
Benoit Boissinot
add "requires" file to the repo, specifying the requirements
r3851 reqfile = self.opener("requires", "w")
for r in requirements:
reqfile.write("%s\n" % r)
reqfile.close()
Benoit Boissinot
localrepo: move the repo creation code, fail if the repo exists
r3035 else:
Matt Mackall
error: move repo errors...
r7637 raise error.RepoError(_("repository %s not found") % path)
Benoit Boissinot
localrepo: move the repo creation code, fail if the repo exists
r3035 elif create:
Matt Mackall
error: move repo errors...
r7637 raise error.RepoError(_("repository %s already exists") % path)
Benoit Boissinot
add "requires" file to the repo, specifying the requirements
r3851 else:
# find requirements
Matt Mackall
localrepo: use set for requirements
r8262 requirements = set()
Benoit Boissinot
add "requires" file to the repo, specifying the requirements
r3851 try:
Matt Mackall
localrepo: use set for requirements
r8262 requirements = set(self.opener("requires").read().splitlines())
Benoit Boissinot
add "requires" file to the repo, specifying the requirements
r3851 except IOError, inst:
if inst.errno != errno.ENOENT:
raise
Matt Mackall
localrepo: use set for requirements
r8262 for r in requirements - self.supported:
raise error.RepoError(_("requirement '%s' not supported") % r)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
repo: add internal support for sharing store directories...
r8799 self.sharedpath = self.path
try:
s = os.path.realpath(self.opener("sharedpath").read())
if not os.path.exists(s):
raise error.RepoError(
Dongsheng Song
Fix warning: Seen unexpected token "%"
r8908 _('.hg/sharedpath points to nonexistent directory %s') % s)
Matt Mackall
repo: add internal support for sharing store directories...
r8799 self.sharedpath = s
except IOError, inst:
if inst.errno != errno.ENOENT:
raise
self.store = store.store(requirements, self.sharedpath, util.opener)
Adrian Buehlmann
introduce store classes...
r6840 self.spath = self.store.path
self.sopener = self.store.opener
self.sjoin = self.store.join
self.opener.createmode = self.store.createmode
Benoit Boissinot
move code around
r3850
Greg Ward
localrepo: rename in-memory tag cache instance attributes (issue548)....
r9146 # These two define the set of tags for this repository. _tags
# maps tag name to node; _tagtypes maps tag name to 'global' or
# 'local'. (Global tags are defined by .hgtags across all
# heads, and local tags are defined in .hg/localtags.) They
# constitute the in-memory cache of tags.
self._tags = None
self._tagtypes = None
Matt Mackall
Add branchtags function with cache...
r3417 self.branchcache = None
Alexis S. L. Carvalho
localrepo: keep the UTF-8 version of branchcache around
r6119 self._ubranchcache = None # UTF-8 version of branchcache
Alexis S. L. Carvalho
automatically update the branch cache when tip changes
r6121 self._branchcachetip = None
mpm@selenic.com
Break apart hg.py...
r1089 self.nodetagscache = None
Matt Mackall
unify encode/decode filter routines
r4004 self.filterpats = {}
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 self._datafilters = {}
Matt Mackall
Use a weakref for recursive transactions
r4916 self._transref = self._lockref = self._wlockref = None
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
localrepo: use propertycache
r8260 @propertycache
def changelog(self):
c = changelog.changelog(self.sopener)
if 'HG_PENDING' in os.environ:
p = os.environ['HG_PENDING']
if p.startswith(self.root):
c.readpending('00changelog.i.a')
self.sopener.defversion = c.version
return c
@propertycache
def manifest(self):
return manifest.manifest(self.sopener)
@propertycache
def dirstate(self):
return dirstate.dirstate(self.opener, self.ui, self.root)
Vadim Gelfer
support hooks written in python....
r2155
Matt Mackall
use repo[changeid] to get a changectx
r6747 def __getitem__(self, changeid):
Martin Geisler
use 'x is None' instead of 'x == None'...
r8527 if changeid is None:
Matt Mackall
use repo[changeid] to get a changectx
r6747 return context.workingctx(self)
return context.changectx(self, changeid)
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 def __nonzero__(self):
return True
def __len__(self):
return len(self.changelog)
def __iter__(self):
for i in xrange(len(self)):
yield i
Vadim Gelfer
support hooks written in python....
r2155
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673 def url(self):
return 'file:' + self.root
Vadim Gelfer
make hook code nicer....
r1718 def hook(self, name, throw=False, **args):
Matt Mackall
hooks: separate hook code into a separate module
r4622 return hook.hook(self.ui, self, name, throw, **args)
mpm@selenic.com
Break apart hg.py...
r1089
Vadim Gelfer
move most of tag code to localrepository class.
r2601 tag_disallowed = ':\r\n'
Matt Mackall
tag: drop unused use_dirstate and parent from _tag()
r8402 def _tag(self, names, node, message, local, user, date, extra={}):
John Coomes
tag: allow multiple tags to be added or removed...
r6321 if isinstance(names, str):
allchars = names
names = (names,)
else:
allchars = ''.join(names)
Brendan Cully
Break core of repo.tag into dirstate/hook-free repo._tag for convert-repo
r4118 for c in self.tag_disallowed:
John Coomes
tag: allow multiple tags to be added or removed...
r6321 if c in allchars:
Brendan Cully
Break core of repo.tag into dirstate/hook-free repo._tag for convert-repo
r4118 raise util.Abort(_('%r cannot be used in a tag name') % c)
John Coomes
tag: allow multiple tags to be added or removed...
r6321 for name in names:
self.hook('pretag', throw=True, node=hex(node), tag=name,
local=local)
Brendan Cully
Break core of repo.tag into dirstate/hook-free repo._tag for convert-repo
r4118
John Coomes
tag: allow multiple tags to be added or removed...
r6321 def writetags(fp, names, munge, prevtags):
Alexis S. L. Carvalho
localrepo._tag: add a seek before writing the new tag...
r5985 fp.seek(0, 2)
Bryan O'Sullivan
tag: handle .hgtags and .hg/localtags with missing final newline (issue 601)...
r4932 if prevtags and prevtags[-1] != '\n':
fp.write('\n')
John Coomes
tag: allow multiple tags to be added or removed...
r6321 for name in names:
Matt Mackall
tag: record tag we're superseding, if any (issue 1102)
r6671 m = munge and munge(name) or name
Greg Ward
localrepo: rename in-memory tag cache instance attributes (issue548)....
r9146 if self._tagtypes and name in self._tagtypes:
old = self._tags.get(name, nullid)
Matt Mackall
tag: record tag we're superseding, if any (issue 1102)
r6671 fp.write('%s %s\n' % (hex(old), m))
fp.write('%s %s\n' % (hex(node), m))
Bryan O'Sullivan
tag: handle .hgtags and .hg/localtags with missing final newline (issue 601)...
r4932 fp.close()
Thomas Arendsen Hein
Remove trailing spaces
r5081
Bryan O'Sullivan
tag: handle .hgtags and .hg/localtags with missing final newline (issue 601)...
r4932 prevtags = ''
Brendan Cully
Break core of repo.tag into dirstate/hook-free repo._tag for convert-repo
r4118 if local:
Bryan O'Sullivan
tag: handle .hgtags and .hg/localtags with missing final newline (issue 601)...
r4932 try:
fp = self.opener('localtags', 'r+')
Peter Arrenbrecht
cleanup: drop unused assignments
r7875 except IOError:
Bryan O'Sullivan
tag: handle .hgtags and .hg/localtags with missing final newline (issue 601)...
r4932 fp = self.opener('localtags', 'a')
else:
prevtags = fp.read()
Brendan Cully
Break core of repo.tag into dirstate/hook-free repo._tag for convert-repo
r4118 # local tags are stored in the current charset
John Coomes
tag: allow multiple tags to be added or removed...
r6321 writetags(fp, names, None, prevtags)
for name in names:
self.hook('tag', node=hex(node), tag=name, local=local)
Brendan Cully
Break core of repo.tag into dirstate/hook-free repo._tag for convert-repo
r4118 return
Matt Mackall
tag: drop unused use_dirstate and parent from _tag()
r8402 try:
fp = self.wfile('.hgtags', 'rb+')
except IOError:
fp = self.wfile('.hgtags', 'ab')
Bryan O'Sullivan
tag: handle .hgtags and .hg/localtags with missing final newline (issue 601)...
r4932 else:
Matt Mackall
tag: drop unused use_dirstate and parent from _tag()
r8402 prevtags = fp.read()
Bryan O'Sullivan
tag: handle .hgtags and .hg/localtags with missing final newline (issue 601)...
r4932
Brendan Cully
Break core of repo.tag into dirstate/hook-free repo._tag for convert-repo
r4118 # committed tags are stored in UTF-8
Matt Mackall
move encoding bits from util to encoding...
r7948 writetags(fp, names, encoding.fromlocal, prevtags)
Bryan O'Sullivan
tag: handle .hgtags and .hg/localtags with missing final newline (issue 601)...
r4932
Matt Mackall
tag: drop unused use_dirstate and parent from _tag()
r8402 if '.hgtags' not in self.dirstate:
Brendan Cully
Break core of repo.tag into dirstate/hook-free repo._tag for convert-repo
r4118 self.add(['.hgtags'])
Matt Mackall
tag: use match.exact for commit
r8705 m = match_.exact(self.root, '', ['.hgtags'])
Matt Mackall
commit: drop the now-unused files parameter
r8706 tagnode = self.commit(message, user, date, extra=extra, match=m)
Brendan Cully
Break core of repo.tag into dirstate/hook-free repo._tag for convert-repo
r4118
John Coomes
tag: allow multiple tags to be added or removed...
r6321 for name in names:
self.hook('tag', node=hex(node), tag=name, local=local)
Brendan Cully
Break core of repo.tag into dirstate/hook-free repo._tag for convert-repo
r4118
return tagnode
John Coomes
tag: allow multiple tags to be added or removed...
r6321 def tag(self, names, node, message, local, user, date):
'''tag a revision with one or more symbolic names.
Vadim Gelfer
move most of tag code to localrepository class.
r2601
John Coomes
tag: allow multiple tags to be added or removed...
r6321 names is a list of strings or, when adding a single tag, names may be a
string.
Thomas Arendsen Hein
tab/space cleanup
r6334
John Coomes
tag: allow multiple tags to be added or removed...
r6321 if local is True, the tags are stored in a per-repository file.
otherwise, they are stored in the .hgtags file, and a new
Vadim Gelfer
move most of tag code to localrepository class.
r2601 changeset is committed with the change.
keyword arguments:
John Coomes
tag: allow multiple tags to be added or removed...
r6321 local: whether to store tags in non-version-controlled file
Vadim Gelfer
move most of tag code to localrepository class.
r2601 (default False)
message: commit message to use if committing
user: name of user to use if committing
date: date tuple to use if committing'''
Vadim Gelfer
remove localrepository.changes....
r2875 for x in self.status()[:5]:
Vadim Gelfer
move most of tag code to localrepository class.
r2601 if '.hgtags' in x:
raise util.Abort(_('working copy of .hgtags is changed '
'(please commit .hgtags manually)'))
Matt Mackall
tag: force load of tag cache
r7814 self.tags() # instantiate the cache
John Coomes
tag: allow multiple tags to be added or removed...
r6321 self._tag(names, node, message, local, user, date)
Vadim Gelfer
move most of tag code to localrepository class.
r2601
mpm@selenic.com
Break apart hg.py...
r1089 def tags(self):
'''return a mapping of tag to node'''
Greg Ward
localrepo: rename in-memory tag cache instance attributes (issue548)....
r9146 if self._tags is None:
(self._tags, self._tagtypes) = self._findtags()
Greg Ward
localrepo: factor _findtags() out of tags() (issue548)....
r9145
Greg Ward
localrepo: rename in-memory tag cache instance attributes (issue548)....
r9146 return self._tags
Greg Ward
localrepo: factor _findtags() out of tags() (issue548)....
r9145
def _findtags(self):
'''Do the hard work of finding tags. Return a pair of dicts
(tags, tagtypes) where tags maps tag name to node, and tagtypes
maps tag name to a string like \'global\' or \'local\'.
Subclasses or extensions are free to add their own tags, but
should be aware that the returned dicts will be retained for the
duration of the localrepo object.'''
# XXX what tagtype should subclasses/extensions use? Currently
# mq and bookmarks add tags, but do not set the tagtype at all.
# Should each extension invent its own tag type? Should there
# be one tagtype for all such "virtual" tags? Or is the status
# quo fine?
Matt Mackall
Refactor tags code to prepare for improving the algorithm
r4210
Greg Ward
localrepo: factor updatetags() out of readtags() (issue548).
r9148 alltags = {} # map tag name to (node, hist)
tagtypes = {}
Greg Ward
Factor tags module out of localrepo (issue548)....
r9149 tags_.findglobaltags(self.ui, self, alltags, tagtypes)
tags_.readlocaltags(self.ui, self, alltags, tagtypes)
mpm@selenic.com
Break apart hg.py...
r1089
Greg Ward
localrepo: factor _findtags() out of tags() (issue548)....
r9145 tags = {}
Greg Ward
localrepo: improve readability of _findtags(), readtags() (issue548)....
r9147 for (name, (node, hist)) in alltags.iteritems():
if node != nullid:
tags[name] = node
Greg Ward
localrepo: factor _findtags() out of tags() (issue548)....
r9145 tags['tip'] = self.changelog.tip()
return (tags, tagtypes)
mpm@selenic.com
Break apart hg.py...
r1089
Osku Salerma
Properly check tag's existence as a local/global tag when removing it.
r5657 def tagtype(self, tagname):
'''
return the type of the given tag. result can be:
'local' : a local tag
'global' : a global tag
None : tag does not exist
'''
self.tags()
Thomas Arendsen Hein
Removed tabs and trailing whitespace in python files
r5760
Greg Ward
localrepo: rename in-memory tag cache instance attributes (issue548)....
r9146 return self._tagtypes.get(tagname)
Osku Salerma
Properly check tag's existence as a local/global tag when removing it.
r5657
mpm@selenic.com
Break apart hg.py...
r1089 def tagslist(self):
'''return a list of tags ordered by revision'''
l = []
Dirkjan Ochtman
use dict.iteritems() rather than dict.items()...
r7622 for t, n in self.tags().iteritems():
mpm@selenic.com
Break apart hg.py...
r1089 try:
r = self.changelog.rev(n)
except:
r = -2 # sort to the beginning of the list if unknown
Thomas Arendsen Hein
Cleanup of indentation, spacing, newlines, strings and line length
r1615 l.append((r, t, n))
Matt Mackall
replace util.sort with sorted built-in...
r8209 return [(t, n) for r, t, n in sorted(l)]
mpm@selenic.com
Break apart hg.py...
r1089
def nodetags(self, node):
'''return the tags associated with a node'''
if not self.nodetagscache:
self.nodetagscache = {}
Dirkjan Ochtman
use dict.iteritems() rather than dict.items()...
r7622 for t, n in self.tags().iteritems():
Thomas Arendsen Hein
Cleanup of indentation, spacing, newlines, strings and line length
r1615 self.nodetagscache.setdefault(n, []).append(t)
mpm@selenic.com
Break apart hg.py...
r1089 return self.nodetagscache.get(node, [])
Alexis S. L. Carvalho
move the reading of branch.cache from _branchtags to branchtags
r6120 def _branchtags(self, partial, lrev):
John Mulligan
store all heads of a branch in the branch cache...
r7654 # TODO: rename this function?
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 tiprev = len(self) - 1
Alexis S. L. Carvalho
Split branchtags into two additional functions....
r3491 if lrev != tiprev:
self._updatebranchcache(partial, lrev+1, tiprev+1)
self._writebranchcache(partial, self.changelog.tip(), tiprev)
Alexis S. L. Carvalho
fix encoding conversion of branch names when mq is loaded
r3826 return partial
Henrik Stuart
named branches: server branchmap wire protocol support (issue736)...
r8562 def branchmap(self):
Alexis S. L. Carvalho
automatically update the branch cache when tip changes
r6121 tip = self.changelog.tip()
if self.branchcache is not None and self._branchcachetip == tip:
Alexis S. L. Carvalho
fix encoding conversion of branch names when mq is loaded
r3826 return self.branchcache
Alexis S. L. Carvalho
automatically update the branch cache when tip changes
r6121 oldtip = self._branchcachetip
self._branchcachetip = tip
if self.branchcache is None:
self.branchcache = {} # avoid recursion in changectx
else:
self.branchcache.clear() # keep using the same dict
if oldtip is None or oldtip not in self.changelog.nodemap:
partial, last, lrev = self._readbranchcache()
else:
lrev = self.changelog.rev(oldtip)
partial = self._ubranchcache
Alexis S. L. Carvalho
move the reading of branch.cache from _branchtags to branchtags
r6120 self._branchtags(partial, lrev)
John Mulligan
store all heads of a branch in the branch cache...
r7654 # this private cache holds all heads (not just tips)
self._ubranchcache = partial
Alexis S. L. Carvalho
fix encoding conversion of branch names when mq is loaded
r3826
Matt Mackall
Handle transcoding of branch names
r3773 # the branch cache is stored on disk as UTF-8, but in the local
# charset internally
Dirkjan Ochtman
use dict.iteritems() rather than dict.items()...
r7622 for k, v in partial.iteritems():
Matt Mackall
move encoding bits from util to encoding...
r7948 self.branchcache[encoding.tolocal(k)] = v
Alexis S. L. Carvalho
Split branchtags into two additional functions....
r3491 return self.branchcache
John Mulligan
store all heads of a branch in the branch cache...
r7654
def branchtags(self):
'''return a dict where branch names map to the tipmost head of
John Mulligan
branch closing: referencing open and closed branches/heads...
r7656 the branch, open heads come before closed'''
bt = {}
Henrik Stuart
named branches: server branchmap wire protocol support (issue736)...
r8562 for bn, heads in self.branchmap().iteritems():
John Mulligan
branch closing: referencing open and closed branches/heads...
r7656 head = None
for i in range(len(heads)-1, -1, -1):
h = heads[i]
if 'close' not in self.changelog.read(h)[5]:
head = h
break
# no open heads were found
if head is None:
head = heads[-1]
bt[bn] = head
return bt
John Mulligan
store all heads of a branch in the branch cache...
r7654
Alexis S. L. Carvalho
Split branchtags into two additional functions....
r3491 def _readbranchcache(self):
partial = {}
Matt Mackall
Add branchtags function with cache...
r3417 try:
John Mulligan
store all heads of a branch in the branch cache...
r7654 f = self.opener("branchheads.cache")
Alexis S. L. Carvalho
don't use readline() to read branches.cache...
r3668 lines = f.read().split('\n')
f.close()
Matt Mackall
branch.cache: silently ignore I/O and OS errors
r4415 except (IOError, OSError):
return {}, nullid, nullrev
try:
Thomas Arendsen Hein
Store empty (default) branch in branch cache, too....
r4167 last, lrev = lines.pop(0).split(" ", 1)
Matt Mackall
Add branchtags function with cache...
r3417 last, lrev = bin(last), int(lrev)
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 if lrev >= len(self) or self[lrev].node() != last:
Alexis S. L. Carvalho
Ignore all errors while parsing the branch cache.
r3761 # invalidate the cache
Thomas Arendsen Hein
Print less scary warning when invalidating the branch cache.
r6056 raise ValueError('invalidating branch cache (tip differs)')
Alexis S. L. Carvalho
Ignore all errors while parsing the branch cache.
r3761 for l in lines:
if not l: continue
Thomas Arendsen Hein
Store empty (default) branch in branch cache, too....
r4167 node, label = l.split(" ", 1)
John Mulligan
store all heads of a branch in the branch cache...
r7654 partial.setdefault(label.strip(), []).append(bin(node))
Matt Mackall
error: move SignalInterrupt...
r7644 except KeyboardInterrupt:
Alexis S. L. Carvalho
Ignore all errors while parsing the branch cache.
r3761 raise
except Exception, inst:
if self.ui.debugflag:
self.ui.warn(str(inst), '\n')
partial, last, lrev = {}, nullid, nullrev
Alexis S. L. Carvalho
Split branchtags into two additional functions....
r3491 return partial, last, lrev
Matt Mackall
Add branchtags function with cache...
r3417
Alexis S. L. Carvalho
Split branchtags into two additional functions....
r3491 def _writebranchcache(self, branches, tip, tiprev):
Matt Mackall
If we can't write the branch cache, fail quietly.
r3452 try:
John Mulligan
store all heads of a branch in the branch cache...
r7654 f = self.opener("branchheads.cache", "w", atomictemp=True)
Alexis S. L. Carvalho
Split branchtags into two additional functions....
r3491 f.write("%s %s\n" % (hex(tip), tiprev))
John Mulligan
store all heads of a branch in the branch cache...
r7654 for label, nodes in branches.iteritems():
for node in nodes:
f.write("%s %s\n" % (hex(node), label))
Alexis S. L. Carvalho
use atomictemp files to write branch.cache
r4329 f.rename()
Matt Mackall
branch.cache: silently ignore I/O and OS errors
r4415 except (IOError, OSError):
Matt Mackall
If we can't write the branch cache, fail quietly.
r3452 pass
Matt Mackall
Add branchtags function with cache...
r3417
Alexis S. L. Carvalho
Split branchtags into two additional functions....
r3491 def _updatebranchcache(self, partial, start, end):
Brendan Cully
Branch heads should not include "heads" that are ancestors of other heads....
r8954 # collect new branch entries
newbranches = {}
Alexis S. L. Carvalho
Split branchtags into two additional functions....
r3491 for r in xrange(start, end):
Matt Mackall
use repo[changeid] to get a changectx
r6747 c = self[r]
Brendan Cully
Branch heads should not include "heads" that are ancestors of other heads....
r8954 newbranches.setdefault(c.branch(), []).append(c.node())
# if older branchheads are reachable from new ones, they aren't
# really branchheads. Note checking parents is insufficient:
# 1 (branch a) -> 2 (branch b) -> 3 (branch a)
for branch, newnodes in newbranches.iteritems():
bheads = partial.setdefault(branch, [])
bheads.extend(newnodes)
if len(bheads) < 2:
continue
newbheads = []
# starting from tip means fewer passes over reachable
while newnodes:
latest = newnodes.pop()
if latest not in bheads:
continue
Henrik Stuart
branch heads: optimise computation of branch head cache (issue1734)...
r9120 minbhrev = self[min([self[bh].rev() for bh in bheads])].node()
reachable = self.changelog.reachable(latest, minbhrev)
Brendan Cully
Branch heads should not include "heads" that are ancestors of other heads....
r8954 bheads = [b for b in bheads if b not in reachable]
newbheads.insert(0, latest)
bheads.extend(newbheads)
partial[branch] = bheads
Alexis S. L. Carvalho
Split branchtags into two additional functions....
r3491
mpm@selenic.com
Break apart hg.py...
r1089 def lookup(self, key):
Matt Mackall
lookup: fast-paths for int and 'tip'
r7377 if isinstance(key, int):
return self.changelog.node(key)
elif key == '.':
Matt Mackall
lookup: optimize '.'...
r6736 return self.dirstate.parents()[0]
Brendan Cully
Add "null" pseudo-tag pointing to nullid
r3801 elif key == 'null':
return nullid
Matt Mackall
lookup: fast-paths for int and 'tip'
r7377 elif key == 'tip':
return self.changelog.tip()
Matt Mackall
Only look up tags and branches as a last resort
r3453 n = self.changelog._match(key)
if n:
return n
Matt Mackall
Make lookup aware of branch labels...
r3418 if key in self.tags():
mpm@selenic.com
Break apart hg.py...
r1089 return self.tags()[key]
Matt Mackall
Make lookup aware of branch labels...
r3418 if key in self.branchtags():
return self.branchtags()[key]
Matt Mackall
Only look up tags and branches as a last resort
r3453 n = self.changelog._partialmatch(key)
if n:
return n
Matt Mackall
lookup: check for dirstate damage on failure
r8639
# can't find key, check if it might have come from damaged dirstate
if key in self.dirstate.parents():
raise error.Abort(_("working directory has unknown parent '%s'!")
% short(key))
Matt Mackall
Use a weakref for recursive transactions
r4916 try:
if len(key) == 20:
key = hex(key)
except:
pass
Matt Mackall
error: move repo errors...
r7637 raise error.RepoError(_("unknown revision '%s'") % key)
mpm@selenic.com
Break apart hg.py...
r1089
def local(self):
mpm@selenic.com
Separate out old-http support...
r1101 return True
mpm@selenic.com
Break apart hg.py...
r1089
def join(self, f):
return os.path.join(self.path, f)
def wjoin(self, f):
return os.path.join(self.root, f)
Bryan O'Sullivan
repo: add rjoin method
r6526 def rjoin(self, f):
return os.path.join(self.root, util.pconvert(f))
Dirkjan Ochtman
remove trailing whitespace introduced in cfeeac24fc1e
r6528
mpm@selenic.com
Break apart hg.py...
r1089 def file(self, f):
Thomas Arendsen Hein
Cleanup of indentation, spacing, newlines, strings and line length
r1615 if f[0] == '/':
f = f[1:]
Matt Mackall
revlog: simplify revlog version handling...
r4258 return filelog.filelog(self.sopener, f)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
context: avoid using None for working parent
r6739 def changectx(self, changeid):
Matt Mackall
use repo[changeid] to get a changectx
r6747 return self[changeid]
Matt Mackall
merge: use new working context object in update
r3218
Matt Mackall
Add localrepo.parents to get parent changectxs.
r3163 def parents(self, changeid=None):
Matt Mackall
context: clean up parents()
r6742 '''get list of changectxs for parents of changeid'''
Matt Mackall
use repo[changeid] to get a changectx
r6747 return self[changeid].parents()
Matt Mackall
Add localrepo.parents to get parent changectxs.
r3163
Matt Mackall
Add context helper functions to localrepo
r2564 def filectx(self, path, changeid=None, fileid=None):
"""changeid can be a changeset revision, node, or tag.
fileid can be a file revision or node."""
return context.filectx(self, path, changeid, fileid)
mpm@selenic.com
Break apart hg.py...
r1089 def getcwd(self):
return self.dirstate.getcwd()
Alexis S. L. Carvalho
Add dirstate.pathto and localrepo.pathto....
r4525 def pathto(self, f, cwd=None):
return self.dirstate.pathto(f, cwd)
mpm@selenic.com
Break apart hg.py...
r1089 def wfile(self, f, mode='r'):
return self.wopener(f, mode)
Alexis S. L. Carvalho
use os.path.islink instead of util.is_link; remove util.is_link
r4275 def _link(self, f):
return os.path.islink(self.wjoin(f))
Matt Mackall
unify encode/decode filter routines
r4004 def _filter(self, filter, filename, data):
if filter not in self.filterpats:
mpm@selenic.com
Add file encoding/decoding support
r1258 l = []
Matt Mackall
unify encode/decode filter routines
r4004 for pat, cmd in self.ui.configitems(filter):
Mads Kiilerich
Make it possible to disable filtering for a pattern....
r7226 if cmd == '!':
continue
Matt Mackall
match: add some default args
r8567 mf = match_.match(self.root, '', [pat])
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 fn = None
Jesse Glick
Strip filter name from command before passing to filter function....
r6066 params = cmd
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 for name, filterfn in self._datafilters.iteritems():
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210 if cmd.startswith(name):
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 fn = filterfn
Jesse Glick
Strip filter name from command before passing to filter function....
r6066 params = cmd[len(name):].lstrip()
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 break
if not fn:
Jesse Glick
Provide better context for custom Python encode/decode filters....
r5967 fn = lambda s, c, **kwargs: util.filter(s, c)
# Wrap old filters not supporting keyword arguments
if not inspect.getargspec(fn)[2]:
oldfn = fn
fn = lambda s, c, **kwargs: oldfn(s, c)
Jesse Glick
Strip filter name from command before passing to filter function....
r6066 l.append((mf, fn, params))
Matt Mackall
unify encode/decode filter routines
r4004 self.filterpats[filter] = l
mpm@selenic.com
Add file encoding/decoding support
r1258
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 for mf, fn, cmd in self.filterpats[filter]:
mpm@selenic.com
Add file encoding/decoding support
r1258 if mf(filename):
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.ui.debug(_("filtering %s through %s\n") % (filename, cmd))
Jesse Glick
Provide better context for custom Python encode/decode filters....
r5967 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
mpm@selenic.com
Add file encoding/decoding support
r1258 break
return data
mpm@selenic.com
Break apart hg.py...
r1089
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 def adddatafilter(self, name, filter):
self._datafilters[name] = filter
Matt Mackall
unify encode/decode filter routines
r4004 def wread(self, filename):
if self._link(filename):
data = os.readlink(self.wjoin(filename))
else:
data = self.wopener(filename, 'r').read()
return self._filter("encode", filename, data)
mpm@selenic.com
Add file encoding/decoding support
r1258
Matt Mackall
symlinks: add flags param to wwrite...
r4006 def wwrite(self, filename, data, flags):
Matt Mackall
unify encode/decode filter routines
r4004 data = self._filter("decode", filename, data)
Matt Mackall
wwrite: simplify with util.set_flags...
r5703 try:
os.unlink(self.wjoin(filename))
except OSError:
pass
Matt Mackall
util: set_flags shouldn't know about repo flag formats
r6877 if 'l' in flags:
self.wopener.symlink(data, filename)
else:
self.wopener(filename, 'w').write(data)
if 'x' in flags:
util.set_flags(self.wjoin(filename), False, True)
mpm@selenic.com
Add file encoding/decoding support
r1258
Matt Mackall
replace filehandle version of wwrite with wwritedata
r4005 def wwritedata(self, filename, data):
return self._filter("decode", filename, data)
mpm@selenic.com
Break apart hg.py...
r1089
def transaction(self):
Henrik Stuart
transaction: support multiple, separate transactions...
r8072 tr = self._transref and self._transref() or None
if tr and tr.running():
return tr.nest()
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806
Matt Mackall
transactions: don't show a backtrace when journal exists...
r5865 # abort here if the journal already exists
if os.path.exists(self.sjoin("journal")):
Matt Mackall
error: move repo errors...
r7637 raise error.RepoError(_("journal already exists - run hg recover"))
Matt Mackall
transactions: don't show a backtrace when journal exists...
r5865
Thomas Arendsen Hein
Renamed localrepo.undo() to rollback() and talk about "rollback information".
r2362 # save dirstate for rollback
mpm@selenic.com
Break apart hg.py...
r1089 try:
ds = self.opener("dirstate").read()
except IOError:
ds = ""
self.opener("journal.dirstate", "w").write(ds)
Alexandre Vassalotti
restore branch after rollback (issue 902)
r5814 self.opener("journal.branch", "w").write(self.dirstate.branch())
mpm@selenic.com
Break apart hg.py...
r1089
Benoit Boissinot
localrepo: change aftertrans to be independant of the store path
r3790 renames = [(self.sjoin("journal"), self.sjoin("undo")),
Alexandre Vassalotti
restore branch after rollback (issue 902)
r5814 (self.join("journal.dirstate"), self.join("undo.dirstate")),
(self.join("journal.branch"), self.join("undo.branch"))]
Matt Mackall
localrepo: add separate methods for manipulating repository data...
r3457 tr = transaction.transaction(self.ui.warn, self.sopener,
Alexis S. L. Carvalho
make the journal/undo files from transactions inherit the mode from .hg/store
r6065 self.sjoin("journal"),
aftertrans(renames),
Matt Mackall
localrepo: kill _createmode
r6894 self.store.createmode)
Matt Mackall
Use a weakref for recursive transactions
r4916 self._transref = weakref.ref(tr)
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806 return tr
mpm@selenic.com
Break apart hg.py...
r1089
def recover(self):
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 lock = self.lock()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
if os.path.exists(self.sjoin("journal")):
self.ui.status(_("rolling back interrupted transaction\n"))
Henrik Stuart
transaction: refactor transaction.abort and rollback to use the same code...
r8294 transaction.rollback(self.sopener, self.sjoin("journal"), self.ui.warn)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.invalidate()
return True
else:
self.ui.warn(_("no interrupted transaction available\n"))
return False
finally:
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 lock.release()
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 def rollback(self):
wlock = lock = None
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
mason@suse.com
Allow callers to pass in the dirstate lock in most localrepo.py funcs....
r1712 wlock = self.wlock()
Eric Hopper
Fix hg import --exact bug that hangs hg on failure.
r4438 lock = self.lock()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 if os.path.exists(self.sjoin("undo")):
self.ui.status(_("rolling back last transaction\n"))
Henrik Stuart
transaction: refactor transaction.abort and rollback to use the same code...
r8294 transaction.rollback(self.sopener, self.sjoin("undo"), self.ui.warn)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 util.rename(self.join("undo.dirstate"), self.join("dirstate"))
Thomas Arendsen Hein
Do not abort rollback if undo.branch isn't available, but warn.
r6058 try:
branch = self.opener("undo.branch").read()
self.dirstate.setbranch(branch)
except IOError:
self.ui.warn(_("Named branch could not be reset, "
"current branch still is: %s\n")
Matt Mackall
move encoding bits from util to encoding...
r7948 % encoding.tolocal(self.dirstate.branch()))
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.invalidate()
self.dirstate.invalidate()
Greg Ward
localrepo: add destroyed() method for strip/rollback to use (issue548).
r9150 self.destroyed()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 else:
self.ui.warn(_("no rollback information available\n"))
finally:
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 release(lock, wlock)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
localrepo and dirstate: rename reload to invalidate...
r4613 def invalidate(self):
for a in "changelog manifest".split():
Alexis S. L. Carvalho
don't use hasattr in repo.invalidate...
r6371 if a in self.__dict__:
delattr(self, a)
Greg Ward
localrepo: rename in-memory tag cache instance attributes (issue548)....
r9146 self._tags = None
self._tagtypes = None
Benoit Boissinot
revalidate revlog data after locking the repo (issue132)
r1784 self.nodetagscache = None
Alexis S. L. Carvalho
localrepo.invalidate: invalidate branchcache
r6118 self.branchcache = None
Alexis S. L. Carvalho
localrepo: keep the UTF-8 version of branchcache around
r6119 self._ubranchcache = None
Alexis S. L. Carvalho
automatically update the branch cache when tip changes
r6121 self._branchcachetip = None
Benoit Boissinot
revalidate revlog data after locking the repo (issue132)
r1784
Matt Mackall
rename and simplify do_lock
r4913 def _lock(self, lockname, wait, releasefn, acquirefn, desc):
mpm@selenic.com
Break apart hg.py...
r1089 try:
Matt Mackall
localrepo: add separate methods for manipulating repository data...
r3457 l = lock.lock(lockname, 0, releasefn, desc=desc)
Matt Mackall
error: move lock errors...
r7640 except error.LockHeld, inst:
Benoit Boissinot
add localrepo.wlock for protecting the dirstate...
r1531 if not wait:
Vadim Gelfer
fix backtrace printed when cannot get lock....
r2016 raise
Thomas Arendsen Hein
Corrected "waiting for lock on repository FOO held by BAR" message....
r3688 self.ui.warn(_("waiting for lock on %s held by %r\n") %
(desc, inst.locker))
Vadim Gelfer
fix backtrace printed when cannot get lock....
r2016 # default to 600 seconds timeout
Matt Mackall
localrepo: add separate methods for manipulating repository data...
r3457 l = lock.lock(lockname, int(self.ui.config("ui", "timeout", "600")),
Vadim Gelfer
fix backtrace printed when cannot get lock....
r2016 releasefn, desc=desc)
Benoit Boissinot
localrepo: refactor the locking functions
r1751 if acquirefn:
acquirefn()
return l
Matt Mackall
repo locks: use True/False
r4914 def lock(self, wait=True):
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 l = self._lockref and self._lockref()
if l is not None and l.held:
l.lock()
return l
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917
l = self._lock(self.sjoin("lock"), wait, None, self.invalidate,
_('repository %s') % self.origroot)
self._lockref = weakref.ref(l)
return l
Benoit Boissinot
localrepo: refactor the locking functions
r1751
Matt Mackall
repo locks: use True/False
r4914 def wlock(self, wait=True):
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 l = self._wlockref and self._wlockref()
if l is not None and l.held:
l.lock()
return l
Benoit Boissinot
add localrepo.wlock for protecting the dirstate...
r1531
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 l = self._lock(self.join("wlock"), wait, self.dirstate.write,
self.dirstate.invalidate, _('working directory of %s') %
self.origroot)
self._wlockref = weakref.ref(l)
return l
Benoit Boissinot
add localrepo.wlock for protecting the dirstate...
r1531
Matt Mackall
filecommit: swallow some bits from _commitctx, add _
r8401 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist):
Matt Mackall
merge: remember rename copies and parents properly on commit...
r3292 """
Matt Mackall
commit: unify file-level commit code
r3294 commit an individual file as part of a larger transaction
"""
Matt Mackall
merge: remember rename copies and parents properly on commit...
r3292
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 fname = fctx.path()
text = fctx.data()
flog = self.file(fname)
fparent1 = manifest1.get(fname, nullid)
Matt Mackall
filecommit: swallow some bits from _commitctx, add _
r8401 fparent2 = fparent2o = manifest2.get(fname, nullid)
Matt Mackall
Refactor excessive merge detection, add test
r1716
Matt Mackall
merge: remember rename copies and parents properly on commit...
r3292 meta = {}
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 copy = fctx.renamed()
if copy and copy[0] != fname:
Alexis S. L. Carvalho
filecommit: don't forget the local parent on a merge with a local rename
r4058 # Mark the new revision of this file as a copy of another
Thomas Arendsen Hein
Removed trailing whitespace and tabs from python files
r4516 # file. This copy data will effectively act as a parent
# of this new revision. If this is a merge, the first
Alexis S. L. Carvalho
filecommit: don't forget the local parent on a merge with a local rename
r4058 # parent will be the nullid (meaning "look up the copy data")
# and the second one will be the other parent. For example:
#
# 0 --- 1 --- 3 rev1 changes file foo
# \ / rev2 renames foo to bar and changes it
# \- 2 -/ rev3 should have bar with all changes and
# should record that bar descends from
# bar in rev2 and foo in rev1
#
# this allows this merge to succeed:
#
# 0 --- 1 --- 3 rev4 reverts the content change from rev2
# \ / merging rev3 and rev4 should use bar@rev2
# \- 2 --- 4 as the merge base
#
Matt Mackall
commit: simplify file copy logic
r6874
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 cfname = copy[0]
crev = manifest1.get(cfname)
newfparent = fparent2
Matt Mackall
commit: simplify file copy logic
r6874
if manifest2: # branch merge
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 if fparent2 == nullid or crev is None: # copied on remote side
if cfname in manifest2:
crev = manifest2[cfname]
newfparent = fparent1
Matt Mackall
commit: simplify file copy logic
r6874
Matt Mackall
add a fix for issue 1175...
r6875 # find source in nearest ancestor if we've lost track
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 if not crev:
Matt Mackall
add a fix for issue 1175...
r6875 self.ui.debug(_(" %s: searching for copy revision for %s\n") %
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 (fname, cfname))
for ancestor in self['.'].ancestors():
if cfname in ancestor:
crev = ancestor[cfname].filenode()
Matt Mackall
Merge with stable...
r6876 break
Matt Mackall
add a fix for issue 1175...
r6875
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 self.ui.debug(_(" %s: copy %s:%s\n") % (fname, cfname, hex(crev)))
meta["copy"] = cfname
meta["copyrev"] = hex(crev)
fparent1, fparent2 = nullid, newfparent
elif fparent2 != nullid:
Matt Mackall
Refactor excessive merge detection, add test
r1716 # is one parent an ancestor of the other?
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 fparentancestor = flog.ancestor(fparent1, fparent2)
if fparentancestor == fparent1:
fparent1, fparent2 = fparent2, nullid
elif fparentancestor == fparent2:
fparent2 = nullid
Matt Mackall
Refactor excessive merge detection, add test
r1716
Matt Mackall
filecommit: swallow some bits from _commitctx, add _
r8401 # is the file changed?
if fparent2 != nullid or flog.cmp(fparent1, text) or meta:
changelist.append(fname)
return flog.add(text, meta, tr, linkrev, fparent1, fparent2)
Matt Mackall
Refactor excessive merge detection, add test
r1716
Matt Mackall
filecommit: swallow some bits from _commitctx, add _
r8401 # are just the flags changed during merge?
if fparent1 != fparent2o and manifest1.flags(fname) != fctx.flags():
changelist.append(fname)
return fparent1
Matt Mackall
Refactor excessive merge detection, add test
r1716
Matt Mackall
commit: drop the now-unused files parameter
r8706 def commit(self, text="", user=None, date=None, match=None, force=False,
editor=False, extra={}):
Benoit Boissinot
localrepo: update commit*() docstrings
r8515 """Add a new revision to current repository.
Matt Mackall
commit: drop the now-unused files parameter
r8706 Revision information is gathered from the working directory,
match can be used to filter the committed files. If editor is
supplied, it is called to get a commit message.
Benoit Boissinot
localrepo: update commit*() docstrings
r8515 """
Matt Mackall
commit: move explicit file checking into repo.commit
r8709
Matt Mackall
commit: move some setup outside the lock
r8715 def fail(f, msg):
raise util.Abort('%s: %s' % (f, msg))
if not match:
match = match_.always(self.root, '')
if not force:
vdirs = []
match.dir = vdirs.append
match.bad = fail
Matt Mackall
commit: push repo lock down into _commitctx
r8405 wlock = self.wlock()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
Matt Mackall
remove deprecated rawcommit
r8397 p1, p2 = self.dirstate.parents()
Matt Mackall
commit: recurse into subrepositories
r8813 wctx = self[None]
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
commit: some tidying...
r8501 if (not force and p2 != nullid and match and
(match.files() or match.anypats())):
Matt Mackall
remove deprecated rawcommit
r8397 raise util.Abort(_('cannot partially commit a merge '
'(do not specify files or patterns)'))
Patrick Mezard
localrepo: replace dirstate by workingfilectx in filecommit()
r6706
Matt Mackall
commit: drop the now-unused files parameter
r8706 changes = self.status(match=match, clean=force)
if force:
changes[0].extend(changes[6]) # mq may commit unchanged files
Benoit Boissinot
localrepo: factor commit and rawcommit...
r3621
Matt Mackall
commit: recurse into subrepositories
r8813 # check subrepos
subs = []
for s in wctx.substate:
if match(s) and wctx.sub(s).dirty():
subs.append(s)
if subs and '.hgsubstate' not in changes[0]:
changes[0].insert(0, '.hgsubstate')
Matt Mackall
commit: move explicit file checking into repo.commit
r8709 # make sure all explicit patterns are matched
if not force and match.files():
Matt Mackall
commit: trade O(n^2) file checks for O(n^2) dir checks
r8710 matched = set(changes[0] + changes[1] + changes[2])
Matt Mackall
commit: move explicit file checking into repo.commit
r8709
for f in match.files():
Matt Mackall
commit: recurse into subrepositories
r8813 if f == '.' or f in matched or f in wctx.substate:
Matt Mackall
commit: move explicit file checking into repo.commit
r8709 continue
if f in changes[3]: # missing
fail(f, _('file not found!'))
if f in vdirs: # visited directory
d = f + '/'
Matt Mackall
commit: trade O(n^2) file checks for O(n^2) dir checks
r8710 for mf in matched:
if mf.startswith(d):
break
else:
Matt Mackall
commit: move explicit file checking into repo.commit
r8709 fail(f, _("no match under directory!"))
elif f not in self.dirstate:
fail(f, _("file not tracked!"))
Matt Mackall
commit: some tidying...
r8501 if (not force and not extra.get("close") and p2 == nullid
and not (changes[0] or changes[1] or changes[2])
and self[None].branch() == self['.'].branch()):
Matt Mackall
commit: move 'nothing changed' test into commit()
r8404 return None
Stefano Tortarolo
make commit fail when committing unresolved files
r6888 ms = merge_.mergestate(self)
for f in changes[0]:
if f in ms and ms[f] == 'u':
raise util.Abort(_("unresolved merge conflicts "
"(see hg resolve)"))
Matt Mackall
commit: move editor outside transaction...
r8496
Matt Mackall
commit: rename wctx to cctx
r8712 cctx = context.workingctx(self, (p1, p2), text, user, date,
Patrick Mezard
localrepo: do not expose workingctx options...
r6711 extra, changes)
Matt Mackall
commit: move editor outside transaction...
r8496 if editor:
Matt Mackall
commit: report modified subrepos in commit editor
r8994 cctx._text = editor(self, cctx, subs)
Matt Mackall
commit: recurse into subrepositories
r8813
# commit subs
if subs:
state = wctx.substate.copy()
for s in subs:
self.ui.status(_('committing subrepository %s\n') % s)
sr = wctx.sub(s).commit(cctx._text, user, date)
state[s] = (state[s][0], sr)
subrepo.writestate(self, state)
Matt Mackall
commit: rename wctx to cctx
r8712 ret = self.commitctx(cctx, True)
Matt Mackall
commit: move editor outside transaction...
r8496
Matt Mackall
commit: tidy up mergestate slightly
r8503 # update dirstate and mergestate
Matt Mackall
commit: hoist the rest of the dirstate manipulation out of commitctx
r8416 for f in changes[0] + changes[1]:
self.dirstate.normal(f)
for f in changes[2]:
self.dirstate.forget(f)
self.dirstate.setparents(ret)
Matt Mackall
commit: tidy up mergestate slightly
r8503 ms.reset()
Matt Mackall
commit: hoist the rest of the dirstate manipulation out of commitctx
r8416
Matt Mackall
commit: hoist up dirstate invalidate
r8415 return ret
Matt Mackall
resolve: move reset to localrepo.commit...
r7848
Patrick Mezard
localrepo: extract _commitctx() from commit()...
r6710 finally:
Matt Mackall
commit: push repo lock down into _commitctx
r8405 wlock.release()
Patrick Mezard
localrepo: extract _commitctx() from commit()...
r6710
Matt Mackall
commit: move editor outside transaction...
r8496 def commitctx(self, ctx, error=False):
Patrick Mezard
context: improve memctx documentation
r7077 """Add a new revision to current repository.
Matt Mackall
commit: combine _commitctx and commitctx, drop unused force argument
r8410 Revision information is passed via the context argument.
Patrick Mezard
context: improve memctx documentation
r7077 """
Patrick Mezard
context: add memctx for memory commits
r6715
Matt Mackall
commitctx: eliminate some variables
r8412 tr = lock = None
Matt Mackall
commit: simplify manifest commit
r8498 removed = ctx.removed()
Matt Mackall
commitctx: use contexts more fully
r8414 p1, p2 = ctx.p1(), ctx.p2()
m1 = p1.manifest().copy()
m2 = p2.manifest()
Matt Mackall
commitctx: eliminate some variables
r8412 user = ctx.user()
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
commitctx: use contexts more fully
r8414 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
Matt Mackall
commit: move lots of commitctx outside of the repo lock
r8411 self.hook("precommit", throw=True, parent1=xp1, parent2=xp2)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
commit: move lots of commitctx outside of the repo lock
r8411 lock = self.lock()
try:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 tr = self.transaction()
Matt Mackall
transactions: avoid late tear-down (issue641)...
r4970 trp = weakref.proxy(tr)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 # check in files
new = {}
Patrick Mezard
localrepo: extract _commitctx() from commit()...
r6710 changed = []
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 linkrev = len(self)
Matt Mackall
commitctx: eliminate some variables
r8412 for f in sorted(ctx.modified() + ctx.added()):
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.ui.note(f + "\n")
try:
Matt Mackall
filecommit: swallow some bits from _commitctx, add _
r8401 fctx = ctx[f]
new[f] = self._filecommit(fctx, m1, m2, linkrev, trp,
changed)
m1.set(f, fctx.flags())
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 except (OSError, IOError):
Matt Mackall
commit: hoist the rest of the dirstate manipulation out of commitctx
r8416 if error:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.ui.warn(_("trouble committing %s!\n") % f)
raise
else:
Matt Mackall
commit: simplify manifest commit
r8498 removed.append(f)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 # update manifest
m1.update(new)
Matt Mackall
commit: simplify manifest commit
r8498 removed = [f for f in sorted(removed) if f in m1 or f in m2]
drop = [f for f in removed if f in m1]
for f in drop:
del m1[f]
Matt Mackall
commitctx: use contexts more fully
r8414 mn = self.manifest.add(m1, trp, linkrev, p1.manifestnode(),
Matt Mackall
commit: simplify manifest commit
r8498 p2.manifestnode(), (new, drop))
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
commit: move description trimming into changelog
r8499 # update changelog
Matt Mackall
Introduce HG_PREPEND to solve pretxn races...
r7787 self.changelog.delayupdate()
Matt Mackall
commit: move description trimming into changelog
r8499 n = self.changelog.add(mn, changed + removed, ctx.description(),
trp, p1.node(), p2.node(),
Matt Mackall
commitctx: eliminate some variables
r8412 user, ctx.date(), ctx.extra().copy())
Matt Mackall
Introduce HG_PREPEND to solve pretxn races...
r7787 p = lambda: self.changelog.writepending() and self.root or ""
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
Matt Mackall
Introduce HG_PREPEND to solve pretxn races...
r7787 parent2=xp2, pending=p)
self.changelog.finalize(trp)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 tr.close()
mpm@selenic.com
Break apart hg.py...
r1089
Alexis S. L. Carvalho
automatically update the branch cache when tip changes
r6121 if self.branchcache:
self.branchtags()
Simon 'corecode' Schubert
When committing, record the changeset in the branchcache.
r4019
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2)
return n
finally:
Patrick Mezard
localrepo: extract _commitctx() from commit()...
r6710 del tr
Matt Mackall
commit: push repo lock down into _commitctx
r8405 lock.release()
mpm@selenic.com
Break apart hg.py...
r1089
Greg Ward
localrepo: add destroyed() method for strip/rollback to use (issue548).
r9150 def destroyed(self):
'''Inform the repository that nodes have been destroyed.
Intended for use by strip and rollback, so there's a common
place for anything that has to be done after destroying history.'''
# XXX it might be nice if we could take the list of destroyed
# nodes, but I don't see an easy way for rollback() to do that
Greg Ward
tags: implement persistent tag caching (issue548)....
r9151
# Ensure the persistent tag cache is updated. Doing it now
# means that the tag cache only has to worry about destroyed
# heads immediately after a strip/rollback. That in turn
# guarantees that "cachetip == currenttip" (comparing both rev
# and node) always means no nodes have been added or destroyed.
# XXX this is suboptimal when qrefresh'ing: we strip the current
# head, refresh the tag cache, then immediately add a new head.
# But I think doing it this way is necessary for the "instant
# tag cache retrieval" case to work.
tags_.findglobaltags(self.ui, self, {}, {})
Greg Ward
localrepo: add destroyed() method for strip/rollback to use (issue548).
r9150
Matt Mackall
walk: remove cmdutil.walk
r6585 def walk(self, match, node=None):
Matt Mackall
improve walk docstrings
r3532 '''
walk recursively through the directory tree or a given
changeset, finding all files matched by the match
function
'''
Matt Mackall
context: add walk method
r6764 return self[node].walk(match)
Matt Mackall
improve walk docstrings
r3532
Matt Mackall
status: use contexts
r6769 def status(self, node1='.', node2=None, match=None,
Matt Mackall
status: clean up all users for unknown files
r6760 ignored=False, clean=False, unknown=False):
Vadim Gelfer
status: add -c (clean) and -A (all files) options...
r2661 """return status of files between two nodes or node and working directory
Thomas Arendsen Hein
Cleaned up localrepo.changes()
r1616
If node1 is None, use the first dirstate parent instead.
If node2 is None, compare node1 with working directory.
"""
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
status: use contexts
r6769 def mfmatches(ctx):
mf = ctx.manifest().copy()
mpm@selenic.com
Break apart hg.py...
r1089 for fn in mf.keys():
if not match(fn):
del mf[fn]
return mf
Matt Mackall
diff: pass contexts to status...
r7090 if isinstance(node1, context.changectx):
ctx1 = node1
else:
ctx1 = self[node1]
if isinstance(node2, context.changectx):
ctx2 = node2
else:
ctx2 = self[node2]
Dirkjan Ochtman
bundlerepo doesn't really have a dirstate, throw AttributeError if requested
r7435 working = ctx2.rev() is None
Matt Mackall
status: use contexts
r6769 parentworking = working and ctx1 == self['.']
Matt Mackall
status: various cleanups...
r6770 match = match or match_.always(self.root, self.getcwd())
Matt Mackall
repo.status: eliminate list_
r6753 listignored, listclean, listunknown = ignored, clean, unknown
Chris Mason
Fix cold cache diff performance...
r2474
Matt Mackall
diff: pass contexts to status...
r7090 # load earliest manifest first for caching reasons
if not working and ctx2.rev() < ctx1.rev():
ctx2.manifest()
Matt Mackall
status: don't warn about missing files present in base revision (issue1323)
r7067 if not parentworking:
def bad(f, msg):
if f not in ctx1:
self.ui.warn('%s: %s\n' % (self.dirstate.pathto(f), msg))
match.bad = bad
Matt Mackall
status: various cleanups...
r6770 if working: # we need to scan the working dir
s = self.dirstate.status(match, listignored, listclean, listunknown)
cmp, modified, added, removed, deleted, unknown, ignored, clean = s
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
status: various cleanups...
r6770 # check for any possibly clean files
if parentworking and cmp:
fixup = []
# do a full compare of any files that might have changed
Matt Mackall
status: check cmp list in order
r8395 for f in sorted(cmp):
Matt Mackall
status: various cleanups...
r6770 if (f not in ctx1 or ctx2.flags(f) != ctx1.flags(f)
or ctx1[f].cmp(ctx2[f].data())):
modified.append(f)
else:
fixup.append(f)
if listclean:
Matt Mackall
dirstate.walk: push sorting up
r6827 clean += fixup
Matt Mackall
simplify dirstate fixups in repo.status()
r4912
Matt Mackall
status: various cleanups...
r6770 # update dirstate for files that are actually clean
if fixup:
try:
Adrian Buehlmann
localrepo: move comment
r8647 # updating the dirstate is optional
# so we don't wait on the lock
Simon Heimberg
localrepo: use lock.release for single lock
r8646 wlock = self.wlock(False)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
Matt Mackall
status: various cleanups...
r6770 for f in fixup:
self.dirstate.normal(f)
Simon Heimberg
localrepo: use lock.release for single lock
r8646 finally:
wlock.release()
except error.LockError:
pass
Vadim Gelfer
status: add -c (clean) and -A (all files) options...
r2661
Matt Mackall
status: use contexts
r6769 if not parentworking:
mf1 = mfmatches(ctx1)
Matt Mackall
status: various cleanups...
r6770 if working:
Thomas Arendsen Hein
Cleaned up localrepo.changes()
r1616 # we are comparing working dir against non-parent
# generate a pseudo-manifest for the working dir
Matt Mackall
status: use contexts
r6769 mf2 = mfmatches(self['.'])
Matt Mackall
status: various cleanups...
r6770 for f in cmp + modified + added:
Matt Mackall
status: use contexts
r6769 mf2[f] = None
Matt Mackall
minor status fixups
r6817 mf2.set(f, ctx2.flags(f))
Thomas Arendsen Hein
Make localrepo.changes() internally distinguish between removed and deleted.
r1617 for f in removed:
Thomas Arendsen Hein
Cleaned up localrepo.changes()
r1616 if f in mf2:
del mf2[f]
Matt Mackall
status: various cleanups...
r6770 else:
# we are comparing two revisions
deleted, unknown, ignored = [], [], []
mf2 = mfmatches(ctx2)
Bryan O'Sullivan
localrepository.status: only acquire wlock if actually needed....
r4372
Vadim Gelfer
status: add -c (clean) and -A (all files) options...
r2661 modified, added, clean = [], [], []
Matt Mackall
dirstate.walk: push sorting up
r6827 for fn in mf2:
Christian Ebert
Prefer i in d over d.has_key(i)
r5915 if fn in mf1:
Thomas Arendsen Hein
Cleanup of whitespace, indentation and line continuation.
r4633 if (mf1.flags(fn) != mf2.flags(fn) or
(mf1[fn] != mf2[fn] and
Matt Mackall
minor status fixups
r6817 (mf2[fn] or ctx1[fn].cmp(ctx2[fn].data())))):
Thomas Arendsen Hein
Cleaned up localrepo.changes()
r1616 modified.append(fn)
Matt Mackall
repo.status: eliminate list_
r6753 elif listclean:
Vadim Gelfer
status: add -c (clean) and -A (all files) options...
r2661 clean.append(fn)
Thomas Arendsen Hein
Cleaned up localrepo.changes()
r1616 del mf1[fn]
else:
added.append(fn)
Thomas Arendsen Hein
Make localrepo.changes() internally distinguish between removed and deleted.
r1617 removed = mf1.keys()
Matt Mackall
dirstate.walk: push sorting up
r6827 r = modified, added, removed, deleted, unknown, ignored, clean
[l.sort() for l in r]
return r
Vadim Gelfer
status: add -c (clean) and -A (all files) options...
r2661
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 def add(self, list):
wlock = self.wlock()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
Patrick Mezard
commands: add exits(1) if a specified file cannot be added (issue 891)
r5688 rejected = []
Benoit Boissinot
refactor some unlink/remove code and make sure we prune empty dir
r1415 for f in list:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 p = self.wjoin(f)
Benoit Boissinot
refactor some unlink/remove code and make sure we prune empty dir
r1415 try:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 st = os.lstat(p)
except:
self.ui.warn(_("%s does not exist!\n") % f)
Patrick Mezard
commands: add exits(1) if a specified file cannot be added (issue 891)
r5688 rejected.append(f)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 continue
if st.st_size > 10000000:
self.ui.warn(_("%s: files over 10MB may cause memory and"
" performance problems\n"
"(use 'hg revert %s' to unadd the file)\n")
% (f, f))
if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
self.ui.warn(_("%s not added: only files and symlinks "
"supported currently\n") % f)
Patrick Mezard
commands: add exits(1) if a specified file cannot be added (issue 891)
r5688 rejected.append(p)
Benoit Boissinot
abort when adding a file in merged state
r5206 elif self.dirstate[f] in 'amn':
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.ui.warn(_("%s already tracked!\n") % f)
Benoit Boissinot
make hg add of a removed file unremove the file...
r5207 elif self.dirstate[f] == 'r':
Alexis S. L. Carvalho
merge: forcefully mark files that we get from the second parent as dirty...
r5210 self.dirstate.normallookup(f)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 else:
self.dirstate.add(f)
Patrick Mezard
commands: add exits(1) if a specified file cannot be added (issue 891)
r5688 return rejected
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 finally:
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 wlock.release()
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 def forget(self, list):
wlock = self.wlock()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
for f in list:
if self.dirstate[f] != 'a':
self.ui.warn(_("%s not added!\n") % f)
else:
self.dirstate.forget(f)
finally:
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 wlock.release()
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 def remove(self, list, unlink=False):
Simon Heimberg
localrepo: use lock.release for single lock
r8646 if unlink:
for f in list:
try:
util.unlink(self.wjoin(f))
except OSError, inst:
if inst.errno != errno.ENOENT:
raise
wlock = self.wlock()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
Benoit Boissinot
refactor some unlink/remove code and make sure we prune empty dir
r1415 for f in list:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 if unlink and os.path.exists(self.wjoin(f)):
self.ui.warn(_("%s still exists!\n") % f)
elif self.dirstate[f] == 'a':
self.dirstate.forget(f)
elif f not in self.dirstate:
self.ui.warn(_("%s not tracked!\n") % f)
else:
self.dirstate.remove(f)
finally:
Simon Heimberg
localrepo: use lock.release for single lock
r8646 wlock.release()
Benoit Boissinot
revert added and removed files to their normal state before reverting...
r1447
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 def undelete(self, list):
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 manifests = [self.manifest.read(self.changelog.read(p)[0])
for p in self.dirstate.parents() if p != nullid]
wlock = self.wlock()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
for f in list:
if self.dirstate[f] != 'r':
Martin Geisler
i18n: mark strings for translation in Mercurial
r6953 self.ui.warn(_("%s not removed!\n") % f)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 else:
Patrick Mezard
Merge with crew-stable
r5323 m = f in manifests[0] and manifests[0] or manifests[1]
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 t = self.file(f).read(m[f])
self.wwrite(f, t, m.flags(f))
self.dirstate.normal(f)
finally:
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 wlock.release()
Benoit Boissinot
revert added and removed files to their normal state before reverting...
r1447
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 def copy(self, source, dest):
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 p = self.wjoin(dest)
if not (os.path.exists(p) or os.path.islink(p)):
self.ui.warn(_("%s does not exist!\n") % dest)
elif not (os.path.isfile(p) or os.path.islink(p)):
self.ui.warn(_("copy failed: %s is not a file or a "
"symbolic link\n") % dest)
else:
wlock = self.wlock()
try:
Matt Mackall
rename: handle renaming to a target marked removed
r7121 if self.dirstate[dest] in '?r':
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.dirstate.add(dest)
self.dirstate.copy(source, dest)
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 finally:
wlock.release()
mpm@selenic.com
Break apart hg.py...
r1089
John Mulligan
localrepo: remove 'closed' argument to heads(...) function...
r8796 def heads(self, start=None):
Benoit Boissinot
add a -r/--rev option to heads to show only heads descendant from rev
r1550 heads = self.changelog.heads(start)
# sort the output in rev descending order
John Mulligan
localrepo: remove 'closed' argument to heads(...) function...
r8796 heads = [(-self.changelog.rev(h), h) for h in heads]
Matt Mackall
replace util.sort with sorted built-in...
r8209 return [n for (r, n) in sorted(heads)]
mpm@selenic.com
Break apart hg.py...
r1089
John Mulligan
localrepo: set heads and branchheads to be closed=False by default...
r8694 def branchheads(self, branch=None, start=None, closed=False):
Matt Mackall
use repo[changeid] to get a changectx
r6747 if branch is None:
branch = self[None].branch()
Henrik Stuart
named branches: server branchmap wire protocol support (issue736)...
r8562 branches = self.branchmap()
Eric Hopper
Add option to heads to show only heads for current branch.
r4648 if branch not in branches:
return []
John Mulligan
store all heads of a branch in the branch cache...
r7654 bheads = branches[branch]
# the cache returns heads ordered lowest to highest
bheads.reverse()
Eric Hopper
Add option to heads to show only heads for current branch.
r4648 if start is not None:
John Mulligan
store all heads of a branch in the branch cache...
r7654 # filter out the heads that cannot be reached from startrev
bheads = self.changelog.nodesbetween([start], bheads)[2]
John Mulligan
branch closing: referencing open and closed branches/heads...
r7656 if not closed:
Dirkjan Ochtman
kill some trailing whitespace
r7670 bheads = [h for h in bheads if
John Mulligan
branch closing: referencing open and closed branches/heads...
r7656 ('close' not in self.changelog.read(h)[5])]
John Mulligan
store all heads of a branch in the branch cache...
r7654 return bheads
Eric Hopper
Add option to heads to show only heads for current branch.
r4648
mpm@selenic.com
Break apart hg.py...
r1089 def branches(self, nodes):
Thomas Arendsen Hein
Cleanup of indentation, spacing, newlines, strings and line length
r1615 if not nodes:
nodes = [self.changelog.tip()]
mpm@selenic.com
Break apart hg.py...
r1089 b = []
for n in nodes:
t = n
Benoit Boissinot
n is always 'True', we can only stop the loop with the break statement
r2345 while 1:
mpm@selenic.com
Break apart hg.py...
r1089 p = self.changelog.parents(n)
if p[1] != nullid or p[0] == nullid:
b.append((t, n, p[0], p[1]))
break
n = p[0]
return b
def between(self, pairs):
r = []
for top, bottom in pairs:
n, l, i = top, [], 0
f = 1
Matt Mackall
wire protocol: avoid infinite loop (issue1483)
r7708 while n != bottom and n != nullid:
mpm@selenic.com
Break apart hg.py...
r1089 p = self.changelog.parents(n)[0]
if i == f:
l.append(n)
f = f * 2
n = p
i += 1
r.append(l)
return r
Vadim Gelfer
add -f/--force to pull, incoming, outgoing, to work on unrelated repo....
r1959 def findincoming(self, remote, base=None, heads=None, force=False):
Benoit Boissinot
document and fix findincoming...
r2339 """Return list of roots of the subsets of missing nodes from remote
If base dict is specified, assume that these nodes and their parents
exist on the remote side and that no child of a node of base exists
in both remote and self.
Furthermore base will be updated to include the nodes that exists
in self and remote but no children exists in self and remote.
If a list of heads is specified, return only nodes which are heads
or ancestors of these heads.
All the ancestors of base are in self and in remote.
All the descendants of the list returned are missing in self.
(and so we know that the rest of the nodes are missing in remote, see
outgoing)
"""
Benoit Boissinot
protocol: use changegroupsubset() if possible (issue1389)...
r7415 return self.findcommonincoming(remote, base, heads, force)[1]
def findcommonincoming(self, remote, base=None, heads=None, force=False):
"""Return a tuple (common, missing roots, heads) used to identify
missing nodes from remote.
If base dict is specified, assume that these nodes and their parents
exist on the remote side and that no child of a node of base exists
in both remote and self.
Furthermore base will be updated to include the nodes that exists
in self and remote but no children exists in self and remote.
If a list of heads is specified, return only nodes which are heads
or ancestors of these heads.
All the ancestors of base are in self and in remote.
"""
mpm@selenic.com
Break apart hg.py...
r1089 m = self.changelog.nodemap
search = []
Martin Geisler
localrepo: use sets in findcommonincoming
r8156 fetch = set()
seen = set()
seenbranch = set()
Martin Geisler
use 'x is None' instead of 'x == None'...
r8527 if base is None:
mpm@selenic.com
Break apart hg.py...
r1089 base = {}
Matt Mackall
Move empty local repo logic for pull into findincoming...
r2108 if not heads:
heads = remote.heads()
if self.changelog.tip() == nullid:
Benoit Boissinot
document and fix findincoming...
r2339 base[nullid] = 1
Matt Mackall
Move empty local repo logic for pull into findincoming...
r2108 if heads != [nullid]:
Benoit Boissinot
protocol: use changegroupsubset() if possible (issue1389)...
r7415 return [nullid], [nullid], list(heads)
return [nullid], [], []
Matt Mackall
Move empty local repo logic for pull into findincoming...
r2108
mpm@selenic.com
Break apart hg.py...
r1089 # assume we're closer to the tip than the root
# and start by examining the heads
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.ui.status(_("searching for changes\n"))
mpm@selenic.com
Break apart hg.py...
r1089
unknown = []
for h in heads:
if h not in m:
unknown.append(h)
else:
base[h] = 1
Benoit Boissinot
protocol: use changegroupsubset() if possible (issue1389)...
r7415 heads = unknown
mpm@selenic.com
Break apart hg.py...
r1089 if not unknown:
Benoit Boissinot
protocol: use changegroupsubset() if possible (issue1389)...
r7415 return base.keys(), [], []
mpm@selenic.com
Break apart hg.py...
r1089
Martin Geisler
replace set-like dictionaries with real sets...
r8152 req = set(unknown)
mpm@selenic.com
Break apart hg.py...
r1089 reqcnt = 0
# search through remote branches
# a 'branch' here is a linear segment of history, with four parts:
# head, root, first parent, second parent
# (a branch always has two parents (or none) by definition)
unknown = remote.branches(unknown)
while unknown:
r = []
while unknown:
n = unknown.pop(0)
if n[0] in seen:
continue
Thomas Arendsen Hein
Cleanup of indentation, spacing, newlines, strings and line length
r1615 self.ui.debug(_("examining %s:%s\n")
% (short(n[0]), short(n[1])))
Benoit Boissinot
document and fix findincoming...
r2339 if n[0] == nullid: # found the end of the branch
pass
elif n in seenbranch:
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.ui.debug(_("branch already found\n"))
mpm@selenic.com
Break apart hg.py...
r1089 continue
Benoit Boissinot
document and fix findincoming...
r2339 elif n[1] and n[1] in m: # do we know the base?
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.ui.debug(_("found incomplete branch %s:%s\n")
mpm@selenic.com
Break apart hg.py...
r1089 % (short(n[0]), short(n[1])))
Benoit Boissinot
findincoming: build the correct list from the start
r7237 search.append(n[0:2]) # schedule branch range for scanning
Martin Geisler
localrepo: use sets in findcommonincoming
r8156 seenbranch.add(n)
mpm@selenic.com
Break apart hg.py...
r1089 else:
if n[1] not in seen and n[1] not in fetch:
if n[2] in m and n[3] in m:
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.ui.debug(_("found new changeset %s\n") %
mpm@selenic.com
Break apart hg.py...
r1089 short(n[1]))
Martin Geisler
localrepo: use sets in findcommonincoming
r8156 fetch.add(n[1]) # earliest unknown
Benoit Boissinot
document and fix findincoming...
r2339 for p in n[2:4]:
if p in m:
base[p] = 1 # latest known
mpm@selenic.com
Break apart hg.py...
r1089
Benoit Boissinot
document and fix findincoming...
r2339 for p in n[2:4]:
if p not in req and p not in m:
r.append(p)
Martin Geisler
replace set-like dictionaries with real sets...
r8152 req.add(p)
Martin Geisler
localrepo: use sets in findcommonincoming
r8156 seen.add(n[0])
mpm@selenic.com
Break apart hg.py...
r1089
if r:
reqcnt += 1
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.ui.debug(_("request %d: %s\n") %
mpm@selenic.com
Break apart hg.py...
r1089 (reqcnt, " ".join(map(short, r))))
Benoit Boissinot
use xrange instead of range
r3473 for p in xrange(0, len(r), 10):
mpm@selenic.com
Break apart hg.py...
r1089 for b in remote.branches(r[p:p+10]):
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.ui.debug(_("received %s:%s\n") %
mpm@selenic.com
Break apart hg.py...
r1089 (short(b[0]), short(b[1])))
Benoit Boissinot
document and fix findincoming...
r2339 unknown.append(b)
mpm@selenic.com
Break apart hg.py...
r1089
# do binary search on the branches we found
while search:
Benoit Boissinot
findincoming: do the binary search in branches in parallel
r7208 newsearch = []
mpm@selenic.com
Break apart hg.py...
r1089 reqcnt += 1
Benoit Boissinot
findincoming: do the binary search in branches in parallel
r7208 for n, l in zip(search, remote.between(search)):
l.append(n[1])
p = n[0]
f = 1
for i in l:
self.ui.debug(_("narrowing %d:%d %s\n") % (f, len(l), short(i)))
if i in m:
if f <= 2:
self.ui.debug(_("found new branch changeset %s\n") %
short(p))
Martin Geisler
localrepo: use sets in findcommonincoming
r8156 fetch.add(p)
Benoit Boissinot
findincoming: do the binary search in branches in parallel
r7208 base[i] = 1
else:
self.ui.debug(_("narrowed branch search to %s:%s\n")
% (short(p), short(i)))
newsearch.append((p, i))
break
p, f = i, f * 2
search = newsearch
mpm@selenic.com
Break apart hg.py...
r1089
# sanity check our fetch list
Martin Geisler
localrepo: use sets in findcommonincoming
r8156 for f in fetch:
mpm@selenic.com
Break apart hg.py...
r1089 if f in m:
Matt Mackall
error: move repo errors...
r7637 raise error.RepoError(_("already have changeset ")
+ short(f[:4]))
mpm@selenic.com
Break apart hg.py...
r1089
if base.keys() == [nullid]:
Vadim Gelfer
add -f/--force to pull, incoming, outgoing, to work on unrelated repo....
r1959 if force:
self.ui.warn(_("warning: repository is unrelated\n"))
else:
raise util.Abort(_("repository is unrelated"))
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Demote a pull note to a debug message
r2965 self.ui.debug(_("found new changesets starting at ") +
mpm@selenic.com
Break apart hg.py...
r1089 " ".join([short(f) for f in fetch]) + "\n")
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.ui.debug(_("%d total queries\n") % reqcnt)
mpm@selenic.com
Break apart hg.py...
r1089
Martin Geisler
localrepo: use sets in findcommonincoming
r8156 return base.keys(), list(fetch), heads
mpm@selenic.com
Break apart hg.py...
r1089
Vadim Gelfer
add -f/--force to pull, incoming, outgoing, to work on unrelated repo....
r1959 def findoutgoing(self, remote, base=None, heads=None, force=False):
Thomas Arendsen Hein
Fix hg push and hg push -r sometimes creating new heads without --force....
r2021 """Return list of nodes that are roots of subsets not in remote
If base dict is specified, assume that these nodes and their parents
exist on the remote side.
If a list of heads is specified, return only nodes which are heads
or ancestors of these heads, and return a second element which
contains all remote heads which get new children.
"""
Martin Geisler
use 'x is None' instead of 'x == None'...
r8527 if base is None:
mpm@selenic.com
Break apart hg.py...
r1089 base = {}
Vadim Gelfer
add -f/--force to pull, incoming, outgoing, to work on unrelated repo....
r1959 self.findincoming(remote, base, heads, force=force)
mpm@selenic.com
Break apart hg.py...
r1089
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.ui.debug(_("common changesets up to ")
mpm@selenic.com
Break apart hg.py...
r1089 + " ".join(map(short, base.keys())) + "\n")
Martin Geisler
replace set-like dictionaries with real sets...
r8152 remain = set(self.changelog.nodemap)
mpm@selenic.com
Break apart hg.py...
r1089
# prune everything remote has from the tree
Martin Geisler
replace set-like dictionaries with real sets...
r8152 remain.remove(nullid)
mpm@selenic.com
Break apart hg.py...
r1089 remove = base.keys()
while remove:
n = remove.pop(0)
if n in remain:
Martin Geisler
replace set-like dictionaries with real sets...
r8152 remain.remove(n)
mpm@selenic.com
Break apart hg.py...
r1089 for p in self.changelog.parents(n):
remove.append(p)
# find every node whose parents have been pruned
subset = []
Thomas Arendsen Hein
Fix hg push and hg push -r sometimes creating new heads without --force....
r2021 # find every remote head that will get new children
Benoit Boissinot
localrepo: use set instead of dict
r8469 updated_heads = set()
mpm@selenic.com
Break apart hg.py...
r1089 for n in remain:
p1, p2 = self.changelog.parents(n)
if p1 not in remain and p2 not in remain:
subset.append(n)
Thomas Arendsen Hein
Fix hg push and hg push -r sometimes creating new heads without --force....
r2021 if heads:
if p1 in heads:
Benoit Boissinot
localrepo: use set instead of dict
r8469 updated_heads.add(p1)
Thomas Arendsen Hein
Fix hg push and hg push -r sometimes creating new heads without --force....
r2021 if p2 in heads:
Benoit Boissinot
localrepo: use set instead of dict
r8469 updated_heads.add(p2)
mpm@selenic.com
Break apart hg.py...
r1089
# this is the set of all roots we have to push
Thomas Arendsen Hein
Fix hg push and hg push -r sometimes creating new heads without --force....
r2021 if heads:
Benoit Boissinot
localrepo: use set instead of dict
r8469 return subset, list(updated_heads)
Thomas Arendsen Hein
Fix hg push and hg push -r sometimes creating new heads without --force....
r2021 else:
return subset
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 def pull(self, remote, heads=None, force=False):
lock = self.lock()
Vadim Gelfer
fetch: hold lock and wlock across all operations
r2827 try:
Benoit Boissinot
protocol: use changegroupsubset() if possible (issue1389)...
r7415 common, fetch, rheads = self.findcommonincoming(remote, heads=heads,
force=force)
Vadim Gelfer
fetch: hold lock and wlock across all operations
r2827 if fetch == [nullid]:
self.ui.status(_("requesting all changes\n"))
mpm@selenic.com
Break apart hg.py...
r1089
Vadim Gelfer
fetch: hold lock and wlock across all operations
r2827 if not fetch:
self.ui.status(_("no changes found\n"))
return 0
mpm@selenic.com
Break apart hg.py...
r1089
Benoit Boissinot
protocol: use changegroupsubset() if possible (issue1389)...
r7415 if heads is None and remote.capable('changegroupsubset'):
heads = rheads
Vadim Gelfer
fetch: hold lock and wlock across all operations
r2827 if heads is None:
cg = remote.changegroup(fetch, 'pull')
else:
Benoit Boissinot
protocol: use changegroupsubset() if possible (issue1389)...
r7415 if not remote.capable('changegroupsubset'):
Martin Geisler
wrap string literals in error messages
r8663 raise util.Abort(_("Partial pull cannot be done because "
"other repository doesn't support "
"changegroupsubset."))
Vadim Gelfer
fetch: hold lock and wlock across all operations
r2827 cg = remote.changegroupsubset(fetch, heads, 'pull')
return self.addchangegroup(cg, 'pull', remote.url())
finally:
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 lock.release()
mpm@selenic.com
Break apart hg.py...
r1089
Benoit Boissinot
add an optional argument to push only the specified revisions (push -r)
r1781 def push(self, remote, force=False, revs=None):
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 # there are two ways to push to remote repo:
#
# addchangegroup assumes local user can lock remote
# repo (local filesystem, old ssh servers).
#
# unbundle assumes local user cannot lock remote repo (new ssh
# servers, http servers).
mpm@selenic.com
Break apart hg.py...
r1089
Vadim Gelfer
add support for streaming clone....
r2612 if remote.capable('unbundle'):
Vadim Gelfer
localrepository.push: propagate return value
r2463 return self.push_unbundle(remote, force, revs)
return self.push_addchangegroup(remote, force, revs)
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439
def prepush(self, remote, force, revs):
Benoit Boissinot
push: use the fast changegroup() path on push...
r7460 common = {}
Thomas Arendsen Hein
Fix hg push and hg push -r sometimes creating new heads without --force....
r2021 remote_heads = remote.heads()
Benoit Boissinot
push: use the fast changegroup() path on push...
r7460 inc = self.findincoming(remote, common, remote_heads, force=force)
mpm@selenic.com
Break apart hg.py...
r1089
Benoit Boissinot
push: use the fast changegroup() path on push...
r7460 update, updated_heads = self.findoutgoing(remote, common, remote_heads)
Benoit Boissinot
add an optional argument to push only the specified revisions (push -r)
r1781 if revs is not None:
msng_cl, bases, heads = self.changelog.nodesbetween(update, revs)
else:
bases, heads = update, self.changelog.heads()
Sune Foldager
named branches: improve pre-push logic (issue736)...
r8564 def checkbranch(lheads, rheads, updatelh):
'''
check whether there are more local heads than remote heads on
a specific branch.
lheads: local branch heads
rheads: remote branch heads
updatelh: outgoing local branch heads
'''
warn = 0
if not revs and len(lheads) > len(rheads):
warn = 1
else:
updatelheads = [self.changelog.heads(x, lheads)
for x in updatelh]
newheads = set(sum(updatelheads, [])) & set(lheads)
if not newheads:
return True
for r in rheads:
if r in self.changelog.nodemap:
desc = self.changelog.heads(r, heads)
l = [h for h in heads if h in desc]
if not l:
newheads.add(r)
else:
newheads.add(r)
if len(newheads) > len(rheads):
warn = 1
if warn:
if not rheads: # new branch requires --force
self.ui.warn(_("abort: push creates new"
Dongsheng Song
Fix warning: Seen unexpected token "%"
r8908 " remote branch '%s'!\n") %
self[updatelh[0]].branch())
Sune Foldager
named branches: improve pre-push logic (issue736)...
r8564 else:
self.ui.warn(_("abort: push creates new remote heads!\n"))
self.ui.status(_("(did you forget to merge?"
" use push -f to force)\n"))
return False
return True
Benoit Boissinot
add an optional argument to push only the specified revisions (push -r)
r1781 if not bases:
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.ui.status(_("no changes found\n"))
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 return None, 1
mpm@selenic.com
Break apart hg.py...
r1089 elif not force:
Sune Foldager
named branches: improve pre-push logic (issue736)...
r8564 # Check for each named branch if we're creating new remote heads.
# To be a remote head after push, node must be either:
Matt Mackall
correct remote heads test in prepush
r3684 # - unknown locally
# - a local outgoing head descended from update
# - a remote head that's known locally and not
# ancestral to an outgoing head
Sune Foldager
named branches: improve pre-push logic (issue736)...
r8564 #
# New named branches cannot be created without --force.
Matt Mackall
correct remote heads test in prepush
r3684
Sune Foldager
named branches: improve pre-push logic (issue736)...
r8564 if remote_heads != [nullid]:
if remote.capable('branchmap'):
localhds = {}
if not revs:
localhds = self.branchmap()
else:
for n in heads:
branch = self[n].branch()
if branch in localhds:
localhds[branch].append(n)
else:
localhds[branch] = [n]
remotehds = remote.branchmap()
Matt Mackall
correct remote heads test in prepush
r3684
Sune Foldager
named branches: improve pre-push logic (issue736)...
r8564 for lh in localhds:
if lh in remotehds:
rheads = remotehds[lh]
else:
rheads = []
lheads = localhds[lh]
updatelh = [upd for upd in update
if self[upd].branch() == lh]
if not updatelh:
continue
if not checkbranch(lheads, rheads, updatelh):
return None, 0
else:
if not checkbranch(heads, remote_heads, update):
return None, 0
Matt Mackall
correct remote heads test in prepush
r3684
Sune Foldager
named branches: improve pre-push logic (issue736)...
r8564 if inc:
Matt Mackall
correct remote heads test in prepush
r3684 self.ui.warn(_("note: unsynced remote changes!\n"))
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
reorder tests in prepush...
r3682
Benoit Boissinot
add an optional argument to push only the specified revisions (push -r)
r1781 if revs is None:
Benoit Boissinot
push: use the fast changegroup() path on push...
r7460 # use the fast path, no race possible on push
cg = self._changegroup(common.keys(), 'push')
Benoit Boissinot
add an optional argument to push only the specified revisions (push -r)
r1781 else:
Benoit Boissinot
merge with crew
r1782 cg = self.changegroupsubset(update, revs, 'push')
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 return cg, remote_heads
def push_addchangegroup(self, remote, force, revs):
lock = remote.lock()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
ret = self.prepush(remote, force, revs)
if ret[0] is not None:
cg, remote_heads = ret
return remote.addchangegroup(cg, 'push', self.url())
return ret[1]
finally:
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 lock.release()
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439
def push_unbundle(self, remote, force, revs):
# local repo finds heads on server, finds out what revs it
# must push. once revs transferred, if server finds it has
# different heads (someone else won commit/push race), server
# aborts.
ret = self.prepush(remote, force, revs)
if ret[0] is not None:
cg, remote_heads = ret
if force: remote_heads = ['force']
return remote.unbundle(cg, remote_heads, 'push')
return ret[1]
mpm@selenic.com
Break apart hg.py...
r1089
Thomas Arendsen Hein
Show number of changesets written to bundle files by default (issue569)...
r5763 def changegroupinfo(self, nodes, source):
if self.ui.verbose or source == 'bundle':
self.ui.status(_("%d changesets found\n") % len(nodes))
Thomas Arendsen Hein
Show number (-v) and list (--debug) of changesets with bundle/pull/push etc.
r3513 if self.ui.debugflag:
Martin Geisler
lowercase ui.debug and assert output...
r7599 self.ui.debug(_("list of changesets:\n"))
Thomas Arendsen Hein
Show number (-v) and list (--debug) of changesets with bundle/pull/push etc.
r3513 for node in nodes:
self.ui.debug("%s\n" % hex(node))
Alexis S. L. Carvalho
changegroupsubset: accept list of per-revlog nodes to include...
r5908 def changegroupsubset(self, bases, heads, source, extranodes=None):
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 """This function generates a changegroup consisting of all the nodes
that are descendents of any of the bases, and ancestors of any of
the heads.
It is fairly complex as determining which filenodes and which
manifest nodes need to be included for the changeset to be complete
is non-trivial.
Another wrinkle is doing the reverse, figuring out which changeset in
Alexis S. L. Carvalho
changegroupsubset: accept list of per-revlog nodes to include...
r5908 the changegroup a particular filenode or manifestnode belongs to.
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210
Alexis S. L. Carvalho
changegroupsubset: accept list of per-revlog nodes to include...
r5908 The caller can specify some nodes that must be included in the
changegroup using the extranodes argument. It should be a dict
where the keys are the filenames (or 1 for the manifest), and the
values are lists of (node, linknode) tuples, where node is a wanted
node and linknode is the changelog node that should be transmitted as
the linkrev.
"""
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233 if extranodes is None:
# can we go through the fast path ?
heads.sort()
allheads = self.heads()
allheads.sort()
if heads == allheads:
common = []
# parents of bases are known from both sides
for n in bases:
for p in self.changelog.parents(n):
if p != nullid:
common.append(p)
return self._changegroup(common, source)
Vadim Gelfer
add preoutgoing and outgoing hooks....
r1736 self.hook('preoutgoing', throw=True, source=source)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Set up some initial variables
# Make it easy to refer to self.changelog
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 cl = self.changelog
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # msng is short for missing - compute the list of changesets in this
# changegroup.
Eric Hopper
Bug fixing in localrepository.changegroupsubset. Bugs found in testing.
r1460 msng_cl_lst, bases, heads = cl.nodesbetween(bases, heads)
Thomas Arendsen Hein
Show number of changesets written to bundle files by default (issue569)...
r5763 self.changegroupinfo(msng_cl_lst, source)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Some bases may turn out to be superfluous, and some heads may be
# too. nodesbetween will return the minimal set of bases and heads
# necessary to re-create the changegroup.
# Known heads are the list of heads that it is assumed the recipient
# of this changegroup will know about.
Benoit Boissinot
localrepo: use set instead of dict
r8469 knownheads = set()
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # We assume that all parents of bases are known heads.
Eric Hopper
Bug fixing in localrepository.changegroupsubset. Bugs found in testing.
r1460 for n in bases:
Martin Geisler
localrepo: use set.update for bulk updates
r8481 knownheads.update(cl.parents(n))
knownheads.discard(nullid)
Benoit Boissinot
localrepo: use set instead of dict
r8469 knownheads = list(knownheads)
Eric Hopper
Bug fixing in localrepository.changegroupsubset. Bugs found in testing.
r1460 if knownheads:
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Now that we know what heads are known, we can compute which
# changesets are known. The recipient must know about all
# changesets required to reach the known heads from the null
# changeset.
Eric Hopper
Bug fixing in localrepository.changegroupsubset. Bugs found in testing.
r1460 has_cl_set, junk, junk = cl.nodesbetween(None, knownheads)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 junk = None
Martin Geisler
localrepo: corrected outdated comment
r8239 # Transform the list into a set.
Martin Geisler
replace set-like dictionaries with real sets...
r8152 has_cl_set = set(has_cl_set)
Eric Hopper
Bug fixing in localrepository.changegroupsubset. Bugs found in testing.
r1460 else:
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # If there were no known heads, the recipient cannot be assumed to
# know about any changesets.
Martin Geisler
replace set-like dictionaries with real sets...
r8152 has_cl_set = set()
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Make it easy to refer to self.manifest
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 mnfst = self.manifest
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # We don't know which manifests are missing yet
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 msng_mnfst_set = {}
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Nor do we know which filenodes are missing.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 msng_filenode_set = {}
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 junk = mnfst.index[len(mnfst) - 1] # Get around a bug in lazyindex
Eric Hopper
Bug fixing in localrepository.changegroupsubset. Bugs found in testing.
r1460 junk = None
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # A changeset always belongs to itself, so the changenode lookup
# function for a changenode is identity.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 def identity(x):
return x
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # If we determine that a particular file or manifest node must be a
# node that the recipient of the changegroup will already have, we can
# also assume the recipient will have all the parents. This function
# prunes them from the set of missing nodes.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 def prune_parents(revlog, hasset, msngset):
Benoit Boissinot
localrepo: use set instead of dict
r8469 haslst = list(hasset)
Martin Geisler
localrepo: removed unnecessary revkey sort helper
r9038 haslst.sort(key=revlog.rev)
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 for node in haslst:
parentlst = [p for p in revlog.parents(node) if p != nullid]
while parentlst:
n = parentlst.pop()
if n not in hasset:
Benoit Boissinot
localrepo: use set instead of dict
r8469 hasset.add(n)
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 p = [p for p in revlog.parents(n) if p != nullid]
parentlst.extend(p)
for n in hasset:
msngset.pop(n, None)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # This is a function generating function used to set up an environment
# for the inner function to execute in.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 def manifest_and_file_collector(changedfileset):
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # This is an information gathering function that gathers
# information from each changeset node that goes out as part of
# the changegroup. The information gathered is a list of which
# manifest nodes are potentially required (the recipient may
# already have them) and total list of all files which were
# changed in any changeset in the changegroup.
#
# We also remember the first changenode we saw any manifest
# referenced by so we can later determine which changenode 'owns'
# the manifest.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 def collect_manifests_and_files(clnode):
c = cl.read(clnode)
for f in c[3]:
# This is to make sure we only have one instance of each
# filename string for each filename.
Eric Hopper
Bug fixing in localrepository.changegroupsubset. Bugs found in testing.
r1460 changedfileset.setdefault(f, f)
msng_mnfst_set.setdefault(c[0], clnode)
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 return collect_manifests_and_files
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Figure out which manifest nodes (of the ones we think might be part
# of the changegroup) the recipient must know about and remove them
# from the changegroup.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 def prune_manifests():
Benoit Boissinot
localrepo: use set instead of dict
r8469 has_mnfst_set = set()
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 for n in msng_mnfst_set:
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # If a 'missing' manifest thinks it belongs to a changenode
# the recipient is assumed to have, obviously the recipient
# must have that manifest.
Matt Mackall
linkrev: take a revision number rather than a hash
r7361 linknode = cl.node(mnfst.linkrev(mnfst.rev(n)))
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 if linknode in has_cl_set:
Benoit Boissinot
localrepo: use set instead of dict
r8469 has_mnfst_set.add(n)
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 prune_parents(mnfst, has_mnfst_set, msng_mnfst_set)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Use the information collected in collect_manifests_and_files to say
# which changenode any manifestnode belongs to.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 def lookup_manifest_link(mnfstnode):
return msng_mnfst_set[mnfstnode]
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # A function generating function that sets up the initial environment
# the inner function.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 def filenode_collector(changedfiles):
Eric Hopper
Optimizing manifest reads in changegroupsubset by using deltas.
r1462 next_rev = [0]
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # This gathers information from each manifestnode included in the
# changegroup about which filenodes the manifest node references
# so we can include those in the changegroup too.
#
# It also remembers which changenode each filenode belongs to. It
# does this by assuming the a filenode belongs to the changenode
# the first manifest that references it belongs to.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 def collect_msng_filenodes(mnfstnode):
Eric Hopper
Optimizing manifest reads in changegroupsubset by using deltas.
r1462 r = mnfst.rev(mnfstnode)
if r == next_rev[0]:
# If the last rev we looked at was the one just previous,
# we only need to see a diff.
Matt Mackall
remove unneeded imports of mdiff
r5175 deltamf = mnfst.readdelta(mnfstnode)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # For each line in the delta
Dirkjan Ochtman
use dict.iteritems() rather than dict.items()...
r7622 for f, fnode in deltamf.iteritems():
Eric Hopper
Optimizing manifest reads in changegroupsubset by using deltas.
r1462 f = changedfiles.get(f, None)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # And if the file is in the list of files we care
# about.
Eric Hopper
Optimizing manifest reads in changegroupsubset by using deltas.
r1462 if f is not None:
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Get the changenode this manifest belongs to
clnode = msng_mnfst_set[mnfstnode]
# Create the set of filenodes for the file if
# there isn't one already.
ndset = msng_filenode_set.setdefault(f, {})
# And set the filenode's changelog node to the
# manifest's if it hasn't been set already.
ndset.setdefault(fnode, clnode)
else:
# Otherwise we need a full manifest.
m = mnfst.read(mnfstnode)
# For every file in we care about.
for f in changedfiles:
fnode = m.get(f, None)
# If it's in the manifest
if fnode is not None:
# See comments above.
Eric Hopper
Optimizing manifest reads in changegroupsubset by using deltas.
r1462 clnode = msng_mnfst_set[mnfstnode]
ndset = msng_filenode_set.setdefault(f, {})
ndset.setdefault(fnode, clnode)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Remember the revision we hope to see next.
Eric Hopper
Optimizing manifest reads in changegroupsubset by using deltas.
r1462 next_rev[0] = r + 1
Eric Hopper
Bug fixing in localrepository.changegroupsubset. Bugs found in testing.
r1460 return collect_msng_filenodes
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # We have a list of filenodes we think we need for a file, lets remove
Martin Geisler
localrepo: fixed typos in comments
r8238 # all those we know the recipient must have.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 def prune_filenodes(f, filerevlog):
msngset = msng_filenode_set[f]
Benoit Boissinot
localrepo: use set instead of dict
r8469 hasset = set()
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # If a 'missing' filenode thinks it belongs to a changenode we
# assume the recipient must have, then the recipient must have
# that filenode.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 for n in msngset:
Matt Mackall
linkrev: take a revision number rather than a hash
r7361 clnode = cl.node(filerevlog.linkrev(filerevlog.rev(n)))
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 if clnode in has_cl_set:
Benoit Boissinot
localrepo: use set instead of dict
r8469 hasset.add(n)
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 prune_parents(filerevlog, hasset, msngset)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # A function generator function that sets up the a context for the
# inner function.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 def lookup_filenode_link_func(fname):
msngset = msng_filenode_set[fname]
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Lookup the changenode the filenode belongs to.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 def lookup_filenode_link(fnode):
return msngset[fnode]
return lookup_filenode_link
mpm@selenic.com
Break apart hg.py...
r1089
Alexis S. L. Carvalho
changegroupsubset: accept list of per-revlog nodes to include...
r5908 # Add the nodes that were explicitly requested.
def add_extra_nodes(name, nodes):
if not extranodes or name not in extranodes:
return
for node, linknode in extranodes[name]:
if node not in nodes:
nodes[node] = linknode
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Now that we have all theses utility functions to help out and
# logically divide up the task, generate the group.
mpm@selenic.com
Break apart hg.py...
r1089 def gengroup():
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # The set of changed files starts empty.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 changedfiles = {}
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Create a changenode group generator that will call our functions
# back to lookup the owning changenode and collect information.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 group = cl.group(msng_cl_lst, identity,
manifest_and_file_collector(changedfiles))
for chnk in group:
yield chnk
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466
# The list of manifests has been collected by the generator
# calling our functions back.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 prune_manifests()
Alexis S. L. Carvalho
changegroupsubset: accept list of per-revlog nodes to include...
r5908 add_extra_nodes(1, msng_mnfst_set)
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 msng_mnfst_lst = msng_mnfst_set.keys()
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Sort the manifestnodes by revision number.
Martin Geisler
localrepo: removed unnecessary revkey sort helper
r9038 msng_mnfst_lst.sort(key=mnfst.rev)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Create a generator for the manifestnodes that calls our lookup
# and data collection functions back.
Eric Hopper
Bug fixing in localrepository.changegroupsubset. Bugs found in testing.
r1460 group = mnfst.group(msng_mnfst_lst, lookup_manifest_link,
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 filenode_collector(changedfiles))
for chnk in group:
yield chnk
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466
# These are no longer needed, dereference and toss the memory for
# them.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 msng_mnfst_lst = None
msng_mnfst_set.clear()
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466
Alexis S. L. Carvalho
changegroupsubset: accept list of per-revlog nodes to include...
r5908 if extranodes:
for fname in extranodes:
if isinstance(fname, int):
continue
Benoit Boissinot
fix issue with strip() for revlog with non-monotonic linkrevs (issue1342)...
r7134 msng_filenode_set.setdefault(fname, {})
Alexis S. L. Carvalho
changegroupsubset: accept list of per-revlog nodes to include...
r5908 changedfiles[fname] = 1
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Go through all our files in order sorted by name.
Matt Mackall
replace util.sort with sorted built-in...
r8209 for fname in sorted(changedfiles):
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 filerevlog = self.file(fname)
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 if not len(filerevlog):
Matt Mackall
fix spelling error
r5666 raise util.Abort(_("empty or missing revlog for %s") % fname)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Toss out the filenodes that the recipient isn't really
# missing.
Christian Ebert
Prefer i in d over d.has_key(i)
r5915 if fname in msng_filenode_set:
Eric Hopper
This fixes a bug that Chris Mason found. As for a test case, I can't...
r1630 prune_filenodes(fname, filerevlog)
Benoit Boissinot
fix issue with strip() for revlog with non-monotonic linkrevs (issue1342)...
r7134 add_extra_nodes(fname, msng_filenode_set[fname])
Eric Hopper
This fixes a bug that Chris Mason found. As for a test case, I can't...
r1630 msng_filenode_lst = msng_filenode_set[fname].keys()
else:
msng_filenode_lst = []
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # If any filenodes are left, generate the group for them,
# otherwise don't bother.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 if len(msng_filenode_lst) > 0:
Matt Mackall
changegroup: avoid large copies...
r5368 yield changegroup.chunkheader(len(fname))
yield fname
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Sort the filenodes by their revision #
Martin Geisler
localrepo: removed unnecessary revkey sort helper
r9038 msng_filenode_lst.sort(key=filerevlog.rev)
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Create a group generator and only pass in a changenode
# lookup function as we need to collect no information
# from filenodes.
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 group = filerevlog.group(msng_filenode_lst,
Eric Hopper
Bug fixing in localrepository.changegroupsubset. Bugs found in testing.
r1460 lookup_filenode_link_func(fname))
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 for chnk in group:
yield chnk
Christian Ebert
Prefer i in d over d.has_key(i)
r5915 if fname in msng_filenode_set:
Eric Hopper
This fixes a bug that Chris Mason found. As for a test case, I can't...
r1630 # Don't need this anymore, toss it to free memory.
del msng_filenode_set[fname]
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 # Signal that no more groups are left.
Thomas Arendsen Hein
make incoming work via ssh (issue139); move chunk code into separate module....
r1981 yield changegroup.closechunk()
mpm@selenic.com
Break apart hg.py...
r1089
Benoit Boissinot
fix a NameError in changegroupsubset
r2150 if msng_cl_lst:
Vincent Danjean
allow to pull from an empty repo without getting a backtrace
r2149 self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source)
Vadim Gelfer
add preoutgoing and outgoing hooks....
r1736
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 return util.chunkbuffer(gengroup())
Vadim Gelfer
add preoutgoing and outgoing hooks....
r1736 def changegroup(self, basenodes, source):
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233 # to avoid a race we use changegroupsubset() (issue1320)
return self.changegroupsubset(basenodes, self.heads(), source)
def _changegroup(self, common, source):
Eric Hopper
Added a lot of comments to changegroupsubset.
r1466 """Generate a changegroup of all nodes that we have that a recipient
doesn't.
This is much easier than the previous function as we can assume that
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233 the recipient has any changenode we aren't sending them.
common is the set of common nodes between remote and self"""
Vadim Gelfer
add preoutgoing and outgoing hooks....
r1736
self.hook('preoutgoing', throw=True, source=source)
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 cl = self.changelog
Benoit Boissinot
fix pull racing with push/commit (issue1320)...
r7233 nodes = cl.findmissing(common)
Martin Geisler
replace set-like dictionaries with real sets...
r8152 revset = set([cl.rev(n) for n in nodes])
Thomas Arendsen Hein
Show number of changesets written to bundle files by default (issue569)...
r5763 self.changegroupinfo(nodes, source)
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458
def identity(x):
return x
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 def gennodelst(log):
for r in log:
Matt Mackall
linkrev: take a revision number rather than a hash
r7361 if log.linkrev(r) in revset:
yield log.node(r)
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458
def changed_file_collector(changedfileset):
def collect_changed_files(clnode):
c = cl.read(clnode)
Martin Geisler
localrepo: use set.update for bulk updates
r8481 changedfileset.update(c[3])
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 return collect_changed_files
def lookuprevlink_func(revlog):
def lookuprevlink(n):
Matt Mackall
linkrev: take a revision number rather than a hash
r7361 return cl.node(revlog.linkrev(revlog.rev(n)))
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 return lookuprevlink
def gengroup():
mpm@selenic.com
Break apart hg.py...
r1089 # construct a list of all changed files
Benoit Boissinot
localrepo: use set instead of dict
r8469 changedfiles = set()
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458
for chnk in cl.group(nodes, identity,
changed_file_collector(changedfiles)):
yield chnk
mpm@selenic.com
Break apart hg.py...
r1089
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 mnfst = self.manifest
nodeiter = gennodelst(mnfst)
for chnk in mnfst.group(nodeiter, lookuprevlink_func(mnfst)):
yield chnk
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
replace util.sort with sorted built-in...
r8209 for fname in sorted(changedfiles):
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 filerevlog = self.file(fname)
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 if not len(filerevlog):
Matt Mackall
fix spelling error
r5666 raise util.Abort(_("empty or missing revlog for %s") % fname)
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 nodeiter = gennodelst(filerevlog)
nodeiter = list(nodeiter)
if nodeiter:
Matt Mackall
changegroup: avoid large copies...
r5368 yield changegroup.chunkheader(len(fname))
yield fname
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 lookup = lookuprevlink_func(filerevlog)
for chnk in filerevlog.group(nodeiter, lookup):
yield chnk
mpm@selenic.com
Break apart hg.py...
r1089
Thomas Arendsen Hein
make incoming work via ssh (issue139); move chunk code into separate module....
r1981 yield changegroup.closechunk()
Matt Mackall
Don't die calling outgoing hook if we have no changesets
r2107
if nodes:
self.hook('outgoing', node=hex(nodes[0]), source=source)
mpm@selenic.com
Break apart hg.py...
r1089
Eric Hopper
This changes the revlog.group and re-implements the localrepo.changeroup...
r1458 return util.chunkbuffer(gengroup())
mpm@selenic.com
Break apart hg.py...
r1089
Alexis S. L. Carvalho
addchangegroup: add option to skip check for empty changelog group
r5907 def addchangegroup(self, source, srctype, url, emptyok=False):
Vadim Gelfer
add merge command. means same thing as "update -m"....
r2019 """add changegroup to repo.
mpm@selenic.com
Break apart hg.py...
r1089
Thomas Arendsen Hein
Don't report an error when closing heads during local push (issue387)
r3803 return values:
- nothing changed or no source: 0
- more heads than before: 1+added heads (2..n)
- less heads than before: -1-removed heads (-2..-n)
- number of heads stays the same: 1
"""
mpm@selenic.com
Break apart hg.py...
r1089 def csmap(x):
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.ui.debug(_("add changeset %s\n") % short(x))
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 return len(cl)
mpm@selenic.com
Break apart hg.py...
r1089
def revmap(x):
Vadim Gelfer
fix race in localrepo.addchangegroup....
r1998 return cl.rev(x)
mpm@selenic.com
Break apart hg.py...
r1089
Thomas Arendsen Hein
Cleanup of indentation, spacing, newlines, strings and line length
r1615 if not source:
Vadim Gelfer
add merge command. means same thing as "update -m"....
r2019 return 0
Vadim Gelfer
add prechangegroup and pretxnchangegroup hooks....
r1730
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673 self.hook('prechangegroup', throw=True, source=srctype, url=url)
Vadim Gelfer
add prechangegroup and pretxnchangegroup hooks....
r1730
mpm@selenic.com
Break apart hg.py...
r1089 changesets = files = revisions = 0
Benoit Boissinot
remove appendfile for the manifest when adding a changegroup...
r2395 # write changelog data to temp files so concurrent readers will not see
# inconsistent view
Matt Mackall
restructure changelog file appending...
r4261 cl = self.changelog
cl.delayupdate()
oldheads = len(cl.heads())
Vadim Gelfer
fix race in localrepo.addchangegroup....
r1998
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 tr = self.transaction()
try:
Matt Mackall
transactions: avoid late tear-down (issue641)...
r4970 trp = weakref.proxy(tr)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 # pull off the changeset group
self.ui.status(_("adding changesets\n"))
Peter Arrenbrecht
localrepo: use more direct vars in addchangegroup
r8393 clstart = len(cl)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 chunkiter = changegroup.chunkiter(source)
Peter Arrenbrecht
drop superfluous param from revlog.addgroup()
r6647 if cl.addgroup(chunkiter, csmap, trp) is None and not emptyok:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 raise util.Abort(_("received changelog group is empty"))
Peter Arrenbrecht
localrepo: use more direct vars in addchangegroup
r8393 clend = len(cl)
changesets = clend - clstart
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 # pull off the manifest group
self.ui.status(_("adding manifests\n"))
chunkiter = changegroup.chunkiter(source)
# no need to check for empty manifest group here:
# if the result of the merge of 1 and 2 is the same in 3 and 4,
# no new manifest will be created and the manifest group will
# be empty during the pull
Matt Mackall
transactions: avoid late tear-down (issue641)...
r4970 self.manifest.addgroup(chunkiter, revmap, trp)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 # process the files
self.ui.status(_("adding file changes\n"))
while 1:
f = changegroup.getchunk(source)
if not f:
break
self.ui.debug(_("adding %s revisions\n") % f)
fl = self.file(f)
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 o = len(fl)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 chunkiter = changegroup.chunkiter(source)
Matt Mackall
transactions: avoid late tear-down (issue641)...
r4970 if fl.addgroup(chunkiter, revmap, trp) is None:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 raise util.Abort(_("received file revlog group is empty"))
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 revisions += len(fl) - o
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 files += 1
Peter Arrenbrecht
localrepo: use cl throughout in addchangegroup
r8392 newheads = len(cl.heads())
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 heads = ""
if oldheads and newheads != oldheads:
heads = _(" (%+d heads)") % (newheads - oldheads)
Vadim Gelfer
fix race in localrepo.addchangegroup....
r1998
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.ui.status(_("added %d changesets"
" with %d changes to %d files%s\n")
% (changesets, revisions, files, heads))
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 if changesets > 0:
Peter Arrenbrecht
localrepo: use cl throughout in addchangegroup
r8392 p = lambda: cl.writepending() and self.root or ""
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.hook('pretxnchangegroup', throw=True,
Peter Arrenbrecht
localrepo: use more direct vars in addchangegroup
r8393 node=hex(cl.node(clstart)), source=srctype,
Matt Mackall
Introduce HG_PREPEND to solve pretxn races...
r7787 url=url, pending=p)
# make changelog see real files again
cl.finalize(trp)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 tr.close()
finally:
del tr
mpm@selenic.com
Break apart hg.py...
r1089
Benoit Boissinot
Fix traceback when nothing was added during unbundle...
r1375 if changesets > 0:
Alexis S. L. Carvalho
update the branch cache at the end of addchangegroup...
r5988 # forcefully update the on-disk branch cache
self.ui.debug(_("updating the branch cache\n"))
self.branchtags()
Peter Arrenbrecht
localrepo: use more direct vars in addchangegroup
r8393 self.hook("changegroup", node=hex(cl.node(clstart)),
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673 source=srctype, url=url)
mpm@selenic.com
Break apart hg.py...
r1089
Peter Arrenbrecht
localrepo: use more direct vars in addchangegroup
r8393 for i in xrange(clstart, clend):
Peter Arrenbrecht
localrepo: use cl throughout in addchangegroup
r8392 self.hook("incoming", node=hex(cl.node(i)),
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673 source=srctype, url=url)
mpm@selenic.com
Hook fixups...
r1316
Thomas Arendsen Hein
Don't report an error when closing heads during local push (issue387)
r3803 # never return 0 here:
if newheads < oldheads:
return newheads - oldheads - 1
else:
return newheads - oldheads + 1
Vadim Gelfer
add merge command. means same thing as "update -m"....
r2019
mpm@selenic.com
Break apart hg.py...
r1089
Vadim Gelfer
add support for streaming clone....
r2612 def stream_in(self, remote):
Vadim Gelfer
clone: disable stream support on server side by default....
r2621 fp = remote.stream_out()
Thomas Arendsen Hein
New UnexpectedOutput exception to catch server errors in localrepo.stream_in...
r3564 l = fp.readline()
try:
resp = int(l)
except ValueError:
Matt Mackall
error: move UnexpectedOutput (now ResponseError)
r7641 raise error.ResponseError(
Thomas Arendsen Hein
New UnexpectedOutput exception to catch server errors in localrepo.stream_in...
r3564 _('Unexpected response from remote server:'), l)
Thomas Arendsen Hein
Handle locking exceptions if streaming clone can't lock the repo. (Issue324)
r3687 if resp == 1:
Vadim Gelfer
clone: disable stream support on server side by default....
r2621 raise util.Abort(_('operation forbidden by server'))
Thomas Arendsen Hein
Handle locking exceptions if streaming clone can't lock the repo. (Issue324)
r3687 elif resp == 2:
raise util.Abort(_('locking the remote repository failed'))
elif resp != 0:
raise util.Abort(_('the server sent an unknown error code'))
Vadim Gelfer
add support for streaming clone....
r2612 self.ui.status(_('streaming all changes\n'))
Thomas Arendsen Hein
New UnexpectedOutput exception to catch server errors in localrepo.stream_in...
r3564 l = fp.readline()
try:
total_files, total_bytes = map(int, l.split(' ', 1))
Benoit Boissinot
fix error spotted by pychecker
r6407 except (ValueError, TypeError):
Matt Mackall
error: move UnexpectedOutput (now ResponseError)
r7641 raise error.ResponseError(
Thomas Arendsen Hein
New UnexpectedOutput exception to catch server errors in localrepo.stream_in...
r3564 _('Unexpected response from remote server:'), l)
Vadim Gelfer
add support for streaming clone....
r2612 self.ui.status(_('%d files to transfer, %s of data\n') %
(total_files, util.bytecount(total_bytes)))
start = time.time()
for i in xrange(total_files):
Benoit Boissinot
add a comment about '\n' and '\r' and streaming clone
r3720 # XXX doesn't support '\n' or '\r' in filenames
Thomas Arendsen Hein
New UnexpectedOutput exception to catch server errors in localrepo.stream_in...
r3564 l = fp.readline()
try:
name, size = l.split('\0', 1)
size = int(size)
Bernhard Leiner
Add missing catch of a TypeError
r7063 except (ValueError, TypeError):
Matt Mackall
error: move UnexpectedOutput (now ResponseError)
r7641 raise error.ResponseError(
Thomas Arendsen Hein
New UnexpectedOutput exception to catch server errors in localrepo.stream_in...
r3564 _('Unexpected response from remote server:'), l)
Martin Geisler
i18n: mark strings for translation in Mercurial
r6953 self.ui.debug(_('adding %s (%s)\n') % (name, util.bytecount(size)))
Benoit Boissinot
filelog encoding: move the encoding/decoding into store...
r8531 # for backwards compat, name was partially encoded
ofp = self.sopener(store.decodedir(name), 'w')
Vadim Gelfer
add support for streaming clone....
r2612 for chunk in util.filechunkiter(fp, limit=size):
ofp.write(chunk)
ofp.close()
elapsed = time.time() - start
Patrick Mezard
localrepo: stream_in may raise ZeroDivisionError with nul float elapsed argument.
r4128 if elapsed <= 0:
elapsed = 0.001
Vadim Gelfer
add support for streaming clone....
r2612 self.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') %
(util.bytecount(total_bytes), elapsed,
util.bytecount(total_bytes / elapsed)))
Matt Mackall
localrepo and dirstate: rename reload to invalidate...
r4613 self.invalidate()
Vadim Gelfer
add support for streaming clone....
r2612 return len(self.heads()) + 1
mpm@selenic.com
Break apart hg.py...
r1089
Vadim Gelfer
clone: do not make streaming default. add --stream option instead.
r2613 def clone(self, remote, heads=[], stream=False):
Vadim Gelfer
add support for streaming clone....
r2612 '''clone remote repository.
Matt Mackall
hg verify: more consistency checking between changesets and manifests
r1382
Vadim Gelfer
add support for streaming clone....
r2612 keyword arguments:
heads: list of revs to clone (forces use of pull)
Vadim Gelfer
clone: disable stream support on server side by default....
r2621 stream: use streaming clone if possible'''
mpm@selenic.com
Break apart hg.py...
r1089
Vadim Gelfer
clone: disable stream support on server side by default....
r2621 # now, all clients that can request uncompressed clones can
# read repo formats supported by all servers that can serve
# them.
mpm@selenic.com
Break apart hg.py...
r1089
Vadim Gelfer
add support for streaming clone....
r2612 # if revlog format changes, client will have to check version
Vadim Gelfer
clone: disable stream support on server side by default....
r2621 # and format flags on "stream" capability, and use
# uncompressed only if compatible.
mpm@selenic.com
Break apart hg.py...
r1089
Vadim Gelfer
clone: do not make streaming default. add --stream option instead.
r2613 if stream and not heads and remote.capable('stream'):
Vadim Gelfer
add support for streaming clone....
r2612 return self.stream_in(remote)
return self.pull(remote, heads)
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806
# used to avoid circular references so destructors work
Benoit Boissinot
localrepo: change aftertrans to be independant of the store path
r3790 def aftertrans(files):
renamefiles = [tuple(t) for t in files]
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806 def a():
Benoit Boissinot
localrepo: change aftertrans to be independant of the store path
r3790 for src, dest in renamefiles:
util.rename(src, dest)
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806 return a
Vadim Gelfer
clean up hg.py: move repo constructor code into each repo module
r2740 def instance(ui, path, create):
return localrepository(ui, util.drop_scheme('file', path), create)
Thomas Arendsen Hein
Whitespace/Tab cleanup
r3223
Vadim Gelfer
clean up hg.py: move repo constructor code into each repo module
r2740 def islocal(path):
return True