def __init__(self, ui, path, rev=None):
     converter_source.__init__(self, ui, path, rev)
     self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
     self.ignored = set()
     self.saverev = ui.configbool('convert', 'hg.saverev', False)
     try:
         self.repo = hg.repository(self.ui, path)
         # try to provoke an exception if this isn't really a hg
         # repo, but some other bogus compatible-looking url
         if not self.repo.local():
             raise error.RepoError()
     except error.RepoError:
         ui.traceback()
         raise NoRepo(_("%s is not a local Mercurial repository") % path)
     self.lastrev = None
     self.lastctx = None
     self._changescache = None
     self.convertfp = None
     # Restrict converted revisions to startrev descendants
     startnode = ui.config('convert', 'hg.startrev')
     if startnode is not None:
         try:
             startnode = self.repo.lookup(startnode)
         except error.RepoError:
             raise util.Abort(
                 _('%s is not a valid start revision') % startnode)
         startrev = self.repo.changelog.rev(startnode)
         children = {startnode: 1}
         for rev in self.repo.changelog.descendants(startrev):
             children[self.repo.changelog.node(rev)] = 1
         self.keep = children.__contains__
     else:
         self.keep = util.always
Esempio n. 2
0
def pull(oldpull, ui, repo, source="default", **opts):
    # translate bookmark args to rev args for actual pull
    if opts.get('bookmark'):
        # this is an unpleasant hack as pull will do this internally
        source, branches = hg.parseurl(ui.expandpath(source),
                                       opts.get('branch'))
        other = hg.repository(hg.remoteui(repo, opts), source)
        rb = other.listkeys('bookmarks')

        for b in opts['bookmark']:
            if b not in rb:
                raise util.Abort(_('remote bookmark %s not found!') % b)
            opts.setdefault('rev', []).append(b)

    result = oldpull(ui, repo, source, **opts)

    # update specified bookmarks
    if opts.get('bookmark'):
        for b in opts['bookmark']:
            # explicit pull overrides local bookmark if any
            ui.status(_("importing bookmark %s\n") % b)
            repo._bookmarks[b] = repo[rb[b]].node()
        write(repo)

    return result
Esempio n. 3
0
        def rawentries(subdir="", **map):

            descend = self.ui.configbool('web', 'descend', True)
            for name, path in self.repos:

                if not name.startswith(subdir):
                    continue
                name = name[len(subdir):]
                if not descend and '/' in name:
                    continue

                u = self.ui.copy()
                try:
                    u.readconfig(os.path.join(path, '.hg', 'hgrc'))
                except Exception, e:
                    u.warn(_('error reading %s/.hg/hgrc: %s\n') % (path, e))
                    continue
                def get(section, name, default=None):
                    return u.config(section, name, default, untrusted=True)

                if u.configbool("web", "hidden", untrusted=True):
                    continue

                if not self.read_allowed(u, req):
                    continue

                parts = [name]
                if 'PATH_INFO' in req.env:
                    parts.insert(0, req.env['PATH_INFO'].rstrip('/'))
                if req.env['SCRIPT_NAME']:
                    parts.insert(0, req.env['SCRIPT_NAME'])
                url = re.sub(r'/+', '/', '/'.join(parts) + '/')

                # update time with local timezone
                try:
                    r = hg.repository(self.ui, path)
                except error.RepoError:
                    u.warn(_('error accessing repository at %s\n') % path)
                    continue
                try:
                    d = (get_mtime(r.spath), util.makedate()[1])
                except OSError:
                    continue

                contact = get_contact(get)
                description = get("web", "description", "")
                name = get("web", "name", name)
                row = dict(contact=contact or "unknown",
                           contact_sort=contact.upper() or "unknown",
                           name=name,
                           name_sort=name,
                           url=url,
                           description=description or "unknown",
                           description_sort=description.upper() or "unknown",
                           lastchange=d,
                           lastchange_sort=d[1]-d[0],
                           archives=archivelist(u, "tip", url))
                yield row
Esempio n. 4
0
def outgoing(oldoutgoing, ui, repo, dest=None, **opts):
    if opts.get('bookmarks'):
        dest = ui.expandpath(dest or 'default-push', dest or 'default')
        dest, branches = hg.parseurl(dest, opts.get('branch'))
        other = hg.repository(hg.remoteui(repo, opts), dest)
        ui.status(_('comparing with %s\n') % url.hidepassword(dest))
        return diffbookmarks(ui, other, repo)
    else:
        return oldoutgoing(ui, repo, dest, **opts)
