##// END OF EJS Templates
context: add an assertion checking linerange consistency in blockdescendants()...
context: add an assertion checking linerange consistency in blockdescendants() If this assertion fails, this indicates a flaw in the algorithm. So fail fast instead of possibly producing wrong results. Also extend the target line range in test to catch a merge changeset with all its parents.

File last commit:

r31991:55987fc8 default
r31991:55987fc8 default
Show More
context.py
2150 lines | 75.8 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
Gregory Szorc
context: use absolute_import
r27506 from __future__ import absolute_import
import errno
import os
Mads Kiilerich
context: don't hex encode all unknown 20 char revision specs (issue4890)...
r26604 import re
Gregory Szorc
context: use absolute_import
r27506 import stat
Mads Kiilerich
context: don't hex encode all unknown 20 char revision specs (issue4890)...
r26604
Gregory Szorc
context: use absolute_import
r27506 from .i18n import _
from .node import (
Durham Goode
dirstate: change added/modified placeholder hash length to 20 bytes...
r30361 addednodeid,
Gregory Szorc
context: use absolute_import
r27506 bin,
hex,
Durham Goode
dirstate: change added/modified placeholder hash length to 20 bytes...
r30361 modifiednodeid,
Gregory Szorc
context: use absolute_import
r27506 nullid,
nullrev,
short,
wdirid,
Durham Goode
status: handle more node indicators in buildstatus...
r31258 wdirnodes,
Gregory Szorc
context: use absolute_import
r27506 )
from . import (
encoding,
error,
fileset,
match as matchmod,
mdiff,
obsolete as obsmod,
patch,
phases,
Augie Fackler
context: work around `long` not existing on Python 3...
r31343 pycompat,
Gregory Szorc
context: use absolute_import
r27506 repoview,
revlog,
scmutil,
subrepo,
util,
)
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
Mads Kiilerich
context: don't hex encode all unknown 20 char revision specs (issue4890)...
r26604 nonascii = re.compile(r'[^\x21-\x7f]').search
Sean Farley
basectx: add an empty class that will be used as a parent of all contexts...
r19537 class basectx(object):
"""A basectx object represents the common logic for its children:
changectx: read-only context that is already present in the repo,
workingctx: a context that represents the working directory and can
be committed,
memctx: a context that represents changes in-memory and can also
be committed."""
def __new__(cls, repo, changeid='', *args, **kwargs):
Sean Farley
basectx: return a copied context if changeid is already a basectx...
r19538 if isinstance(changeid, basectx):
return changeid
o = super(basectx, cls).__new__(cls)
o._repo = repo
o._rev = nullrev
o._node = nullid
return o
Sean Farley
basectx: add an empty class that will be used as a parent of all contexts...
r19537
Sean Farley
basectx: move __str__ from changectx
r19540 def __str__(self):
Augie Fackler
context: implement both __bytes__ and __str__ for Python 3...
r31344 r = short(self.node())
if pycompat.ispy3:
return r.decode('ascii')
return r
def __bytes__(self):
Sean Farley
basectx: move __str__ from changectx
r19540 return short(self.node())
Sean Farley
basectx: move __int__ from changectx
r19545 def __int__(self):
return self.rev()
Sean Farley
basectx: move __repr__ from changectx...
r19546 def __repr__(self):
return "<%s %s>" % (type(self).__name__, str(self))
Sean Farley
basectx: move __eq__ from changectx...
r19547 def __eq__(self, other):
try:
return type(self) == type(other) and self._rev == other._rev
except AttributeError:
return False
Sean Farley
basectx: move __ne__ from changectx
r19548 def __ne__(self, other):
return not (self == other)
Sean Farley
basectx: move __contains__ from changectx
r19550 def __contains__(self, key):
return key in self._manifest
Sean Farley
basectx: move __getitem__ from changectx
r19551 def __getitem__(self, key):
return self.filectx(key)
Sean Farley
basectx: move __iter__ from changectx
r19552 def __iter__(self):
Augie Fackler
context: don't sort manifest entries...
r24227 return iter(self._manifest)
Sean Farley
basectx: move __iter__ from changectx
r19552
Durham Goode
context: remove uses of manifest.matches...
r31261 def _buildstatusmanifest(self, status):
"""Builds a manifest that includes the given status results, if this is
a working copy context. For non-working copy contexts, it just returns
the normal manifest."""
return self.manifest()
Siddharth Agarwal
context: generate filtered manifest efficiently for exact matchers...
r21880
Martin von Zweigbergk
context.status: remove unused arguments from _matchstatus()
r23237 def _matchstatus(self, other, match):
Sean Farley
basectx: add _matchstatus method for factoring out last of parentworking logic...
r21481 """return match.always if match is none
This internal method provides a way for child objects to override the
match operator.
"""
return match or matchmod.always(self._repo.root, self._repo.getcwd())
Sean Farley
context: add _buildstatus method...
r21471 def _buildstatus(self, other, s, match, listignored, listclean,
Sean Farley
context: fix wrong indentation from renaming method
r21663 listunknown):
Sean Farley
context: add _buildstatus method...
r21471 """build a status with respect to another context"""
Martin von Zweigbergk
context.status: explain "caching reasons" more fully...
r23257 # Load earliest manifest first for caching reasons. More specifically,
# if you have revisions 1000 and 1001, 1001 is probably stored as a
# delta against 1000. Thus, if you read 1000 first, we'll reconstruct
# 1000 and cache it so that when you read 1001, we just need to apply a
# delta to what's in the cache. So that's one full reconstruction + one
# delta application.
Durham Goode
context: remove assumptions about manifest creation during _buildstatus...
r31260 mf2 = None
Martin von Zweigbergk
context.status: move manifest caching trick to _buildstatus()...
r23238 if self.rev() is not None and self.rev() < other.rev():
Durham Goode
context: remove uses of manifest.matches...
r31261 mf2 = self._buildstatusmanifest(s)
mf1 = other._buildstatusmanifest(s)
Durham Goode
context: remove assumptions about manifest creation during _buildstatus...
r31260 if mf2 is None:
Durham Goode
context: remove uses of manifest.matches...
r31261 mf2 = self._buildstatusmanifest(s)
Sean Farley
context: add _buildstatus method...
r21471
Augie Fackler
context: use manifest.diff() to compute most of status...
r23755 modified, added = [], []
removed = []
Augie Fackler
context: use new manifest.diff(clean=True) support...
r23757 clean = []
Martin von Zweigbergk
context.status: pass status tuple into _buildstatus...
r23304 deleted, unknown, ignored = s.deleted, s.unknown, s.ignored
Martin von Zweigbergk
status: make 'hg status --rev' faster when there are deleted files...
r23085 deletedset = set(deleted)
Durham Goode
context: remove uses of manifest.matches...
r31261 d = mf1.diff(mf2, match=match, clean=listclean)
Augie Fackler
context: use new manifest.diff(clean=True) support...
r23757 for fn, value in d.iteritems():
Martin von Zweigbergk
status: don't list files as both clean and deleted...
r23731 if fn in deletedset:
continue
Augie Fackler
context: use new manifest.diff(clean=True) support...
r23757 if value is None:
clean.append(fn)
continue
(node1, flag1), (node2, flag2) = value
Augie Fackler
context: use manifest.diff() to compute most of status...
r23755 if node1 is None:
added.append(fn)
elif node2 is None:
removed.append(fn)
Martin von Zweigbergk
context: check for differing flags a little earlier...
r27749 elif flag1 != flag2:
modified.append(fn)
Durham Goode
status: handle more node indicators in buildstatus...
r31258 elif node2 not in wdirnodes:
Martin von Zweigbergk
context: clarify why we don't compare file contents when nodeid differs...
r27748 # When comparing files between two commits, we save time by
# not comparing the file contents when the nodeids differ.
# Note that this means we incorrectly report a reverted change
# to a file as a modification.
Martin von Zweigbergk
status: back out changeset 89f49813526c...
r27747 modified.append(fn)
Augie Fackler
context: use manifest.diff() to compute most of status...
r23755 elif self[fn].cmp(other[fn]):
modified.append(fn)
Martin von Zweigbergk
status: don't list files as both clean and deleted...
r23731 else:
Augie Fackler
context: use new manifest.diff(clean=True) support...
r23757 clean.append(fn)
Augie Fackler
context: use manifest.diff() to compute most of status...
r23755
Pierre-Yves David
status: explicitly exclude removed file from unknown and ignored...
r21971 if removed:
# need to filter files if they are already reported as removed
Durham Goode
context: remove uses of manifest.matches...
r31261 unknown = [fn for fn in unknown if fn not in mf1 and
(not match or match(fn))]
ignored = [fn for fn in ignored if fn not in mf1 and
(not match or match(fn))]
Martin von Zweigbergk
status: don't list files as both removed and deleted...
r23730 # if they're deleted, don't report them as removed
removed = [fn for fn in removed if fn not in deletedset]
Sean Farley
context: add _buildstatus method...
r21471
Martin von Zweigbergk
context.status: make _dirstatestatus() return an status tuple...
r23302 return scmutil.status(modified, added, removed, deleted, unknown,
ignored, clean)
Sean Farley
context: add _buildstatus method...
r21471
Sean Farley
basectx: move substate from changectx
r19549 @propertycache
def substate(self):
return subrepo.state(self, self._repo.ui)
Sean Farley
basectx: add subrev method to return the rev of a subrepo given a subpath...
r21586 def subrev(self, subpath):
return self.substate[subpath][1]
Sean Farley
basectx: move rev from changectx
r19541 def rev(self):
return self._rev
Sean Farley
basectx: move node from changectx
r19542 def node(self):
return self._node
Sean Farley
basectx: move hex from changectx
r19543 def hex(self):
Sean Farley
basectx: change _node to node() in hex...
r19544 return hex(self.node())
Sean Farley
basectx: move manifest from changectx
r19553 def manifest(self):
return self._manifest
Durham Goode
context: add manifestctx property on changectx...
r30344 def manifestctx(self):
return self._manifestctx
Matt Harbison
context: add a repo accessor...
r24300 def repo(self):
return self._repo
Sean Farley
basectx: move phasestr from changectx
r19554 def phasestr(self):
return phases.phasenames[self.phase()]
Sean Farley
basectx: move mutable from changectx
r19555 def mutable(self):
return self.phase() > phases.public
Sean Farley
basectx: move rev from changectx
r19541
Augie Fackler
context: add a getfileset() method so fewer things need fileset directly...
r20400 def getfileset(self, expr):
return fileset.getfileset(self, expr)
Sean Farley
context: move evolution functions from changectx to basectx...
r19734 def obsolete(self):
"""True if the changeset is obsolete"""
return self.rev() in obsmod.getrevs(self._repo, 'obsolete')
def extinct(self):
"""True if the changeset is extinct"""
return self.rev() in obsmod.getrevs(self._repo, 'extinct')
def unstable(self):
"""True if the changeset is not obsolete but it's ancestor are"""
return self.rev() in obsmod.getrevs(self._repo, 'unstable')
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')
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')
def troubled(self):
"""True if the changeset is either unstable, bumped or divergent"""
return self.unstable() or self.bumped() or self.divergent()
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
Sean Farley
basectx: move parents from changectx
r19556 def parents(self):
"""return contexts for each parent changeset"""
return self._parents
Sean Farley
basectx: move p1 from changectx
r19557 def p1(self):
return self._parents[0]
Sean Farley
basectx: move p2 from changectx
r19558 def p2(self):
Gregory Szorc
context: avoid extra parents lookups...
r27064 parents = self._parents
if len(parents) == 2:
return parents[1]
return changectx(self._repo, nullrev)
Sean Farley
basectx: move p2 from changectx
r19558
Sean Farley
basectx: move _fileinfo from changectx
r19559 def _fileinfo(self, path):
if '_manifest' in self.__dict__:
try:
return self._manifest[path], self._manifest.flags(path)
except KeyError:
raise error.ManifestLookupError(self._node, path,
_('not found in manifest'))
if '_manifestdelta' in self.__dict__ or path in self.files():
if path in self._manifestdelta:
return (self._manifestdelta[path],
self._manifestdelta.flags(path))
Durham Goode
manifest: remove manifest.find...
r30340 mfl = self._repo.manifestlog
try:
node, flag = mfl[self._changeset.manifest].find(path)
except KeyError:
Sean Farley
basectx: move _fileinfo from changectx
r19559 raise error.ManifestLookupError(self._node, path,
_('not found in manifest'))
return node, flag
Sean Farley
basectx: move filenode from changectx
r19560 def filenode(self, path):
return self._fileinfo(path)[0]
Sean Farley
basectx: move flags from changectx
r19561 def flags(self, path):
try:
return self._fileinfo(path)[1]
except error.LookupError:
return ''
Matt Harbison
verify: don't init subrepo when missing one is referenced (issue5128) (API)...
r29021 def sub(self, path, allowcreate=True):
Matt Harbison
subrepo: allow a representation of the working directory subrepo...
r25600 '''return a subrepo for the stored revision of path, never wdir()'''
Matt Harbison
verify: don't init subrepo when missing one is referenced (issue5128) (API)...
r29021 return subrepo.subrepo(self, path, allowcreate=allowcreate)
Sean Farley
basectx: move sub from changectx
r19562
Matt Harbison
context: introduce the nullsub() method...
r25417 def nullsub(self, path, pctx):
return subrepo.nullsubrepo(self, path, pctx)
Matt Harbison
subrepo: allow a representation of the working directory subrepo...
r25600 def workingsub(self, path):
'''return a subrepo for the stored revision, or wdir if this is a wdir
context.
'''
return subrepo.subrepo(self, path, allowwdir=True)
Gregory Szorc
context: don't use mutable default argument value...
r31388 def match(self, pats=None, include=None, exclude=None, default='glob',
Matt Harbison
context: add an optional constructor parameter for a match.bad() override...
r25465 listsubrepos=False, badfn=None):
Pierre-Yves David
context: explicitly tests for None...
r31437 if pats is None:
pats = []
Sean Farley
basectx: move match from changectx
r19563 r = self._repo
Pierre-Yves David
context: explicitly tests for None...
r31437 return matchmod.match(r.root, r.getcwd(), pats,
Sean Farley
basectx: move match from changectx
r19563 include, exclude, default,
Pierre-Yves David
context: use a the nofsauditor when matching file in history (issue4749)...
r27234 auditor=r.nofsauditor, ctx=self,
Matt Harbison
context: add an optional constructor parameter for a match.bad() override...
r25465 listsubrepos=listsubrepos, badfn=badfn)
Sean Farley
basectx: move match from changectx
r19563
Sean Farley
basectx: move diff from changectx
r19564 def diff(self, ctx2=None, match=None, **opts):
"""Returns a diff generator for the given contexts and matcher"""
if ctx2 is None:
ctx2 = self.p1()
Sean Farley
basectx: remove unnecessary check of instance...
r19568 if ctx2 is not None:
Sean Farley
basectx: move diff from changectx
r19564 ctx2 = self._repo[ctx2]
diffopts = patch.diffopts(self._repo.ui, opts)
Sean Farley
basectx: pass raw context objects to patch.diff
r21834 return patch.diff(self._repo, ctx2, self, match=match, opts=diffopts)
Sean Farley
basectx: move diff from changectx
r19564
Drew Gottlieb
manifest: have context's dirs() call its manifest's dirs()...
r24323 def dirs(self):
return self._manifest.dirs()
Sean Farley
basectx: move _dirs from changectx
r19565
Drew Gottlieb
manifest: add hasdir() to context...
r24325 def hasdir(self, dir):
return self._manifest.hasdir(dir)
Sean Farley
basectx: move dirs from changectx
r19566
Sean Farley
basectx: add missing, merge, and branch args to dirty method...
r22055 def dirty(self, missing=False, merge=True, branch=True):
Sean Farley
basectx: move dirty from changectx
r19567 return False
Sean Farley
basectx: copy localrepo.status method...
r21594 def status(self, other=None, match=None, listignored=False,
listclean=False, listunknown=False, listsubrepos=False):
"""return status of files between two nodes or node and working
directory.
If other is None, compare this node with working directory.
Pierre-Yves David
status: document the content of the returned tuple in the docstring...
r21722
returns (modified, added, removed, deleted, unknown, ignored, clean)
Sean Farley
basectx: copy localrepo.status method...
r21594 """
ctx1 = self
ctx2 = self._repo[other]
# This next code block is, admittedly, fragile logic that tests for
# reversing the contexts and wouldn't need to exist if it weren't for
# the fast (and common) code path of comparing the working directory
# with its first parent.
#
# What we're aiming for here is the ability to call:
#
# workingctx.status(parentctx)
#
# If we always built the manifest for each context and compared those,
# then we'd be done. But the special case of the above call means we
# just copy the manifest of the parent.
reversed = False
if (not isinstance(ctx1, changectx)
and isinstance(ctx2, changectx)):
reversed = True
ctx1, ctx2 = ctx2, ctx1
Martin von Zweigbergk
context.status: remove unused arguments from _matchstatus()
r23237 match = ctx2._matchstatus(ctx1, match)
Martin von Zweigbergk
context.status: pass status tuple into _buildstatus...
r23304 r = scmutil.status([], [], [], [], [], [], [])
Sean Farley
basectx: copy localrepo.status method...
r21594 r = ctx2._buildstatus(ctx1, r, match, listignored, listclean,
Sean Farley
context: fix wrong indentation from renaming method
r21663 listunknown)
Sean Farley
basectx: copy localrepo.status method...
r21594
if reversed:
Martin von Zweigbergk
context.status: wipe deleted/unknown/ignored fields when reversed...
r23301 # Reverse added and removed. Clear deleted, unknown and ignored as
# these make no sense to reverse.
r = scmutil.status(r.modified, r.removed, r.added, [], [], [],
r.clean)
Sean Farley
basectx: copy localrepo.status method...
r21594
if listsubrepos:
for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
try:
Andrew Zwicky
extdiff: correctly handle deleted subrepositories (issue3153)...
r27183 rev2 = ctx2.subrev(subpath)
except KeyError:
# A subrepo that existed in node1 was deleted between
# node1 and node2 (inclusive). Thus, ctx2's substate
# won't contain that subpath. The best we can do ignore it.
rev2 = None
Martin von Zweigbergk
match: rename "narrowmatcher" to "subdirmatcher" (API)...
r28017 submatch = matchmod.subdirmatcher(subpath, match)
Andrew Zwicky
extdiff: correctly handle deleted subrepositories (issue3153)...
r27183 s = sub.status(rev2, match=submatch, ignored=listignored,
clean=listclean, unknown=listunknown,
listsubrepos=True)
for rfiles, sfiles in zip(r, s):
rfiles.extend("%s/%s" % (subpath, f) for f in sfiles)
Sean Farley
basectx: copy localrepo.status method...
r21594
for l in r:
l.sort()
Sean Farley
context: explicitly return a tuple...
r21616
Martin von Zweigbergk
context.status: wipe deleted/unknown/ignored fields when reversed...
r23301 return r
Sean Farley
basectx: copy localrepo.status method...
r21594
Augie Fackler
makememctx: move from patch to context to break import cycle
r20035 def makememctx(repo, parents, text, user, date, branch, files, store,
Laurent Charignon
patch: add 'extra' argument to makememctx...
r25303 editor=None, extra=None):
Augie Fackler
makememctx: move from patch to context to break import cycle
r20035 def getfilectx(repo, memctx, path):
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 data, mode, copied = store.getfile(path)
if data is None:
return None
islink, isexec = mode
Sean Farley
memfilectx: call super.__init__ instead of duplicating code...
r21689 return memfilectx(repo, path, data, islink=islink, isexec=isexec,
copied=copied, memctx=memctx)
Laurent Charignon
patch: add 'extra' argument to makememctx...
r25303 if extra is None:
extra = {}
Augie Fackler
makememctx: move from patch to context to break import cycle
r20035 if branch:
extra['branch'] = encoding.fromlocal(branch)
timeless
cleanup: remove superfluous space after space after equals (python)
r27637 ctx = memctx(repo, parents, text, files, getfilectx, user,
date, extra, editor)
Augie Fackler
makememctx: move from patch to context to break import cycle
r20035 return ctx
Sean Farley
basectx: add an empty class that will be used as a parent of all contexts...
r19537 class changectx(basectx):
Matt Mackall
Add context.py: changeset and file revision contexts
r2563 """A changecontext object makes access to data related to a particular
Mads Kiilerich
spelling: random spell checker fixes
r19951 changeset convenient. It represents a read-only context already present in
Sean Farley
basectx: add an empty class that will be used as a parent of all contexts...
r19537 the repo."""
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"""
Sean Farley
changectx: if passing a basectx then exit __init__ immediately
r19539
# since basectx.__new__ already took care of copying the object, we
# don't need to do anything in __init__, so we just exit here
if isinstance(changeid, basectx):
return
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
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 try:
if isinstance(changeid, int):
Pierre-Yves David
changectx: move `IndexError` handling in the top level try except...
r23013 self._node = repo.changelog.node(changeid)
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 self._rev = changeid
return
Augie Fackler
context: work around `long` not existing on Python 3...
r31343 if not pycompat.ispy3 and isinstance(changeid, long):
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 changeid = str(changeid)
if changeid == 'null':
self._node = nullid
self._rev = nullrev
return
if changeid == 'tip':
self._node = repo.changelog.tip()
self._rev = repo.changelog.rev(self._node)
return
Martin von Zweigbergk
context: use unfiltered repo for '.'...
r24050 if changeid == '.' or changeid == repo.dirstate.p1():
# this is a hack to delay/avoid loading obsmarkers
# when we know that '.' won't be hidden
self._node = repo.dirstate.p1()
self._rev = repo.unfiltered().changelog.rev(self._node)
return
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 if len(changeid) == 20:
try:
self._node = changeid
self._rev = repo.changelog.rev(changeid)
return
Pierre-Yves David
changectx: issue a FilteredRepoLookupError when applicable...
r23017 except error.FilteredRepoLookupError:
raise
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 except LookupError:
pass
Pierre-Yves David
clfilter: ensure context raise RepoLookupError when the revision is filtered...
r18084 try:
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 r = int(changeid)
Augie Fackler
context: use portable construction to verify int parsing
r31351 if '%d' % r != changeid:
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 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)
Matt Mackall
context: internalize lookup logic...
r16376 return
Pierre-Yves David
changectx: issue a FilteredRepoLookupError when applicable...
r23017 except error.FilteredIndexError:
raise
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 except (ValueError, OverflowError, IndexError):
Matt Mackall
context: internalize lookup logic...
r16376 pass
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 if len(changeid) == 40:
try:
self._node = bin(changeid)
self._rev = repo.changelog.rev(self._node)
return
Pierre-Yves David
changectx: issue a FilteredRepoLookupError when applicable...
r23017 except error.FilteredLookupError:
raise
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 except (TypeError, LookupError):
pass
Matt Mackall
context: internalize lookup logic...
r16376
Sean Farley
changectx: use names api to simplify and extend node lookup...
r23560 # lookup bookmarks through the name interface
try:
Ryan McElroy
namespaces: remove weakref; always pass in repo...
r23561 self._node = repo.names.singlenode(repo, changeid)
Matt Mackall
context: internalize lookup logic...
r16376 self._rev = repo.changelog.rev(self._node)
return
Sean Farley
changectx: use names api to simplify and extend node lookup...
r23560 except KeyError:
pass
Pierre-Yves David
changectx: issue a FilteredRepoLookupError when applicable...
r23017 except error.FilteredRepoLookupError:
raise
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 except error.RepoLookupError:
Matt Mackall
context: internalize lookup logic...
r16376 pass
Pierre-Yves David
changectx: issue a FilteredRepoLookupError when applicable...
r23017 self._node = repo.unfiltered().changelog._partialmatch(changeid)
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 if self._node is not None:
self._rev = repo.changelog.rev(self._node)
return
Matt Mackall
context: internalize lookup logic...
r16376
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 # lookup failed
# check if it might have come from damaged dirstate
#
# XXX we could avoid the unfiltered if we had a recognizable
# exception for filtered changeset access
if changeid in repo.unfiltered().dirstate.parents():
msg = _("working directory has unknown parent '%s'!")
raise error.Abort(msg % short(changeid))
try:
Mads Kiilerich
context: don't hex encode all unknown 20 char revision specs (issue4890)...
r26604 if len(changeid) == 20 and nonascii(changeid):
Pierre-Yves David
changectx: wrap the `changeid` processing in a try/except...
r23012 changeid = hex(changeid)
except TypeError:
pass
Pierre-Yves David
changectx: issue a FilteredRepoLookupError when applicable...
r23017 except (error.FilteredIndexError, error.FilteredLookupError,
error.FilteredRepoLookupError):
Laurent Charignon
context: make warning message for hidden revision extensible...
r24922 if repo.filtername.startswith('visible'):
Pierre-Yves David
repoview: issue a special message when filtering hidden changesets...
r23046 msg = _("hidden revision '%s'") % changeid
hint = _('use --hidden to access hidden revisions')
raise error.FilteredRepoLookupError(msg, hint=hint)
Pierre-Yves David
repoview: include the filter name in filtered revision error messages...
r23045 msg = _("filtered revision '%s' (not in '%s' subset)")
msg %= (changeid, repo.filtername)
raise error.FilteredRepoLookupError(msg)
Pierre-Yves David
changectx: move `IndexError` handling in the top level try except...
r23013 except IndexError:
pass
Matt Mackall
context: internalize lookup logic...
r16376 raise error.RepoLookupError(
_("unknown revision '%s'") % changeid)
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
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
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
Gregory Szorc
py3: add __bool__ to every class defining __nonzero__...
r31476 __bool__ = __nonzero__
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):
Gregory Szorc
context: use changelogrevision...
r28488 return self._repo.changelog.changelogrevision(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):
Durham Goode
context: add manifestctx property on changectx...
r30344 return self._manifestctx.read()
@propertycache
def _manifestctx(self):
return self._repo.manifestlog[self._changeset.manifest]
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 _manifestdelta(self):
Durham Goode
context: add manifestctx property on changectx...
r30344 return self._manifestctx.readdelta()
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 _parents(self):
Gregory Szorc
context: optimize _parents()...
r27063 repo = self._repo
p1, p2 = repo.changelog.parentrevs(self._rev)
if p2 == nullrev:
return [changectx(repo, p1)]
return [changectx(repo, p1), changectx(repo, p2)]
Matt Mackall
contexts: use __getattr__ rather than try/except in changectx
r3215
Matt Mackall
many, many trivial check-code fixups
r10282 def changeset(self):
Gregory Szorc
context: use changelogrevision...
r28488 c = self._changeset
return (
c.manifest,
c.user,
c.date,
c.files,
c.description,
c.extra,
)
Matt Mackall
many, many trivial check-code fixups
r10282 def manifestnode(self):
Gregory Szorc
context: use changelogrevision...
r28488 return self._changeset.manifest
Matt Mackall
Add context.py: changeset and file revision contexts
r2563
Matt Mackall
many, many trivial check-code fixups
r10282 def user(self):
Gregory Szorc
context: use changelogrevision...
r28488 return self._changeset.user
Matt Mackall
many, many trivial check-code fixups
r10282 def date(self):
Gregory Szorc
context: use changelogrevision...
r28488 return self._changeset.date
Matt Mackall
many, many trivial check-code fixups
r10282 def files(self):
Gregory Szorc
context: use changelogrevision...
r28488 return self._changeset.files
Matt Mackall
many, many trivial check-code fixups
r10282 def description(self):
Gregory Szorc
context: use changelogrevision...
r28488 return self._changeset.description
Matt Mackall
many, many trivial check-code fixups
r10282 def branch(self):
Gregory Szorc
context: use changelogrevision...
r28488 return encoding.tolocal(self._changeset.extra.get("branch"))
Brodie Rao
context: add changectx.closesbranch() method...
r16720 def closesbranch(self):
Gregory Szorc
context: use changelogrevision...
r28488 return 'close' in self._changeset.extra
Matt Mackall
many, many trivial check-code fixups
r10282 def extra(self):
Gregory Szorc
context: use changelogrevision...
r28488 return self._changeset.extra
Matt Mackall
many, many trivial check-code fixups
r10282 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
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 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)
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
ancestor: silence multiple ancestor warning outside of merge (issue4234)...
r21203 def ancestor(self, c2, warn=False):
Mads Kiilerich
comments: describe ancestor consistently - avoid 'least common ancestor'...
r22389 """return the "best" ancestor context of self and c2
If there are multiple candidates, it will show a message and check
merge.preferancestor configuration before falling back to the
revlog ancestor."""
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
Mads Kiilerich
context: tell when .ancestor picks one of multiple common ancestors heads...
r21125 cahs = self._repo.changelog.commonancestorsheads(self._node, n2)
if not cahs:
anc = nullid
elif len(cahs) == 1:
anc = cahs[0]
else:
Matt Mackall
merge: make merge.preferancestor type and default consistent...
r25844 # experimental config: merge.preferancestor
for r in self._repo.ui.configlist('merge', 'preferancestor', ['*']):
Mads Kiilerich
changectx: skip all invalid merge.preferancestor values...
r22671 try:
ctx = changectx(self._repo, r)
except error.RepoLookupError:
Mads Kiilerich
changectx: ancestor should only prefer merge.preferancestor if it is a revision...
r22180 continue
Mads Kiilerich
context: introduce merge.preferancestor for controlling which ancestor to pick...
r21126 anc = ctx.node()
if anc in cahs:
break
else:
anc = self._repo.changelog.ancestor(self._node, n2)
Matt Mackall
ancestor: silence multiple ancestor warning outside of merge (issue4234)...
r21203 if warn:
self._repo.ui.status(
(_("note: using %s as ancestor of %s and %s\n") %
(short(anc), short(self._node), short(n2))) +
''.join(_(" alternatively, use --config "
"merge.preferancestor=%s\n") %
short(n) for n in sorted(cahs) if n != anc))
Mads Kiilerich
context: tell when .ancestor picks one of multiple common ancestors heads...
r21125 return changectx(self._repo, anc)
Matt Mackall
changectx: add ancestor function
r3125
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):
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646 '''Generates matching file names.'''
Durham Goode
changectx: increase perf of walk function...
r20292
Matt Harbison
context: replace match.bad() monkey patching with match.badmatch()...
r25435 # Wrap match.bad method to have message with nodeid
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646 def bad(fn, msg):
Matt Harbison
context: don't complain about a matcher's subrepo paths in changectx.walk()...
r25193 # The manifest doesn't know about subrepos, so don't complain about
# paths into valid subrepos.
Matt Mackall
merge with stable
r25195 if any(fn == s or fn.startswith(s + '/')
for s in self.substate):
Matt Harbison
context: don't complain about a matcher's subrepo paths in changectx.walk()...
r25193 return
Matt Harbison
context: replace match.bad() monkey patching with match.badmatch()...
r25435 match.bad(fn, _('no such file in rev %s') % self)
Durham Goode
changectx: increase perf of walk function...
r20292
Matt Harbison
context: replace match.bad() monkey patching with match.badmatch()...
r25435 m = matchmod.badmatch(match, bad)
return self._manifest.walk(m)
Matt Mackall
context: add walk method
r6764
Siddharth Agarwal
context: add a method to efficiently filter by match if possible...
r21985 def matches(self, match):
return self.walk(match)
Sean Farley
basefilectx: add an empty class that will be used as a parent of file contexts...
r19572 class basefilectx(object):
"""A filecontext object represents the common logic for its children:
filectx: read-only access to a filerevision that is already present
in the repo,
workingfilectx: a filecontext that represents files from the working
directory,
memfilectx: a filecontext that represents files in-memory."""
def __new__(cls, repo, path, *args, **kwargs):
return super(basefilectx, cls).__new__(cls)
Sean Farley
basefilectx: move _filelog from filectx
r19573 @propertycache
def _filelog(self):
return self._repo.file(self._path)
Sean Farley
basefilectx: move _changeid from filectx
r19574 @propertycache
def _changeid(self):
if '_changeid' in self.__dict__:
return self._changeid
elif '_changectx' in self.__dict__:
return self._changectx.rev()
Matt Mackall
filectx: if we have a _descendantrev, use it to adjust linkrev...
r23983 elif '_descendantrev' in self.__dict__:
# this file context was created from a revision with a known
# descendant, we can (lazily) correct for linkrev aliases
Jun Wu
adjustlinkrev: remove unnecessary parameters...
r30275 return self._adjustlinkrev(self._descendantrev)
Sean Farley
basefilectx: move _changeid from filectx
r19574 else:
return self._filelog.linkrev(self._filerev)
Sean Farley
basefilectx: move _filenode from filectx
r19575 @propertycache
def _filenode(self):
if '_fileid' in self.__dict__:
return self._filelog.lookup(self._fileid)
else:
return self._changectx.filenode(self._path)
Sean Farley
basefilectx: move _filerev from filectx
r19576 @propertycache
def _filerev(self):
return self._filelog.rev(self._filenode)
Sean Farley
basefilectx: move _repopath from filectx
r19577 @propertycache
def _repopath(self):
return self._path
Sean Farley
basefilectx: move __nonzero__ from filectx
r19578 def __nonzero__(self):
try:
self._filenode
return True
except error.LookupError:
# file is missing
return False
Gregory Szorc
py3: add __bool__ to every class defining __nonzero__...
r31476 __bool__ = __nonzero__
Sean Farley
basefilectx: move __str__ from filectx
r19579 def __str__(self):
Mads Kiilerich
context: make sure __str__ works, also when there is no _changectx...
r30270 try:
return "%s@%s" % (self.path(), self._changectx)
except error.LookupError:
return "%s@???" % self.path()
Sean Farley
basefilectx: move __str__ from filectx
r19579
Sean Farley
basefilectx: move __repr__ from filectx...
r19580 def __repr__(self):
return "<%s %s>" % (type(self).__name__, str(self))
Sean Farley
basefilectx: move __hash__ from filectx
r19581 def __hash__(self):
try:
return hash((self._path, self._filenode))
except AttributeError:
return id(self)
Sean Farley
basefilectx: move __eq__ from filectx...
r19582 def __eq__(self, other):
try:
return (type(self) == type(other) and self._path == other._path
and self._filenode == other._filenode)
except AttributeError:
return False
Sean Farley
basefilectx: move __ne__ from filectx
r19583 def __ne__(self, other):
return not (self == other)
Sean Farley
basefilectx: move filerev from filectx
r19584 def filerev(self):
return self._filerev
Sean Farley
basefilectx: move filenode from filectx
r19585 def filenode(self):
return self._filenode
Sean Farley
basefilectx: move flags from filectx
r19586 def flags(self):
return self._changectx.flags(self._path)
Sean Farley
basefilectx: move filelog from filectx
r19587 def filelog(self):
return self._filelog
Sean Farley
basefilectx: move rev from filectx
r19588 def rev(self):
return self._changeid
Sean Farley
basefilectx: move linkrev from filectx
r19589 def linkrev(self):
return self._filelog.linkrev(self._filerev)
Sean Farley
basefilectx: move node from filectx
r19590 def node(self):
return self._changectx.node()
Sean Farley
basefilectx: move hex from filectx...
r19591 def hex(self):
return self._changectx.hex()
Sean Farley
basefilectx: move user from filectx
r19592 def user(self):
return self._changectx.user()
Sean Farley
basefilectx: move date from filectx
r19593 def date(self):
return self._changectx.date()
Sean Farley
basefilectx: move files from filectx
r19594 def files(self):
return self._changectx.files()
Sean Farley
basefilectx: move description from filectx
r19595 def description(self):
return self._changectx.description()
Sean Farley
basefilectx: move branch from filectx
r19596 def branch(self):
return self._changectx.branch()
Sean Farley
basefilectx: move extra from filectx
r19597 def extra(self):
return self._changectx.extra()
Sean Farley
basefilectx: move phase from filectx
r19598 def phase(self):
return self._changectx.phase()
Sean Farley
basefilectx: move phasestr from filectx
r19599 def phasestr(self):
return self._changectx.phasestr()
Sean Farley
basefilectx: move manifest from filectx
r19600 def manifest(self):
return self._changectx.manifest()
Sean Farley
basefilectx: move changectx from filectx
r19601 def changectx(self):
return self._changectx
Matt Harbison
filectx: add a repo accessor...
r24333 def repo(self):
return self._repo
Sean Farley
basefilectx: move filerev from filectx
r19584
Sean Farley
basefilectx: move path from filectx
r19602 def path(self):
return self._path
Sean Farley
basefilectx: move isbinary from filectx
r19603 def isbinary(self):
try:
return util.binary(self.data())
except IOError:
return False
Sean Farley
basefilectx: move isexec and islink from memfilectx...
r22054 def isexec(self):
return 'x' in self.flags()
def islink(self):
return 'l' in self.flags()
Sean Farley
basefilectx: move isbinary from filectx
r19603
Siddharth Agarwal
filectx: add isabsent method...
r26978 def isabsent(self):
"""whether this filectx represents a file not in self._changectx
This is mainly for merge code to detect change/delete conflicts. This is
expected to be True for all subclasses of basectx."""
return False
Siddharth Agarwal
filectx: allow custom comparators...
r26977 _customcmp = False
Sean Farley
basefilectx: move cmp from filectx
r19604 def cmp(self, fctx):
"""compare with other file context
returns True if different than fctx.
"""
Siddharth Agarwal
filectx: allow custom comparators...
r26977 if fctx._customcmp:
return fctx.cmp(self)
Durham Goode
filectx: replace use of _filerev with _filenode...
r28116 if (fctx._filenode is None
Sean Farley
basefilectx: move cmp from filectx
r19604 and (self._repo._encodefilterpats
# if file data starts with '\1\n', empty metadata block is
# prepended, which adds 4 bytes to filelog.size().
or self.size() - 4 == fctx.size())
or self.size() == fctx.size()):
return self._filelog.cmp(self._filenode, fctx.data())
return True
Jun Wu
adjustlinkrev: remove unnecessary parameters...
r30275 def _adjustlinkrev(self, srcrev, inclusive=False):
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r24180 """return the first ancestor of <srcrev> introducing <fnode>
Pierre-Yves David
filectx: move _adjustlinkrev to a method...
r23979
If the linkrev of the file revision does not point to an ancestor of
srcrev, we'll walk down the ancestors until we find one introducing
this file revision.
:srcrev: the changeset revision we search ancestors from
:inclusive: if true, the src revision will also be checked
"""
repo = self._repo
cl = repo.unfiltered().changelog
Durham Goode
manifest: adds manifestctx.readfast...
r29939 mfl = repo.manifestlog
Pierre-Yves David
filectx: move _adjustlinkrev to a method...
r23979 # fetch the linkrev
Jun Wu
adjustlinkrev: remove unnecessary parameters...
r30275 lkr = self.linkrev()
Pierre-Yves David
_adjustlinkrev: reuse ancestors set during rename detection (issue4514)...
r23980 # hack to reuse ancestor computation when searching for renames
memberanc = getattr(self, '_ancestrycontext', None)
iteranc = None
Pierre-Yves David
adjustlinkrev: handle 'None' value as source...
r24411 if srcrev is None:
# wctx case, used by workingfilectx during mergecopy
revs = [p.rev() for p in self._repo[None].parents()]
inclusive = True # we skipped the real (revless) source
else:
revs = [srcrev]
Pierre-Yves David
_adjustlinkrev: reuse ancestors set during rename detection (issue4514)...
r23980 if memberanc is None:
Pierre-Yves David
adjustlinkrev: handle 'None' value as source...
r24411 memberanc = iteranc = cl.ancestors(revs, lkr,
inclusive=inclusive)
Pierre-Yves David
filectx: move _adjustlinkrev to a method...
r23979 # check if this linkrev is an ancestor of srcrev
Pierre-Yves David
_adjustlinkrev: reuse ancestors set during rename detection (issue4514)...
r23980 if lkr not in memberanc:
if iteranc is None:
Pierre-Yves David
adjustlinkrev: prepare source revs for ancestry only once...
r24410 iteranc = cl.ancestors(revs, lkr, inclusive=inclusive)
Jun Wu
adjustlinkrev: remove unnecessary parameters...
r30275 fnode = self._filenode
path = self._path
Pierre-Yves David
_adjustlinkrev: reuse ancestors set during rename detection (issue4514)...
r23980 for a in iteranc:
Pierre-Yves David
filectx: move _adjustlinkrev to a method...
r23979 ac = cl.read(a) # get changeset data (we avoid object creation)
if path in ac[3]: # checking the 'files' field.
# The file has been touched, check if the content is
# similar to the one we search for.
Durham Goode
manifest: adds manifestctx.readfast...
r29939 if fnode == mfl[ac[0]].readfast().get(path):
Pierre-Yves David
filectx: move _adjustlinkrev to a method...
r23979 return a
# In theory, we should never get out of that loop without a result.
# But if manifest uses a buggy file revision (not children of the
# one it replaces) we could. Such a buggy situation will likely
# result is crash somewhere else at to some point.
return lkr
Pierre-Yves David
linkrev: introduce an 'introrev' method on filectx...
r23703 def introrev(self):
"""return the rev of the changeset which introduced this file revision
This method is different from linkrev because it take into account the
changeset the filectx was created from. It ensures the returned
revision is one of its ancestors. This prevents bugs from
'linkrev-shadowing' when a file revision is used by multiple
changesets.
"""
lkr = self.linkrev()
attrs = vars(self)
noctx = not ('_changeid' in attrs or '_changectx' in attrs)
if noctx or self.rev() == lkr:
return self.linkrev()
Jun Wu
adjustlinkrev: remove unnecessary parameters...
r30275 return self._adjustlinkrev(self.rev(), inclusive=True)
Pierre-Yves David
linkrev: introduce an 'introrev' method on filectx...
r23703
Yuya Nishihara
filectx: extract function to create parent fctx keeping ancestry info...
r24816 def _parentfilectx(self, path, fileid, filelog):
"""create parent filectx keeping ancestry info for _adjustlinkrev()"""
fctx = filectx(self._repo, path, fileid=fileid, filelog=filelog)
if '_changeid' in vars(self) or '_changectx' in vars(self):
# If self is associated with a changeset (probably explicitly
# fed), ensure the created filectx is associated with a
# changeset that is an ancestor of self.changectx.
# This lets us later use _adjustlinkrev to get a correct link.
fctx._descendantrev = self.rev()
fctx._ancestrycontext = getattr(self, '_ancestrycontext', None)
elif '_descendantrev' in vars(self):
# Otherwise propagate _descendantrev if we have one associated.
fctx._descendantrev = self._descendantrev
fctx._ancestrycontext = getattr(self, '_ancestrycontext', None)
return fctx
Sean Farley
basefilectx: move parents from filectx
r19605 def parents(self):
Mads Kiilerich
cleanup: fix some list comprehension redefinitions of existing vars...
r22201 _path = self._path
Sean Farley
basefilectx: move parents from filectx
r19605 fl = self._filelog
Pierre-Yves David
filectx.parents: filter nullrev parent sooner...
r23688 parents = self._filelog.parents(self._filenode)
pl = [(_path, node, fl) for node in parents if node != nullid]
Sean Farley
basefilectx: move parents from filectx
r19605
Pierre-Yves David
filectx.parents: enforce changeid of parent to be in own changectx ancestors...
r23702 r = fl.renamed(self._filenode)
Sean Farley
basefilectx: move parents from filectx
r19605 if r:
Pierre-Yves David
filectx.parents: filter nullrev parent sooner...
r23688 # - In the simple rename case, both parent are nullid, pl is empty.
# - In case of merge, only one of the parent is null id and should
# be replaced with the rename information. This parent is -always-
# the first one.
#
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r24180 # As null id have always been filtered out in the previous list
Pierre-Yves David
filectx.parents: filter nullrev parent sooner...
r23688 # comprehension, inserting to 0 will always result in "replacing
# first nullid parent with rename information.
Pierre-Yves David
filectx.parents: also fetch the filelog of rename source too...
r23699 pl.insert(0, (r[0], r[1], self._repo.file(r[0])))
Sean Farley
basefilectx: move parents from filectx
r19605
Yuya Nishihara
filectx: extract function to create parent fctx keeping ancestry info...
r24816 return [self._parentfilectx(path, fnode, l) for path, fnode, l in pl]
Sean Farley
basefilectx: move parents from filectx
r19605
Sean Farley
basefilectx: move p1 from filectx
r19606 def p1(self):
return self.parents()[0]
Sean Farley
basefilectx: move p2 from filectx
r19607 def p2(self):
p = self.parents()
if len(p) == 2:
return p[1]
return filectx(self._repo, self._path, fileid=-1, filelog=self._filelog)
Denis Laxalde
context: eliminate handling of linenumber being None in annotate...
r29527 def annotate(self, follow=False, linenumber=False, diffopts=None):
'''returns a list of tuples of ((ctx, number), line) for each line
Brendan Cully
Refactor annotate copy support.
r3172 in the file, where ctx is the filectx of the node where
Denis Laxalde
context: eliminate handling of linenumber being None in annotate...
r29527 that line was last changed; if linenumber parameter is true, number is
the line number at the first appearance in the managed file, otherwise,
number has a fixed value of False.
'''
Brendan Cully
Refactor annotate copy support.
r3172
Matt Mackall
annotate: optimize line counting...
r29223 def lines(text):
if text.endswith("\n"):
return text.count("\n")
Jun Wu
annotate: calculate line count correctly...
r30040 return text.count("\n") + int(bool(text))
Matt Mackall
annotate: optimize line counting...
r29223
Denis Laxalde
context: eliminate handling of linenumber being None in annotate...
r29527 if linenumber:
Yuya Nishihara
annotate: inline definition of decorate() functions
r22192 def decorate(text, rev):
Matt Mackall
annotate: optimize line counting...
r29223 return ([(rev, i) for i in xrange(1, lines(text) + 1)], text)
Yuya Nishihara
annotate: rewrite long short-circuit statement by if-elif-else
r22191 else:
Yuya Nishihara
annotate: inline definition of decorate() functions
r22192 def decorate(text, rev):
Matt Mackall
annotate: optimize line counting...
r29223 return ([(rev, False)] * lines(text), text)
FUJIWARA Katsunori
Allow filectx.annotate to return the line number of first appearance.
r4856
Brendan Cully
Refactor annotate copy support.
r3172 def pair(parent, child):
Philippe Pepiot
mdiff: remove unused parameter 'refine' from allblocks()
r30023 blocks = mdiff.allblocks(parent[1], child[1], opts=diffopts)
Patrick Mezard
annotate: support diff whitespace filtering flags (issue3030)...
r15528 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 parents(f):
Yuya Nishihara
annotate: always adjust linkrev before walking down to parents (issue4623)...
r24862 # Cut _descendantrev here to mitigate the penalty of lazy linkrev
# adjustment. Otherwise, p._adjustlinkrev() would walk changelog
# from the topmost introrev (= srcrev) down to p.linkrev() if it
# isn't an ancestor of the srcrev.
f._changeid
Durham Goode
annotate: simplify annotate parent function...
r19292 pl = f.parents()
# Don't return renamed parents if we aren't following.
if not follow:
pl = [p for p in pl if p.path() == f.path()]
Brendan Cully
Refactor annotate copy support.
r3172
Durham Goode
annotate: simplify annotate parent function...
r19292 # renamed filectx won't have a filelog yet, so set it
# from the cache to save time
for p in pl:
if not '_filelog' in p.__dict__:
p._filelog = getlog(p.path())
Brendan Cully
filectx.annotate: return filectx for each line instead of rev
r3146
Durham Goode
annotate: simplify annotate parent function...
r19292 return pl
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
Pierre-Yves David
linkrev: also adjust linkrev when bootstrapping annotate (issue4305)...
r23705 base = self
introrev = self.introrev()
if self.rev() != introrev:
Durham Goode
filectx: fix annotate to not directly instantiate filectx...
r23770 base = self.filectx(self.filenode(), changeid=introrev)
Yuya Nishihara
annotate: prepare ancestry context of workingfilectx...
r24818 if getattr(base, '_ancestrycontext', None) is None:
cl = self._repo.changelog
if introrev is None:
# wctx is not inclusive, but works because _ancestrycontext
# is used to test filelog revisions
ac = cl.ancestors([p.rev() for p in base.parents()],
inclusive=True)
else:
ac = cl.ancestors([introrev], inclusive=True)
Pierre-Yves David
annotate: reuse ancestry context when adjusting linkrev (issue4532)...
r24407 base._ancestrycontext = ac
Brendan Cully
Fix annotate where linkrev != rev without exporting linkrev
r3404
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.
Jun Wu
annotate: pre-calculate the "needed" dictionary (issue5360)...
r29861 # 1st DFS pre-calculates pcache and needed
Matt Mackall
ancestor: rewrite to deal with crossed linkrevs (issue2682)...
r13552 visit = [base]
pcache = {}
Brendan Cully
Fix annotate where linkrev != rev without exporting linkrev
r3404 needed = {base: 1}
Brendan Cully
Refactor annotate copy support.
r3172 while visit:
Jun Wu
annotate: pre-calculate the "needed" dictionary (issue5360)...
r29861 f = visit.pop()
if f in pcache:
continue
pl = parents(f)
pcache[f] = pl
for p in pl:
needed[p] = needed.get(p, 0) + 1
if p not in pcache:
visit.append(p)
# 2nd DFS does the actual annotate
visit[:] = [base]
hist = {}
while visit:
Matt Mackall
ancestor: rewrite to deal with crossed linkrevs (issue2682)...
r13552 f = visit[-1]
Jun Wu
annotate: pre-calculate the "needed" dictionary (issue5360)...
r29861 if f in hist:
visit.pop()
continue
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)
if ready:
visit.pop()
Jun Wu
annotate: pre-calculate the "needed" dictionary (issue5360)...
r29861 curr = decorate(f.data(), f)
Matt Mackall
ancestor: rewrite to deal with crossed linkrevs (issue2682)...
r13552 for p in pl:
Jun Wu
annotate: pre-calculate the "needed" dictionary (issue5360)...
r29861 curr = pair(hist[p], curr)
Matt Mackall
ancestor: rewrite to deal with crossed linkrevs (issue2682)...
r13552 if needed[p] == 1:
del hist[p]
FUJIWARA Katsunori
annotate: discard refcount of discarded annotation for memory efficiency...
r19061 del needed[p]
Matt Mackall
ancestor: rewrite to deal with crossed linkrevs (issue2682)...
r13552 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
Jun Wu
annotate: pre-calculate the "needed" dictionary (issue5360)...
r29861 del 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
Sean Farley
basefilectx: move ancestors from filectx
r19610 def ancestors(self, followfirst=False):
visit = {}
c = self
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if followfirst:
cut = 1
else:
cut = None
Sean Farley
basefilectx: move ancestors from filectx
r19610 while True:
for parent in c.parents()[:cut]:
Matt Mackall
filectx: use linkrev to sort ancestors...
r23981 visit[(parent.linkrev(), parent.filenode())] = parent
Sean Farley
basefilectx: move ancestors from filectx
r19610 if not visit:
break
c = visit.pop(max(visit))
yield c
Sean Farley
basefilectx: move annotate from filectx
r19608 class filectx(basefilectx):
"""A filecontext object makes access to data related to a particular
filerevision convenient."""
def __init__(self, repo, path, changeid=None, fileid=None,
filelog=None, changectx=None):
"""changeid can be a changeset revision, node, or tag.
fileid can be a file revision or node."""
self._repo = repo
self._path = path
assert (changeid is not None
or fileid is not None
or changectx is not None), \
("bad args: changeid=%r, fileid=%r, changectx=%r"
% (changeid, fileid, changectx))
if filelog is not None:
self._filelog = filelog
if changeid is not None:
self._changeid = changeid
if changectx is not None:
self._changectx = changectx
if fileid is not None:
self._fileid = fileid
@propertycache
def _changectx(self):
try:
return changectx(self._repo, self._changeid)
Pierre-Yves David
context: catch FilteredRepoLookupError instead of RepoLookupError...
r23687 except error.FilteredRepoLookupError:
Sean Farley
basefilectx: move annotate from filectx
r19608 # 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 complex operations that care about
# filtering.
#
# This fallback is a cheap and dirty fix that prevent several
# crashes. 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)
Durham Goode
filectx: fix annotate to not directly instantiate filectx...
r23770 def filectx(self, fileid, changeid=None):
Sean Farley
basefilectx: move annotate from filectx
r19608 '''opens an arbitrary revision of the file without
opening a new filelog'''
return filectx(self._repo, self._path, fileid=fileid,
Durham Goode
filectx: fix annotate to not directly instantiate filectx...
r23770 filelog=self._filelog, changeid=changeid)
Sean Farley
basefilectx: move annotate from filectx
r19608
Remi Chaintron
revlog: add 'raw' argument to revision and _addrevision...
r30743 def rawdata(self):
return self._filelog.revision(self._filenode, raw=True)
Sean Farley
basefilectx: move annotate from filectx
r19608 def data(self):
Mike Edgar
context: handle censored data in an on-disk file context based on config...
r22932 try:
return self._filelog.read(self._filenode)
except error.CensoredNodeError:
if self._repo.ui.config("censor", "policy", "abort") == "ignore":
return ""
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("censored node: %s") % short(self._filenode),
FUJIWARA Katsunori
i18n: make hint message of exception translatable
r23110 hint=_("set censor.policy to ignore errors"))
Mike Edgar
context: handle censored data in an on-disk file context based on config...
r22932
Sean Farley
basefilectx: move annotate from filectx
r19608 def size(self):
return self._filelog.size(self._filerev)
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
except error.LookupError:
pass
return renamed
def children(self):
# hard for renames
c = self._filelog.children(self._filenode)
return [filectx(self._repo, self._path, fileid=x,
filelog=self._filelog) for x in c]
Denis Laxalde
context: extract _changesinrange() out of blockancestors()...
r30824 def _changesrange(fctx1, fctx2, linerange2, diffopts):
"""Return `(diffinrange, linerange1)` where `diffinrange` is True
if diff from fctx2 to fctx1 has changes in linerange2 and
`linerange1` is the new line range for fctx1.
"""
blocks = mdiff.allblocks(fctx1.data(), fctx2.data(), diffopts)
filteredblocks, linerange1 = mdiff.blocksinrange(blocks, linerange2)
diffinrange = any(stype == '!' for _, stype in filteredblocks)
return diffinrange, linerange1
Denis Laxalde
context: add a followfirst flag to blockancestors
r31075 def blockancestors(fctx, fromline, toline, followfirst=False):
Denis Laxalde
context: add a `blockancestors(fctx, fromline, toline)` function...
r30718 """Yield ancestors of `fctx` with respect to the block of lines within
`fromline`-`toline` range.
"""
Denis Laxalde
context: extract _changesinrange() out of blockancestors()...
r30824 diffopts = patch.diffopts(fctx._repo.ui)
Denis Laxalde
context: add a `blockancestors(fctx, fromline, toline)` function...
r30718 visit = {(fctx.linkrev(), fctx.filenode()): (fctx, (fromline, toline))}
while visit:
c, linerange2 = visit.pop(max(visit))
pl = c.parents()
Denis Laxalde
context: add a followfirst flag to blockancestors
r31075 if followfirst:
pl = pl[:1]
Denis Laxalde
context: add a `blockancestors(fctx, fromline, toline)` function...
r30718 if not pl:
# The block originates from the initial revision.
Denis Laxalde
context: also return ancestor's line range in blockancestors
r31076 yield c, linerange2
Denis Laxalde
context: add a `blockancestors(fctx, fromline, toline)` function...
r30718 continue
inrange = False
for p in pl:
Denis Laxalde
context: extract _changesinrange() out of blockancestors()...
r30824 inrangep, linerange1 = _changesrange(p, c, linerange2, diffopts)
Denis Laxalde
context: add a `blockancestors(fctx, fromline, toline)` function...
r30718 inrange = inrange or inrangep
if linerange1[0] == linerange1[1]:
# Parent's linerange is empty, meaning that the block got
# introduced in this revision; no need to go futher in this
# branch.
continue
visit[p.linkrev(), p.filenode()] = p, linerange1
if inrange:
Denis Laxalde
context: also return ancestor's line range in blockancestors
r31076 yield c, linerange2
Denis Laxalde
context: add a `blockancestors(fctx, fromline, toline)` function...
r30718
Denis Laxalde
context: add a blockdescendants function...
r31937 def blockdescendants(fctx, fromline, toline):
"""Yield descendants of `fctx` with respect to the block of lines within
`fromline`-`toline` range.
"""
diffopts = patch.diffopts(fctx._repo.ui)
fl = fctx.filelog()
seen = {fctx.filerev(): (fctx, (fromline, toline))}
for i in fl.descendants([fctx.filerev()]):
c = fctx.filectx(i)
Denis Laxalde
context: follow all branches in blockdescendants()...
r31955 inrange = False
Denis Laxalde
context: add a blockdescendants function...
r31937 for x in fl.parentrevs(i):
try:
Denis Laxalde
context: follow all branches in blockdescendants()...
r31955 p, linerange2 = seen[x]
Denis Laxalde
context: add a blockdescendants function...
r31937 except KeyError:
# nullrev or other branch
continue
Denis Laxalde
context: follow all branches in blockdescendants()...
r31955 inrangep, linerange1 = _changesrange(c, p, linerange2, diffopts)
inrange = inrange or inrangep
Denis Laxalde
context: add an assertion checking linerange consistency in blockdescendants()...
r31991 # If revision 'i' has been seen (it's a merge), we assume that its
# line range is the same independently of which parents was used
# to compute it.
assert i not in seen or seen[i][1] == linerange1, (
'computed line range for %s is not consistent between '
'ancestor branches' % c)
Denis Laxalde
context: add a blockdescendants function...
r31937 seen[i] = c, linerange1
Denis Laxalde
context: follow all branches in blockdescendants()...
r31955 if inrange:
yield c, linerange1
Denis Laxalde
context: add a blockdescendants function...
r31937
Sean Farley
context: use correct spelling of committable
r19733 class committablectx(basectx):
"""A committablectx object provides common functionality for a context that
Sean Farley
commitablectx: add a class that will be used as a parent of mutable contexts...
r19664 wants the ability to commit, e.g. workingctx or memctx."""
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:
Sean Farley
committablectx: simplify caching the status...
r21592 self._status = changes
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:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('branch name not in UTF-8!'))
Patrick Mezard
localrepo: let commit() get extra data from workingctx
r6708 self._extra['branch'] = branch
if self._extra['branch'] == '':
self._extra['branch'] = 'default'
Sean Farley
commitablectx: move __str__ from workingctx
r19666 def __str__(self):
return str(self._parents[0]) + "+"
Sean Farley
commitablectx: move __nonzero__ from workingctx
r19667 def __nonzero__(self):
return True
Gregory Szorc
py3: add __bool__ to every class defining __nonzero__...
r31476 __bool__ = __nonzero__
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
Gregory Szorc
context: avoid extra parents lookups...
r27064 parents = self.parents()
if len(parents) < 2:
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337 # when we have one parent, it's easy: copy from parent
Gregory Szorc
context: avoid extra parents lookups...
r27064 man = parents[0].manifest()
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337 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)
Gregory Szorc
context: avoid extra parents lookups...
r27064 p1, p2 = parents
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337 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
Sean Farley
commitablectx: move _flagfunc from workingctx
r19670 @propertycache
def _flagfunc(self):
return self._repo.dirstate.flagfunc(self._buildflagfunc)
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337 @propertycache
Sean Farley
commitablectx: move _status from workingctx
r19672 def _status(self):
Sean Farley
committablectx: simplify caching the status...
r21592 return self._repo.status()
Sean Farley
commitablectx: move _status from workingctx
r19672
Sean Farley
commitablectx: move _user from workingctx
r19674 @propertycache
def _user(self):
return self._repo.ui.username()
Sean Farley
commitablectx: move _date from workingctx
r19676 @propertycache
def _date(self):
return util.makedate()
Sean Farley
committablectx: add subrev method to return None...
r21587 def subrev(self, subpath):
return None
Yuya Nishihara
committablectx: override manifestnode() to return None...
r24719 def manifestnode(self):
return None
Sean Farley
commitablectx: move user from workingctx
r19675 def user(self):
return self._user or self._repo.ui.username()
Sean Farley
commitablectx: move date from workingctx
r19677 def date(self):
return self._date
Sean Farley
commitablectx: move description from workingctx
r19678 def description(self):
return self._text
Sean Farley
commitablectx: move files from workingctx
r19679 def files(self):
Martin von Zweigbergk
context: store status class instead of plain tuple in self._status...
r22916 return sorted(self._status.modified + self._status.added +
self._status.removed)
Sean Farley
commitablectx: move user from workingctx
r19675
Sean Farley
commitablectx: move modified from workingctx
r19680 def modified(self):
Martin von Zweigbergk
context: store status class instead of plain tuple in self._status...
r22916 return self._status.modified
Sean Farley
commitablectx: move added from workingctx
r19681 def added(self):
Martin von Zweigbergk
context: store status class instead of plain tuple in self._status...
r22916 return self._status.added
Sean Farley
commitablectx: move removed from workingctx
r19682 def removed(self):
Martin von Zweigbergk
context: store status class instead of plain tuple in self._status...
r22916 return self._status.removed
Sean Farley
commitablectx: move deleted from workingctx
r19683 def deleted(self):
Martin von Zweigbergk
context: store status class instead of plain tuple in self._status...
r22916 return self._status.deleted
Sean Farley
commitablectx: move branch from workingctx
r19687 def branch(self):
return encoding.tolocal(self._extra['branch'])
Sean Farley
commitablectx: move closesbranch from workingctx
r19688 def closesbranch(self):
return 'close' in self._extra
Sean Farley
commitablectx: move extra from workingctx
r19689 def extra(self):
return self._extra
Sean Farley
commitablectx: move modified from workingctx
r19680
Sean Farley
commitablectx: move tags from workingctx
r19690 def tags(self):
Matt Harbison
workingctx: don't report the tags for its parents...
r25688 return []
Sean Farley
commitablectx: move tags from workingctx
r19690
Sean Farley
commitablectx: move bookmarks from workingctx
r19691 def bookmarks(self):
b = []
for p in self.parents():
b.extend(p.bookmarks())
return b
Sean Farley
commitablectx: move phase from workingctx
r19692 def phase(self):
phase = phases.draft # default phase to draft
for p in self.parents():
phase = max(phase, p.phase())
return phase
Sean Farley
commitablectx: move hidden from workingctx
r19693 def hidden(self):
return False
Sean Farley
commitablectx: move children from workingctx
r19694 def children(self):
return []
Sean Farley
commitablectx: move flags from workingctx
r19695 def flags(self, path):
if '_manifest' in self.__dict__:
try:
return self._manifest.flags(path)
except KeyError:
return ''
try:
return self._flagfunc(path)
except OSError:
return ''
Sean Farley
commitablectx: move ancestor from workingctx
r19696 def ancestor(self, c2):
Mads Kiilerich
comments: describe ancestor consistently - avoid 'least common ancestor'...
r22389 """return the "best" ancestor context of self and c2"""
Sean Farley
commitablectx: move ancestor from workingctx
r19696 return self._parents[0].ancestor(c2) # punt on two parents for now
Sean Farley
commitablectx: move walk from workingctx
r19697 def walk(self, match):
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646 '''Generates matching file names.'''
Sean Farley
commitablectx: move walk from workingctx
r19697 return sorted(self._repo.dirstate.walk(match, sorted(self.substate),
True, False))
Siddharth Agarwal
context: add a method to efficiently filter by match if possible...
r21985 def matches(self, match):
return sorted(self._repo.dirstate.matches(match))
Sean Farley
commitablectx: move ancestors from workingctx
r19698 def ancestors(self):
Durham Goode
context: return dirstate parents in workingctx.ancestors()...
r23616 for p in self._parents:
yield p
Sean Farley
commitablectx: move ancestors from workingctx
r19698 for a in self._repo.changelog.ancestors(
[p.rev() for p in self._parents]):
yield changectx(self._repo, a)
Sean Farley
commitablectx: move markcommitted from workingctx
r19699 def markcommitted(self, node):
"""Perform post-commit cleanup necessary after committing this ctx
Specifically, this updates backing stores this working context
wraps to reflect the fact that the changes reflected by this
workingctx have been committed. For example, it marks
modified and added files as normal in the dirstate.
"""
Durham Goode
dirstate: wrap setparent calls with begin/endparentchange (issue4353)...
r22405 self._repo.dirstate.beginparentchange()
Sean Farley
commitablectx: move markcommitted from workingctx
r19699 for f in self.modified() + self.added():
self._repo.dirstate.normal(f)
for f in self.removed():
self._repo.dirstate.drop(f)
self._repo.dirstate.setparents(node)
Durham Goode
dirstate: wrap setparent calls with begin/endparentchange (issue4353)...
r22405 self._repo.dirstate.endparentchange()
Sean Farley
commitablectx: move markcommitted from workingctx
r19699
FUJIWARA Katsunori
context: write dirstate out explicitly at the end of markcommitted...
r25757 # write changes out explicitly, because nesting wlock at
# runtime may prevent 'wlock.release()' in 'repo.commit()'
# from immediately doing so for subsequent changing files
FUJIWARA Katsunori
dirstate: make dirstate.write() callers pass transaction object to it...
r26748 self._repo.dirstate.write(self._repo.currenttransaction())
FUJIWARA Katsunori
context: write dirstate out explicitly at the end of markcommitted...
r25757
Sean Farley
context: use correct spelling of committable
r19733 class workingctx(committablectx):
Sean Farley
commitablectx: move _manifest from workingctx
r19671 """A workingctx object makes access to data related to
the current working directory convenient.
date - any valid date string or (unixtime, offset), or None.
user - username string, or None.
extra - a dictionary of extra values, or None.
changes - a list of file lists as returned by localrepo.status()
or None to use the repository status.
"""
def __init__(self, repo, text="", user=None, date=None, extra=None,
changes=None):
super(workingctx, self).__init__(repo, text, user, date, extra, changes)
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
Sean Farley
committablectx: move __contains__ into workingctx...
r21845 def __contains__(self, key):
return self._repo.dirstate[key] not in "?r"
Matt Harbison
context: override workingctx.hex() to avoid a crash...
r25590 def hex(self):
Yuya Nishihara
workingctx: use node.wdirid constant
r25738 return hex(wdirid)
Matt Harbison
context: override workingctx.hex() to avoid a crash...
r25590
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
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
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)
Bryan O'Sullivan
with: use context manager for wlock in workingctx.add
r27809 with self._repo.wlock():
ui, ds = self._repo.ui, self._repo.dirstate
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 rejected = []
FUJIWARA Katsunori
context: use "vfs.lstat()" instead of "os.lstat()"...
r19900 lstat = self._repo.wvfs.lstat
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 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 try:
FUJIWARA Katsunori
context: use "vfs.lstat()" instead of "os.lstat()"...
r19900 st = lstat(f)
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))
FUJIWARA Katsunori
context: use "vfs.lstat()" instead of "os.lstat()"...
r19900 rejected.append(f)
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 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
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)
Bryan O'Sullivan
with: use context manager for wlock in workingctx.forget
r27810 with self._repo.wlock():
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
def undelete(self, list):
pctxs = self.parents()
Bryan O'Sullivan
with: use context manager for wlock in workingctx.undelete
r27811 with self._repo.wlock():
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 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)
def copy(self, source, dest):
FUJIWARA Katsunori
context: use "vfs.lstat()" to examine target path instead of "os.path.*"...
r19902 try:
st = self._repo.wvfs.lstat(dest)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as err:
FUJIWARA Katsunori
context: use "vfs.lstat()" to examine target path instead of "os.path.*"...
r19902 if err.errno != errno.ENOENT:
raise
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 self._repo.ui.warn(_("%s does not exist!\n") % dest)
FUJIWARA Katsunori
context: use "vfs.lstat()" to examine target path instead of "os.path.*"...
r19902 return
if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 self._repo.ui.warn(_("copy failed: %s is not a file or a "
"symbolic link\n") % dest)
else:
Bryan O'Sullivan
with: use context manager for wlock in copy
r27812 with self._repo.wlock():
Pierre-Yves David
rename: properly report removed and added file as modified (issue4458)...
r23402 if self._repo.dirstate[dest] in '?':
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 self._repo.dirstate.add(dest)
Pierre-Yves David
rename: properly report removed and added file as modified (issue4458)...
r23402 elif self._repo.dirstate[dest] in 'r':
self._repo.dirstate.normallookup(dest)
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 self._repo.dirstate.copy(source, dest)
Gregory Szorc
context: don't use mutable default argument value...
r31388 def match(self, pats=None, include=None, exclude=None, default='glob',
Matt Harbison
context: add an optional constructor parameter for a match.bad() override...
r25465 listsubrepos=False, badfn=None):
Pierre-Yves David
context: explicitly tests for None...
r31437 if pats is None:
pats = []
Matt Harbison
match: add a subclass for dirstate normalizing of the matched patterns...
r24790 r = self._repo
# Only a case insensitive filesystem needs magic to translate user input
# to actual case in the filesystem.
Pierre-Yves David
context: simplify call to icase matcher in 'match()'...
r31464 matcherfunc = matchmod.match
Martin von Zweigbergk
util: rename checkcase() to fscasesensitive() (API)...
r29889 if not util.fscasesensitive(r.root):
Pierre-Yves David
context: simplify call to icase matcher in 'match()'...
r31464 matcherfunc = matchmod.icasefsmatcher
return matcherfunc(r.root, r.getcwd(), pats,
include, exclude, default,
auditor=r.auditor, ctx=self,
listsubrepos=listsubrepos, badfn=badfn)
Matt Harbison
match: add a subclass for dirstate normalizing of the matched patterns...
r24790
Sean Farley
localrepo: move symlink logic to workingctx
r21393 def _filtersuspectsymlink(self, files):
if not files or self._repo.dirstate._checklink:
return files
# Symlink placeholders may get non-symlink-like contents
# via user error or dereferencing by NFS or Samba servers,
# so we filter out any placeholders that don't look like a
# symlink
sane = []
for f in files:
if self.flags(f) == 'l':
d = self[f].data()
if d == '' or len(d) >= 1024 or '\n' in d or util.binary(d):
self._repo.ui.debug('ignoring suspect symlink placeholder'
' "%s"\n' % f)
continue
sane.append(f)
return sane
Sean Farley
localrepo: factor out parentworking logic for comparing files...
r21395 def _checklookup(self, files):
# check for any possibly clean files
if not files:
return [], []
modified = []
fixup = []
pctx = self._parents[0]
# do a full compare of any files that might have changed
for f in sorted(files):
if (f not in pctx or self.flags(f) != pctx.flags(f)
or pctx[f].cmp(self[f])):
modified.append(f)
else:
fixup.append(f)
# update dirstate for files that are actually clean
if fixup:
try:
# updating the dirstate is optional
# so we don't wait on the lock
Siddharth Agarwal
context: call normal on the right object...
r21990 # wlock can invalidate the dirstate, so cache normal _after_
# taking the lock
Bryan O'Sullivan
with: use context manager for wlock in checklookup
r27813 with self._repo.wlock(False):
normal = self._repo.dirstate.normal
Sean Farley
localrepo: factor out parentworking logic for comparing files...
r21395 for f in fixup:
normal(f)
FUJIWARA Katsunori
context: write dirstate out explicitly after marking files as clean...
r25753 # write changes out explicitly, because nesting
# wlock at runtime may prevent 'wlock.release()'
Bryan O'Sullivan
with: use context manager for wlock in checklookup
r27813 # after this block from doing so for subsequent
# changing files
FUJIWARA Katsunori
dirstate: make dirstate.write() callers pass transaction object to it...
r26748 self._repo.dirstate.write(self._repo.currenttransaction())
Sean Farley
localrepo: factor out parentworking logic for comparing files...
r21395 except error.LockError:
pass
return modified, fixup
Sean Farley
context: add private _dirstatestatus method...
r21397 def _dirstatestatus(self, match=None, ignored=False, clean=False,
unknown=False):
'''Gets the status from the dirstate -- internal use only.'''
listignored, listclean, listunknown = ignored, clean, unknown
match = match or matchmod.always(self._repo.root, self._repo.getcwd())
subrepos = []
if '.hgsub' in self:
subrepos = sorted(self.substate)
Martin von Zweigbergk
dirstate: separate 'lookup' status field from others...
r22911 cmp, s = self._repo.dirstate.status(match, subrepos, listignored,
listclean, listunknown)
Sean Farley
context: add private _dirstatestatus method...
r21397
# check for any possibly clean files
if cmp:
modified2, fixup = self._checklookup(cmp)
Martin von Zweigbergk
context.status: avoid de- and reconstructing status tuple...
r23303 s.modified.extend(modified2)
Sean Farley
context: add private _dirstatestatus method...
r21397
# update dirstate for files that are actually clean
if fixup and listclean:
Martin von Zweigbergk
context.status: avoid de- and reconstructing status tuple...
r23303 s.clean.extend(fixup)
Sean Farley
context: add private _dirstatestatus method...
r21397
Martin von Zweigbergk
status: cache dirstate status in _dirstatestatus()...
r23776 if match.always():
# cache for performance
if s.unknown or s.ignored or s.clean:
# "_status" is cached with list*=False in the normal route
self._status = scmutil.status(s.modified, s.added, s.removed,
s.deleted, [], [], [])
else:
self._status = s
Martin von Zweigbergk
context.status: avoid de- and reconstructing status tuple...
r23303 return s
Sean Farley
context: add private _dirstatestatus method...
r21397
Durham Goode
context: move _manifest from committablectx to workingctx...
r31259 @propertycache
def _manifest(self):
"""generate a manifest corresponding to the values in self._status
This reuse the file nodeid from parent, but we use special node
identifiers for added and modified files. This is used by manifests
merge to see that files are different and by update logic to avoid
deleting newly added files.
"""
return self._buildstatusmanifest(self._status)
def _buildstatusmanifest(self, status):
"""Builds a manifest that includes the given status results."""
parents = self.parents()
man = parents[0].manifest().copy()
ff = self._flagfunc
for i, l in ((addednodeid, status.added),
(modifiednodeid, status.modified)):
for f in l:
man[f] = i
try:
man.setflag(f, ff(f))
except OSError:
pass
for f in status.deleted + status.removed:
if f in man:
del man[f]
return man
Sean Farley
workingctx: use inheritance for _buildstatus while keeping the fastpath...
r21480 def _buildstatus(self, other, s, match, listignored, listclean,
Sean Farley
context: fix wrong indentation from renaming method
r21663 listunknown):
Sean Farley
workingctx: use inheritance for _buildstatus while keeping the fastpath...
r21480 """build a status with respect to another context
This includes logic for maintaining the fast path of status when
comparing the working directory against its parent, which is to skip
building a new manifest if self (working directory) is not comparing
against its parent (repo['.']).
"""
Martin von Zweigbergk
context.status: call _dirstatestatus() from within _buildstatus()...
r23239 s = self._dirstatestatus(match, listignored, listclean, listunknown)
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23543 # Filter out symlinks that, in the case of FAT32 and NTFS filesystems,
Martin von Zweigbergk
context.status: only filter suspect symlinks in the dirstate status...
r23242 # might have accidentally ended up with the entire contents of the file
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23543 # they are supposed to be linking to.
Martin von Zweigbergk
context.status: make _dirstatestatus() return an status tuple...
r23302 s.modified[:] = self._filtersuspectsymlink(s.modified)
Sean Farley
workingctx: use inheritance for _buildstatus while keeping the fastpath...
r21480 if other != self._repo['.']:
s = super(workingctx, self)._buildstatus(other, s, match,
listignored, listclean,
listunknown)
return s
Martin von Zweigbergk
context.status: remove unused arguments from _matchstatus()
r23237 def _matchstatus(self, other, match):
Sean Farley
workingctx: override _matchstatus for parentworking case...
r21482 """override the match method with a filter for directory patterns
We use inheritance to customize the match.bad method only in cases of
workingctx since it belongs only to the working directory when
comparing against the parent changeset.
If we aren't comparing against the working directory's parent, then we
just use the default match object sent to us.
"""
superself = super(workingctx, self)
Martin von Zweigbergk
context.status: remove unused arguments from _matchstatus()
r23237 match = superself._matchstatus(other, match)
Sean Farley
workingctx: override _matchstatus for parentworking case...
r21482 if other != self._repo['.']:
def bad(f, msg):
# 'f' may be a directory pattern from 'match.files()',
# so 'f not in ctx1' is not enough
Drew Gottlieb
manifest: have context use self.hasdir()...
r24326 if f not in other and not other.hasdir(f):
Sean Farley
workingctx: override _matchstatus for parentworking case...
r21482 self._repo.ui.warn('%s: %s\n' %
(self._repo.dirstate.pathto(f), msg))
match.bad = bad
return match
Sean Farley
context: use correct spelling of committable
r19733 class committablefilectx(basefilectx):
"""A committablefilectx provides common functionality for a file context
that wants the ability to commit, e.g. workingfilectx or memfilectx."""
Sean Farley
commitablefilectx: add a class that will be used for mutable file contexts...
r19701 def __init__(self, repo, path, filelog=None, ctx=None):
Matt Mackall
contexts: add working dir and working file contexts...
r3217 self._repo = repo
self._path = path
self._changeid = None
self._filerev = self._filenode = None
Durham Goode
filecontext: use 'is not None' to check for filelog existence...
r19149 if filelog is not None:
Matt Mackall
contexts: add working dir and working file contexts...
r3217 self._filelog = filelog
Sean Farley
commitablefilectx: move __init__ from workingfilectx
r19702 if ctx:
self._changectx = ctx
Sean Farley
commitablefilectx: move __nonzero__ from workingfilectx
r19703 def __nonzero__(self):
return True
Gregory Szorc
py3: add __bool__ to every class defining __nonzero__...
r31476 __bool__ = __nonzero__
Yuya Nishihara
committablefilectx: override linkrev() to point to the associated changectx...
r24420 def linkrev(self):
# linked to self._changectx no matter if file is modified or not
return self.rev()
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
Yuya Nishihara
committablefilectx: propagate ancestry info to parent to fix annotation...
r24817 return [self._parentfilectx(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
Sean Farley
commitablefilectx: move children from workingfilectx
r19705 def children(self):
return []
Sean Farley
context: use correct spelling of committable
r19733 class workingfilectx(committablefilectx):
Sean Farley
commitablefilectx: move parents from workingfilectx
r19704 """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):
super(workingfilectx, self).__init__(repo, path, filelog, workingctx)
@propertycache
def _changectx(self):
return workingctx(self._repo)
def data(self):
return self._repo.wread(self._path)
def renamed(self):
rp = self._repo.dirstate.copied(self._path)
if not rp:
return None
return rp, self._changectx._parents[0]._manifest.get(rp, nullid)
Matt Mackall
many, many trivial check-code fixups
r10282 def size(self):
FUJIWARA Katsunori
context: use "vfs.lstat()" instead of "os.lstat()"
r19901 return self._repo.wvfs.lstat(self._path).st_size
Benoit Boissinot
add date attribute to workingfilectx
r3962 def date(self):
t, tz = self._changectx.date()
try:
Matt Mackall
util: drop statmtimesec...
r27016 return (self._repo.wvfs.lstat(self._path).st_mtime, tz)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as 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
Sean Farley
workingfilectx: add remove and write methods...
r22073 def remove(self, ignoremissing=False):
"""wraps unlink for a repo's working directory"""
Mads Kiilerich
vfs: use repo.wvfs.unlinkpath
r31309 self._repo.wvfs.unlinkpath(self._path, ignoremissing=ignoremissing)
Sean Farley
workingfilectx: add remove and write methods...
r22073
def write(self, data, flags):
"""wraps repo.wwrite"""
self._repo.wwrite(self._path, data, flags)
FUJIWARA Katsunori
context: add workingcommitctx for exact context to be committed...
r23710 class workingcommitctx(workingctx):
"""A workingcommitctx object makes access to data related to
the revision being committed convenient.
This hides changes in the working directory, if they aren't
committed in this context.
"""
def __init__(self, repo, changes,
text="", user=None, date=None, extra=None):
super(workingctx, self).__init__(repo, text, user, date, extra,
changes)
FUJIWARA Katsunori
context: override _dirstatestatus in workingcommitctx for correct matching...
r23712 def _dirstatestatus(self, match=None, ignored=False, clean=False,
unknown=False):
"""Return matched files only in ``self._status``
Uncommitted files appear "clean" via this context, even if
they aren't actually so in the working directory.
"""
match = match or matchmod.always(self._repo.root, self._repo.getcwd())
if clean:
clean = [f for f in self._manifest if f not in self._changedset]
else:
clean = []
return scmutil.status([f for f in self._status.modified if match(f)],
[f for f in self._status.added if match(f)],
[f for f in self._status.removed if match(f)],
[], [], [], clean)
@propertycache
def _changedset(self):
"""Return the set of files changed in this context
"""
changed = set(self._status.modified)
changed.update(self._status.added)
changed.update(self._status.removed)
return changed
Gregory Szorc
context: don't use util.cachefunc due to cycle creation (issue5043)...
r27906 def makecachingfilectxfn(func):
"""Create a filectxfn that caches based on the path.
We can't use util.cachefunc because it uses all arguments as the cache
key and this creates a cycle since the arguments include the repo and
memctx.
"""
cache = {}
def getfilectx(repo, memctx, path):
if path not in cache:
cache[path] = func(repo, memctx, path)
return cache[path]
return getfilectx
Sean Farley
memctx: inherit from committablectx...
r21665 class memctx(committablectx):
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
FUJIWARA Katsunori
misc: update descriptions about removed file for filectxfn...
r31612 object. If the file was removed, filectxfn return None for recent
Mercurial. Moved files are represented by marking the source file
Patrick Mezard
context: improve memctx documentation
r7077 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 """
Siddharth Agarwal
memctx: allow extensions to determine what filectxfn should do...
r22313
# Mercurial <= 3.1 expects the filectxfn to raise IOError for missing files.
# Extensions that need to retain compatibility across Mercurial 3.1 can use
# this field to determine what to do in filectxfn.
_returnnoneformissingfiles = True
Dirkjan Ochtman
kill some trailing spaces
r6721 def __init__(self, repo, parents, text, files, filectxfn, user=None,
FUJIWARA Katsunori
context: move editor invocation from "makememctx()" to "memctx.__init__()"...
r21238 date=None, extra=None, editor=False):
Sean Farley
memctx: call super.__init__ instead of duplicating code
r21666 super(memctx, self).__init__(repo, text, user, date, extra)
Patrick Mezard
context: add memctx for memory commits
r6715 self._rev = None
self._node = None
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))
FUJIWARA Katsunori
memctx: calculate exact status being committed from specified files...
r23587 self._files = files
Sean Farley
memctx: substate needs to be {} instead of None...
r21938 self.substate = {}
Patrick Mezard
context: add memctx for memory commits
r6715
Sean Farley
memctx: create a filectxfn if it is not callable...
r22072 # if store is not callable, wrap it in a function
if not callable(filectxfn):
def getfilectx(repo, memctx, path):
fctx = filectxfn[path]
# this is weird but apparently we only keep track of one parent
# (why not only store that instead of a tuple?)
copied = fctx.renamed()
if copied:
copied = copied[0]
return memfilectx(repo, path, fctx.data(),
islink=fctx.islink(), isexec=fctx.isexec(),
copied=copied, memctx=memctx)
self._filectxfn = getfilectx
FUJIWARA Katsunori
memctx: calculate exact status being committed from specified files...
r23587 else:
Gregory Szorc
context: don't use util.cachefunc due to cycle creation (issue5043)...
r27906 # memoizing increases performance for e.g. vcs convert scenarios.
self._filectxfn = makecachingfilectxfn(filectxfn)
Sean Farley
memctx: create a filectxfn if it is not callable...
r22072
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if extra:
self._extra = extra.copy()
else:
self._extra = {}
Patrick Mezard
memctx: simplify constructor
r14528 if self._extra.get('branch', '') == '':
Patrick Mezard
context: add memctx for memory commits
r6715 self._extra['branch'] = 'default'
FUJIWARA Katsunori
context: move editor invocation from "makememctx()" to "memctx.__init__()"...
r21238 if editor:
self._text = editor(self._repo, self, [])
self._repo.savecommitmessage(self._text)
Patrick Mezard
context: add memctx for memory commits
r6715 def filectx(self, path, filelog=None):
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 """get a file context from the working directory
Returns None if file doesn't exist and should be removed."""
Patrick Mezard
context: add memctx for memory commits
r6715 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)
Sean Farley
memctx: add _manifest implementation that computes the filenode...
r21835 @propertycache
def _manifest(self):
"""generate a manifest based on the return values of filectxfn"""
# keep this simple for now; just worry about p1
pctx = self._parents[0]
man = pctx.manifest().copy()
FUJIWARA Katsunori
memctx: calculate manifest more efficiently...
r23603 for f in self._status.modified:
Sean Farley
memctx: add _manifest implementation that computes the filenode...
r21835 p1node = nullid
p2node = nullid
Sean Farley
memctx: add note about p2
r22075 p = pctx[f].parents() # if file isn't in pctx, check p2?
Sean Farley
memctx: add _manifest implementation that computes the filenode...
r21835 if len(p) > 0:
Durham Goode
memctx: fix memctx manifest file hashes...
r27983 p1node = p[0].filenode()
Sean Farley
memctx: add _manifest implementation that computes the filenode...
r21835 if len(p) > 1:
Durham Goode
memctx: fix memctx manifest file hashes...
r27983 p2node = p[1].filenode()
FUJIWARA Katsunori
memctx: calculate manifest more efficiently...
r23603 man[f] = revlog.hash(self[f].data(), p1node, p2node)
Sean Farley
memctx: add _manifest implementation that computes the filenode...
r21835
FUJIWARA Katsunori
memctx: calculate manifest including newly added files correctly...
r23588 for f in self._status.added:
man[f] = revlog.hash(self[f].data(), nullid, nullid)
FUJIWARA Katsunori
memctx: calculate manifest correctly with newly-removed files (issue4470)...
r23589 for f in self._status.removed:
if f in man:
del man[f]
Sean Farley
memctx: add _manifest implementation that computes the filenode...
r21835
return man
FUJIWARA Katsunori
memctx: calculate exact status being committed from specified files...
r23587 @propertycache
def _status(self):
"""Calculate exact status from ``files`` specified at construction
"""
man1 = self.p1().manifest()
p2 = self._parents[1]
# "1 < len(self._parents)" can't be used for checking
# existence of the 2nd parent, because "memctx._parents" is
# explicitly initialized by the list, of which length is 2.
if p2.node() != nullid:
man2 = p2.manifest()
managing = lambda f: f in man1 or f in man2
else:
managing = lambda f: f in man1
modified, added, removed = [], [], []
for f in self._files:
if not managing(f):
added.append(f)
elif self[f]:
modified.append(f)
else:
removed.append(f)
return scmutil.status(modified, added, removed, [], [], [], [])
Sean Farley
memctx: add _manifest implementation that computes the filenode...
r21835
Sean Farley
memfilectx: inherit from committablefilectx...
r21688 class memfilectx(committablefilectx):
Patrick Mezard
context: improve memctx documentation
r7077 """memfilectx represents an in-memory file to commit.
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23139 See memctx and committablefilectx for more details.
Patrick Mezard
context: add memctx for memory commits
r6715 """
Sean Farley
memfilectx: call super.__init__ instead of duplicating code...
r21689 def __init__(self, repo, path, data, islink=False,
isexec=False, copied=None, memctx=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."""
Sean Farley
memfilectx: call super.__init__ instead of duplicating code...
r21689 super(memfilectx, self).__init__(repo, path, None, memctx)
Patrick Mezard
context: add memctx for memory commits
r6715 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 data(self):
return self._data
Sean Farley
memfilectx: add a size method...
r21710 def size(self):
return len(self.data())
Matt Mackall
many, many trivial check-code fixups
r10282 def flags(self):
return self._flags
def renamed(self):
return self._copied
Sean Farley
memfilectx: add remove and write methods...
r22074
def remove(self, ignoremissing=False):
"""wraps unlink for a repo's working directory"""
# need to figure out what to do here
del self._changectx[self._path]
def write(self, data, flags):
"""wraps repo.wwrite"""
self._data = data
Mateusz Kwapich
memctx: allow the metadataonlyctx thats reusing the manifest node...
r30567
class metadataonlyctx(committablectx):
"""Like memctx but it's reusing the manifest of different commit.
Intended to be used by lightweight operations that are creating
metadata-only changes.
Revision information is supplied at initialization time. 'repo' is the
current localrepo, 'ctx' is original revision which manifest we're reuisng
'parents' is a sequence of two parent revisions identifiers (pass None for
every missing parent), 'text' is the commit.
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.
"""
Jun Wu
context: correct metadataonlyctx's parameter...
r30609 def __new__(cls, repo, originalctx, *args, **kwargs):
Mateusz Kwapich
memctx: allow the metadataonlyctx thats reusing the manifest node...
r30567 return super(metadataonlyctx, cls).__new__(cls, repo)
def __init__(self, repo, originalctx, parents, text, user=None, date=None,
extra=None, editor=False):
super(metadataonlyctx, self).__init__(repo, text, user, date, extra)
self._rev = None
self._node = None
self._originalctx = originalctx
self._manifestnode = originalctx.manifestnode()
parents = [(p or nullid) for p in parents]
p1, p2 = self._parents = [changectx(self._repo, p) for p in parents]
# sanity check to ensure that the reused manifest parents are
# manifests of our commit parents
mp1, mp2 = self.manifestctx().parents
Jun Wu
metadataonlyctx: replace "changeset()[0]" to "manifestnode()"...
r31840 if p1 != nullid and p1.manifestnode() != mp1:
Mateusz Kwapich
memctx: allow the metadataonlyctx thats reusing the manifest node...
r30567 raise RuntimeError('can\'t reuse the manifest: '
'its p1 doesn\'t match the new ctx p1')
Jun Wu
metadataonlyctx: replace "changeset()[0]" to "manifestnode()"...
r31840 if p2 != nullid and p2.manifestnode() != mp2:
Mateusz Kwapich
memctx: allow the metadataonlyctx thats reusing the manifest node...
r30567 raise RuntimeError('can\'t reuse the manifest: '
'its p2 doesn\'t match the new ctx p2')
self._files = originalctx.files()
self.substate = {}
if extra:
self._extra = extra.copy()
else:
self._extra = {}
if self._extra.get('branch', '') == '':
self._extra['branch'] = 'default'
if editor:
self._text = editor(self._repo, self, [])
self._repo.savecommitmessage(self._text)
def manifestnode(self):
return self._manifestnode
@propertycache
def _manifestctx(self):
return self._repo.manifestlog[self._manifestnode]
def filectx(self, path, filelog=None):
return self._originalctx.filectx(path, filelog=filelog)
def commit(self):
"""commit context to the repo"""
return self._repo.commitctx(self)
@property
def _manifest(self):
return self._originalctx.manifest()
@propertycache
def _status(self):
"""Calculate exact status from ``files`` specified in the ``origctx``
and parents manifests.
"""
man1 = self.p1().manifest()
p2 = self._parents[1]
# "1 < len(self._parents)" can't be used for checking
# existence of the 2nd parent, because "metadataonlyctx._parents" is
# explicitly initialized by the list, of which length is 2.
if p2.node() != nullid:
man2 = p2.manifest()
managing = lambda f: f in man1 or f in man2
else:
managing = lambda f: f in man1
modified, added, removed = [], [], []
for f in self._files:
if not managing(f):
added.append(f)
elif self[f]:
modified.append(f)
else:
removed.append(f)
return scmutil.status(modified, added, removed, [], [], [], [])