Пример #1
0
def _backupbookmarkprefix(repo, username=None, hostname=None, reporoot=None):
    """returns the backup bookmark prefix for this user and repo

    The naming convention is:
    - infinitepush/backups/<username>/<hostname>/<reporoot>/bookmarks/<name>
    - infinitepush/backups/<username>/<hostname>/<reporoot>/heads/<hash>

    This function returns everything up to just after the reporoot.
    """
    if not username:
        username = util.shortuser(repo.ui.username())
    if not hostname:
        hostname = backuphostname(repo)
    if not reporoot:
        reporoot = repo.sharedroot
    reporoot = reporoot.strip("/")
    return "/".join(("infinitepush", "backups", username, hostname, reporoot))
Пример #2
0
    def rendercommit(win, state):
        """Renders the commit window that shows the log of the current selected
        commit"""
        pos = state["pos"]
        rules = state["rules"]
        rule = rules[pos]

        ctx = rule.ctx
        win.box()

        maxy, maxx = win.getmaxyx()
        length = maxx - 3

        line = "changeset: {0}:{1:<12}".format(ctx.rev(), str(ctx))
        win.addstr(1, 1, line[:length])

        line = "user:      {0}".format(util.shortuser(ctx.user()))
        win.addstr(2, 1, line[:length])

        bms = repo.nodebookmarks(ctx.node())
        line = "bookmark:  {0}".format(" ".join(bms))
        win.addstr(3, 1, line[:length])

        line = "files:     {0}".format(",".join(ctx.files()))
        win.addstr(4, 1, line[:length])

        line = "summary:   {0}".format(ctx.description().splitlines()[0])
        win.addstr(5, 1, line[:length])

        conflicts = rule.conflicts
        if len(conflicts) > 0:
            conflictstr = ",".join([str(r.ctx) for r in conflicts])
            conflictstr = "changed files overlap with {0}".format(conflictstr)
        else:
            conflictstr = "no overlap"

        win.addstr(6, 1, conflictstr[:length])
        win.noutrefresh()
Пример #3
0
def cloudlistbackups(ui, repo, dest=None, **opts):
    """list backups that are available on the server"""

    remotepath = ccutil.getremotepath(repo, dest)
    getconnection = lambda: repo.connectionpool.get(remotepath, opts)

    sourceusername = opts.get("user")
    if not sourceusername:
        sourceusername = util.shortuser(repo.ui.username())
    backupinfo = backupbookmarks.downloadbackupbookmarks(
        repo, remotepath, getconnection, sourceusername)

    if opts.get("json"):
        jsondict = util.sortdict()
        for hostname, reporoot in backupinfo.keys():
            jsondict.setdefault(hostname, []).append(reporoot)
        ui.write("%s\n" % json.dumps(jsondict, indent=4))
    elif not backupinfo:
        ui.write(_("no backups available for %s\n") % sourceusername)
    else:
        backupbookmarks.printbackupbookmarks(ui,
                                             sourceusername,
                                             backupinfo,
                                             all=bool(opts.get("all")))
Пример #4
0
def getusername(ui):
    try:
        return util.shortuser(ui.username())
    except Exception:
        return "unknown"
Пример #5
0
    def putcommit(self, files, copies, parents, commit, source, revmap, full, cleanp2):
        for parent in parents:
            try:
                return self.revid(self.childmap[parent])
            except KeyError:
                pass

        # Apply changes to working copy
        for f, v in files:
            data, mode = source.getfile(f, v)
            if data is None:
                self.delete.append(f)
            else:
                self.putfile(f, mode, data)
                if f in copies:
                    self.copies.append([copies[f], f])
        if full:
            self.delete.extend(sorted(self.manifest.difference(files)))
        files = [f[0] for f in files]

        entries = set(self.delete)
        files = frozenset(files)
        entries.update(self.add_dirs(files.difference(entries)))
        if self.copies:
            for s, d in self.copies:
                self._copyfile(s, d)
            self.copies = []
        if self.delete:
            self.xargs(self.delete, "delete")
            for f in self.delete:
                self.manifest.remove(f)
            self.delete = []
        entries.update(self.add_files(files.difference(entries)))
        if self.delexec:
            self.xargs(self.delexec, "propdel", "svn:executable")
            self.delexec = []
        if self.setexec:
            self.xargs(self.setexec, "propset", "svn:executable", "*")
            self.setexec = []

        fd, messagefile = tempfile.mkstemp(prefix="hg-convert-")
        fp = util.fdopen(fd, "w")
        fp.write(commit.desc)
        fp.close()
        try:
            output = self.run0(
                "commit",
                username=util.shortuser(commit.author),
                file=messagefile,
                encoding="utf-8",
            )
            try:
                rev = self.commit_re.search(output).group(1)
            except AttributeError:
                if parents and not files:
                    return parents[0]
                self.ui.warn(_("unexpected svn output:\n"))
                self.ui.warn(output)
                raise error.Abort(_("unable to cope with svn output"))
            if commit.rev:
                self.run(
                    "propset", "hg:convert-rev", commit.rev, revprop=True, revision=rev
                )
            if commit.branch and commit.branch != "default":
                self.run(
                    "propset",
                    "hg:convert-branch",
                    commit.branch,
                    revprop=True,
                    revision=rev,
                )
            for parent in parents:
                self.addchild(parent, rev)
            return self.revid(rev)
        finally:
            os.unlink(messagefile)