Esempio n. 5
0
def incoming(oldincoming, ui, repo, source="default", **opts):
    if opts.get('bookmarks'):
        source, branches = hg.parseurl(ui.expandpath(source),
                                       opts.get('branch'))
        other = hg.repository(hg.remoteui(repo, opts), source)
        ui.status(_('comparing with %s\n') % url.hidepassword(source))
        return diffbookmarks(ui, repo, other)
    else:
        return oldincoming(ui, repo, source, **opts)
    def create_repository(self):
        """
        Create a source code repository
        """
        import os
        #os.umask(0)

        u = ui.ui()
        if self.anonymous_access:
            hg.repository(
                u,
                os.path.join(
                    global_settings.DJANGO_HG_REPOSITORIES_DIR['public'],
                    self.repo_path), True)
        else:
            hg.repository(
                u,
                os.path.join(
                    global_settings.DJANGO_HG_REPOSITORIES_DIR['public'],
                    self.repo_path), True)
    def setbranch(self, branch, pbranches):
        if not self.clonebranches:
            return

        setbranch = (branch != self.lastbranch)
        self.lastbranch = branch
        if not branch:
            branch = 'default'
        pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
        pbranch = pbranches and pbranches[0][1] or 'default'

        branchpath = os.path.join(self.path, branch)
        if setbranch:
            self.after()
            try:
                self.repo = hg.repository(self.ui, branchpath)
            except:
                self.repo = hg.repository(self.ui, branchpath, create=True)
            self.before()

        # pbranches may bring revisions from other branches (merge parents)
        # Make sure we have them, or pull them.
        missings = {}
        for b in pbranches:
            try:
                self.repo.lookup(b[0])
            except:
                missings.setdefault(b[1], []).append(b[0])

        if missings:
            self.after()
            for pbranch, heads in missings.iteritems():
                pbranchpath = os.path.join(self.path, pbranch)
                prepo = hg.repository(self.ui, pbranchpath)
                self.ui.note(
                    _('pulling from %s into %s\n') % (pbranch, branch))
                self.repo.pull(prepo, [prepo.lookup(h) for h in heads])
            self.before()
Esempio n. 8
0
 def refresh(self, request=None):
     if request:
         self.repo.ui.environ = request.env
     mtime = get_mtime(self.repo.spath)
     if mtime != self.mtime:
         self.mtime = mtime
         self.repo = hg.repository(self.repo.ui, self.repo.root)
         self.maxchanges = int(self.config("web", "maxchanges", 10))
         self.stripecount = int(self.config("web", "stripes", 1))
         self.maxshortchanges = int(self.config("web", "maxshortchanges", 60))
         self.maxfiles = int(self.config("web", "maxfiles", 10))
         self.allowpull = self.configbool("web", "allowpull", True)
         encoding.encoding = self.config("web", "encoding",
                                         encoding.encoding)
 def getoutgoing(dest, revs):
     '''Return the revisions present locally but not in dest'''
     dest = ui.expandpath(dest or 'default-push', dest or 'default')
     dest, branches = hg.parseurl(dest)
     revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
     if revs:
         revs = [repo.lookup(rev) for rev in revs]
     other = hg.repository(hg.remoteui(repo, opts), dest)
     ui.status(_('comparing with %s\n') % url.hidepassword(dest))
     o = discovery.findoutgoing(repo, other)
     if not o:
         ui.status(_("no changes found\n"))
         return []
     o = repo.changelog.nodesbetween(o, revs)[0]
     return [str(repo.changelog.rev(r)) for r in o]
 def __init__(self, ui, path):
     converter_sink.__init__(self, ui, path)
     self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
     self.clonebranches = ui.configbool('convert', 'hg.clonebranches',
                                        False)
     self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
     self.lastbranch = None
     if os.path.isdir(path) and len(os.listdir(path)) > 0:
         try:
             self.repo = hg.repository(self.ui, path)
             if not self.repo.local():
                 raise NoRepo(
                     _('%s is not a local Mercurial repository') % path)
         except error.RepoError, err:
             ui.traceback()
             raise NoRepo(err.args[0])
    def __init__(self, repo, hash=None):
        if hash is None:
            hash = 'tip'
        # get a repo object for the current directory
        self.repository = hg.repository(ui.ui(), os.path.join(repo.repo_path))

        # get a context object for the "rev" revision
        self.ctx = self.repository[hash]
        self.user = self.ctx.user()
        self.description = self.ctx.description()
        self.time = datetime.fromtimestamp(self.ctx.date()[0]).time()
        self.date = date.fromtimestamp(self.ctx.date()[0])
        self.hash = self.ctx  #hash
        self.rev = self.ctx.rev()
        self.files_count = len(self.ctx.files())

        self.revision = self.repository[self.rev]
