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))
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()
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")))
def getusername(ui): try: return util.shortuser(ui.username()) except Exception: return "unknown"
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)
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
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