Mercurial > hg
changeset 35998:dce43aaaf209
lfs: allow a pointer to be extracted from a context that removes the file
This is needed to let 'set:lfs()' and '{lfs_files}' work normally on removed
files.
Yuya suggested returning a null pointer for removed files, instead of the
pointer from the parent. The first attempt at this was to return None for a non
LFS file, and a (pointer, ctx) tuple to hold the pointer and context (or parent
pointer and context for a removed file). But this complicated the callers, even
the ones that didn't care about removed files.
Instead, let's use {} to represent a removed pointer. This has the added
convenience of being a useful representation in the template language, and only
affects the callers that care about removed files (and only slightly). Since
pointers are explicitly serialized with a call to a member function, there is no
danger of writing these to disk.
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Sat, 27 Jan 2018 18:56:24 -0500 |
parents | 24f05489377b |
children | 8c7d5e90e6bd |
files | hgext/lfs/wrapper.py |
diffstat | 1 files changed, 30 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/lfs/wrapper.py Sat Feb 10 19:33:19 2018 +0100 +++ b/hgext/lfs/wrapper.py Sat Jan 27 18:56:24 2018 -0500 @@ -349,26 +349,46 @@ pointers[p.oid()] = p return sorted(pointers.values()) -def pointerfromctx(ctx, f): +def pointerfromctx(ctx, f, removed=False): """return a pointer for the named file from the given changectx, or None if - the file isn't LFS.""" + the file isn't LFS. + + Optionally, the pointer for a file deleted from the context can be returned. + Since no such pointer is actually stored, and to distinguish from a non LFS + file, this pointer is represented by an empty dict. + """ + _ctx = ctx if f not in ctx: - return None - fctx = ctx[f] + if not removed: + return None + if f in ctx.p1(): + _ctx = ctx.p1() + elif f in ctx.p2(): + _ctx = ctx.p2() + else: + return None + fctx = _ctx[f] if not _islfs(fctx.filelog(), fctx.filenode()): return None try: - return pointer.deserialize(fctx.rawdata()) + p = pointer.deserialize(fctx.rawdata()) + if ctx == _ctx: + return p + return {} except pointer.InvalidPointer as ex: raise error.Abort(_('lfs: corrupted pointer (%s@%s): %s\n') - % (f, short(ctx.node()), ex)) + % (f, short(_ctx.node()), ex)) -def pointersfromctx(ctx): - """return a dict {path: pointer} for given single changectx""" +def pointersfromctx(ctx, removed=False): + """return a dict {path: pointer} for given single changectx. + + If ``removed`` == True and the LFS file was removed from ``ctx``, the value + stored for the path is an empty dict. + """ result = {} for f in ctx.files(): - p = pointerfromctx(ctx, f) - if p: + p = pointerfromctx(ctx, f, removed=removed) + if p is not None: result[f] = p return result