Esempio n. 12
0
def relink(ui, repo, origin=None, **opts):
    """recreate hardlinks between two repositories

    When repositories are cloned locally, their data files will be
    hardlinked so that they only use the space of a single repository.

    Unfortunately, subsequent pulls into either repository will break
    hardlinks for any files touched by the new changesets, even if
    both repositories end up pulling the same changes.

    Similarly, passing --rev to "hg clone" will fail to use any
    hardlinks, falling back to a complete copy of the source
    repository.

    This command lets you recreate those hardlinks and reclaim that
    wasted space.

    This repository will be relinked to share space with ORIGIN, which
    must be on the same local disk. If ORIGIN is omitted, looks for
    "default-relink", then "default", in [paths].

    Do not attempt any read operations on this repository while the
    command is running. (Both repositories will be locked against
    writes.)
    """
    if not hasattr(util, 'samefile') or not hasattr(util, 'samedevice'):
        raise util.Abort(_('hardlinks are not supported on this system'))
    src = hg.repository(
        hg.remoteui(repo, opts),
        ui.expandpath(origin or 'default-relink', origin or 'default'))
    if not src.local():
        raise util.Abort('must specify local origin repository')
    ui.status(_('relinking %s to %s\n') % (src.store.path, repo.store.path))
    locallock = repo.lock()
    try:
        remotelock = src.lock()
        try:
            candidates = sorted(collect(src, ui))
            targets = prune(candidates, src.store.path, repo.store.path, ui)
            do_relink(src.store.path, repo.store.path, targets, ui)
        finally:
            remotelock.release()
    finally:
        locallock.release()
Esempio n. 13
0
    def __init__(self, repo, name=None, baseui=None):
        if isinstance(repo, str):
            if baseui:
                u = baseui.copy()
            else:
                u = ui.ui()
            self.repo = hg.repository(u, repo)
        else:
            self.repo = repo

        self.repo.ui.setconfig('ui', 'report_untrusted', 'off')
        self.repo.ui.setconfig('ui', 'interactive', 'off')
        hook.redirect(True)
        self.mtime = -1
        self.reponame = name
        self.archives = 'zip', 'gz', 'bz2'
        self.stripecount = 1
        # a repo owner may set web.templates in .hg/hgrc to get any file
        # readable by the user running the CGI script
        self.templatepath = self.config('web', 'templates')
Esempio n. 14
0
    def run_wsgi(self, req):
        try:
            try:
                self.refresh()

                virtual = req.env.get("PATH_INFO", "").strip('/')
                tmpl = self.templater(req)
                ctype = tmpl('mimetype', encoding=encoding.encoding)
                ctype = templater.stringify(ctype)

                # a static file
                if virtual.startswith('static/') or 'static' in req.form:
                    if virtual.startswith('static/'):
                        fname = virtual[7:]
                    else:
                        fname = req.form['static'][0]
                    static = templater.templatepath('static')
                    return (staticfile(static, fname, req),)

                # top-level index
                elif not virtual:
                    req.respond(HTTP_OK, ctype)
                    return self.makeindex(req, tmpl)

                # nested indexes and hgwebs

                repos = dict(self.repos)
                virtualrepo = virtual
                while virtualrepo:
                    real = repos.get(virtualrepo)
                    if real:
                        req.env['REPO_NAME'] = virtualrepo
                        try:
                            repo = hg.repository(self.ui, real)
                            return hgweb(repo).run_wsgi(req)
                        except IOError, inst:
                            msg = inst.strerror
                            raise ErrorResponse(HTTP_SERVER_ERROR, msg)
                        except error.RepoError, inst:
                            raise ErrorResponse(HTTP_SERVER_ERROR, str(inst))
