Esempio n. 1
0
def checkhgserver(ui, repo, opts, path):
    ui.status(
        _("Testing connection to Mercurial on the server: querying master bookmark\n"
          ),
        component="debugnetwork",
    )
    starttime = util.timer()
    peer = None
    try:
        peer = hg.peer(repo, opts, path)
        bookmarks = peer.listkeys("bookmarks")
        master = bookmarks.get("master")
    except Exception as e:
        ui.status(_("failed to connect to Mercurial: %s\n") % e,
                  error=_("error"))
        return False
    finally:
        if peer:
            peer.close()
    endtime = util.timer()

    ui.status(
        _("Connected ok: %s\n") % util.timecount(endtime - starttime),
        component="debugnetwork",
    )
    if master:
        ui.status(_("Server master bookmark is %s\n") % master,
                  component="debugnetwork")
    else:
        ui.status(_("Server has no master bookmark\n"),
                  component="debugnetwork")
    return True
Esempio n. 2
0
def _lookup_node(repo, hexnode, from_scm_type):
    gitlookupnode = "_gitlookup_%s_%s" % (from_scm_type, hexnode)

    # ui.expandpath('default') returns 'default' if there is no default
    # path. This can be the case when command is ran on the server.
    # In that case let's run lookup() command locally.
    try:
        result = repo.lookup(gitlookupnode)
    except error.RepoLookupError:
        # Note: RepoLookupError is caught here because repo.lookup()
        # can throw only this exception.
        peerpath = repo.ui.expandpath("default")

        # sshing can cause junk 'remote: ...' output to stdout, so we need to
        # redirect it temporarily so automation can parse the result easily.
        oldfout = repo.ui.fout
        try:
            repo.baseui.fout = repo.ui.ferr
            remoterepo = hg.peer(repo, {}, peerpath)
            result = remoterepo.lookup(gitlookupnode)
        except error.RepoError:
            # Note: RepoError can be thrown by hg.peer(), RepoLookupError
            # can be thrown by remoterepo.lookup(). RepoLookupError is a
            # subclass of RepoError so catching just error.RepoError is enough.
            return None
        finally:
            repo.baseui.fout = oldfout

    # Sanity check - result must be 20 chars
    if len(result) != 20:
        return None
    else:
        return result
Esempio n. 3
0
def annotatepeer(repo):
    ui = repo.ui

    # fileservice belongs to remotefilelog
    fileservice = getattr(repo, "fileservice", None)
    sharepeer = ui.configbool("fastannotate", "clientsharepeer", True)

    if sharepeer and fileservice:
        ui.debug("fastannotate: using remotefilelog connection pool\n")
        conn = repo.connectionpool.get(repo.fallbackpath)
        peer = conn.peer
        stolen = True
    else:
        remotepath = ui.expandpath(
            ui.config("fastannotate", "remotepath", "default"))
        peer = hg.peer(ui, {}, remotepath)
        stolen = False

    try:
        # Note: fastannotate requests should never trigger a remotefilelog
        # "getfiles" request, because "getfiles" puts the stream into a state
        # that does not exit. See "clientfetch": it does "getannotate" before
        # any hg stuff that could potentially trigger a "getfiles".
        yield peer
    finally:
        if not stolen:
            for i in ["close", "cleanup"]:
                getattr(peer, i, lambda: None)()
        else:
            conn.__exit__(None, None, None)
Esempio n. 4
0
def _getremotepeer(ui, repo, opts):
    remotepath = opts.get("remote_path")
    path = ui.paths.getpath(remotepath or None, default="default")

    destpath = path.pushloc or path.loc
    other = hg.peer(repo, opts, destpath)
    return other
Esempio n. 5
0
def _findbundle(repo, rev):
    """Returns the backup bundle that contains the given rev. If found, it
    returns the bundle peer and the full rev hash. If not found, it return None
    and the given rev value.
    """
    ui = repo.ui
    backuppath = repo.localvfs.join("strip-backup")
    backups = filter(os.path.isfile, glob.glob(backuppath + "/*.hg"))
    backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
    for backup in backups:
        # Much of this is copied from the hg incoming logic
        source = os.path.relpath(backup, pycompat.getcwd())
        source = ui.expandpath(source)
        source, branches = hg.parseurl(source)
        other = hg.peer(repo, {}, source)

        quiet = ui.quiet
        try:
            ui.quiet = True
            ret = bundlerepo.getremotechanges(ui, repo, other, None, None, None)
            localother, chlist, cleanupfn = ret
            for node in chlist:
                if hex(node).startswith(rev):
                    return other, node
        except error.LookupError:
            continue
        finally:
            ui.quiet = quiet

    return None, rev
