##// END OF EJS Templates
rebase: mention --rev in the help...
rebase: mention --rev in the help This changeset adds a small mention of it in the help to prevent confusion. This small addition references online help that is easier to update and improve at release time. Following Wagner Bruna's advice, this is added in a plain new paragraph to not invalidate current translation this close to the release.

File last commit:

r18464:a2e9fe93 stable
r18518:0324a1d8 stable
Show More
context.py
1364 lines | 43.6 KiB | text/x-python | PythonLexer
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 # context.py - changeset and file context objects for mercurial
#
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 #
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
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Matt Mackall
context: internalize lookup logic...
r16376 from node import nullid, nullrev, short, hex, bin
Matt Mackall
Simplify i18n imports
r3891 from i18n import _
Pierre-Yves David
phases: store phase values in constant instead of using raw integer...
r15818 import ancestor, mdiff, error, util, scmutil, subrepo, patch, encoding, phases
Matt Mackall
context: add copies method with caching
r16602 import copies
Matt Mackall
context: add a match builder method...
r14669 import match as matchmod
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 import os, errno, stat
Pierre-Yves David
obsolete: introduce caches for all meaningful sets...
r17469 import obsolete as obsmod
Pierre-Yves David
context: retrieve hidden from filteredrevs...
r18252 import repoview
Matt Mackall
filectx: add rename traversal for parents()
r3122
Matt Mackall
util: take propertycache from context.py
r8207 propertycache = util.propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 class changectx(object):
"""A changecontext object makes access to data related to a particular
changeset convenient."""
Matt Mackall
context: simplify changeid logic
r6741 def __init__(self, repo, changeid=''):
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 """changeid is a revision number, node, or tag"""
Matt Mackall
context: simplify changeid logic
r6741 if changeid == '':
changeid = '.'
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 self._repo = repo
Matt Mackall
context: internalize lookup logic...
r16376
if isinstance(changeid, int):
Pierre-Yves David
clfilter: ensure context raise RepoLookupError when the revision is filtered...
r18084 try:
self._node = repo.changelog.node(changeid)
except IndexError:
raise error.RepoLookupError(
_("unknown revision '%s'") % changeid)
Dirkjan Ochtman
context: special-case changectx setup for integer changeid
r7367 self._rev = changeid
Matt Mackall
context: internalize lookup logic...
r16376 return
Matt Mackall
context: grudging accept longs in constructor
r16760 if isinstance(changeid, long):
changeid = str(changeid)
Matt Mackall
context: internalize lookup logic...
r16376 if changeid == '.':
self._node = repo.dirstate.p1()
self._rev = repo.changelog.rev(self._node)
return
if changeid == 'null':
self._node = nullid
self._rev = nullrev
return
if changeid == 'tip':
Pierre-Yves David
changectx: fix the handling of `tip`...
r18464 self._node = repo.changelog.tip()
self._rev = repo.changelog.rev(self._node)
Matt Mackall
context: internalize lookup logic...
r16376 return
if len(changeid) == 20:
try:
self._node = changeid
self._rev = repo.changelog.rev(changeid)
return
except LookupError:
pass
try:
r = int(changeid)
if str(r) != changeid:
raise ValueError
l = len(repo.changelog)
if r < 0:
r += l
if r < 0 or r >= l:
raise ValueError
self._rev = r
self._node = repo.changelog.node(r)
return
Pierre-Yves David
clfilter: stronger detection of filtered changeset in changectx.__init__...
r18423 except (ValueError, OverflowError, IndexError):
Matt Mackall
context: internalize lookup logic...
r16376 pass
if len(changeid) == 40:
try:
self._node = bin(changeid)
self._rev = repo.changelog.rev(self._node)
return
except (TypeError, LookupError):
pass
if changeid in repo._bookmarks:
self._node = repo._bookmarks[changeid]
self._rev = repo.changelog.rev(self._node)
return
if changeid in repo._tagscache.tags:
self._node = repo._tagscache.tags[changeid]
self._rev = repo.changelog.rev(self._node)
return
Brodie Rao
localrepo: add branchtip() method for faster single-branch lookups...
r16719 try:
self._node = repo.branchtip(changeid)
Matt Mackall
context: internalize lookup logic...
r16376 self._rev = repo.changelog.rev(self._node)
return
Brodie Rao
localrepo: add branchtip() method for faster single-branch lookups...
r16719 except error.RepoLookupError:
pass
Matt Mackall
context: internalize lookup logic...
r16376
self._node = repo.changelog._partialmatch(changeid)
if self._node is not None:
self._rev = repo.changelog.rev(self._node)
return
# lookup failed
# check if it might have come from damaged dirstate
Pierre-Yves David
clfilter: prevent unwanted warning about filtered parents as unknown...
r18005 #
# XXX we could avoid the unfiltered if we had a recognizable exception
# for filtered changeset access
if changeid in repo.unfiltered().dirstate.parents():
Matt Mackall
context: internalize lookup logic...
r16376 raise error.Abort(_("working directory has unknown parent '%s'!")
% short(changeid))
try:
if len(changeid) == 20:
changeid = hex(changeid)
except TypeError:
pass
raise error.RepoLookupError(
_("unknown revision '%s'") % changeid)
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Matt Mackall
Add str methods to contexts
r3166 def __str__(self):
return short(self.node())
Matt Mackall
context: add __int__ and hex methods
r6763 def __int__(self):
return self.rev()
Matt Mackall
context: add __repr__ methods
r3151 def __repr__(self):
Matt Mackall
context: simplify repr methods
r3216 return "<changectx %s>" % str(self)
Matt Mackall
context: add __repr__ methods
r3151
Paul Moore
python 2.6 compatibility: add __hash__ to classes that have __eq__
r6469 def __hash__(self):
try:
return hash(self._rev)
except AttributeError:
return id(self)
Matt Mackall
Add equality operators to changectx and filectx
r3165 def __eq__(self, other):
Brendan Cully
Make context __eq__ handle arbitrary RHS values
r3715 try:
return self._rev == other._rev
except AttributeError:
return False
Matt Mackall
Add equality operators to changectx and filectx
r3165
Matt Mackall
merge: make test for fast-forward merge stricter (issue619)...
r4748 def __ne__(self, other):
return not (self == other)
Matt Mackall
context: add __nonzero__ methods
r3168 def __nonzero__(self):
Thomas Arendsen Hein
Define and use nullrev (revision of nullid) instead of -1.
r3578 return self._rev != nullrev
Matt Mackall
context: add __nonzero__ methods
r3168
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _changeset(self):
Matt Mackall
context: use rev for changelog lookup...
r16377 return self._repo.changelog.read(self.rev())
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _manifest(self):
return self._repo.manifest.read(self._changeset[0])
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _manifestdelta(self):
return self._repo.manifest.readdelta(self._changeset[0])
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _parents(self):
p = self._repo.changelog.parentrevs(self._rev)
if p[1] == nullrev:
p = p[:-1]
return [changectx(self._repo, x) for x in p]
Matt Mackall
contexts: use __getattr__ rather than try/except in changectx
r3215
Matt Mackall
subrepo: introduce basic state parsing
r8812 @propertycache
def substate(self):
Martin Geisler
subrepos: support remapping of .hgsub source paths...
r11775 return subrepo.state(self, self._repo.ui)
Matt Mackall
subrepo: introduce basic state parsing
r8812
Matt Mackall
context: add __contains__, __getitem__, and __iter__
r4909 def __contains__(self, key):
return key in self._manifest
def __getitem__(self, key):
return self.filectx(key)
def __iter__(self):
Matt Mackall
replace util.sort with sorted built-in...
r8209 for f in sorted(self._manifest):
Bryan O'Sullivan
Fix context iterator.
r5485 yield f
Matt Mackall
context: add __contains__, __getitem__, and __iter__
r4909
Matt Mackall
many, many trivial check-code fixups
r10282 def changeset(self):
return self._changeset
def manifest(self):
return self._manifest
def manifestnode(self):
return self._changeset[0]
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Matt Mackall
many, many trivial check-code fixups
r10282 def rev(self):
return self._rev
def node(self):
return self._node
def hex(self):
return hex(self._node)
def user(self):
return self._changeset[1]
def date(self):
return self._changeset[2]
def files(self):
return self._changeset[3]
def description(self):
return self._changeset[4]
def branch(self):
Matt Mackall
branch: operate on branch names in local string space where possible...
r13047 return encoding.tolocal(self._changeset[5].get("branch"))
Brodie Rao
context: add changectx.closesbranch() method...
r16720 def closesbranch(self):
return 'close' in self._changeset[5]
Matt Mackall
many, many trivial check-code fixups
r10282 def extra(self):
return self._changeset[5]
def tags(self):
return self._repo.nodetags(self._node)
David Soria Parra
context: add method to return all bookmarks pointing to a node
r13384 def bookmarks(self):
return self._repo.nodebookmarks(self._node)
Pierre-Yves David
phases: add a phase method to context
r15421 def phase(self):
Patrick Mezard
phases: introduce phasecache...
r16657 return self._repo._phasecache.phase(self._repo, self._rev)
Pierre-Yves David
phases: add a phasestr method on context
r15822 def phasestr(self):
return phases.phasenames[self.phase()]
Pierre-Yves David
phases: add a mutable boolean property on context
r15703 def mutable(self):
Patrick Mezard
context: make changectx.mutable() benefit from .phase() logic...
r16359 return self.phase() > phases.public
Pierre-Yves David
hidden: Add ``hidden`` method for context
r14644 def hidden(self):
Kevin Bullock
filtering: rename filters to their antonyms...
r18382 return self._rev in repoview.filterrevs(self._repo, 'visible')
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
def parents(self):
"""return contexts for each parent changeset"""
Matt Mackall
context: clean up parents()
r6742 return self._parents
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Matt Mackall
context: add p1 and p2 methods
r8406 def p1(self):
return self._parents[0]
def p2(self):
if len(self._parents) == 2:
return self._parents[1]
return changectx(self._repo, -1)
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 def children(self):
"""return contexts for each child changeset"""
Benoit Boissinot
context.py: self.repo is not defined, change to self._repo
r2627 c = self._repo.changelog.children(self._node)
Thomas Arendsen Hein
white space and line break cleanups
r3673 return [changectx(self._repo, x) for x in c]
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Matt Mackall
Merge with stable...
r6876 def ancestors(self):
Bryan O'Sullivan
revlog: ancestors(*revs) becomes ancestors(revs) (API)...
r16866 for a in self._repo.changelog.ancestors([self._rev]):
Matt Mackall
Merge with stable...
r6876 yield changectx(self._repo, a)
def descendants(self):
Bryan O'Sullivan
revlog: descendants(*revs) becomes descendants(revs) (API)...
r16867 for d in self._repo.changelog.descendants([self._rev]):
Matt Mackall
Merge with stable...
r6876 yield changectx(self._repo, d)
Pierre-Yves.David@ens-lyon.org
obsolete: function and method to access some obsolete data...
r17076 def obsolete(self):
"""True if the changeset is obsolete"""
Pierre-Yves David
obsolete: rename `getobscache` into `getrevs`...
r17825 return self.rev() in obsmod.getrevs(self._repo, 'obsolete')
Pierre-Yves.David@ens-lyon.org
obsolete: function and method to access some obsolete data...
r17076
Pierre-Yves David
obsolete: compute extinct changesets...
r17173 def extinct(self):
"""True if the changeset is extinct"""
Pierre-Yves David
obsolete: rename `getobscache` into `getrevs`...
r17825 return self.rev() in obsmod.getrevs(self._repo, 'extinct')
Pierre-Yves David
obsolete: compute extinct changesets...
r17173
Pierre-Yves David
obsolete: compute unstable changeset...
r17171 def unstable(self):
"""True if the changeset is not obsolete but it's ancestor are"""
Pierre-Yves David
obsolete: rename `getobscache` into `getrevs`...
r17825 return self.rev() in obsmod.getrevs(self._repo, 'unstable')
Pierre-Yves David
obsolete: compute unstable changeset...
r17171
Pierre-Yves David
context: add a `bumped` method to `changectx`...
r17832 def bumped(self):
"""True if the changeset try to be a successor of a public changeset
Only non-public and non-obsolete changesets may be bumped.
"""
return self.rev() in obsmod.getrevs(self._repo, 'bumped')
Pierre-Yves David
obsolete: add a divergent method on context...
r18072 def divergent(self):
"""Is a successors of a changeset with multiple possible successors set
Only non-public and non-obsolete changesets may be divergent.
"""
return self.rev() in obsmod.getrevs(self._repo, 'divergent')
Pierre-Yves David
obsolete: introduce a troubled method on context...
r18160 def troubled(self):
"""True if the changeset is either unstable, bumped or divergent"""
return self.unstable() or self.bumped() or self.divergent()
Pierre-Yves David
obsolete: introduce a troubles method on context...
r18161 def troubles(self):
"""return the list of troubles affecting this changesets.
Troubles are returned as strings. possible values are:
- unstable,
- bumped,
- divergent.
"""
troubles = []
if self.unstable():
troubles.append('unstable')
if self.bumped():
troubles.append('bumped')
if self.divergent():
troubles.append('divergent')
return troubles
Patrick Mezard
context: add fileflags() to avoid rebuilding manifests
r5389 def _fileinfo(self, path):
Brendan Cully
context: check self.__dict__ instead of using hasattr...
r3336 if '_manifest' in self.__dict__:
Brendan Cully
Make changectx.filenode raise repo.LookupError on failure
r3242 try:
Patrick Mezard
context: add fileflags() to avoid rebuilding manifests
r5389 return self._manifest[path], self._manifest.flags(path)
Brendan Cully
Make changectx.filenode raise repo.LookupError on failure
r3242 except KeyError:
Matt Mackall
errors: move revlog errors...
r7633 raise error.LookupError(self._node, path,
_('not found in manifest'))
Brendan Cully
changectx: search manifest delta for filenode
r3337 if '_manifestdelta' in self.__dict__ or path in self.files():
if path in self._manifestdelta:
Brodie Rao
cleanup: eradicate long lines
r16683 return (self._manifestdelta[path],
self._manifestdelta.flags(path))
Matt Mackall
contexts: use __getattr__ rather than try/except in changectx
r3215 node, flag = self._repo.manifest.find(self._changeset[0], path)
Brendan Cully
Make changectx.filenode raise repo.LookupError on failure
r3242 if not node:
Matt Mackall
errors: move revlog errors...
r7633 raise error.LookupError(self._node, path,
_('not found in manifest'))
Brendan Cully
Make changectx.filenode raise repo.LookupError on failure
r3242
Patrick Mezard
context: add fileflags() to avoid rebuilding manifests
r5389 return node, flag
def filenode(self, path):
return self._fileinfo(path)[0]
Matt Mackall
simplify flag handling...
r6743 def flags(self, path):
Patrick Mezard
context: add fileflags() to avoid rebuilding manifests
r5389 try:
return self._fileinfo(path)[1]
Matt Mackall
errors: move revlog errors...
r7633 except error.LookupError:
Patrick Mezard
context: add fileflags() to avoid rebuilding manifests
r5389 return ''
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Benoit Boissinot
context: create a filectxt with filelog reuse
r3966 def filectx(self, path, fileid=None, filelog=None):
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 """get a file context from this changeset"""
Benoit Boissinot
context.py: filectxs was using a keyword arg, add it to filectx
r2628 if fileid is None:
fileid = self.filenode(path)
Benoit Boissinot
context: create a filectxt with filelog reuse
r3966 return filectx(self._repo, path, fileid=fileid,
changectx=self, filelog=filelog)
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Matt Mackall
changectx: add ancestor function
r3125 def ancestor(self, c2):
"""
return the ancestor context of self and c2
"""
Matt Mackall
merge: fix changectx.ancestor(workingctx) (issue1327)
r9843 # deal with workingctxs
n2 = c2._node
Martin Geisler
code style: prefer 'is' and 'is not' tests with singletons
r13031 if n2 is None:
Matt Mackall
merge: fix changectx.ancestor(workingctx) (issue1327)
r9843 n2 = c2._parents[0]._node
n = self._repo.changelog.ancestor(self._node, n2)
Matt Mackall
changectx: add ancestor function
r3125 return changectx(self._repo, n)
FUJIWARA Katsunori
context: add "descendant()" to changectx for efficient descendant examination...
r17626 def descendant(self, other):
"""True if other is descendant of this changeset"""
return self._repo.changelog.descendant(self._rev, other._rev)
Matt Mackall
context: add walk method
r6764 def walk(self, match):
Simon Heimberg
context: replace pseudo-set by real set
r8380 fset = set(match.files())
Matt Mackall
context: add walk method
r6764 # for dirstate.walk, files=['.'] means "walk the whole tree".
# follow that here, too
Simon Heimberg
context: replace pseudo-set by real set
r8380 fset.discard('.')
Matt Mackall
context: add walk method
r6764 for fn in self:
FUJIWARA Katsunori
context: use 'changectx.dirs()' in 'walk()' for directory patterns...
r16145 if fn in fset:
# specified pattern is the exact name
fset.remove(fn)
Matt Mackall
context: add walk method
r6764 if match(fn):
yield fn
Simon Heimberg
context: replace pseudo-set by real set
r8380 for fn in sorted(fset):
FUJIWARA Katsunori
context: use 'changectx.dirs()' in 'walk()' for directory patterns...
r16145 if fn in self._dirs:
# specified pattern is a directory
continue
Martin Geisler
Lowercase error messages
r12067 if match.bad(fn, _('no such file in rev %s') % self) and match(fn):
Matt Mackall
context: add walk method
r6764 yield fn
Matt Mackall
commit: recurse into subrepositories
r8813 def sub(self, path):
return subrepo.subrepo(self, path)
Matt Mackall
context: add a match builder method...
r14669 def match(self, pats=[], include=None, exclude=None, default='glob'):
r = self._repo
return matchmod.match(r.root, r.getcwd(), pats,
Matt Mackall
match: allow passing a context object to match core
r14674 include, exclude, default,
auditor=r.auditor, ctx=self)
Matt Mackall
context: add a match builder method...
r14669
Steve Borho
changectx: change diff() to accept keyword opts
r11106 def diff(self, ctx2=None, match=None, **opts):
Steve Borho
context: add a changectx.diff() convenience function...
r11097 """Returns a diff generator for the given contexts and matcher"""
if ctx2 is None:
ctx2 = self.p1()
if ctx2 is not None and not isinstance(ctx2, changectx):
ctx2 = self._repo[ctx2]
Steve Borho
changectx: use repo.ui diffopts, allow argument override
r11105 diffopts = patch.diffopts(self._repo.ui, opts)
return patch.diff(self._repo, ctx2.node(), self.node(),
match=match, opts=diffopts)
Steve Borho
context: add a changectx.diff() convenience function...
r11097
FUJIWARA Katsunori
context: add 'dirs()' to changectx/workingctx for directory patterns...
r16143 @propertycache
def _dirs(self):
dirs = set()
for f in self._manifest:
pos = f.rfind('/')
while pos != -1:
f = f[:pos]
if f in dirs:
break # dirs already contains this and above
dirs.add(f)
pos = f.rfind('/')
return dirs
def dirs(self):
return self._dirs
David Schleimer
merge: support calculating merge actions against non-working contexts...
r18036 def dirty(self):
return False
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 class filectx(object):
"""A filecontext object makes access to data related to a particular
filerevision convenient."""
Matt Mackall
context: make filectx remember changectx in changectx.filectx
r3214 def __init__(self, repo, path, changeid=None, fileid=None,
filelog=None, changectx=None):
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 """changeid can be a changeset revision, node, or tag.
fileid can be a file revision or node."""
self._repo = repo
self._path = path
Benoit Boissinot
make it possible to use changectx to create a filectx
r3964 assert (changeid is not None
or fileid is not None
Greg Ward
context: improve arg-checking assert.
r9024 or changectx is not None), \
("bad args: changeid=%r, fileid=%r, changectx=%r"
% (changeid, fileid, changectx))
Benoit Boissinot
fix filectxt to really work...
r2643
Matt Mackall
filectx: allow passing filelog in init to avoid opening new filelogs
r3124 if filelog:
self._filelog = filelog
Maxim Dounin
context: preserve changeset in filectx if we have one...
r5810 if changeid is not None:
self._changeid = changeid
if changectx is not None:
self._changectx = changectx
if fileid is not None:
Matt Mackall
Make filectx lazier...
r3213 self._fileid = fileid
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _changectx(self):
Pierre-Yves David
clfilter: fallback to unfiltered version when linkrev point to filtered history...
r18211 try:
return changectx(self._repo, self._changeid)
except error.RepoLookupError:
# Linkrev may point to any revision in the repository. When the
# repository is filtered this may lead to `filectx` trying to build
# `changectx` for filtered revision. In such case we fallback to
# creating `changectx` on the unfiltered version of the reposition.
# This fallback should not be an issue because`changectx` from
# `filectx` are not used in complexe operation that care about
# filtering.
#
# This fallback is a cheap and dirty fix that prevent several
# crash. It does not ensure the behavior is correct. However the
# behavior was not correct before filtering either and "incorrect
# behavior" is seen as better as "crash"
#
# Linkrevs have several serious troubles with filtering that are
# complicated to solve. Proper handling of the issue here should be
# considered when solving linkrev issue are on the table.
return changectx(self._repo.unfiltered(), self._changeid)
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _filelog(self):
return self._repo.file(self._path)
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _changeid(self):
if '_changectx' in self.__dict__:
return self._changectx.rev()
Brendan Cully
Make filectx lazier - some users never use filenode
r3144 else:
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 return self._filelog.linkrev(self._filerev)
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _filenode(self):
if '_fileid' in self.__dict__:
return self._filelog.lookup(self._fileid)
else:
return self._changectx.filenode(self._path)
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _filerev(self):
return self._filelog.rev(self._filenode)
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _repopath(self):
return self._path
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Matt Mackall
context: add __nonzero__ methods
r3168 def __nonzero__(self):
Benoit Boissinot
context: None is not a valid filenode (revert from 23ede9e7ad4d)
r3712 try:
Peter Arrenbrecht
cleanup: drop variables for unused return values...
r7874 self._filenode
Benoit Boissinot
context: None is not a valid filenode (revert from 23ede9e7ad4d)
r3712 return True
Matt Mackall
errors: move revlog errors...
r7633 except error.LookupError:
Benoit Boissinot
context: None is not a valid filenode (revert from 23ede9e7ad4d)
r3712 # file is missing
return False
Matt Mackall
context: add __nonzero__ methods
r3168
Matt Mackall
Add str methods to contexts
r3166 def __str__(self):
return "%s@%s" % (self.path(), short(self.node()))
Matt Mackall
context: add __repr__ methods
r3151 def __repr__(self):
Matt Mackall
context: simplify repr methods
r3216 return "<filectx %s>" % str(self)
Matt Mackall
context: add __repr__ methods
r3151
Paul Moore
python 2.6 compatibility: add __hash__ to classes that have __eq__
r6469 def __hash__(self):
try:
Benoit Boissinot
filectx: _fileid isn't normalized, use _filenode instead...
r10942 return hash((self._path, self._filenode))
Paul Moore
python 2.6 compatibility: add __hash__ to classes that have __eq__
r6469 except AttributeError:
return id(self)
Matt Mackall
Add equality operators to changectx and filectx
r3165 def __eq__(self, other):
Brendan Cully
Make context __eq__ handle arbitrary RHS values
r3715 try:
return (self._path == other._path
Benoit Boissinot
filectx: _fileid isn't normalized, use _filenode instead...
r10942 and self._filenode == other._filenode)
Brendan Cully
Make context __eq__ handle arbitrary RHS values
r3715 except AttributeError:
return False
Matt Mackall
Add equality operators to changectx and filectx
r3165
Matt Mackall
merge: make test for fast-forward merge stricter (issue619)...
r4748 def __ne__(self, other):
return not (self == other)
Brendan Cully
Add lookup method to filectx
r3207 def filectx(self, fileid):
'''opens an arbitrary revision of the file without
opening a new filelog'''
return filectx(self._repo, self._path, fileid=fileid,
filelog=self._filelog)
Matt Mackall
many, many trivial check-code fixups
r10282 def filerev(self):
return self._filerev
def filenode(self):
return self._filenode
def flags(self):
return self._changectx.flags(self._path)
def filelog(self):
return self._filelog
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Matt Mackall
filectx: lazy linkrev usage
r3150 def rev(self):
Brendan Cully
context: check self.__dict__ instead of using hasattr...
r3336 if '_changectx' in self.__dict__:
Matt Mackall
filectx: lazy linkrev usage
r3150 return self._changectx.rev()
Maxim Dounin
context: preserve changeset in filectx if we have one...
r5810 if '_changeid' in self.__dict__:
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210 return self._changectx.rev()
Matt Mackall
linkrev: take a revision number rather than a hash
r7361 return self._filelog.linkrev(self._filerev)
Matt Mackall
filectx: lazy linkrev usage
r3150
Matt Mackall
many, many trivial check-code fixups
r10282 def linkrev(self):
return self._filelog.linkrev(self._filerev)
def node(self):
return self._changectx.node()
def hex(self):
return hex(self.node())
def user(self):
return self._changectx.user()
def date(self):
return self._changectx.date()
def files(self):
return self._changectx.files()
def description(self):
return self._changectx.description()
def branch(self):
return self._changectx.branch()
def extra(self):
return self._changectx.extra()
Sean Farley
phases: add a phase and phasestr method to file context
r17792 def phase(self):
return self._changectx.phase()
def phasestr(self):
return self._changectx.phasestr()
Matt Mackall
many, many trivial check-code fixups
r10282 def manifest(self):
return self._changectx.manifest()
def changectx(self):
return self._changectx
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Matt Mackall
many, many trivial check-code fixups
r10282 def data(self):
return self._filelog.read(self._filenode)
def path(self):
return self._path
def size(self):
return self._filelog.size(self._filerev)
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Laurens Holst
context: add isbinary function
r15738 def isbinary(self):
try:
return util.binary(self.data())
except IOError:
return False
Nicolas Dumazet
filectx: use cmp(self, fctx) instead of cmp(self, text)...
r11702 def cmp(self, fctx):
"""compare with other file context
Nicolas Dumazet
cmp: document the fact that we return True if content is different...
r11539
Nicolas Dumazet
filectx: use cmp(self, fctx) instead of cmp(self, text)...
r11702 returns True if different than fctx.
Nicolas Dumazet
cmp: document the fact that we return True if content is different...
r11539 """
Yuya Nishihara
filectx: fix cmp() of file starting with '\1\n'...
r15848 if (fctx._filerev is None
and (self._repo._encodefilterpats
# if file data starts with '\1\n', empty metadata block is
Christian Ebert
filectx: typo in comment
r15872 # prepended, which adds 4 bytes to filelog.size().
Yuya Nishihara
filectx: fix cmp() of file starting with '\1\n'...
r15848 or self.size() - 4 == fctx.size())
Christian Ebert
context: narrow down filter special case in filectx.cmp()...
r12731 or self.size() == fctx.size()):
return self._filelog.cmp(self._filenode, fctx.data())
Nicolas Dumazet
filectx: use ctx.size comparisons to speed up ctx.cmp...
r12709
Christian Ebert
context: narrow down filter special case in filectx.cmp()...
r12731 return True
Matt Mackall
context: add cmp for filectxs
r3310
Maxim Dounin
Fix copies reporting in log and convert....
r5811 def renamed(self):
"""check if file was actually renamed in this changeset revision
If rename logged in file revision, we report copy for changeset only
if file revisions linkrev points back to the changeset in question
or both changeset parents contain different file revisions.
"""
renamed = self._filelog.renamed(self._filenode)
if not renamed:
return renamed
if self.rev() == self.linkrev():
return renamed
name = self.path()
fnode = self._filenode
for p in self._changectx.parents():
try:
if fnode == p.filenode(name):
return None
Matt Mackall
errors: move revlog errors...
r7633 except error.LookupError:
Maxim Dounin
Fix copies reporting in log and convert....
r5811 pass
return renamed
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 def parents(self):
Matt Mackall
filectx: allow passing filelog in init to avoid opening new filelogs
r3124 p = self._path
fl = self._filelog
Thomas Arendsen Hein
white space and line break cleanups
r3673 pl = [(p, n, fl) for n in self._filelog.parents(self._filenode)]
Matt Mackall
filelog: make metadata method private
r3123
Patrick Mezard
context: fix filectx.parents() bug introduced when editing 180a3eee4b75
r5813 r = self._filelog.renamed(self._filenode)
Matt Mackall
filectx: add rename traversal for parents()
r3122 if r:
Matt Mackall
filectx: allow passing filelog in init to avoid opening new filelogs
r3124 pl[0] = (r[0], r[1], None)
Thomas Arendsen Hein
white space and line break cleanups
r3673 return [filectx(self._repo, p, fileid=n, filelog=l)
Matt Mackall
many, many trivial check-code fixups
r10282 for p, n, l in pl if n != nullid]
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Matt Mackall
filectx: introduce p1/p2 convenience methods
r13877 def p1(self):
return self.parents()[0]
def p2(self):
p = self.parents()
if len(p) == 2:
return p[1]
return filectx(self._repo, self._path, fileid=-1, filelog=self._filelog)
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 def children(self):
# hard for renames
c = self._filelog.children(self._filenode)
Thomas Arendsen Hein
white space and line break cleanups
r3673 return [filectx(self._repo, self._path, fileid=x,
filelog=self._filelog) for x in c]
Matt Mackall
Convert hg annotate to context api
r2566
Patrick Mezard
annotate: support diff whitespace filtering flags (issue3030)...
r15528 def annotate(self, follow=False, linenumber=None, diffopts=None):
Brendan Cully
Refactor annotate copy support.
r3172 '''returns a list of tuples of (ctx, line) for each line
in the file, where ctx is the filectx of the node where
FUJIWARA Katsunori
Allow filectx.annotate to return the line number of first appearance.
r4856 that line was last changed.
This returns tuples of ((ctx, linenumber), line) for each line,
if "linenumber" parameter is NOT "None".
In such tuples, linenumber means one at the first appearance
in the managed file.
To reduce annotation cost,
this returns fixed value(False is used) as linenumber,
if "linenumber" parameter is "False".'''
Brendan Cully
Refactor annotate copy support.
r3172
FUJIWARA Katsunori
Allow filectx.annotate to return the line number of first appearance.
r4856 def decorate_compat(text, rev):
Brendan Cully
Refactor annotate copy support.
r3172 return ([rev] * len(text.splitlines()), text)
FUJIWARA Katsunori
Allow filectx.annotate to return the line number of first appearance.
r4856 def without_linenumber(text, rev):
return ([(rev, False)] * len(text.splitlines()), text)
def with_linenumber(text, rev):
size = len(text.splitlines())
return ([(rev, i) for i in xrange(1, size + 1)], text)
decorate = (((linenumber is None) and decorate_compat) or
(linenumber and with_linenumber) or
without_linenumber)
Brendan Cully
Refactor annotate copy support.
r3172 def pair(parent, child):
Patrick Mezard
annotate: support diff whitespace filtering flags (issue3030)...
r15528 blocks = mdiff.allblocks(parent[1], child[1], opts=diffopts,
refine=True)
for (a1, a2, b1, b2), t in blocks:
# Changed blocks ('!') or blocks made only of blank lines ('~')
# belong to the child.
if t == '=':
child[0][b1:b2] = parent[0][a1:a2]
Brendan Cully
Refactor annotate copy support.
r3172 return child
Matt Mackall
fix memory usage of revlog caches by limiting cache size [issue1639]
r9097 getlog = util.lrucachefunc(lambda x: self._repo.file(x))
Brendan Cully
Refactor annotate copy support.
r3172 def getctx(path, fileid):
log = path == self._path and self._filelog or getlog(path)
return filectx(self._repo, path, fileid=fileid, filelog=log)
Matt Mackall
fix memory usage of revlog caches by limiting cache size [issue1639]
r9097 getctx = util.lrucachefunc(getctx)
Brendan Cully
Refactor annotate copy support.
r3172
def parents(f):
# we want to reuse filectx objects as much as possible
p = f._path
Matt Mackall
contexts: add working dir and working file contexts...
r3217 if f._filerev is None: # working dir
Thomas Arendsen Hein
white space and line break cleanups
r3673 pl = [(n.path(), n.filerev()) for n in f.parents()]
Matt Mackall
contexts: add working dir and working file contexts...
r3217 else:
Thomas Arendsen Hein
white space and line break cleanups
r3673 pl = [(p, n) for n in f._filelog.parentrevs(f._filerev)]
Brendan Cully
Refactor annotate copy support.
r3172
if follow:
r = f.renamed()
if r:
pl[0] = (r[0], getlog(r[0]).rev(r[1]))
Brendan Cully
filectx.annotate: return filectx for each line instead of rev
r3146
Thomas Arendsen Hein
Define and use nullrev (revision of nullid) instead of -1.
r3578 return [getctx(p, n) for p, n in pl if n != nullrev]
Matt Mackall
contexts: add working dir and working file contexts...
r3217
Brendan Cully
Fix annotate where linkrev != rev without exporting linkrev
r3404 # use linkrev to find the first changeset where self appeared
Maxim Dounin
Fix copies reporting in log and convert....
r5811 if self.rev() != self.linkrev():
Brendan Cully
Fix annotate where linkrev != rev without exporting linkrev
r3404 base = self.filectx(self.filerev())
else:
base = self
Matt Mackall
ancestor: rewrite to deal with crossed linkrevs (issue2682)...
r13552 # This algorithm would prefer to be recursive, but Python is a
# bit recursion-hostile. Instead we do an iterative
# depth-first search.
visit = [base]
hist = {}
pcache = {}
Brendan Cully
Fix annotate where linkrev != rev without exporting linkrev
r3404 needed = {base: 1}
Brendan Cully
Refactor annotate copy support.
r3172 while visit:
Matt Mackall
ancestor: rewrite to deal with crossed linkrevs (issue2682)...
r13552 f = visit[-1]
if f not in pcache:
pcache[f] = parents(f)
Brendan Cully
Refactor annotate copy support.
r3172
Matt Mackall
ancestor: rewrite to deal with crossed linkrevs (issue2682)...
r13552 ready = True
pl = pcache[f]
for p in pl:
if p not in hist:
ready = False
visit.append(p)
needed[p] = needed.get(p, 0) + 1
if ready:
visit.pop()
curr = decorate(f.data(), f)
for p in pl:
curr = pair(hist[p], curr)
if needed[p] == 1:
del hist[p]
else:
needed[p] -= 1
Matt Mackall
util: add sort helper
r6762
Matt Mackall
ancestor: rewrite to deal with crossed linkrevs (issue2682)...
r13552 hist[f] = curr
pcache[f] = []
Brendan Cully
Refactor annotate copy support.
r3172
Matt Mackall
ancestor: rewrite to deal with crossed linkrevs (issue2682)...
r13552 return zip(hist[base][0], hist[base][1].splitlines(True))
Matt Mackall
filectx: allow passing filelog in init to avoid opening new filelogs
r3124
Matt Mackall
filectx: make ancestor require actx...
r16599 def ancestor(self, fc2, actx):
Matt Mackall
filectx: add rename-aware ancestor algorithm...
r3126 """
find the common ancestor file context, if any, of self, and fc2
Peter Arrenbrecht
context: allow passing the common cset ancestor to fctx.ancestor...
r11453
Matt Mackall
filectx: make ancestor require actx...
r16599 actx must be the changectx of the common ancestor
Peter Arrenbrecht
context: allow passing the common cset ancestor to fctx.ancestor...
r11453 of self's and fc2's respective changesets.
Matt Mackall
filectx: add rename-aware ancestor algorithm...
r3126 """
Matt Mackall
filectx: shortcut unrelated files in ancestor() (issue1327)
r9751 # the easy case: no (relevant) renames
if fc2.path() == self.path() and self.path() in actx:
Matt Mackall
merge: first part of fix for issue1327...
r9750 return actx[self.path()]
Matt Mackall
filectx: handle some other simple cases for finding merge ancestor
r16601
# the next easiest cases: unambiguous predecessor (name trumps
# history)
if self.path() in actx and fc2.path() not in actx:
return actx[self.path()]
if fc2.path() in actx and self.path() not in actx:
return actx[fc2.path()]
Matt Mackall
contexts: add working dir and working file contexts...
r3217
# prime the ancestor cache for the working directory
Matt Mackall
filectx: handle some other simple cases for finding merge ancestor
r16601 acache = {}
Matt Mackall
contexts: add working dir and working file contexts...
r3217 for c in (self, fc2):
Martin Geisler
use 'x is None' instead of 'x == None'...
r8527 if c._filerev is None:
Thomas Arendsen Hein
white space and line break cleanups
r3673 pl = [(n.path(), n.filenode()) for n in c.parents()]
Matt Mackall
contexts: add working dir and working file contexts...
r3217 acache[(c._path, None)] = pl
Alexis S. L. Carvalho
filectx.ancestor: use fctx._repopath to cache filelogs (issue1035)...
r6286 flcache = {self._repopath:self._filelog, fc2._repopath:fc2._filelog}
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 def parents(vertex):
if vertex in acache:
return acache[vertex]
f, n = vertex
if f not in flcache:
Matt Mackall
filectx: add rename-aware ancestor algorithm...
r3126 flcache[f] = self._repo.file(f)
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 fl = flcache[f]
Thomas Arendsen Hein
white space and line break cleanups
r3673 pl = [(f, p) for p in fl.parents(n) if p != nullid]
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 re = fl.renamed(n)
if re:
pl.append(re)
Thomas Arendsen Hein
white space and line break cleanups
r3673 acache[vertex] = pl
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 return pl
Matt Mackall
filectx: add rename-aware ancestor algorithm...
r3126
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 a, b = (self._path, self._filenode), (fc2._path, fc2._filenode)
v = ancestor.ancestor(a, b, parents)
if v:
Thomas Arendsen Hein
white space and line break cleanups
r3673 f, n = v
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 return filectx(self._repo, f, fileid=n, filelog=flcache[f])
Matt Mackall
filectx: add rename-aware ancestor algorithm...
r3126
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 return None
Matt Mackall
contexts: add working dir and working file contexts...
r3217
Patrick Mezard
context: add followfirst arg to filectx and workingfilectx...
r16185 def ancestors(self, followfirst=False):
Matt Mackall
context: be even more careful about result order in ancestors() (issue2642)...
r13481 visit = {}
c = self
Patrick Mezard
context: add followfirst arg to filectx and workingfilectx...
r16185 cut = followfirst and 1 or None
Matt Mackall
context: be even more careful about result order in ancestors() (issue2642)...
r13481 while True:
Patrick Mezard
context: add followfirst arg to filectx and workingfilectx...
r16185 for parent in c.parents()[:cut]:
Matt Mackall
context: be even more careful about result order in ancestors() (issue2642)...
r13481 visit[(parent.rev(), parent.node())] = parent
if not visit:
break
c = visit.pop(max(visit))
yield c
Matt Mackall
copies: speed up copy detection...
r10262
Matt Mackall
context: add copies method with caching
r16602 def copies(self, c2):
Idan Kamara
context: fix call to util.safehasattr
r16610 if not util.safehasattr(self, "_copycache"):
Matt Mackall
context: add copies method with caching
r16602 self._copycache = {}
sc2 = str(c2)
if sc2 not in self._copycache:
self._copycache[sc2] = copies.pathcopies(c2)
return self._copycache[sc2]
Matt Mackall
contexts: add working dir and working file contexts...
r3217 class workingctx(changectx):
"""A workingctx object makes access to data related to
Patrick Mezard
context: let workingctx parents be overriden
r6705 the current working directory convenient.
Patrick Mezard
context: let workingctx.date(), .user() and description() be overriden
r6709 date - any valid date string or (unixtime, offset), or None.
user - username string, or None.
Patrick Mezard
localrepo: let commit() get extra data from workingctx
r6708 extra - a dictionary of extra values, or None.
Patrick Mezard
localrepo: hide commit() file selection behind workingctx
r6707 changes - a list of file lists as returned by localrepo.status()
or None to use the repository status.
Patrick Mezard
context: let workingctx parents be overriden
r6705 """
Benoit Boissinot
context: remove parents parameter to workingctx...
r10969 def __init__(self, repo, text="", user=None, date=None, extra=None,
changes=None):
Matt Mackall
contexts: add working dir and working file contexts...
r3217 self._repo = repo
self._rev = None
self._node = None
Patrick Mezard
context: let workingctx.date(), .user() and description() be overriden
r6709 self._text = text
Christian Ebert
Fix commit date (issue1193)...
r6718 if date:
Patrick Mezard
context: let workingctx.date(), .user() and description() be overriden
r6709 self._date = util.parsedate(date)
Matt Mackall
minor status fixups
r6817 if user:
self._user = user
Patrick Mezard
localrepo: hide commit() file selection behind workingctx
r6707 if changes:
Matt Mackall
context: only scan unknowns when needed
r11101 self._status = list(changes[:4])
self._unknown = changes[4]
Steve Borho
workingctx: use member variables to store ignored and clean...
r11099 self._ignored = changes[5]
self._clean = changes[6]
else:
Matt Mackall
context: only scan unknowns when needed
r11101 self._unknown = None
Steve Borho
workingctx: use member variables to store ignored and clean...
r11099 self._ignored = None
self._clean = None
Matt Mackall
contexts: add working dir and working file contexts...
r3217
Patrick Mezard
localrepo: let commit() get extra data from workingctx
r6708 self._extra = {}
if extra:
self._extra = extra.copy()
if 'branch' not in self._extra:
try:
Matt Mackall
branch: operate on branch names in local string space where possible...
r13047 branch = encoding.fromlocal(self._repo.dirstate.branch())
Patrick Mezard
localrepo: let commit() get extra data from workingctx
r6708 except UnicodeDecodeError:
raise util.Abort(_('branch name not in UTF-8!'))
self._extra['branch'] = branch
if self._extra['branch'] == '':
self._extra['branch'] = 'default'
Matt Mackall
contexts: add working dir and working file contexts...
r3217 def __str__(self):
Matt Mackall
context: change workingctx str() from . to <node>+
r3313 return str(self._parents[0]) + "+"
Matt Mackall
contexts: add working dir and working file contexts...
r3217
Nicolas Dumazet
context: add __repr__ methods to workingfilectx and workingctx
r12947 def __repr__(self):
return "<workingctx %s>" % str(self)
Matt Mackall
contexts: add working dir and working file contexts...
r3217 def __nonzero__(self):
return True
Matt Mackall
workingctx: add __contains__ method
r6771 def __contains__(self, key):
Patrick Mezard
context: fix workingctx.__contains__
r8061 return self._repo.dirstate[key] not in "?r"
Matt Mackall
workingctx: add __contains__ method
r6771
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337 def _buildflagfunc(self):
# Create a fallback function for getting file flags when the
# filesystem doesn't support them
copiesget = self._repo.dirstate.copies().get
if len(self._parents) < 2:
# when we have one parent, it's easy: copy from parent
man = self._parents[0].manifest()
def func(f):
f = copiesget(f, f)
return man.flags(f)
else:
# merges are tricky: we try to reconstruct the unstored
# result from the merge (issue1802)
p1, p2 = self._parents
pa = p1.ancestor(p2)
m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
def func(f):
f = copiesget(f, f) # may be wrong for merges with copies
fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
if fl1 == fl2:
return fl1
if fl1 == fla:
return fl2
if fl2 == fla:
return fl1
return '' # punt for conflicts
return func
@propertycache
def _flagfunc(self):
return self._repo.dirstate.flagfunc(self._buildflagfunc)
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _manifest(self):
Matt Mackall
contexts: add working dir and working file contexts...
r3217 """generate a manifest corresponding to the working directory"""
Matt Mackall
merge: use new working context object in update
r3218 man = self._parents[0].manifest().copy()
Benoit Boissinot
workingctx: correctly compute the flag for noexec filesystems+merge...
r10921 if len(self._parents) > 1:
man2 = self.p2().manifest()
def getman(f):
if f in man:
return man
return man2
else:
getman = lambda f: man
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337
copied = self._repo.dirstate.copies()
ff = self._flagfunc
Matt Mackall
context: only scan unknowns when needed
r11101 modified, added, removed, deleted = self._status
Matt Mackall
merge: don't use unknown()...
r16094 for i, l in (("a", added), ("m", modified)):
Matt Mackall
contexts: add working dir and working file contexts...
r3217 for f in l:
Benoit Boissinot
workingctx: correctly compute the flag for noexec filesystems+merge...
r10921 orig = copied.get(f, f)
man[f] = getman(orig).get(orig, nullid) + i
Matt Mackall
context: don't spuriously raise abort when a file goes missing.
r3823 try:
Matt Mackall
simplify flag handling...
r6743 man.set(f, ff(f))
Matt Mackall
context: don't spuriously raise abort when a file goes missing.
r3823 except OSError:
pass
Matt Mackall
contexts: add working dir and working file contexts...
r3217
for f in deleted + removed:
Giorgos Keramidas
Revert changeset c67920d78248....
r3325 if f in man:
del man[f]
Matt Mackall
contexts: add working dir and working file contexts...
r3217
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 return man
Matt Mackall
context: provide an efficient iterator for workingctx...
r14129 def __iter__(self):
d = self._repo.dirstate
for f in d:
if d[f] != 'r':
yield f
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _status(self):
Matt Mackall
context: only scan unknowns when needed
r11101 return self._repo.status()[:4]
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _user(self):
return self._repo.ui.username()
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _date(self):
return util.makedate()
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _parents(self):
p = self._repo.dirstate.parents()
if p[1] == nullid:
p = p[:-1]
Patrick Mezard
context: simplify workingctx._parents
r17330 return [changectx(self._repo, x) for x in p]
Matt Mackall
contexts: add working dir and working file contexts...
r3217
Steve Borho
workingctx: add explicit status method, add ignored and fix clean...
r11098 def status(self, ignored=False, clean=False, unknown=False):
"""Explicit status query
Unless this method is used to query the working copy status, the
_status property will implicitly read the status using its default
arguments."""
Steve Borho
workingctx: use member variables to store ignored and clean...
r11099 stat = self._repo.status(ignored=ignored, clean=clean, unknown=unknown)
Matt Mackall
context: only scan unknowns when needed
r11101 self._unknown = self._ignored = self._clean = None
if unknown:
self._unknown = stat[4]
if ignored:
self._ignored = stat[5]
if clean:
self._clean = stat[6]
self._status = stat[:4]
return stat
Steve Borho
workingctx: add explicit status method, add ignored and fix clean...
r11098
Matt Mackall
many, many trivial check-code fixups
r10282 def manifest(self):
return self._manifest
def user(self):
return self._user or self._repo.ui.username()
def date(self):
return self._date
def description(self):
return self._text
Matt Mackall
contexts: add working dir and working file contexts...
r3217 def files(self):
Matt Mackall
replace util.sort with sorted built-in...
r8209 return sorted(self._status[0] + self._status[1] + self._status[2])
Matt Mackall
contexts: add working dir and working file contexts...
r3217
Matt Mackall
many, many trivial check-code fixups
r10282 def modified(self):
return self._status[0]
def added(self):
return self._status[1]
def removed(self):
return self._status[2]
def deleted(self):
return self._status[3]
def unknown(self):
Matt Mackall
context: only scan unknowns when needed
r11101 assert self._unknown is not None # must call status first
return self._unknown
Steve Borho
workingctx: add explicit status method, add ignored and fix clean...
r11098 def ignored(self):
Matt Mackall
context: use asserts for ignored and clean exceptions
r11100 assert self._ignored is not None # must call status first
Steve Borho
workingctx: use member variables to store ignored and clean...
r11099 return self._ignored
Matt Mackall
many, many trivial check-code fixups
r10282 def clean(self):
Matt Mackall
context: use asserts for ignored and clean exceptions
r11100 assert self._clean is not None # must call status first
Steve Borho
workingctx: use member variables to store ignored and clean...
r11099 return self._clean
Matt Mackall
many, many trivial check-code fixups
r10282 def branch(self):
Matt Mackall
branch: operate on branch names in local string space where possible...
r13047 return encoding.tolocal(self._extra['branch'])
Brodie Rao
context: add changectx.closesbranch() method...
r16720 def closesbranch(self):
return 'close' in self._extra
Matt Mackall
many, many trivial check-code fixups
r10282 def extra(self):
return self._extra
Matt Mackall
contexts: add working dir and working file contexts...
r3217
Matt Mackall
context: add tags() method
r4663 def tags(self):
t = []
Martin Geisler
remove unnecessary list comprehensions...
r13412 for p in self.parents():
t.extend(p.tags())
Matt Mackall
context: add tags() method
r4663 return t
Kevin Bullock
workingctx: overload bookmarks() to return parents' bookmarks...
r13476 def bookmarks(self):
b = []
for p in self.parents():
b.extend(p.bookmarks())
return b
Pierre-Yves David
phases: implement ``phase()`` and ``hidden()`` method for workingctx...
r15707 def phase(self):
Pierre-Yves David
phases: store phase values in constant instead of using raw integer...
r15818 phase = phases.draft # default phase to draft
Pierre-Yves David
phases: implement ``phase()`` and ``hidden()`` method for workingctx...
r15707 for p in self.parents():
phase = max(phase, p.phase())
return phase
def hidden(self):
return False
Matt Mackall
contexts: add working dir and working file contexts...
r3217 def children(self):
return []
Matt Mackall
simplify flag handling...
r6743 def flags(self, path):
Patrick Mezard
context: add fileflags() to avoid rebuilding manifests
r5389 if '_manifest' in self.__dict__:
try:
return self._manifest.flags(path)
except KeyError:
return ''
Thomas Arendsen Hein
Removed tabs and trailing whitespace in python files
r5760
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337 try:
return self._flagfunc(path)
except OSError:
Patrick Mezard
context: add fileflags() to avoid rebuilding manifests
r5389 return ''
Benoit Boissinot
context: create a filectxt with filelog reuse
r3966 def filectx(self, path, filelog=None):
Matt Mackall
contexts: add working dir and working file contexts...
r3217 """get a file context from the working directory"""
Benoit Boissinot
context: create a filectxt with filelog reuse
r3966 return workingfilectx(self._repo, path, workingctx=self,
filelog=filelog)
Matt Mackall
contexts: add working dir and working file contexts...
r3217
def ancestor(self, c2):
"""return the ancestor context of self and c2"""
return self._parents[0].ancestor(c2) # punt on two parents for now
Matt Mackall
context: add walk method
r6764 def walk(self, match):
Mads Kiilerich
subrepos: process subrepos in sorted order...
r18364 return sorted(self._repo.dirstate.walk(match, sorted(self.substate),
Augie Fackler
dirstate: don't check state of subrepo directories
r10176 True, False))
Matt Mackall
context: add walk method
r6764
Patrick Mezard
update: make --check abort with dirty subrepos...
r16491 def dirty(self, missing=False, merge=True, branch=True):
Matt Mackall
context: add a dirty method to detect modified contexts
r8717 "check whether a working directory is modified"
Edouard Gomez
subrepo: dirtiness checks should iterate over subrepos
r11110 # check subrepos first
Mads Kiilerich
subrepos: process subrepos in sorted order...
r18364 for s in sorted(self.substate):
Edouard Gomez
subrepo: dirtiness checks should iterate over subrepos
r11110 if self.sub(s).dirty():
return True
# check current working dir
Patrick Mezard
update: make --check abort with dirty subrepos...
r16491 return ((merge and self.p2()) or
(branch and self.branch() != self.p1().branch()) or
Matt Mackall
context: add a dirty method to detect modified contexts
r8717 self.modified() or self.added() or self.removed() or
(missing and self.deleted()))
Martin Geisler
add: recurse into subrepositories with --subrepos/-S flag
r12270 def add(self, list, prefix=""):
join = lambda f: os.path.join(prefix, f)
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 wlock = self._repo.wlock()
ui, ds = self._repo.ui, self._repo.dirstate
try:
rejected = []
for f in list:
Adrian Buehlmann
add: introduce a warning message for non-portable filenames (issue2756) (BC)...
r13962 scmutil.checkportable(ui, join(f))
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 p = self._repo.wjoin(f)
try:
st = os.lstat(p)
Idan Kamara
eliminate various naked except clauses
r14004 except OSError:
Martin Geisler
add: recurse into subrepositories with --subrepos/-S flag
r12270 ui.warn(_("%s does not exist!\n") % join(f))
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 rejected.append(f)
continue
if st.st_size > 10000000:
ui.warn(_("%s: up to %d MB of RAM may be required "
"to manage this file\n"
"(use 'hg revert %s' to cancel the "
"pending addition)\n")
Martin Geisler
add: recurse into subrepositories with --subrepos/-S flag
r12270 % (f, 3 * st.st_size // 1000000, join(f)))
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
ui.warn(_("%s not added: only files and symlinks "
Martin Geisler
add: recurse into subrepositories with --subrepos/-S flag
r12270 "supported currently\n") % join(f))
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 rejected.append(p)
elif ds[f] in 'amn':
Martin Geisler
add: recurse into subrepositories with --subrepos/-S flag
r12270 ui.warn(_("%s already tracked!\n") % join(f))
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 elif ds[f] == 'r':
ds.normallookup(f)
else:
ds.add(f)
return rejected
finally:
wlock.release()
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 def forget(self, files, prefix=""):
join = lambda f: os.path.join(prefix, f)
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 wlock = self._repo.wlock()
try:
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 rejected = []
Matt Mackall
context: make forget work like commands.forget...
r14435 for f in files:
Patrick Mezard
context: make workingctx.forget() really warn about untracked files
r16111 if f not in self._repo.dirstate:
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 self._repo.ui.warn(_("%s not tracked!\n") % join(f))
rejected.append(f)
Patrick Mezard
context: make workingctx.forget() really warn about untracked files
r16111 elif self._repo.dirstate[f] != 'a':
self._repo.dirstate.remove(f)
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 else:
Matt Mackall
dirstate: rename forget to drop...
r14434 self._repo.dirstate.drop(f)
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 return rejected
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 finally:
wlock.release()
Patrick Mezard
context: revert workingctx.ancestors() followfirst option...
r16410 def ancestors(self):
Matt Mackall
context: walk both parents for workingctx.ancestors()
r12999 for a in self._repo.changelog.ancestors(
Bryan O'Sullivan
revlog: ancestors(*revs) becomes ancestors(revs) (API)...
r16866 [p.rev() for p in self._parents]):
Matt Mackall
context: walk both parents for workingctx.ancestors()
r12999 yield changectx(self._repo, a)
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 def undelete(self, list):
pctxs = self.parents()
wlock = self._repo.wlock()
try:
for f in list:
if self._repo.dirstate[f] != 'r':
self._repo.ui.warn(_("%s not removed!\n") % f)
else:
Patrick Mezard
context: fix filectx.undelete() (issue2388)
r12360 fctx = f in pctxs[0] and pctxs[0][f] or pctxs[1][f]
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 t = fctx.data()
self._repo.wwrite(f, t, fctx.flags())
self._repo.dirstate.normal(f)
finally:
wlock.release()
def copy(self, source, dest):
p = self._repo.wjoin(dest)
Patrick Mezard
Use lexists() instead of exists() where appropriate
r12344 if not os.path.lexists(p):
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 self._repo.ui.warn(_("%s does not exist!\n") % dest)
elif not (os.path.isfile(p) or os.path.islink(p)):
self._repo.ui.warn(_("copy failed: %s is not a file or a "
"symbolic link\n") % dest)
else:
wlock = self._repo.wlock()
try:
if self._repo.dirstate[dest] in '?r':
self._repo.dirstate.add(dest)
self._repo.dirstate.copy(source, dest)
finally:
wlock.release()
FUJIWARA Katsunori
context: add 'dirs()' to changectx/workingctx for directory patterns...
r16143 def dirs(self):
Matt Mackall
copies: re-include root directory in directory rename detection (issue3511)
r17055 return set(self._repo.dirstate.dirs())
FUJIWARA Katsunori
context: add 'dirs()' to changectx/workingctx for directory patterns...
r16143
Matt Mackall
contexts: add working dir and working file contexts...
r3217 class workingfilectx(filectx):
"""A workingfilectx object makes access to data related to a particular
file in the working directory convenient."""
def __init__(self, repo, path, filelog=None, workingctx=None):
"""changeid can be a changeset revision, node, or tag.
fileid can be a file revision or node."""
self._repo = repo
self._path = path
self._changeid = None
self._filerev = self._filenode = None
if filelog:
self._filelog = filelog
if workingctx:
self._changectx = workingctx
Martin Geisler
context: use Python 2.4 decorator syntax
r8157 @propertycache
Dirkjan Ochtman
context: use descriptors to speed up lazy attributes
r7368 def _changectx(self):
return workingctx(self._repo)
Matt Mackall
contexts: add working dir and working file contexts...
r3217 def __nonzero__(self):
return True
def __str__(self):
Matt Mackall
context: change workingctx str() from . to <node>+
r3313 return "%s@%s" % (self.path(), self._changectx)
Matt Mackall
contexts: add working dir and working file contexts...
r3217
Nicolas Dumazet
context: add __repr__ methods to workingfilectx and workingctx
r12947 def __repr__(self):
return "<workingfilectx %s>" % str(self)
Matt Mackall
many, many trivial check-code fixups
r10282 def data(self):
return self._repo.wread(self._path)
Matt Mackall
contexts: add working dir and working file contexts...
r3217 def renamed(self):
Benoit Boissinot
workingfilectx: always use the same filelog, even for renames...
r8528 rp = self._repo.dirstate.copied(self._path)
if not rp:
Matt Mackall
contexts: add working dir and working file contexts...
r3217 return None
Benoit Boissinot
context: fix a bug in workingfilectx.renamed
r3965 return rp, self._changectx._parents[0]._manifest.get(rp, nullid)
Matt Mackall
contexts: add working dir and working file contexts...
r3217
def parents(self):
'''return parent filectxs, following copies if necessary'''
Benoit Boissinot
workingfilectx: always use the same filelog, even for renames...
r8528 def filenode(ctx, path):
return ctx._manifest.get(path, nullid)
path = self._path
Matt Mackall
contexts: add working dir and working file contexts...
r3217 fl = self._filelog
Benoit Boissinot
workingfilectx: always use the same filelog, even for renames...
r8528 pcl = self._changectx._parents
renamed = self.renamed()
if renamed:
pl = [renamed + (None,)]
else:
pl = [(path, filenode(pcl[0], path), fl)]
for pc in pcl[1:]:
pl.append((path, filenode(pc, path), fl))
Matt Mackall
contexts: add working dir and working file contexts...
r3217
Thomas Arendsen Hein
white space and line break cleanups
r3673 return [filectx(self._repo, p, fileid=n, filelog=l)
Matt Mackall
many, many trivial check-code fixups
r10282 for p, n, l in pl if n != nullid]
Matt Mackall
contexts: add working dir and working file contexts...
r3217
def children(self):
return []
Matt Mackall
many, many trivial check-code fixups
r10282 def size(self):
Nicolas Dumazet
context: use os.lstat instead of os.stat to fetch file size...
r11605 return os.lstat(self._repo.wjoin(self._path)).st_size
Benoit Boissinot
add date attribute to workingfilectx
r3962 def date(self):
t, tz = self._changectx.date()
try:
Thomas Arendsen Hein
Use only integer part of mtime in workingfilectx.date(), fixes test-context.py...
r4117 return (int(os.lstat(self._repo.wjoin(self._path)).st_mtime), tz)
Benoit Boissinot
add date attribute to workingfilectx
r3962 except OSError, err:
Matt Mackall
many, many trivial check-code fixups
r10282 if err.errno != errno.ENOENT:
raise
Benoit Boissinot
add date attribute to workingfilectx
r3962 return (t, tz)
Matt Mackall
context: add cmp for filectxs
r3310
Nicolas Dumazet
filectx: use cmp(self, fctx) instead of cmp(self, text)...
r11702 def cmp(self, fctx):
"""compare with other file context
Nicolas Dumazet
cmp: document the fact that we return True if content is different...
r11539
Nicolas Dumazet
filectx: use cmp(self, fctx) instead of cmp(self, text)...
r11702 returns True if different than fctx.
Nicolas Dumazet
cmp: document the fact that we return True if content is different...
r11539 """
Mads Kiilerich
fix wording and not-completely-trivial spelling errors and bad docstrings
r17425 # fctx should be a filectx (not a workingfilectx)
Nicolas Dumazet
context: reuse filecontext.cmp in workingfilecontext.cmp...
r11703 # invert comparison to reuse the same code path
return fctx.cmp(self)
Patrick Mezard
context: add memctx for memory commits
r6715
class memctx(object):
Patrick Mezard
context: improve memctx documentation
r7077 """Use memctx to perform in-memory commits via localrepo.commitctx().
Patrick Mezard
context: add memctx for memory commits
r6715
Patrick Mezard
context: improve memctx documentation
r7077 Revision information is supplied at initialization time while
related files data and is made available through a callback
mechanism. 'repo' is the current localrepo, 'parents' is a
sequence of two parent revisions identifiers (pass None for every
missing parent), 'text' is the commit message and 'files' lists
names of files touched by the revision (normalized and relative to
repository root).
Patrick Mezard
context: add memctx for memory commits
r6715
Patrick Mezard
context: improve memctx documentation
r7077 filectxfn(repo, memctx, path) is a callable receiving the
repository, the current memctx object and the normalized path of
requested file, relative to repository root. It is fired by the
commit function for every file in 'files', but calls order is
undefined. If the file is available in the revision being
committed (updated or added), filectxfn returns a memfilectx
object. If the file was removed, filectxfn raises an
IOError. Moved files are represented by marking the source file
removed and the new file added with copy information (see
memfilectx).
user receives the committer name and defaults to current
repository username, date is the commit date in any format
supported by util.parsedate() and defaults to current date, extra
is a dictionary of metadata or is left empty.
Patrick Mezard
context: add memctx for memory commits
r6715 """
Dirkjan Ochtman
kill some trailing spaces
r6721 def __init__(self, repo, parents, text, files, filectxfn, user=None,
Patrick Mezard
context: add memctx for memory commits
r6715 date=None, extra=None):
self._repo = repo
self._rev = None
self._node = None
self._text = text
self._date = date and util.parsedate(date) or util.makedate()
Patrick Mezard
context: trigger missing username warning only when necessary
r6809 self._user = user
Patrick Mezard
context: add memctx for memory commits
r6715 parents = [(p or nullid) for p in parents]
p1, p2 = parents
Matt Mackall
use repo[changeid] to get a changectx
r6747 self._parents = [changectx(self._repo, p) for p in (p1, p2)]
Matt Mackall
replace util.sort with sorted built-in...
r8209 files = sorted(set(files))
Patrick Mezard
context: add memctx for memory commits
r6715 self._status = [files, [], [], [], []]
self._filectxfn = filectxfn
self._extra = extra and extra.copy() or {}
Patrick Mezard
memctx: simplify constructor
r14528 if self._extra.get('branch', '') == '':
Patrick Mezard
context: add memctx for memory commits
r6715 self._extra['branch'] = 'default'
def __str__(self):
return str(self._parents[0]) + "+"
Matt Mackall
context: add __int__ and hex methods
r6763 def __int__(self):
return self._rev
Patrick Mezard
context: add memctx for memory commits
r6715 def __nonzero__(self):
return True
Matt Mackall
filecommit: swallow some bits from _commitctx, add _
r8401 def __getitem__(self, key):
return self.filectx(key)
Matt Mackall
many, many trivial check-code fixups
r10282 def p1(self):
return self._parents[0]
def p2(self):
return self._parents[1]
Matt Mackall
context: add p1 and p2 methods
r8406
Matt Mackall
many, many trivial check-code fixups
r10282 def user(self):
return self._user or self._repo.ui.username()
def date(self):
return self._date
def description(self):
return self._text
def files(self):
return self.modified()
def modified(self):
return self._status[0]
def added(self):
return self._status[1]
def removed(self):
return self._status[2]
def deleted(self):
return self._status[3]
def unknown(self):
return self._status[4]
Steve Borho
workingctx: add explicit status method, add ignored and fix clean...
r11098 def ignored(self):
return self._status[5]
Matt Mackall
many, many trivial check-code fixups
r10282 def clean(self):
Steve Borho
workingctx: add explicit status method, add ignored and fix clean...
r11098 return self._status[6]
Matt Mackall
many, many trivial check-code fixups
r10282 def branch(self):
Matt Mackall
branch: operate on branch names in local string space where possible...
r13047 return encoding.tolocal(self._extra['branch'])
Matt Mackall
many, many trivial check-code fixups
r10282 def extra(self):
return self._extra
def flags(self, f):
return self[f].flags()
Patrick Mezard
context: add memctx for memory commits
r6715
def parents(self):
"""return contexts for each parent changeset"""
return self._parents
def filectx(self, path, filelog=None):
"""get a file context from the working directory"""
return self._filectxfn(self._repo, self, path)
Alexander Solovyov
slightly improve memctx api
r11151 def commit(self):
"""commit context to the repo"""
return self._repo.commitctx(self)
Patrick Mezard
context: add memctx for memory commits
r6715 class memfilectx(object):
Patrick Mezard
context: improve memctx documentation
r7077 """memfilectx represents an in-memory file to commit.
See memctx for more details.
Patrick Mezard
context: add memctx for memory commits
r6715 """
Alexander Solovyov
slightly improve memctx api
r11151 def __init__(self, path, data, islink=False, isexec=False, copied=None):
Patrick Mezard
context: improve memctx documentation
r7077 """
path is the normalized file path relative to repository root.
data is the file content as a string.
islink is True if the file is a symbolic link.
isexec is True if the file is executable.
copied is the source file path if current file was copied in the
revision being committed, or None."""
Patrick Mezard
context: add memctx for memory commits
r6715 self._path = path
self._data = data
self._flags = (islink and 'l' or '') + (isexec and 'x' or '')
self._copied = None
if copied:
self._copied = (copied, nullid)
Matt Mackall
many, many trivial check-code fixups
r10282 def __nonzero__(self):
return True
def __str__(self):
return "%s@%s" % (self.path(), self._changectx)
def path(self):
return self._path
def data(self):
return self._data
def flags(self):
return self._flags
def isexec(self):
return 'x' in self._flags
def islink(self):
return 'l' in self._flags
def renamed(self):
return self._copied