filemerge: introduce class whose objects represent files not in a context

Most code is going to barf at the return values here (particularly from data
and size), so we restrict it to the filemerge code.

This is already somewhat supported via:

  ctx.filectx(f, fileid=nullid)

Indeed, for add/add conflicts (ancestor doesn't have the file) we use precisely
that. However, that is broken in subtle ways:
- The cmp() function in filectx returns False (identical) for such a filectx
  when compared to a zero-length file.
- size() returns 0 rather than some sort of value indicating that the file isn't
  present.
- data() returns '' rather than some sort of value indicating that the file isn't
  present.

Given the relatively niche use of such filectxes, this seems to be the simplest
way to fix all these issues.
This commit is contained in:
Siddharth Agarwal 2015-11-16 11:45:35 -08:00
parent 8529661292
commit d26567458a

View File

@ -13,7 +13,7 @@ import re
import tempfile
from .i18n import _
from .node import short
from .node import nullid, short
from . import (
cmdutil,
@ -44,6 +44,50 @@ nomerge = None
mergeonly = 'mergeonly' # just the full merge, no premerge
fullmerge = 'fullmerge' # both premerge and merge
class absentfilectx(object):
"""Represents a file that's ostensibly in a context but is actually not
present in it.
This is here because it's very specific to the filemerge code for now --
other code is likely going to break with the values this returns."""
def __init__(self, ctx, f):
self._ctx = ctx
self._f = f
def path(self):
return self._f
def size(self):
return None
def data(self):
return None
def filenode(self):
return nullid
_customcmp = True
def cmp(self, fctx):
"""compare with other file context
returns True if different from fctx.
"""
return not (fctx.isabsent() and
fctx.ctx() == self.ctx() and
fctx.path() == self.path())
def flags(self):
return ''
def changectx(self):
return self._ctx
def isbinary(self):
return False
def isabsent(self):
return True
def internaltool(name, mergetype, onfailure=None, precheck=None):
'''return a decorator for populating internal merge tool table'''
def decorator(func):