Esempio n. 6
0
def listserverbookmarks(ui, **opts):
    """List the bookmarks for a remote server"""
    path = opts["path"]
    remote = hg.peer(ui, {}, path)
    bookmarks = remote.listkeys("bookmarks")

    for pair in bookmarks.items():
        ui.write("%s\1%s\0" % pair)
    ui.flush()
Esempio n. 7
0
def openrepo(ui, repopath):
    repo = None
    try:
        repo = hg.peer(ui, {}, repopath)
        yield repo
    except error.RepoError:
        yield None
    finally:
        if repo:
            repo.close()
Esempio n. 8
0
def _bookmarks(orig, ui, repo, *names, **opts):
    pattern = opts.get("list_remote")
    delete = opts.get("delete")
    remotepath = opts.get("remote_path")
    path = ui.paths.getpath(remotepath or None, default=(pathname.default, ))

    if pattern:
        destpath = path.pushloc or path.loc
        other = hg.peer(repo, opts, destpath)
        if not names:
            raise error.Abort(
                "--list-remote requires a bookmark pattern",
                hint='use "hg book" to get a list of your local bookmarks',
            )
        else:
            # prefix bookmark listing is not yet supported by Edenapi.
            usehttp = repo.ui.configbool(
                "infinitepush",
                "httpbookmarks") and not any(n.endswith("*") for n in names)

            if usehttp:
                fetchedbookmarks = _http_bookmark_fetch(repo, names)
            else:
                fetchedbookmarks = other.listkeyspatterns("bookmarks",
                                                          patterns=names)
        _showbookmarks(ui, fetchedbookmarks, **opts)
        return
    elif delete and "remotenames" in extensions._extensions:
        with repo.wlock(), repo.lock(), repo.transaction("bookmarks"):
            existing_local_bms = set(repo._bookmarks.keys())
            scratch_bms = []
            other_bms = []
            for name in names:
                if (repo._scratchbranchmatcher.match(name)
                        and name not in existing_local_bms):
                    scratch_bms.append(name)
                else:
                    other_bms.append(name)

            if len(scratch_bms) > 0:
                if remotepath == "":
                    remotepath = pathname.default
                bookmarks.deleteremotebookmarks(ui, repo, remotepath,
                                                scratch_bms)

            if len(other_bms) > 0 or len(scratch_bms) == 0:
                return orig(ui, repo, *other_bms, **opts)
    else:
        return orig(ui, repo, *names, **opts)
Esempio n. 9
0
def getflogheads(ui, repo, path):
    """
    Extension printing a remotefilelog's heads

    Used for testing purpose
    """

    dest = repo.ui.expandpath("default")
    peer = hg.peer(repo, {}, dest)

    flogheads = peer.getflogheads(path)

    if flogheads:
        for head in flogheads:
            ui.write(head + "\n")
    else:
        ui.write(_("EMPTY\n"))
Esempio n. 10
0
File: hg.py Progetto: xmonader/eden
    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]
        if pbranches:
            pbranch = pbranches[0][1]
        else:
            pbranch = "default"

        branchpath = os.path.join(self.path, branch)
        if setbranch:
            self.after()
            try:
                self.repo = hg.repository(self.ui, branchpath)
            except Exception:
                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 Exception:
                missings.setdefault(b[1], []).append(b[0])

        if missings:
            self.after()
            for pbranch, heads in sorted(pycompat.iteritems(missings)):
                pbranchpath = os.path.join(self.path, pbranch)
                prepo = hg.peer(self.ui, {}, pbranchpath)
                self.ui.note(
                    _("pulling from %s into %s\n") % (pbranch, branch))
                exchange.pull(self.repo, prepo,
                              [prepo.lookup(h) for h in heads])
            self.before()