Esempio n. 15
0
def push(oldpush, ui, repo, dest=None, **opts):
    dopush = True
    if opts.get('bookmark'):
        dopush = False
        for b in opts['bookmark']:
            if b in repo._bookmarks:
                dopush = True
                opts.setdefault('rev', []).append(b)

    result = 0
    if dopush:
        result = oldpush(ui, repo, dest, **opts)

    if opts.get('bookmark'):
        # this is an unpleasant hack as push will do this internally
        dest = ui.expandpath(dest or 'default-push', dest or 'default')
        dest, branches = hg.parseurl(dest, opts.get('branch'))
        other = hg.repository(hg.remoteui(repo, opts), dest)
        rb = other.listkeys('bookmarks')
        for b in opts['bookmark']:
            # explicit push overrides remote bookmark if any
            if b in repo._bookmarks:
                ui.status(_("exporting bookmark %s\n") % b)
                new = repo[b].hex()
            elif b in rb:
                ui.status(_("deleting remote bookmark %s\n") % b)
                new = ''  # delete
            else:
                ui.warn(
                    _('bookmark %s does not exist on the local '
                      'or remote repository!\n') % b)
                return 2
            old = rb.get(b, '')
            r = other.pushkey('bookmarks', b, old, new)
            if not r:
                ui.warn(_('updating bookmark %s failed!\n') % b)
                if not result:
                    result = 2

    return result
def fetch(ui, repo, source='default', **opts):
    '''pull changes from a remote repository, merge new changes if needed.

    This finds all changes from the repository at the specified path
    or URL and adds them to the local repository.

    If the pulled changes add a new branch head, the head is
    automatically merged, and the result of the merge is committed.
    Otherwise, the working directory is updated to include the new
    changes.

    When a merge occurs, the newly pulled changes are assumed to be
    "authoritative". The head of the new changes is used as the first
    parent, with local changes as the second. To switch the merge
    order, use --switch-parent.

    See :hg:`help dates` for a list of formats valid for -d/--date.

    Returns 0 on success.
    '''

    date = opts.get('date')
    if date:
        opts['date'] = util.parsedate(date)

    parent, p2 = repo.dirstate.parents()
    branch = repo.dirstate.branch()
    branchnode = repo.branchtags().get(branch)
    if parent != branchnode:
        raise util.Abort(
            _('working dir not at branch tip '
              '(use "hg update" to check out branch tip)'))

    if p2 != nullid:
        raise util.Abort(_('outstanding uncommitted merge'))

    wlock = lock = None
    try:
        wlock = repo.wlock()
        lock = repo.lock()
        mod, add, rem, del_ = repo.status()[:4]

        if mod or add or rem:
            raise util.Abort(_('outstanding uncommitted changes'))
        if del_:
            raise util.Abort(_('working directory is missing some files'))
        bheads = repo.branchheads(branch)
        bheads = [head for head in bheads if len(repo[head].children()) == 0]
        if len(bheads) > 1:
            raise util.Abort(
                _('multiple heads in this branch '
                  '(use "hg heads ." and "hg merge" to merge)'))

        other = hg.repository(hg.remoteui(repo, opts), ui.expandpath(source))
        ui.status(
            _('pulling from %s\n') % url.hidepassword(ui.expandpath(source)))
        revs = None
        if opts['rev']:
            try:
                revs = [other.lookup(rev) for rev in opts['rev']]
            except error.CapabilityError:
                err = _("Other repository doesn't support revision lookup, "
                        "so a rev cannot be specified.")
                raise util.Abort(err)

        # Are there any changes at all?
        modheads = repo.pull(other, heads=revs)
        if modheads == 0:
            return 0

        # Is this a simple fast-forward along the current branch?
        newheads = repo.branchheads(branch)
        newchildren = repo.changelog.nodesbetween([parent], newheads)[2]
        if len(newheads) == 1:
            if newchildren[0] != parent:
                return hg.clean(repo, newchildren[0])
            else:
                return 0

        # Are there more than one additional branch heads?
        newchildren = [n for n in newchildren if n != parent]
        newparent = parent
        if newchildren:
            newparent = newchildren[0]
            hg.clean(repo, newparent)
        newheads = [n for n in newheads if n != newparent]
        if len(newheads) > 1:
            ui.status(
                _('not merging with %d other new branch heads '
                  '(use "hg heads ." and "hg merge" to merge them)\n') %
                (len(newheads) - 1))
            return 1

        # Otherwise, let's merge.
        err = False
        if newheads:
            # By default, we consider the repository we're pulling
            # *from* as authoritative, so we merge our changes into
            # theirs.
            if opts['switch_parent']:
                firstparent, secondparent = newparent, newheads[0]
            else:
                firstparent, secondparent = newheads[0], newparent
                ui.status(
                    _('updating to %d:%s\n') %
                    (repo.changelog.rev(firstparent), short(firstparent)))
            hg.clean(repo, firstparent)
            ui.status(
                _('merging with %d:%s\n') %
                (repo.changelog.rev(secondparent), short(secondparent)))
            err = hg.merge(repo, secondparent, remind=False)

        if not err:
            # we don't translate commit messages
            message = (cmdutil.logmessage(opts)
                       or ('Automated merge with %s' %
                           url.removeauth(other.url())))
            editor = cmdutil.commiteditor
            if opts.get('force_editor') or opts.get('edit'):
                editor = cmdutil.commitforceeditor
            n = repo.commit(message, opts['user'], opts['date'], editor=editor)
            ui.status(
                _('new changeset %d:%s merges remote changes '
                  'with local\n') % (repo.changelog.rev(n), short(n)))

        return err

    finally:
        release(lock, wlock)
