def pull()

in eden/scm/edenscm/mercurial/commands/__init__.py [0:0]


def pull(ui, repo, source="default", **opts):
    """pull changes from the specified source

    Pull changes from a remote repository to a local one. This command modifies
    the commit graph, but doesn't affect local commits or files on disk.

    If SOURCE is omitted, the default path is used.
    See :hg:`help urls` for more information.

    .. container:: verbose

        You can use ``.`` for BOOKMARK to specify the active bookmark.

    Returns 0 on success, 1 if ``--update`` was specified but the update had unresolved conflicts.
    """
    if ui.configbool("pull", "automigrate"):
        repo.automigratestart()

    if ui.configbool("commands", "update.requiredest") and opts.get("update"):
        msg = _("update destination required by configuration")
        hint = _("use hg pull followed by hg update DEST")
        raise error.Abort(msg, hint=hint)

    # Allows us to announce larger changes affecting all the users by displaying
    # config-driven hint on pull.
    for name, _message in ui.configitems("hint-definitions"):
        if name.startswith("pull:"):
            hintutil.trigger(name)

    source, branches = hg.parseurl(ui.expandpath(source))
    ui.status_err(_("pulling from %s\n") % util.hidepassword(source))

    hasselectivepull = ui.configbool("remotenames", "selectivepull")
    if (
        hasselectivepull
        and ui.configbool("commands", "new-pull")
        and not branches[0]
        and not branches[1]
    ):
        # Use the new repo.pull API.
        # - Does not support non-selectivepull.
        # - Does not support named branches.
        modheads, checkout = _newpull(ui, repo, source, **opts)
    else:
        if git.isgitpeer(repo):
            raise error.Abort(_("pull: branch name in URL is not supported"))
        # The legacy pull implementation. Problems:
        # - Remotenames:
        #   - Inefficiency: Call listkey proto twice.
        #   - Race condition: Because listkey is called twice, remotenames can
        #     fail to update properly (if it has moved server-side after
        #     pulling the commits).
        # - Features considered as tech-debt:
        #   - Has named branch support (and overhead listing branchmap).
        #   - Has "pull everything" (non-selectivepull) support.
        # - Slow algorithms:
        #   - visibility.add the entire changeroup can be inefficient.
        with repo.connectionpool.get(
            source, opts=opts
        ) as conn, repo.wlock(), repo.lock(), repo.transaction("pull"):
            other = conn.peer
            revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get("rev"))
            if revs:
                revs = autopull.rewritepullrevs(repo, revs)

            implicitbookmarks = set()
            # If any revision is given, ex. pull -r HASH, include selectivepull
            # bookmarks automatically. This check exists so the no-argument
            # pull is unaffected (pulls everything instead of just
            # selectivepull bookmarks)
            if revs:
                remotename = bookmarks.remotenameforurl(
                    ui, other.url()
                )  # ex. 'default' or 'remote'
                # Include selective pull bookmarks automatically.
                implicitbookmarks.update(
                    bookmarks.selectivepullbookmarknames(repo, remotename)
                )

            # If any revision is given, ex. pull -r HASH and the commit is known locally make it visible again.
            if revs:
                if visibility.enabled(repo):
                    visibility.add(
                        repo,
                        [
                            repo[r].node()
                            for r in revs
                            if r in repo and repo[r].mutable()
                        ],
                    )

            pullopargs = {}
            if opts.get("bookmark") or implicitbookmarks:
                if not revs:
                    revs = []
                # The list of bookmark used here is not the one used to actually
                # update the bookmark name. This can result in the revision pulled
                # not ending up with the name of the bookmark because of a race
                # condition on the server. (See issue 4689 for details)
                # TODO: Consider migrate to repo.pull to avoid the race
                # condition.
                remotebookmarks = other.listkeys("bookmarks")
                remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
                pullopargs["remotebookmarks"] = remotebookmarks
                for b in opts["bookmark"]:
                    b = repo._bookmarks.expandname(b)
                    if b not in remotebookmarks:
                        raise error.Abort(_("remote bookmark %s not found!") % b)
                    revs.append(hex(remotebookmarks[b]))
                    implicitbookmarks.discard(b)
                for b in implicitbookmarks:
                    if b in remotebookmarks:
                        revs.append(hex(remotebookmarks[b]))

            if revs:
                try:
                    # When 'rev' is a bookmark name, we cannot guarantee that it
                    # will be updated with that name because of a race condition
                    # server side. (See issue 4689 for details)
                    oldrevs = revs
                    revs = []  # actually, nodes
                    for r in oldrevs:
                        node = other.lookup(r)
                        revs.append(node)
                        if r == checkout:
                            checkout = node
                except error.CapabilityError:
                    err = _(
                        "other repository doesn't support revision lookup, "
                        "so a rev cannot be specified."
                    )
                    raise error.Abort(err)

            pullopargs.update(opts.get("opargs", {}))
            modheads = exchange.pull(
                repo,
                other,
                heads=revs,
                force=opts.get("force"),
                bookmarks=opts.get("bookmark", ()),
                opargs=pullopargs,
            ).cgresult

    # brev is a name, which might be a bookmark to be activated at
    # the end of the update. In other words, it is an explicit
    # destination of the update
    brev = None

    # Run 'update' in another transaction.
    if checkout and checkout in repo:
        checkout = repo[checkout].node()

        # order below depends on implementation of
        # hg.addbranchrevs(). opts['bookmark'] is ignored,
        # because 'checkout' is determined without it.
        if opts.get("rev"):
            brev = opts["rev"][0]
        else:
            brev = branches[0]
    repo._subtoppath = source
    try:
        ret = postincoming(ui, repo, modheads, opts.get("update"), checkout, brev)

    finally:
        del repo._subtoppath

    if ui.configbool("pull", "automigrate"):
        repo.automigratefinish()

    return ret