Esempio n. 11
0
def _bookmarks(orig, ui, repo, *names, **opts):
    pattern = opts.get("list_remote")
    delete = opts.get("delete")
    remotepath = opts.get("remote_path")
    path = ui.paths.getpath(remotepath or None, default=("default"))
    with repo.wlock(), repo.lock(), repo.transaction("bookmarks"):
        if pattern:
            destpath = path.pushloc or path.loc
            other = hg.peer(repo, opts, destpath)
            if not names:
                raise error.Abort(
                    "--list-remote requires a bookmark pattern",
                    hint='use "hg book" to get a list of your local bookmarks',
                )
            else:
                fetchedbookmarks = other.listkeyspatterns("bookmarks", patterns=names)
            _showbookmarks(ui, fetchedbookmarks, **opts)
            return
        elif delete and "remotenames" in extensions._extensions:
            existing_local_bms = set(repo._bookmarks.keys())
            scratch_bms = []
            other_bms = []
            for name in names:
                if (
                    repo._scratchbranchmatcher.match(name)
                    and name not in existing_local_bms
                ):
                    scratch_bms.append(name)
                else:
                    other_bms.append(name)

            if len(scratch_bms) > 0:
                if remotepath == "":
                    remotepath = "default"
                bookmarks.deleteremotebookmarks(ui, repo, remotepath, scratch_bms)

            if len(other_bms) > 0 or len(scratch_bms) == 0:
                return orig(ui, repo, *other_bms, **opts)
        else:
            return orig(ui, repo, *names, **opts)
Esempio n. 12
0
def gitgetmeta(ui, repo, source="default"):
    """get git metadata from a server that supports fb_gitmeta"""
    source, branch = hg.parseurl(ui.expandpath(source))
    other = hg.peer(repo, {}, source)
    ui.status(_("getting git metadata from %s\n") % util.hidepassword(source))

    kwargs = {"bundlecaps": exchange.caps20to10(repo)}
    capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo))
    kwargs["bundlecaps"].add("bundle2=" + util.urlreq.quote(capsblob))
    # this would ideally not be in the bundlecaps at all, but adding new kwargs
    # for wire transmissions is not possible as of Mercurial d19164a018a1
    kwargs["bundlecaps"].add("fb_gitmeta")
    kwargs["heads"] = [nullid]
    kwargs["cg"] = False
    kwargs["common"] = _getcommonheads(repo)
    bundle = other.getbundle("pull", **kwargs)
    try:
        op = bundle2.processbundle(repo, bundle)
    except error.BundleValueError as exc:
        raise error.Abort("missing support for %s" % exc)
    writebytes = op.records["fb:gitmeta:writebytes"]
    ui.status(_("wrote %d files (%d bytes)\n") % (len(writebytes), sum(writebytes)))