def repo(request, name, action, rev, path='', display=None):
    """
    display a repository or handles the commands sended by an hg client
    (clone, pull, push) if a 'cmd' argument is given
    ``name``
        the name of the repository
    ``action``
        the action to display
    ``rev``
        the revision of the repository. By default, it's equal to ``tip``
    ``path``
        optional. A valid path within the repository. If not given, the root of
        the repository is returned
    """
    if request.GET.get('cmd') and request.GET.get('cmd') in HgRepository.cmds:
        # A clone/pull/push command from Mercurial
        from my_mercurial import hg, ui
        from my_mercurial.hgweb.request import wsgirequest
        from my_mercurial.hgweb import protocol

        repo = __get_repo(request, name, 'tip')
        req = wsgirequest(request.META, None)
        r = hg.repository(ui.ui(), repo.repo_path)

        try:
            resp = protocol.__getattribute__(request.GET.get('cmd'))(r, req)
            #update the repository size only after a push
            #if (request.GET.get('cmd') == 'unbundle'):
            #    print repo.get_size()
        except:
            from my_mercurial.hgweb.common import ErrorResponse, HTTP_OK
            resp = ErrorResponse(HTTP_OK, 'command unrecognized')

        return HttpResponse(resp, protocol.HGTYPE)
    else:
        # Display a view of a repository
        repo = __get_repo(request, name, rev)

        if not repo.user_can_read(request.user.username):
            return HttpResponseRedirect(global_settings.LOGIN_URL)

        # dispatcher
        if action == 'binary':
            return __binary(request, repo, rev, path)
        elif action == 'browse':
            if path.rfind('/') == len(path) - 1:
                # browse the repo tree
                return __browse(request, repo, rev, path)
            else:
                # show a file
                return __show(request, repo, rev, path)
        elif action == 'changesets':
            if path == '':
                if "q" in request.GET:
                    #perform a search
                    return __search(request, repo)
                # display changesets
                elif (rev == 'tip'):
                    # pager of changesets
                    return __changesets(request, repo)
                else:
                    # show a changeset
                    return __changeset(request, repo, rev)
            else:
                if rev == 'tip':
                    # log of a file
                    return __log(request, repo, rev, path)
                else:
                    return __diff(request, repo, rev, path)
        elif action == 'overview':
            return __overview(request, repo, rev)
