Example #1
0
def unidiff(a, ad, b, bd, fn1, fn2, opts=defaultopts):
    def datetag(date, fn=None):
        if not opts.git and not opts.nodates:
            return '\t%s\n' % date
        if fn and ' ' in fn:
            return '\t\n'
        return '\n'

    if not a and not b:
        return ""

    if opts.noprefix:
        aprefix = bprefix = ''
    else:
        aprefix = 'a/'
        bprefix = 'b/'

    epoch = util.datestr((0, 0))

    fn1 = util.pconvert(fn1)
    fn2 = util.pconvert(fn2)

    if not opts.text and (util.binary(a) or util.binary(b)):
        if a and b and len(a) == len(b) and a == b:
            return ""
        l = ['Binary file %s has changed\n' % fn1]
    elif not a:
        b = splitnewlines(b)
        if a is None:
            l1 = '--- /dev/null%s' % datetag(epoch)
        else:
            l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1))
        l2 = "+++ %s%s" % (bprefix + fn2, datetag(bd, fn2))
        l3 = "@@ -0,0 +1,%d @@\n" % len(b)
        l = [l1, l2, l3] + ["+" + e for e in b]
    elif not b:
        a = splitnewlines(a)
        l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1))
        if b is None:
            l2 = '+++ /dev/null%s' % datetag(epoch)
        else:
            l2 = "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2))
        l3 = "@@ -1,%d +0,0 @@\n" % len(a)
        l = [l1, l2, l3] + ["-" + e for e in a]
    else:
        al = splitnewlines(a)
        bl = splitnewlines(b)
        l = list(_unidiff(a, b, al, bl, opts=opts))
        if not l:
            return ""

        l.insert(0, "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1)))
        l.insert(1, "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2)))

    for ln in xrange(len(l)):
        if l[ln][-1] != '\n':
            l[ln] += "\n\ No newline at end of file\n"

    return "".join(l)
Example #2
0
def unidiff(a, ad, b, bd, fn1, fn2, opts=defaultopts):
    def datetag(date, fn=None):
        if not opts.git and not opts.nodates:
            return '\t%s\n' % date
        if fn and ' ' in fn:
            return '\t\n'
        return '\n'

    if not a and not b:
        return ""

    if opts.noprefix:
        aprefix = bprefix = ''
    else:
        aprefix = 'a/'
        bprefix = 'b/'

    epoch = util.datestr((0, 0))

    fn1 = util.pconvert(fn1)
    fn2 = util.pconvert(fn2)

    if not opts.text and (util.binary(a) or util.binary(b)):
        if a and b and len(a) == len(b) and a == b:
            return ""
        l = ['Binary file %s has changed\n' % fn1]
    elif not a:
        b = splitnewlines(b)
        if a is None:
            l1 = '--- /dev/null%s' % datetag(epoch)
        else:
            l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1))
        l2 = "+++ %s%s" % (bprefix + fn2, datetag(bd, fn2))
        l3 = "@@ -0,0 +1,%d @@\n" % len(b)
        l = [l1, l2, l3] + ["+" + e for e in b]
    elif not b:
        a = splitnewlines(a)
        l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1))
        if b is None:
            l2 = '+++ /dev/null%s' % datetag(epoch)
        else:
            l2 = "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2))
        l3 = "@@ -1,%d +0,0 @@\n" % len(a)
        l = [l1, l2, l3] + ["-" + e for e in a]
    else:
        al = splitnewlines(a)
        bl = splitnewlines(b)
        l = list(_unidiff(a, b, al, bl, opts=opts))
        if not l:
            return ""

        l.insert(0, "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1)))
        l.insert(1, "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2)))

    for ln in xrange(len(l)):
        if l[ln][-1] != '\n':
            l[ln] += "\n\ No newline at end of file\n"

    return "".join(l)
Example #3
0
def canonpath(root, cwd, myname, auditor=None):
    '''return the canonical path of myname, given cwd and root'''
    if util.endswithsep(root):
        rootsep = root
    else:
        rootsep = root + os.sep
    name = myname
    if not os.path.isabs(name):
        name = os.path.join(root, cwd, name)
    name = os.path.normpath(name)
    if auditor is None:
        auditor = pathauditor(root)
    if name != rootsep and name.startswith(rootsep):
        name = name[len(rootsep):]
        auditor(name)
        return util.pconvert(name)
    elif name == root:
        return ''
    else:
        # Determine whether `name' is in the hierarchy at or beneath `root',
        # by iterating name=dirname(name) until that causes no change (can't
        # check name == '/', because that doesn't work on windows). The list
        # `rel' holds the reversed list of components making up the relative
        # file name we want.
        rel = []
        while True:
            try:
                s = util.samefile(name, root)
            except OSError:
                s = False
            if s:
                if not rel:
                    # name was actually the same as root (maybe a symlink)
                    return ''
                rel.reverse()
                name = os.path.join(*rel)
                auditor(name)
                return util.pconvert(name)
            dirname, basename = util.split(name)
            rel.append(basename)
            if dirname == name:
                break
            name = dirname

        # A common mistake is to use -R, but specify a file relative to the repo
        # instead of cwd.  Detect that case, and provide a hint to the user.
        hint = None
        try:
            if cwd != root:
                canonpath(root, root, myname, auditor)
                hint = (_("consider using '--cwd %s'")
                        % os.path.relpath(root, cwd))
        except util.Abort:
            pass

        raise util.Abort(_("%s not under root '%s'") % (myname, root),
                         hint=hint)
Example #4
0
def tidyprefix(dest, kind, prefix):
    '''choose prefix to use for names in archive.  make sure prefix is
    safe for consumers.'''

    if prefix:
        prefix = util.normpath(prefix)
    else:
        if not isinstance(dest, str):
            raise ValueError('dest must be string if no prefix')
        prefix = os.path.basename(dest)
        lower = prefix.lower()
        for sfx in exts.get(kind, []):
            if lower.endswith(sfx):
                prefix = prefix[:-len(sfx)]
                break
    lpfx = os.path.normpath(util.localpath(prefix))
    prefix = util.pconvert(lpfx)
    if not prefix.endswith('/'):
        prefix += '/'
    # Drop the leading '.' path component if present, so Windows can read the
    # zip files (issue4634)
    if prefix.startswith('./'):
        prefix = prefix[2:]
    if prefix.startswith('../') or os.path.isabs(lpfx) or '/../' in prefix:
        raise util.Abort(_('archive prefix contains illegal components'))
    return prefix
 def pathto(self, f, cwd=None):
     if cwd is None:
         cwd = self.getcwd()
     path = util.pathto(self._root, cwd, f)
     if self._slash:
         return util.pconvert(path)
     return path
Example #6
0
def tidyprefix(dest, kind, prefix):
    '''choose prefix to use for names in archive.  make sure prefix is
    safe for consumers.'''

    if prefix:
        prefix = util.normpath(prefix)
    else:
        if not isinstance(dest, str):
            raise ValueError('dest must be string if no prefix')
        prefix = os.path.basename(dest)
        lower = prefix.lower()
        for sfx in exts.get(kind, []):
            if lower.endswith(sfx):
                prefix = prefix[:-len(sfx)]
                break
    lpfx = os.path.normpath(util.localpath(prefix))
    prefix = util.pconvert(lpfx)
    if not prefix.endswith('/'):
        prefix += '/'
    # Drop the leading '.' path component if present, so Windows can read the
    # zip files (issue4634)
    if prefix.startswith('./'):
        prefix = prefix[2:]
    if prefix.startswith('../') or os.path.isabs(lpfx) or '/../' in prefix:
        raise util.Abort(_('archive prefix contains illegal components'))
    return prefix
Example #7
0
def stream_out(repo, fileobj, untrusted=False):
    '''stream out all metadata files in repository.
    writes to file-like object, must support write() and optional flush().'''

    if not repo.ui.configbool('server', 'uncompressed', untrusted=untrusted):
        fileobj.write('1\n')
        return

    # get consistent snapshot of repo. lock during scan so lock not
    # needed while we stream, and commits can happen.
    repolock = None
    try:
        try:
            repolock = repo.lock()
        except (lock.LockHeld, lock.LockUnavailable), inst:
            repo.ui.warn('locking the repository failed: %s\n' % (inst, ))
            fileobj.write('2\n')
            return

        fileobj.write('0\n')
        repo.ui.debug('scanning\n')
        entries = []
        total_bytes = 0
        for name, size in walkrepo(repo.spath):
            name = repo.decodefn(util.pconvert(name))
            entries.append((name, size))
            total_bytes += size
Example #8
0
def _abssource(repo, push=False, abort=True):
    """return pull/push path of repo - either based on parent repo .hgsub info
    or on the top repo config. Abort or return None if no source found."""
    if util.safehasattr(repo, '_subparent'):
        source = util.url(repo._subsource)
        if source.isabs():
            return str(source)
        source.path = posixpath.normpath(source.path)
        parent = _abssource(repo._subparent, push, abort=False)
        if parent:
            parent = util.url(util.pconvert(parent))
            parent.path = posixpath.join(parent.path or '', source.path)
            parent.path = posixpath.normpath(parent.path)
            return str(parent)
    else:  # recursion reached top repo
        if util.safehasattr(repo, '_subtoppath'):
            return repo._subtoppath
        if push and repo.ui.config('paths', 'default-push'):
            return repo.ui.config('paths', 'default-push')
        if repo.ui.config('paths', 'default'):
            return repo.ui.config('paths', 'default')
    if abort:
        raise util.Abort(
            _("default path for subrepository %s not found") %
            reporelpath(repo))
Example #9
0
def stream_out(repo, fileobj, untrusted=False):
    '''stream out all metadata files in repository.
    writes to file-like object, must support write() and optional flush().'''

    if not repo.ui.configbool('server', 'uncompressed', untrusted=untrusted):
        fileobj.write('1\n')
        return

    # get consistent snapshot of repo. lock during scan so lock not
    # needed while we stream, and commits can happen.
    repolock = None
    try:
        try:
            repolock = repo.lock()
        except (lock.LockHeld, lock.LockUnavailable), inst:
            repo.ui.warn('locking the repository failed: %s\n' % (inst,))
            fileobj.write('2\n')
            return

        fileobj.write('0\n')
        repo.ui.debug('scanning\n')
        entries = []
        total_bytes = 0
        for name, size in walkrepo(repo.spath):
            name = repo.decodefn(util.pconvert(name))
            entries.append((name, size))
            total_bytes += size
Example #10
0
 def pathto(self, f, cwd=None):
     if cwd is None:
         cwd = self.getcwd()
     path = util.pathto(self._root, cwd, f)
     if self._slash:
         return util.pconvert(path)
     return path
Example #11
0
def canonpath(root, cwd, myname, auditor=None):
    '''return the canonical path of myname, given cwd and root'''
    if util.endswithsep(root):
        rootsep = root
    else:
        rootsep = root + os.sep
    name = myname
    if not os.path.isabs(name):
        name = os.path.join(root, cwd, name)
    name = os.path.normpath(name)
    if auditor is None:
        auditor = pathauditor(root)
    if name != rootsep and name.startswith(rootsep):
        name = name[len(rootsep):]
        auditor(name)
        return util.pconvert(name)
    elif name == root:
        return ''
    else:
        # Determine whether `name' is in the hierarchy at or beneath `root',
        # by iterating name=dirname(name) until that causes no change (can't
        # check name == '/', because that doesn't work on windows).  For each
        # `name', compare dev/inode numbers.  If they match, the list `rel'
        # holds the reversed list of components making up the relative file
        # name we want.
        root_st = os.stat(root)
        rel = []
        while True:
            try:
                name_st = os.stat(name)
            except OSError:
                name_st = None
            if name_st and util.samestat(name_st, root_st):
                if not rel:
                    # name was actually the same as root (maybe a symlink)
                    return ''
                rel.reverse()
                name = os.path.join(*rel)
                auditor(name)
                return util.pconvert(name)
            dirname, basename = os.path.split(name)
            rel.append(basename)
            if dirname == name:
                break
            name = dirname

        raise util.Abort('%s not under root' % myname)
Example #12
0
def canonpath(root, cwd, myname, auditor=None):
    '''return the canonical path of myname, given cwd and root'''
    if util.endswithsep(root):
        rootsep = root
    else:
        rootsep = root + os.sep
    name = myname
    if not os.path.isabs(name):
        name = os.path.join(root, cwd, name)
    name = os.path.normpath(name)
    if auditor is None:
        auditor = pathauditor(root)
    if name != rootsep and name.startswith(rootsep):
        name = name[len(rootsep):]
        auditor(name)
        return util.pconvert(name)
    elif name == root:
        return ''
    else:
        # Determine whether `name' is in the hierarchy at or beneath `root',
        # by iterating name=dirname(name) until that causes no change (can't
        # check name == '/', because that doesn't work on windows).  For each
        # `name', compare dev/inode numbers.  If they match, the list `rel'
        # holds the reversed list of components making up the relative file
        # name we want.
        root_st = os.stat(root)
        rel = []
        while True:
            try:
                name_st = os.stat(name)
            except OSError:
                name_st = None
            if name_st and util.samestat(name_st, root_st):
                if not rel:
                    # name was actually the same as root (maybe a symlink)
                    return ''
                rel.reverse()
                name = os.path.join(*rel)
                auditor(name)
                return util.pconvert(name)
            dirname, basename = os.path.split(name)
            rel.append(basename)
            if dirname == name:
                break
            name = dirname

        raise util.Abort('%s not under root' % myname)
Example #13
0
def canonpath(root, cwd, myname, auditor=None):
    """return the canonical path of myname, given cwd and root"""
    if util.endswithsep(root):
        rootsep = root
    else:
        rootsep = root + os.sep
    name = myname
    if not os.path.isabs(name):
        name = os.path.join(root, cwd, name)
    name = os.path.normpath(name)
    if auditor is None:
        auditor = pathauditor(root)
    if name != rootsep and name.startswith(rootsep):
        name = name[len(rootsep) :]
        auditor(name)
        return util.pconvert(name)
    elif name == root:
        return ""
    else:
        # Determine whether `name' is in the hierarchy at or beneath `root',
        # by iterating name=dirname(name) until that causes no change (can't
        # check name == '/', because that doesn't work on windows). The list
        # `rel' holds the reversed list of components making up the relative
        # file name we want.
        rel = []
        while True:
            try:
                s = util.samefile(name, root)
            except OSError:
                s = False
            if s:
                if not rel:
                    # name was actually the same as root (maybe a symlink)
                    return ""
                rel.reverse()
                name = os.path.join(*rel)
                auditor(name)
                return util.pconvert(name)
            dirname, basename = util.split(name)
            rel.append(basename)
            if dirname == name:
                break
            name = dirname

        raise util.Abort(_("%s not under root '%s'") % (myname, root))
Example #14
0
 def _walk(self, relpath, recurse):
     '''yields (unencoded, encoded, size)'''
     path = self.pathjoiner(self.path, relpath)
     striplen = len(self.path) + len(os.sep)
     l = []
     if os.path.isdir(path):
         visit = [path]
         while visit:
             p = visit.pop()
             for f, kind, st in osutil.listdir(p, stat=True):
                 fp = self.pathjoiner(p, f)
                 if kind == stat.S_IFREG and f[-2:] in ('.d', '.i'):
                     n = util.pconvert(fp[striplen:])
                     l.append((decodedir(n), n, st.st_size))
                 elif kind == stat.S_IFDIR and recurse:
                     visit.append(fp)
     return sorted(l)
Example #15
0
 def _walk(self, relpath, recurse):
     '''yields (unencoded, encoded, size)'''
     path = self.pathjoiner(self.path, relpath)
     striplen = len(self.path) + len(os.sep)
     l = []
     if os.path.isdir(path):
         visit = [path]
         while visit:
             p = visit.pop()
             for f, kind, st in osutil.listdir(p, stat=True):
                 fp = self.pathjoiner(p, f)
                 if kind == stat.S_IFREG and f[-2:] in ('.d', '.i'):
                     n = util.pconvert(fp[striplen:])
                     l.append((decodedir(n), n, st.st_size))
                 elif kind == stat.S_IFDIR and recurse:
                     visit.append(fp)
     return sorted(l)
Example #16
0
 def _walk(self, relpath, recurse):
     """yields (unencoded, encoded, size)"""
     path = self.path
     if relpath:
         path += "/" + relpath
     striplen = len(self.path) + 1
     l = []
     if os.path.isdir(path):
         visit = [path]
         while visit:
             p = visit.pop()
             for f, kind, st in osutil.listdir(p, stat=True):
                 fp = p + "/" + f
                 if kind == stat.S_IFREG and f[-2:] in (".d", ".i"):
                     n = util.pconvert(fp[striplen:])
                     l.append((decodedir(n), n, st.st_size))
                 elif kind == stat.S_IFDIR and recurse:
                     visit.append(fp)
     return sorted(l)
Example #17
0
 def _walk(self, relpath, recurse):
     '''yields (unencoded, encoded, size)'''
     path = self.path
     if relpath:
         path += '/' + relpath
     striplen = len(self.path) + 1
     l = []
     if self.rawvfs.isdir(path):
         visit = [path]
         readdir = self.rawvfs.readdir
         while visit:
             p = visit.pop()
             for f, kind, st in readdir(p, stat=True):
                 fp = p + '/' + f
                 if kind == stat.S_IFREG and f[-2:] in ('.d', '.i'):
                     n = util.pconvert(fp[striplen:])
                     l.append((decodedir(n), n, st.st_size))
                 elif kind == stat.S_IFDIR and recurse:
                     visit.append(fp)
     l.sort()
     return l
Example #18
0
def tidyprefix(dest, kind, prefix):
    """choose prefix to use for names in archive.  make sure prefix is
    safe for consumers."""

    if prefix:
        prefix = util.normpath(prefix)
    else:
        if not isinstance(dest, str):
            raise ValueError("dest must be string if no prefix")
        prefix = os.path.basename(dest)
        lower = prefix.lower()
        for sfx in exts.get(kind, []):
            if lower.endswith(sfx):
                prefix = prefix[: -len(sfx)]
                break
    lpfx = os.path.normpath(util.localpath(prefix))
    prefix = util.pconvert(lpfx)
    if not prefix.endswith("/"):
        prefix += "/"
    if prefix.startswith("../") or os.path.isabs(lpfx) or "/../" in prefix:
        raise util.Abort(_("archive prefix contains illegal components"))
    return prefix
Example #19
0
def tidyprefix(dest, prefix, suffixes):
    '''choose prefix to use for names in archive.  make sure prefix is
    safe for consumers.'''

    if prefix:
        prefix = util.normpath(prefix)
    else:
        if not isinstance(dest, str):
            raise ValueError('dest must be string if no prefix')
        prefix = os.path.basename(dest)
        lower = prefix.lower()
        for sfx in suffixes:
            if lower.endswith(sfx):
                prefix = prefix[:-len(sfx)]
                break
    lpfx = os.path.normpath(util.localpath(prefix))
    prefix = util.pconvert(lpfx)
    if not prefix.endswith('/'):
        prefix += '/'
    if prefix.startswith('../') or os.path.isabs(lpfx) or '/../' in prefix:
        raise util.Abort(_('archive prefix contains illegal components'))
    return prefix
Example #20
0
def tidyprefix(dest, prefix, suffixes):
    '''choose prefix to use for names in archive.  make sure prefix is
    safe for consumers.'''

    if prefix:
        prefix = util.normpath(prefix)
    else:
        if not isinstance(dest, str):
            raise ValueError('dest must be string if no prefix')
        prefix = os.path.basename(dest)
        lower = prefix.lower()
        for sfx in suffixes:
            if lower.endswith(sfx):
                prefix = prefix[:-len(sfx)]
                break
    lpfx = os.path.normpath(util.localpath(prefix))
    prefix = util.pconvert(lpfx)
    if not prefix.endswith('/'):
        prefix += '/'
    if prefix.startswith('../') or os.path.isabs(lpfx) or '/../' in prefix:
        raise util.Abort(_('archive prefix contains illegal components'))
    return prefix
Example #21
0
def _expandsubinclude(kindpats, root):
    '''Returns the list of subinclude matchers and the kindpats without the
    subincludes in it.'''
    relmatchers = []
    other = []

    for kind, pat, source in kindpats:
        if kind == 'subinclude':
            sourceroot = pathutil.dirname(util.normpath(source))
            pat = util.pconvert(pat)
            path = pathutil.join(sourceroot, pat)

            newroot = pathutil.dirname(path)
            relmatcher = match(newroot, '', [], ['include:%s' % path])

            prefix = pathutil.canonpath(root, root, newroot)
            if prefix:
                prefix += '/'
            relmatchers.append((prefix, relmatcher))
        else:
            other.append((kind, pat, source))

    return relmatchers, other
Example #22
0
def _expandsubinclude(kindpats, root):
    '''Returns the list of subinclude matchers and the kindpats without the
    subincludes in it.'''
    relmatchers = []
    other = []

    for kind, pat, source in kindpats:
        if kind == 'subinclude':
            sourceroot = pathutil.dirname(util.normpath(source))
            pat = util.pconvert(pat)
            path = pathutil.join(sourceroot, pat)

            newroot = pathutil.dirname(path)
            relmatcher = match(newroot, '', [], ['include:%s' % path])

            prefix = pathutil.canonpath(root, root, newroot)
            if prefix:
                prefix += '/'
            relmatchers.append((prefix, relmatcher))
        else:
            other.append((kind, pat, source))

    return relmatchers, other
Example #23
0
def _abssource(repo, push=False, abort=True):
    """return pull/push path of repo - either based on parent repo .hgsub info
    or on the top repo config. Abort or return None if no source found."""
    if util.safehasattr(repo, '_subparent'):
        source = util.url(repo._subsource)
        if source.isabs():
            return str(source)
        source.path = posixpath.normpath(source.path)
        parent = _abssource(repo._subparent, push, abort=False)
        if parent:
            parent = util.url(util.pconvert(parent))
            parent.path = posixpath.join(parent.path or '', source.path)
            parent.path = posixpath.normpath(parent.path)
            return str(parent)
    else: # recursion reached top repo
        if util.safehasattr(repo, '_subtoppath'):
            return repo._subtoppath
        if push and repo.ui.config('paths', 'default-push'):
            return repo.ui.config('paths', 'default-push')
        if repo.ui.config('paths', 'default'):
            return repo.ui.config('paths', 'default')
    if abort:
        raise util.Abort(_("default path for subrepository %s not found") %
            reporelpath(repo))
Example #24
0
            parent = _abssource(ctx._repo, abort=False)
            if parent:
                parent = util.url(parent)
                parent.path = posixpath.join(parent.path or '', src)
                parent.path = posixpath.normpath(parent.path)
                joined = str(parent)
                # Remap the full joined path and use it if it changes,
                # else remap the original source.
                remapped = remap(joined)
                if remapped == joined:
                    src = remap(src)
                else:
                    src = remapped

        src = remap(src)
        state[util.pconvert(path)] = (src.strip(), rev.get(path, ''), kind)

    return state

def writestate(repo, state):
    """rewrite .hgsubstate in (outer) repo with these subrepo states"""
    lines = ['%s %s\n' % (state[s][1], s) for s in sorted(state)]
    repo.wwrite('.hgsubstate', ''.join(lines), '')

def submerge(repo, wctx, mctx, actx, overwrite):
    """delegated from merge.applyupdates: merging of .hgsubstate file
    in working context, merging context and ancestor context"""
    if mctx == actx: # backwards?
        actx = wctx.p1()
    s1 = wctx.substate
    s2 = mctx.substate
Example #25
0
            parent = _abssource(ctx._repo, abort=False)
            if parent:
                parent = util.url(parent)
                parent.path = posixpath.join(parent.path or '', src)
                parent.path = posixpath.normpath(parent.path)
                joined = str(parent)
                # Remap the full joined path and use it if it changes,
                # else remap the original source.
                remapped = remap(joined)
                if remapped == joined:
                    src = remap(src)
                else:
                    src = remapped

        src = remap(src)
        state[util.pconvert(path)] = (src.strip(), rev.get(path, ''), kind)

    return state


def writestate(repo, state):
    """rewrite .hgsubstate in (outer) repo with these subrepo states"""
    lines = ['%s %s\n' % (state[s][1], s) for s in sorted(state)]
    repo.wwrite('.hgsubstate', ''.join(lines), '')


def submerge(repo, wctx, mctx, actx, overwrite):
    """delegated from merge.applyupdates: merging of .hgsubstate file
    in working context, merging context and ancestor context"""
    if mctx == actx:  # backwards?
        actx = wctx.p1()