Esempio n. 13
0
def revsetdiff(repo, diffid):
    """Return a set of revisions corresponding to a given Differential ID """

    repo_callsign = repo.ui.config("phrevset", "callsign")
    if repo_callsign is None:
        msg = _("phrevset.callsign is not set - doing a linear search\n")
        hint = _("This will be slow if the diff was not committed recently\n")
        repo.ui.warn(msg)
        repo.ui.warn(hint)
        rev = finddiff(repo, diffid)
        if rev is None:
            raise error.Abort("Could not find diff D%s in changelog" % diffid)
        else:
            return [rev]

    revs, resp = forksearch(repo, diffid)

    if revs is not None:
        # The log walk found the diff, nothing more to do
        return revs

    if resp is None:
        # The graphql query finished but didn't return anything
        return []

    vcs = resp["source_control_system"]

    repo.ui.debug("[diffrev] VCS is %s\n" % vcs)

    if vcs == "git":
        gitrev = parsedesc(repo, resp, ignoreparsefailure=False)
        repo.ui.debug("[diffrev] GIT rev is %s\n" % gitrev)

        peerpath = repo.ui.expandpath("default")
        remoterepo = hg.peer(repo, {}, peerpath)
        remoterev = remoterepo.lookup("_gitlookup_git_%s" % gitrev)

        repo.ui.debug("[diffrev] HG rev is %s\n" % remoterev.encode("hex"))
        if not remoterev:
            repo.ui.debug("[diffrev] Falling back to linear search\n")
            linear_search_result = finddiff(repo, diffid)
            if linear_search_result is None:
                # walked the entire repo and couldn't find the diff
                raise error.Abort("Could not find diff D%s in changelog" % diffid)

            return [linear_search_result]

        return [repo[remoterev].rev()]

    elif vcs == "hg":
        rev = parsedesc(repo, resp, ignoreparsefailure=True)
        if rev:
            # The response from phabricator contains a changeset ID.
            # Convert it back to a rev number.
            try:
                return [repo[rev].rev()]
            except error.RepoLookupError:
                # TODO: 's/svnrev/globalrev' after turning off Subversion
                # servers. We will know about this when we remove the `svnrev`
                # revset.
                #
                # Unfortunately the rev can also be a svnrev/globalrev :(.
                if rev.isdigit():
                    try:
                        return [r for r in repo.revs("svnrev(%s)" % rev)]
                    except error.RepoLookupError:
                        pass

                raise error.Abort(
                    "Landed commit for diff D%s not available "
                    'in current repository: run "hg pull" '
                    "to retrieve it" % diffid
                )

        # commit is still local, get its hash

        props = resp["phabricator_version_properties"]["edges"]
        commits = []
        for prop in props:
            if prop["node"]["property_name"] == "local:commits":
                commits = json.loads(prop["node"]["property_value"])

        revs = [c["commit"] for c in commits.values()]

        # verify all revisions exist in the current repo; if not, try to
        # find their counterpart by parsing the log
        results = set()
        for rev in revs:
            try:
                unfiltered = repo.unfiltered()
                node = unfiltered[rev]
            except error.RepoLookupError:
                raise error.Abort(
                    "Commit %s corresponding to D%s\n not found in the repo"
                    % (rev, diffid)
                )
            successors = list(repo.revs("last(successors(%n))", node.node()))
            if len(successors) != 1:
                results.add(node.rev())
            else:
                results.add(successors[0])

        if not results:
            raise error.Abort("Could not find local commit for D%s" % diffid)

        return set(results)

    else:
        if not vcs:
            msg = (
                "D%s does not have an associated version control system\n"
                "You can view the diff at https:///our.internmc.facebook.com/intern/diff/D%s\n"
            )
            repo.ui.warn(msg % (diffid, diffid))

            return []
        else:
            raise error.Abort(
                "Conduit returned unknown " 'sourceControlSystem "%s"' % vcs
            )
Esempio n. 14
0
def getremote(ui, path):
    return hg.peer(ui, {}, path)
Esempio n. 15
0
def _dopull(orig, ui, repo, source="default", **opts):
    # Copy paste from `pull` command
    source, branches = hg.parseurl(ui.expandpath(source), opts.get("branch"))

    scratchbookmarks = {}
    unfi = repo.unfiltered()
    unknownnodes = []
    pullbookmarks = opts.get("bookmark") or []
    for rev in opts.get("rev", []):
        if repo._scratchbranchmatcher.match(rev):
            # rev is a scratch bookmark, treat it as a bookmark
            pullbookmarks.append(rev)
        elif rev not in unfi:
            unknownnodes.append(rev)
    if pullbookmarks:
        realbookmarks = []
        revs = opts.get("rev") or []
        for bookmark in pullbookmarks:
            if repo._scratchbranchmatcher.match(bookmark):
                # rev is not known yet
                # it will be fetched with listkeyspatterns next
                scratchbookmarks[bookmark] = "REVTOFETCH"
            else:
                realbookmarks.append(bookmark)

        if scratchbookmarks:
            other = hg.peer(repo, opts, source)
            fetchedbookmarks = other.listkeyspatterns(
                "bookmarks", patterns=scratchbookmarks)
            for bookmark in scratchbookmarks:
                if bookmark not in fetchedbookmarks:
                    raise error.Abort("remote bookmark %s not found!" %
                                      bookmark)
                scratchbookmarks[bookmark] = fetchedbookmarks[bookmark]
                revs.append(fetchedbookmarks[bookmark])
        opts["bookmark"] = realbookmarks
        opts["rev"] = [rev for rev in revs if rev not in scratchbookmarks]

    # Pulling revisions that were filtered results in a error.
    # Let's revive them.
    unfi = repo.unfiltered()
    torevive = []
    for rev in opts.get("rev", []):
        try:
            repo[rev]
        except error.FilteredRepoLookupError:
            torevive.append(rev)
        except error.RepoLookupError:
            pass
    if obsolete.isenabled(repo, obsolete.createmarkersopt):
        obsolete.revive([unfi[r] for r in torevive])
    visibility.add(repo, [unfi[r].node() for r in torevive])

    if scratchbookmarks or unknownnodes:
        # Set anyincoming to True
        extensions.wrapfunction(discovery, "findcommonincoming",
                                _findcommonincoming)
    try:
        # Remote scratch bookmarks will be deleted because remotenames doesn't
        # know about them. Let's save it before pull and restore after
        remotescratchbookmarks = bookmarks.readremotebookmarks(
            ui, repo, source)
        result = orig(ui, repo, source, **opts)
        # TODO(stash): race condition is possible
        # if scratch bookmarks was updated right after orig.
        # But that's unlikely and shouldn't be harmful.
        with repo.wlock(), repo.lock(), repo.transaction("pull"):
            if bookmarks.remotebookmarksenabled(ui):
                remotescratchbookmarks.update(scratchbookmarks)
                bookmarks.saveremotebookmarks(repo, remotescratchbookmarks,
                                              source)
            else:
                bookmarks.savelocalbookmarks(repo, scratchbookmarks)
        return result
    finally:
        if scratchbookmarks:
            extensions.unwrapfunction(discovery, "findcommonincoming")
