def inmemorymerge(ui, repo, src, dest, base): """Return memctx representing three way merge of src, dest, and base src is "remote" and dest is "local". """ mergeresult = nativecheckout.mergeresult(src.manifest(), dest.manifest(), base.manifest()) manifestbuilder = mergeresult.manifestbuilder() if manifestbuilder is None: raise error.Abort( _("amend would conflict in %s") % ", ".join(mergeresult.conflict_paths())) try: resolved = rebasemod._simplemerge(ui, base, src, dest, manifestbuilder) except error.InMemoryMergeConflictsError as ex: raise error.Abort( _("amend would conflict in %s") % ", ".join(ex.paths)) mergedctx = mirrorwithmetadata(src, "rebase") for path in manifestbuilder.removed(): mergedctx[path] = None for path, merged in resolved.items(): mergedctx[path] = context.overlayfilectx( src[path], datafunc=lambda data=merged: data, ctx=mergedctx, ) return mergedctx
def overlaycontext( memworkingcopy, ctx, parents=None, extra=None, loginfo=None, mutinfo=None ): """({path: content}, ctx, (p1node, p2node)?, {}?) -> memctx memworkingcopy overrides file contents. """ mctx = context.memctx.mirror( ctx, parentnodes=parents, extra=extra, loginfo=loginfo, mutinfo=mutinfo ) for path, data in memworkingcopy.items(): fctx = context.overlayfilectx(ctx[path], datafunc=lambda data=data: data) mctx[path] = fctx return mctx
def dirsyncctx(ctx, matcher=None): """for changes in ctx that matches matcher, apply dirsync rules Return: (newctx, {path}) This function does not change working copy or dirstate. """ maps = getconfigs(ctx) resultmirrored = set() resultctx = ctx # Do not dirsync if there is nothing to sync. # Do not dirsync metaedit commits, because they might break assertions in # metadataonlyctx (manifest is unchanged). if not maps or (ctx.mutinfo() or {}).get("mutop") == "metaedit": return resultctx, resultmirrored needsync = configstomatcher(maps) repo = ctx.repo() mctx, status = _mctxstatus(ctx) added = set(status.added) modified = set(status.modified) removed = set(status.removed) if matcher is None: matcher = lambda path: True for action, paths in ( ("a", status.added), ("m", status.modified), ("r", status.removed), ): for src in paths: if not needsync.matches(src) or not matcher(src): continue srcmirror, mirrors = getmirrors(maps, src) if not mirrors: continue dstpaths = [] # [(dstpath, dstmirror)] for dstmirror in (m for m in mirrors if m != srcmirror): dst = _mirrorpath(srcmirror, dstmirror, src) dstpaths.append((dst, dstmirror)) if action == "r": fsrc = None else: fsrc = ctx[src] for dst, dstmirror in dstpaths: # changed: whether ctx[dst] is changed, according to status. # conflict: whether the dst change conflicts with src change. if dst in removed: conflict, changed = (action != "r"), True elif dst in modified or dst in added: conflict, changed = (fsrc is None or ctx[dst].cmp(fsrc)), True else: conflict = changed = False if conflict: raise error.Abort( _("path '%s' needs to be mirrored to '%s', but " "the target already has pending changes") % (src, dst)) if changed: if action == "r": fmt = _( "not mirroring remove of '%s' to '%s'; it is already removed\n" ) else: fmt = _( "not mirroring '%s' to '%s'; it already matches\n") repo.ui.note(fmt % (src, dst)) continue # Mirror copyfrom, too. renamed = fsrc and fsrc.renamed() fmirror = fsrc msg = None if renamed: copyfrom, copynode = renamed newcopyfrom = _mirrorpath(srcmirror, dstmirror, copyfrom) if newcopyfrom: if action == "a": msg = _( "mirrored copy '%s -> %s' to '%s -> %s'\n") % ( copyfrom, src, newcopyfrom, dst, ) fmirror = context.overlayfilectx(fsrc, copied=(newcopyfrom, copynode)) mctx[dst] = fmirror resultmirrored.add(dst) if msg is None: if action == "a": fmt = _("mirrored adding '%s' to '%s'\n") elif action == "m": fmt = _("mirrored changes in '%s' to '%s'\n") else: fmt = _("mirrored remove of '%s' to '%s'\n") msg = fmt % (src, dst) repo.ui.status(msg) if resultmirrored: resultctx = mctx return resultctx, resultmirrored
def getfctx(repo, memctx, path): if path not in ctx: return None return context.overlayfilectx(ctx[path])