def transplant(ui, repo, *revs, **opts):
    '''transplant changesets from another branch

    Selected changesets will be applied on top of the current working
    directory with the log of the original changeset. If --log is
    specified, log messages will have a comment appended of the form::

      (transplanted from CHANGESETHASH)

    You can rewrite the changelog message with the --filter option.
    Its argument will be invoked with the current changelog message as
    $1 and the patch as $2.

    If --source/-s is specified, selects changesets from the named
    repository. If --branch/-b is specified, selects changesets from
    the branch holding the named revision, up to that revision. If
    --all/-a is specified, all changesets on the branch will be
    transplanted, otherwise you will be prompted to select the
    changesets you want.

    :hg:`transplant --branch REVISION --all` will rebase the selected
    branch (up to the named revision) onto your current working
    directory.

    You can optionally mark selected transplanted changesets as merge
    changesets. You will not be prompted to transplant any ancestors
    of a merged transplant, and you can merge descendants of them
    normally instead of transplanting them.

    If no merges or revisions are provided, :hg:`transplant` will
    start an interactive changeset browser.

    If a changeset application fails, you can fix the merge by hand
    and then resume where you left off by calling :hg:`transplant
    --continue/-c`.
    '''
    def incwalk(repo, incoming, branches, match=util.always):
        if not branches:
            branches = None
        for node in repo.changelog.nodesbetween(incoming, branches)[0]:
            if match(node):
                yield node

    def transplantwalk(repo, root, branches, match=util.always):
        if not branches:
            branches = repo.heads()
        ancestors = []
        for branch in branches:
            ancestors.append(repo.changelog.ancestor(root, branch))
        for node in repo.changelog.nodesbetween(ancestors, branches)[0]:
            if match(node):
                yield node

    def checkopts(opts, revs):
        if opts.get('continue'):
            if opts.get('branch') or opts.get('all') or opts.get('merge'):
                raise util.Abort(_('--continue is incompatible with '
                                   'branch, all or merge'))
            return
        if not (opts.get('source') or revs or
                opts.get('merge') or opts.get('branch')):
            raise util.Abort(_('no source URL, branch tag or revision '
                               'list provided'))
        if opts.get('all'):
            if not opts.get('branch'):
                raise util.Abort(_('--all requires a branch revision'))
            if revs:
                raise util.Abort(_('--all is incompatible with a '
                                   'revision list'))

    checkopts(opts, revs)

    if not opts.get('log'):
        opts['log'] = ui.config('transplant', 'log')
    if not opts.get('filter'):
        opts['filter'] = ui.config('transplant', 'filter')

    tp = transplanter(ui, repo)

    p1, p2 = repo.dirstate.parents()
    if len(repo) > 0 and p1 == revlog.nullid:
        raise util.Abort(_('no revision checked out'))
    if not opts.get('continue'):
        if p2 != revlog.nullid:
            raise util.Abort(_('outstanding uncommitted merges'))
        m, a, r, d = repo.status()[:4]
        if m or a or r or d:
            raise util.Abort(_('outstanding local changes'))

    bundle = None
    source = opts.get('source')
    if source:
        sourcerepo = ui.expandpath(source)
        source = hg.repository(ui, sourcerepo)
        source, incoming, bundle = bundlerepo.getremotechanges(ui, repo, source,
                                    force=True)
    else:
        source = repo

    try:
        if opts.get('continue'):
            tp.resume(repo, source, opts)
            return

        tf = tp.transplantfilter(repo, source, p1)
        if opts.get('prune'):
            prune = [source.lookup(r)
                     for r in cmdutil.revrange(source, opts.get('prune'))]
            matchfn = lambda x: tf(x) and x not in prune
        else:
            matchfn = tf
        branches = map(source.lookup, opts.get('branch', ()))
        merges = map(source.lookup, opts.get('merge', ()))
        revmap = {}
        if revs:
            for r in cmdutil.revrange(source, revs):
                revmap[int(r)] = source.lookup(r)
        elif opts.get('all') or not merges:
            if source != repo:
                alltransplants = incwalk(source, incoming, branches,
                                         match=matchfn)
            else:
                alltransplants = transplantwalk(source, p1, branches,
                                                match=matchfn)
            if opts.get('all'):
                revs = alltransplants
            else:
                revs, newmerges = browserevs(ui, source, alltransplants, opts)
                merges.extend(newmerges)
            for r in revs:
                revmap[source.changelog.rev(r)] = r
        for r in merges:
            revmap[source.changelog.rev(r)] = r

        tp.apply(repo, source, revmap, merges, opts)
    finally:
        if bundle:
            source.close()
            os.unlink(bundle)
                                           False)
        self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
        self.lastbranch = None
        if os.path.isdir(path) and len(os.listdir(path)) > 0:
            try:
                self.repo = hg.repository(self.ui, path)
                if not self.repo.local():
                    raise NoRepo(
                        _('%s is not a local Mercurial repository') % path)
            except error.RepoError, err:
                ui.traceback()
                raise NoRepo(err.args[0])
        else:
            try:
                ui.status(_('initializing destination %s repository\n') % path)
                self.repo = hg.repository(self.ui, path, create=True)
                if not self.repo.local():
                    raise NoRepo(
                        _('%s is not a local Mercurial repository') % path)
                self.created.append(path)
            except error.RepoError:
                ui.traceback()
                raise NoRepo(
                    _("could not create hg repository %s as sink") % path)
        self.lock = None
        self.wlock = None
        self.filemapmode = False

    def before(self):
        self.ui.debug('run hg sink pre-conversion action\n')
        self.wlock = self.repo.wlock()