Esempio n. 16
0
def _push(orig, ui, repo, dest=None, *args, **opts):
    bookmark = opts.get("to") or ""
    create = opts.get("create") or False

    oldphasemove = None
    overrides = {
        ("experimental", "server-bundlestore-bookmark"): bookmark,
        ("experimental", "server-bundlestore-create"): create,
    }

    with ui.configoverride(
            overrides,
            "infinitepush"), repo.wlock(), repo.lock(), repo.transaction(
                "push"):
        scratchpush = opts.get("bundle_store")
        if repo._scratchbranchmatcher.match(bookmark):
            # We are pushing to a scratch bookmark.  Check that there is
            # exactly one revision that is being pushed (this will be the
            # new bookmarked node).
            revs = opts.get("rev")
            if revs:
                revs = [repo[r] for r in scmutil.revrange(repo, revs)]
            else:
                revs = [repo["."]]
            if len(revs) != 1:
                msg = _("--to requires exactly one commit to push")
                hint = _("use --rev HASH or omit --rev for current commit (.)")
                raise error.Abort(msg, hint=hint)

            # Put the bookmarked node hash in the bundle to avoid ambiguity.
            ui.setconfig("experimental", "server-bundlestore-bookmarknode",
                         revs[0].hex())

            # If the bookmark destination is a public commit, then there will
            # be nothing to push.  We still need to send a changegroup part
            # to update the bookmark, so send the null rev instead.
            if not revs[0].mutable():
                opts["rev"] = ["null"]

            # Hack to fix interaction with remotenames. Remotenames push
            # '--to' bookmark to the server but we don't want to push scratch
            # bookmark to the server. Let's delete '--to' and '--create' and
            # also set allow_anon to True (because if --to is not set
            # remotenames will think that we are pushing anonymoush head)
            if "to" in opts:
                del opts["to"]
            if "create" in opts:
                del opts["create"]
            opts["allow_anon"] = True
            scratchpush = True
            # bundle2 can be sent back after push (for example, bundle2
            # containing `pushkey` part to update bookmarks)
            ui.setconfig("experimental", "bundle2.pushback", True)

        ui.setconfig(
            "experimental",
            "non-forward-move",
            opts.get("non_forward_move"),
            "--non-forward-move",
        )

        otherpath = None

        if scratchpush:
            ui.setconfig("experimental", "infinitepush-scratchpush", True)

            oldphasemove = extensions.wrapfunction(exchange, "_localphasemove",
                                                   _phasemove)

            replicate, path = preparepush(ui, dest)

            # We'll replicate the push if the user intended their push to go to
            # the default infinitepush destination.
            if replicate:
                try:
                    otherpath = repo.ui.paths.getpath(
                        pathname.infinitepushother)
                except error.RepoError:
                    pass
        else:
            path = ui.paths.getpath(dest,
                                    default=(pathname.defaultpush,
                                             pathname.default))

        # Copy-paste from `push` command
        if not path:
            raise error.Abort(
                _("default repository not configured!"),
                hint=_("see 'hg help config.paths'"),
            )
        realdest = path.pushloc or path.loc
        if realdest.startswith("svn+") and scratchpush:
            raise error.Abort(
                "infinite push does not work with svn repo",
                hint="did you forget to `hg push default`?",
            )

        otherdest = otherpath and (otherpath.pushloc or otherpath.loc)

        if scratchpush:
            ui.log(
                "infinitepush_destinations",
                dest=dest,
                real_dest=realdest,
                other_dest=otherdest,
                bookmark=bookmark,
            )

        # Remote scratch bookmarks will be deleted because remotenames doesn't
        # know about them. Let's save it before push and restore after
        remotescratchbookmarks = bookmarks.readremotebookmarks(
            ui, repo, realdest)
        result = orig(ui, repo, realdest, *args, **opts)

        # If an alternate Infinitepush destination is specified, replicate the
        # push there. This ensures scratch bookmarks (and their commits) can
        # properly be replicated to Mononoke.

        if otherdest is not None and otherdest != realdest:
            m = _(
                "please wait while we replicate this push to an alternate repository\n"
            )
            ui.warn(m)
            # NOTE: We ignore the result here (which only represents whether
            # there were changes to land).
            orig(ui, repo, otherdest, *args, **opts)

        if bookmarks.remotebookmarksenabled(ui):
            if bookmark and scratchpush:
                other = hg.peer(repo, opts, realdest)
                fetchedbookmarks = other.listkeyspatterns("bookmarks",
                                                          patterns=[bookmark])
                remotescratchbookmarks.update(fetchedbookmarks)
            bookmarks.saveremotebookmarks(repo, remotescratchbookmarks,
                                          realdest)
    if oldphasemove:
        exchange._localphasemove = oldphasemove
    return result