Пример #6
0
def clouddeletebackup(ui, repo, dest=None, **opts):
    """delete a backup from the server

    Removes all heads and bookmarks associated with a backup from the server.
    The commits themselves are not removed, so you can still update to them
    using 'hg update HASH'.
    """

    remotepath = ccutil.getremotepath(repo, dest)
    getconnection = lambda: repo.connectionpool.get(remotepath, opts)

    sourceusername = util.shortuser(repo.ui.username())
    sourcereporoot = opts.get("reporoot")
    sourcehostname = opts.get("hostname")
    if not sourcereporoot or not sourcehostname:
        msg = _("you must specify a reporoot and hostname to delete a backup")
        hint = _("use 'hg cloud listbackups' to find which backups exist")
        raise error.Abort(msg, hint=hint)

    # Do some sanity checking on the names
    if not re.match(r"^[-a-zA-Z0-9._/:\\ ]+$", sourcereporoot):
        msg = _("repo root contains unexpected characters")
        raise error.Abort(msg)
    if not re.match(r"^[-a-zA-Z0-9.]+$", sourcehostname):
        msg = _("hostname contains unexpected characters")
        raise error.Abort(msg)
    if (sourcereporoot == repo.sharedroot
            and sourcehostname == backupbookmarks.backuphostname(repo)):
        ui.warn(_("this backup matches the current repo\n"),
                notice=_("warning"))

    backupinfo = backupbookmarks.downloadbackupbookmarks(
        repo, remotepath, getconnection, sourceusername)
    deletestate = backupinfo.get((sourcehostname, sourcereporoot))
    if deletestate is None:
        raise error.Abort(
            _("no backup found for %s on %s") %
            (sourcereporoot, sourcehostname))
    ui.write(_("%s on %s:\n") % (sourcereporoot, sourcehostname))
    ui.write(_("    heads:\n"))
    for head in deletestate.get("heads", []):
        ui.write(("        %s\n") % head)
    ui.write(_("    bookmarks:\n"))
    for bookname, booknode in sorted(deletestate.get("bookmarks", {}).items()):
        ui.write(("        %-20s %s\n") % (bookname + ":", booknode))
    if ui.promptchoice(_("delete this backup (yn)? $$ &Yes $$ &No"), 1) == 0:
        ui.status(
            _("deleting backup for %s on %s\n") %
            (sourcereporoot, sourcehostname))
        backupbookmarks.deletebackupbookmarks(
            repo,
            remotepath,
            getconnection,
            sourceusername,
            sourcehostname,
            sourcereporoot,
        )
        ui.status(_("backup deleted\n"))
        ui.status(
            _("(you can still access the commits directly using their hashes)\n"
              ))
    return 0
Пример #7
0
def cloudrestorebackup(ui, repo, dest=None, **opts):
    """restore commits that were previously backed up with 'hg cloud backup'

    If you have only one backup for the repo on the backup server then it will be restored.

    If you have backed up multiple clones of the same repo, then the
    '--reporoot', '--hostname' and '--user' options may be used to disambiguate
    which backup to restore.

    Use 'hg cloud listbackups' to list available backups.
    """

    remotepath = ccutil.getremotepath(repo, dest)
    getconnection = lambda: repo.connectionpool.get(remotepath, opts)

    sourceusername = opts.get("user")
    if not sourceusername:
        sourceusername = util.shortuser(repo.ui.username())
    sourcereporoot = opts.get("reporoot")
    sourcehostname = opts.get("hostname")
    backupinfo = backupbookmarks.downloadbackupbookmarks(
        repo, remotepath, getconnection, sourceusername, sourcehostname,
        sourcereporoot)

    if not backupinfo:
        ui.warn(_("no backups found!"))
        return 1
    if len(backupinfo) > 1:
        backupbookmarks.printbackupbookmarks(ui, sourceusername, backupinfo)
        raise error.Abort(
            _("multiple backups found"),
            hint=_("set --hostname and --reporoot to pick a backup"),
        )

    (restorehostname, restorereporoot), restorestate = backupinfo.popitem()
    repo.ui.status(
        _("restoring backup for %s from %s on %s\n") %
        (sourceusername, restorereporoot, restorehostname))

    pullcmd, pullopts = ccutil.getcommandandoptions("pull|pul")
    # Pull the heads and the nodes that were pointed to by the bookmarks.
    # Note that we are avoiding the use of set() because we want to pull
    # revisions in the same order
    heads = restorestate.get("heads", [])
    bookmarks = restorestate.get("bookmarks", {})
    bookmarknodes = [
        hexnode for hexnode in bookmarks.values() if hexnode not in heads
    ]
    pullopts["rev"] = heads + bookmarknodes
    if dest:
        pullopts["source"] = dest

    with backuplock.lock(repo), repo.wlock(), repo.lock(), repo.transaction(
            "backuprestore") as tr:

        maxrevbeforepull = len(repo.changelog)
        result = pullcmd(ui, repo, **pullopts)
        maxrevafterpull = len(repo.changelog)

        if ui.config("infinitepushbackup", "createlandedasmarkers", False):
            pullcreatemarkers = extensions.find("pullcreatemarkers")
            pullcreatemarkers.createmarkers(result,
                                            repo,
                                            maxrevbeforepull,
                                            maxrevafterpull,
                                            fromdrafts=False)

        changes = []
        for name, hexnode in bookmarks.iteritems():
            if hexnode in repo:
                changes.append((name, nodemod.bin(hexnode)))
            else:
                ui.warn(
                    _("%s not found, not creating %s bookmark") %
                    (hexnode, name))
        repo._bookmarks.applychanges(repo, tr, changes)

        # Update local backup state and flag to not autobackup just after we
        # restored, which would be pointless.
        state = backupstate.BackupState(repo, remotepath)
        state.update(
            [nodemod.bin(hexnode) for hexnode in heads + bookmarknodes])
        backupbookmarks._writelocalbackupstate(
            repo, ccutil.getremotepath(repo, dest), heads, bookmarks)
        repo.ignoreautobackup = True

    return result