Esempio n. 17
0
def expushcmd(orig, ui, repo, dest=None, **opts):
    # during the upgrade from old to new remotenames, tooling that uses --force
    # will continue working if remotenames.forcecompat is enabled
    forcecompat = ui.configbool("remotenames", "forcecompat")

    # needed for discovery method
    opargs = {
        "delete":
        opts.get("delete"),
        "to":
        opts.get("to"),
        "create":
        opts.get("create") or (opts.get("force") and forcecompat),
        "allowanon":
        opts.get("allow_anon")
        or repo.ui.configbool("remotenames", "pushanonheads")
        or (opts.get("force") and forcecompat),
        "nonforwardmove":
        opts.get("non_forward_move")
        or repo.ui.configbool("remotenames", "allownonfastforward")
        or (opts.get("force") and forcecompat),
    }

    if opargs["delete"]:
        flag = None
        for f in ("to", "bookmark", "branch", "rev"):
            if opts.get(f):
                flag = f
                break
        if flag:
            msg = _("do not specify --delete and "
                    "--%s at the same time") % flag
            raise error.Abort(msg)
        # we want to skip pushing any changesets while deleting a remote
        # bookmark, so we send the null revision
        opts["rev"] = ["null"]
        return orig(ui, repo, dest, opargs=opargs, **opts)

    revs = opts.get("rev")

    paths = dict((path, url) for path, url in ui.configitems("paths"))
    # XXX T58629567: The following line triggers an infinite loop in pyre, let's disable it for now.
    if not typing.TYPE_CHECKING:
        revrenames = dict(
            (v, k) for k, v in pycompat.iteritems(_getrenames(ui)))

    origdest = dest
    defaultpush = ui.paths.get("default-push") or ui.paths.get("default")
    if defaultpush:
        defaultpush = defaultpush.loc
    if ((not dest or dest == defaultpush) and not opargs["to"] and not revs
            and _tracking(ui)):
        current = repo._activebookmark
        tracking = _readtracking(repo)
        ui.debug("tracking on %s %s\n" % (current, tracking))
        if current and current in tracking:
            track = tracking[current]
            path, book = splitremotename(track)
            # un-rename a path, if needed
            path = revrenames.get(path, path)
            if book and path in paths:
                dest = path
                opargs["to"] = book

    # un-rename passed path
    dest = revrenames.get(dest, dest)

    # if dest was renamed to default but we aren't specifically requesting
    # to push to default, change dest to default-push, if available
    if not origdest and dest == "default" and "default-push" in paths:
        dest = "default-push"

    # get the actual path we will push to so we can do some url sniffing
    for check in [
            # dest may be a path name, or an actual url
            paths.get(dest, dest),
            paths.get("default-push"),
            paths.get("default"),
    ]:
        if check:
            # hggit does funky things on push. Just call direct.
            if check.startswith("git+"):
                return orig(ui, repo, dest, opargs=opargs, **opts)
            # Once we have found the path where we are pushing, do not continue
            # checking for places we are not pushing.
            break

    if not opargs["to"]:
        if ui.configbool("remotenames", "forceto"):
            msg = _("must specify --to when pushing")
            hint = _("see configuration option %s") % "remotenames.forceto"
            raise error.Abort(msg, hint=hint)

        if not revs:
            opts["rev"] = _pushrevs(repo, ui, None)

        return orig(ui, repo, dest, opargs=opargs, **opts)

    if opts.get("bookmark"):
        msg = _("do not specify --to/-t and --bookmark/-B at the same time")
        raise error.Abort(msg)
    if opts.get("branch"):
        msg = _("do not specify --to/-t and --branch/-b at the same time")
        raise error.Abort(msg)

    # if we are not using the original push command implementation, make sure
    # pushvars is included in opargs
    pushvars = opts.get("pushvars")
    if pushvars:
        opargs["pushvars"] = pushvars

    if revs:
        revs = [repo.lookup(r) for r in repo.anyrevs(revs, user=True)]
    else:
        revs = _pushrevs(repo, ui, ".")
    if len(revs) != 1:
        msg = _("--to requires exactly one rev to push")
        hint = _("use --rev BOOKMARK or omit --rev for current commit (.)")
        raise error.Abort(msg, hint=hint)
    rev = revs[0]

    # big can o' copypasta from commands.push
    dest = ui.expandpath(dest or "default-push", dest or "default")
    dest, branches = hg.parseurl(dest, opts.get("branch"))
    try:
        other = hg.peer(repo, opts, dest)
    except error.RepoError:
        if dest == "default-push":
            hint = _('see the "path" section in "hg help config"')
            raise error.Abort(_("default repository not configured!"),
                              hint=hint)
        else:
            raise

    # all checks pass, go for it!
    node = repo.lookup(rev)
    ui.status_err(
        _("pushing rev %s to destination %s bookmark %s\n") %
        (short(node), dest, opargs["to"]))

    force = opts.get("force")
    bookmark = opargs["to"]
    pattern = ui.config("remotenames", "disallowedto")
    if pattern and re.match(pattern, bookmark):
        msg = _("this remote bookmark name is not allowed")
        hint = ui.config("remotenames",
                         "disallowedhint") or _("use another bookmark name")
        raise error.Abort(msg, hint=hint)
    # NB: despite the name, 'revs' doesn't work if it's a numeric rev
    pushop = exchange.push(repo,
                           other,
                           force,
                           revs=[node],
                           bookmarks=(opargs["to"], ),
                           opargs=opargs)

    result = not pushop.cgresult
    if pushop.bkresult is not None:
        if pushop.bkresult == 2:
            result = 2
        elif not result and pushop.bkresult:
            result = 2

    return result
Esempio n. 18
0
def diffidtonode(repo, diffid):
    """Return node that matches a given Differential ID or None.

    The node might exist or not exist in the repo.
    This function does not raise.
    """

    repo_callsigns = repo.ui.configlist("phrevset", "callsign")
    if not repo_callsigns:
        msg = _("phrevset.callsign is not set - doing a linear search\n")
        hint = _("This will be slow if the diff was not committed recently\n")
        repo.ui.warn(msg)
        repo.ui.warn(hint)
        node = localgetdiff(repo, diffid)
        if node is None:
            repo.ui.warn(_("Could not find diff D%s in changelog\n") % diffid)
        return node

    node, resp = search(repo, diffid)

    if node is not None:
        # The log walk found the diff, nothing more to do
        return node

    if resp is None:
        # The graphql query finished but didn't return anything
        return None

    vcs = resp.get("source_control_system")
    localreponame = repo.ui.config("remotefilelog", "reponame")
    diffreponame = None
    repository = resp.get("repository")
    if repository is not None:
        diffreponame = repository.get("scm_name")
    if diffreponame in repo.ui.configlist("phrevset", "aliases"):
        diffreponame = localreponame

    if not util.istest() and (diffreponame != localreponame):
        raise error.Abort(
            "D%s is for repo '%s', not this repo ('%s')"
            % (diffid, diffreponame, localreponame)
        )

    repo.ui.debug("[diffrev] VCS is %s\n" % vcs)

    if vcs == "git":
        gitrev = parsedesc(repo, resp, ignoreparsefailure=False)
        repo.ui.debug("[diffrev] GIT rev is %s\n" % gitrev)

        peerpath = repo.ui.expandpath("default")
        remoterepo = hg.peer(repo, {}, peerpath)
        remoterev = remoterepo.lookup("_gitlookup_git_%s" % gitrev)

        repo.ui.debug("[diffrev] HG rev is %s\n" % hex(remoterev))
        if not remoterev:
            repo.ui.debug("[diffrev] Falling back to linear search\n")
            node = localgetdiff(repo, diffid)
            if node is None:
                repo.ui.warn(_("Could not find diff D%s in changelog\n") % diffid)

            return node

        return remoterev

    elif vcs == "hg":
        rev = parsedesc(repo, resp, ignoreparsefailure=True)
        if rev:
            # The response from phabricator contains a changeset ID.
            # Convert it back to a node.
            try:
                return repo[rev].node()
            except error.RepoLookupError:
                # TODO: 's/svnrev/globalrev' after turning off Subversion
                # servers. We will know about this when we remove the `svnrev`
                # revset.
                #
                # Unfortunately the rev can also be a svnrev/globalrev :(.
                if rev.isdigit():
                    try:
                        return list(repo.nodes("svnrev(%s)" % rev))[0]
                    except (IndexError, error.RepoLookupError):
                        pass

                if len(rev) == len(nullhex):
                    return bin(rev)
                else:
                    return None

        # commit is still local, get its hash

        try:
            props = resp["phabricator_version_properties"]["edges"]
            commits = {}
            for prop in props:
                if prop["node"]["property_name"] == "local:commits":
                    commits = json.loads(prop["node"]["property_value"])
            hexnodes = [c["commit"] for c in commits.values()]
        except (AttributeError, IndexError, KeyError):
            hexnodes = []

        # find a better alternative of the commit hash specified in
        # graphql response by looking up successors.
        for hexnode in hexnodes:
            if len(hexnode) != len(nullhex):
                continue

            node = bin(hexnode)
            unfi = repo
            if node in unfi:
                # Find a successor.
                successors = list(
                    unfi.nodes("last(successors(%n)-%n-obsolete())", node, node)
                )
                if successors:
                    return successors[0]
            return node

        # local:commits is empty
        return None

    else:
        if not vcs:
            msg = (
                "D%s does not have an associated version control system\n"
                "You can view the diff at https:///our.internmc.facebook.com/intern/diff/D%s\n"
            )
            repo.ui.warn(msg % (diffid, diffid))

            return None
        else:
            repo.ui.warn(
                _("Conduit returned unknown sourceControlSystem: '%s'\n") % vcs
            )

            return None
Esempio n. 19
0
from edenscm.mercurial import commands, fscap, hg, ui as uimod, util

TESTDIR = os.environ["TESTDIR"]
BUNDLEPATH = os.path.join(TESTDIR, "bundles", "test-no-symlinks.hg")

# only makes sense to test on os which supports symlinks
if not getattr(os, "symlink", False):
    sys.exit(80)  # SKIPPED_STATUS defined in run-tests.py

with open(os.environ["HGRCPATH"], "a+") as f:
    f.write(b"[extensions]\n")
    f.write(b"treemanifest=!\n")

u = uimod.ui.load()
# hide outer repo
hg.peer(u, {}, ".", create=True)

# clone with symlink support
hg.clone(u, {}, BUNDLEPATH, "test0")

repo = hg.repository(u, "test0")

# wait a bit, or the status call wont update the dirstate
time.sleep(1)
commands.status(u, repo)


# now disable symlink support -- this is what os.symlink would do on a
# non-symlink file system
def symlink_failure(src, dst):
    raise OSError(1, "Operation not permitted")