def unshelveabort(ui, repo, state, opts): """subcommand that abort an in-progress unshelve""" wlock = repo.wlock() lock = None try: checkparents(repo, state) lock = repo.lock() merge.mergestate(repo).reset() if opts['keep']: repo.setparents(repo.dirstate.parents()[0]) else: revertfiles = readshelvedfiles(repo, state.name) wctx = repo.parents()[0] cmdutil.revert(ui, repo, wctx, [wctx.node(), nullid], *revertfiles, **{'no_backup': True}) # fix up the weird dirstate states the merge left behind mf = wctx.manifest() dirstate = repo.dirstate for f in revertfiles: if f in mf: dirstate.normallookup(f) else: dirstate.drop(f) dirstate._pl = (wctx.node(), nullid) dirstate._dirty = True repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve') shelvedstate.clear(repo) ui.warn(_("unshelve of '%s' aborted\n") % state.name) finally: lockmod.release(lock, wlock)
def updateModel(self, wctx, patchecked): self.tv.setSortingEnabled(False) if self.tv.model(): checked = self.tv.model().getChecked() else: checked = patchecked if self.pats and not checked: qtlib.WarningMsgBox(_('No appropriate files'), _('No files found for this operation'), parent=self) ms = merge.mergestate(self.repo) tm = WctxModel(wctx, ms, self.pctx, self.savechecks, self.opts, checked, self, checkable=self.checkable, defcheck=self.defcheck) if self.checkable: tm.checkToggled.connect(self.checkToggled) tm.checkCountChanged.connect(self.updateCheckCount) self.savechecks = True oldtm = self.tv.model() self.tv.setModel(tm) if oldtm: oldtm.deleteLater() self.tv.setSortingEnabled(True) self.tv.setColumnHidden(COL_PATH, bool(wctx.p2()) or not self.checkable) self.tv.setColumnHidden(COL_MERGE_STATE, not tm.anyMerge()) if self.checkable: self.updateCheckCount() for col in (COL_PATH, COL_STATUS, COL_MERGE_STATE): w = self.tv.sizeHintForColumn(col) self.tv.setColumnWidth(col, w) for col in (COL_PATH_DISPLAY, COL_EXTENSION, COL_SIZE): self.tv.resizeColumnToContents(col) # reset selection, or select first row curidx = tm.index(0, 0) selmodel = self.tv.selectionModel() flags = QItemSelectionModel.Select | QItemSelectionModel.Rows if self.reselection: selected, current = self.reselection for i, row in enumerate(tm.getAllRows()): if row[COL_PATH] in selected: selmodel.select(tm.index(i, 0), flags) if row[COL_PATH] == current: curidx = tm.index(i, 0) else: selmodel.select(curidx, flags) selmodel.currentChanged.connect(self.onCurrentChange) selmodel.selectionChanged.connect(self.onSelectionChange) if curidx and curidx.isValid(): selmodel.setCurrentIndex(curidx, QItemSelectionModel.Current) self.onSelectionChange(None, None)
def resolve(stat, files): wctx = self.repo[None] mctx = wctx.parents()[-1] ms = merge_.mergestate(self.repo) for wfile in files: ms.resolve(wfile, wctx, mctx) ms.commit() self.reload_status()
def recursiveMergeStatus(repo): ms = merge.mergestate(repo) for wfile in ms: yield repo.root, wfile, ms[wfile] try: wctx = repo[None] for s in wctx.substate: sub = wctx.sub(s) if isinstance(sub, subrepo.hgsubrepo): for root, file, status in recursiveMergeStatus(sub._repo): yield root, file, status except (EnvironmentError, error.Abort, error.RepoError): pass
def unshelvecontinue(ui, repo, state, opts): """subcommand to continue an in-progress unshelve""" # We're finishing off a merge. First parent is our original # parent, second is the temporary "fake" commit we're unshelving. wlock = repo.wlock() lock = None try: checkparents(repo, state) ms = merge.mergestate(repo) if [f for f in ms if ms[f] == 'u']: raise util.Abort( _("unresolved conflicts, can't continue"), hint=_("see 'hg resolve', then 'hg unshelve --continue'")) lock = repo.lock() util.rename(repo.join('unshelverebasestate'), repo.join('rebasestate')) try: rebase.rebase(ui, repo, **{ 'continue' : True }) except Exception: util.rename(repo.join('rebasestate'), repo.join('unshelverebasestate')) raise shelvectx = repo['tip'] if not shelvectx in state.pendingctx.children(): # rebase was a no-op, so it produced no child commit shelvectx = state.pendingctx else: # only strip the shelvectx if the rebase produced it state.stripnodes.append(shelvectx.node()) mergefiles(ui, repo, state.wctx, shelvectx) repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve') shelvedstate.clear(repo) unshelvecleanup(ui, repo, state.name, opts) ui.status(_("unshelve of '%s' complete\n") % state.name) finally: lockmod.release(lock, wlock)
def unshelvecontinue(ui, repo, state, opts): """subcommand to continue an in-progress unshelve""" # We're finishing off a merge. First parent is our original # parent, second is the temporary "fake" commit we're unshelving. wlock = repo.wlock() lock = None try: checkparents(repo, state) ms = merge.mergestate(repo) if [f for f in ms if ms[f] == 'u']: raise error.Abort( _("unresolved conflicts, can't continue"), hint=_("see 'hg resolve', then 'hg unshelve --continue'")) lock = repo.lock() util.rename(repo.join('unshelverebasestate'), repo.join('rebasestate')) try: rebase.rebase(ui, repo, **{ 'continue' : True }) except Exception: util.rename(repo.join('rebasestate'), repo.join('unshelverebasestate')) raise shelvectx = repo['tip'] if not shelvectx in state.pendingctx.children(): # rebase was a no-op, so it produced no child commit shelvectx = state.pendingctx else: # only strip the shelvectx if the rebase produced it state.stripnodes.append(shelvectx.node()) mergefiles(ui, repo, state.wctx, shelvectx) repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve') shelvedstate.clear(repo) unshelvecleanup(ui, repo, state.name, opts) ui.status(_("unshelve of '%s' complete\n") % state.name) finally: lockmod.release(lock, wlock)
def unshelvecontinue(ui, repo, state, opts): """subcommand to continue an in-progress unshelve""" # We're finishing off a merge. First parent is our original # parent, second is the temporary "fake" commit we're unshelving. wlock = repo.wlock() lock = None try: checkparents(repo, state) ms = merge.mergestate(repo) if [f for f in ms if ms[f] == 'u']: raise util.Abort( _("unresolved conflicts, can't continue"), hint=_("see 'hg resolve', then 'hg unshelve --continue'")) finishmerge(ui, repo, ms, state.stripnodes, state.name, opts) lock = repo.lock() repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve') unshelvecleanup(ui, repo, state.name, opts) ui.status(_("unshelve of '%s' complete\n") % state.name) finally: lockmod.release(lock, wlock)
debugf("abort: %s", inst) debugf("treat as unknown : %s", path) return UNKNOWN debugf("status() took %g ticks", (GetTickCount() - tc1)) mergestate = repo.dirstate.parents()[1] != node.nullid and \ hasattr(merge, 'mergestate') # cached file info tc = GetTickCount() overlay_cache = {} add(root, ROOT) add(os.path.join(root, '.hg'), NOT_IN_REPO) states = STATUS_STATES if mergestate: mstate = merge.mergestate(repo) unresolved = [f for f in mstate if mstate[f] == 'u'] if unresolved: modified = repostate[0] modified[:] = set(modified) - set(unresolved) repostate.insert(0, unresolved) states = [UNRESOLVED] + states states = zip(repostate, states) states[-1], states[-2] = states[-2], states[-1] #clean before ignored for grp, st in states: add_dirs(grp) for f in grp: fpath = os.path.join(root, os.path.normpath(f)) add(fpath, st) status = overlay_cache.get(path, UNKNOWN) debugf("%s: %s", (path, status))
def refresh_file_tree(self): """Clear out the existing ListStore model and reload it from the repository status. Also recheck and reselect files that remain in the list. """ is_merge = self.is_merge() self.file_sel_column.set_visible(not is_merge) self.merge_state_column.set_visible(self.count_revs() <= 1) selection = self.filetree.get_selection() if selection is None: return (M, A, R, D, U, I, C) = self.status changetypes = (('M', 'modified', M), ('A', 'added', A), ('R', 'removed', R), ('!', 'deleted', D), ('?', 'unknown', U), ('I', 'ignored', I), ('C', 'clean', C)) # List of the currently checked and selected files to pass on to # the new data model, tpaths = selection.get_selected_rows() model = self.filemodel reselect = [model[path][FM_PATH] for path in tpaths] waschecked = {} for row in model: waschecked[row[FM_PATH]] = row[FM_CHECKED], row[FM_PARTIAL_SELECTED] # merge-state of files ms = merge_.mergestate(self.repo) # Load the new data into the tree's model self.filetree.hide() selection.handler_block(self.treeselid) self.filemodel.clear() types = [ct for ct in changetypes if self.opts.get(ct[1])] for stat, _, wfiles in types: for wfile in wfiles: mst = wfile in ms and ms[wfile].upper() or "" lfile = util.localpath(wfile) defcheck = stat in 'MAR' and lfile not in self.excludes ck, p = waschecked.get(lfile, (defcheck, False)) model.append([ck, stat, hglib.toutf(lfile), lfile, mst, p]) if self.test_opt('subrepo') or self.is_merge(): for sdir in self.subrepos: lfile = util.localpath(sdir) defcheck = lfile not in self.excludes ck, p = waschecked.get(lfile, (defcheck, False)) model.append([ck, 'S', hglib.toutf(lfile), lfile, '', p]) self.auto_check() # may check more files for row in model: if row[FM_PARTIAL_SELECTED]: # force refresh of partially selected files self.chunks.update_hunk_model(row[FM_PATH], row[FM_CHECKED]) self.chunks.clear() else: # demand refresh of full or non selection self.chunks.del_file(row[FM_PATH]) # recover selections firstrow = None for i, row in enumerate(model): if row[FM_PATH] in reselect: if firstrow is None: firstrow = i else: selection.select_iter(row.iter) selection.handler_unblock(self.treeselid) if len(model): selection.select_path((firstrow or 0,)) else: # clear diff pane if no files self.diff_text.set_buffer(gtk.TextBuffer()) self.preview_text.set_buffer(gtk.TextBuffer()) if not is_merge: self.chunks.clear() self.filetree.show() if self.mode == 'commit': self.text.grab_focus() else: self.filetree.grab_focus() return True
def mark(parent, ui, repo, files): ms = merge.mergestate(repo) for wfile in files: ms.mark(wfile, 'r') ms.commit() return True
def stripcmd(ui, repo, *revs, **opts): """strip changesets and all their descendants from the repository The strip command removes the specified changesets and all their descendants. If the working directory has uncommitted changes, the operation is aborted unless the --force flag is supplied, in which case changes will be discarded. If a parent of the working directory is stripped, then the working directory will automatically be updated to the most recent available ancestor of the stripped parent after the operation completes. Any stripped changesets are stored in ``.hg/strip-backup`` as a bundle (see :hg:`help bundle` and :hg:`help unbundle`). They can be restored by running :hg:`unbundle .hg/strip-backup/BUNDLE`, where BUNDLE is the bundle file created by the strip. Note that the local revision numbers will in general be different after the restore. Use the --no-backup option to discard the backup bundle once the operation completes. Strip is not a history-rewriting operation and can be used on changesets in the public phase. But if the stripped changesets have been pushed to a remote repository you will likely pull them again. Return 0 on success. """ backup = True if opts.get('no_backup') or opts.get('nobackup'): backup = False cl = repo.changelog revs = list(revs) + opts.get('rev') revs = set(scmutil.revrange(repo, revs)) wlock = repo.wlock() try: if opts.get('bookmark'): mark = opts.get('bookmark') marks = repo._bookmarks if mark not in marks: raise util.Abort(_("bookmark '%s' not found") % mark) # If the requested bookmark is not the only one pointing to a # a revision we have to only delete the bookmark and not strip # anything. revsets cannot detect that case. uniquebm = True for m, n in marks.iteritems(): if m != mark and n == repo[mark].node(): uniquebm = False break if uniquebm: rsrevs = repo.revs("ancestors(bookmark(%s)) - " "ancestors(head() and not bookmark(%s)) - " "ancestors(bookmark() and not bookmark(%s))", mark, mark, mark) revs.update(set(rsrevs)) if not revs: del marks[mark] marks.write() ui.write(_("bookmark '%s' deleted\n") % mark) if not revs: raise util.Abort(_('empty revision set')) descendants = set(cl.descendants(revs)) strippedrevs = revs.union(descendants) roots = revs.difference(descendants) update = False # if one of the wdir parent is stripped we'll need # to update away to an earlier revision for p in repo.dirstate.parents(): if p != nullid and cl.rev(p) in strippedrevs: update = True break rootnodes = set(cl.node(r) for r in roots) q = getattr(repo, 'mq', None) if q is not None and q.applied: # refresh queue state if we're about to strip # applied patches if cl.rev(repo.lookup('qtip')) in strippedrevs: q.applieddirty = True start = 0 end = len(q.applied) for i, statusentry in enumerate(q.applied): if statusentry.node in rootnodes: # if one of the stripped roots is an applied # patch, only part of the queue is stripped start = i break del q.applied[start:end] q.savedirty() revs = sorted(rootnodes) if update and opts.get('keep'): urev, p2 = repo.changelog.parents(revs[0]) if (util.safehasattr(repo, 'mq') and p2 != nullid and p2 in [x.node for x in repo.mq.applied]): urev = p2 uctx = repo[urev] # only reset the dirstate for files that would actually change # between the working context and uctx descendantrevs = repo.revs("%s::." % uctx.rev()) changedfiles = [] for rev in descendantrevs: # blindly reset the files, regardless of what actually changed changedfiles.extend(repo[rev].files()) # reset files that only changed in the dirstate too dirstate = repo.dirstate dirchanges = [f for f in dirstate if dirstate[f] != 'n'] changedfiles.extend(dirchanges) repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles) repo.dirstate.write() # clear resolve state ms = merge.mergestate(repo) ms.reset(repo['.'].node()) update = False strip(ui, repo, revs, backup=backup, update=update, force=opts.get('force'), bookmark=opts.get('bookmark')) finally: wlock.release() return 0
except util.Abort, inst: debugf("abort: %s", inst) debugf("treat as unknown : %s", path) return UNKNOWN debugf("status() took %g ticks", (GetTickCount() - tc1)) mergestate = repo.dirstate.parents()[1] != node.nullid and hasattr(merge, "mergestate") # cached file info tc = GetTickCount() overlay_cache = {} add(root, ROOT) add(os.path.join(root, ".hg"), NOT_IN_REPO) states = STATUS_STATES if mergestate: mstate = merge.mergestate(repo) unresolved = [f for f in mstate if mstate[f] == "u"] if unresolved: modified = repostate[0] modified[:] = set(modified) - set(unresolved) repostate.insert(0, unresolved) states = [UNRESOLVED] + states states = zip(repostate, states) states[-1], states[-2] = states[-2], states[-1] # clean before ignored for grp, st in states: add_dirs(grp) for f in grp: fpath = os.path.join(root, os.path.normpath(f)) add(fpath, st) status = overlay_cache.get(path, UNKNOWN) debugf("%s: %s", (path, status))
def stripcmd(ui, repo, *revs, **opts): """strip changesets and all their descendants from the repository The strip command removes the specified changesets and all their descendants. If the working directory has uncommitted changes, the operation is aborted unless the --force flag is supplied, in which case changes will be discarded. If a parent of the working directory is stripped, then the working directory will automatically be updated to the most recent available ancestor of the stripped parent after the operation completes. Any stripped changesets are stored in ``.hg/strip-backup`` as a bundle (see :hg:`help bundle` and :hg:`help unbundle`). They can be restored by running :hg:`unbundle .hg/strip-backup/BUNDLE`, where BUNDLE is the bundle file created by the strip. Note that the local revision numbers will in general be different after the restore. Use the --no-backup option to discard the backup bundle once the operation completes. Strip is not a history-rewriting operation and can be used on changesets in the public phase. But if the stripped changesets have been pushed to a remote repository you will likely pull them again. Return 0 on success. """ backup = True if opts.get('no_backup') or opts.get('nobackup'): backup = False cl = repo.changelog revs = list(revs) + opts.get('rev') revs = set(scmutil.revrange(repo, revs)) wlock = repo.wlock() try: if opts.get('bookmark'): mark = opts.get('bookmark') marks = repo._bookmarks if mark not in marks: raise error.Abort(_("bookmark '%s' not found") % mark) # If the requested bookmark is not the only one pointing to a # a revision we have to only delete the bookmark and not strip # anything. revsets cannot detect that case. uniquebm = True for m, n in marks.iteritems(): if m != mark and n == repo[mark].node(): uniquebm = False break if uniquebm: rsrevs = repair.stripbmrevset(repo, mark) revs.update(set(rsrevs)) if not revs: del marks[mark] marks.write() ui.write(_("bookmark '%s' deleted\n") % mark) if not revs: raise error.Abort(_('empty revision set')) descendants = set(cl.descendants(revs)) strippedrevs = revs.union(descendants) roots = revs.difference(descendants) update = False # if one of the wdir parent is stripped we'll need # to update away to an earlier revision for p in repo.dirstate.parents(): if p != nullid and cl.rev(p) in strippedrevs: update = True break rootnodes = set(cl.node(r) for r in roots) q = getattr(repo, 'mq', None) if q is not None and q.applied: # refresh queue state if we're about to strip # applied patches if cl.rev(repo.lookup('qtip')) in strippedrevs: q.applieddirty = True start = 0 end = len(q.applied) for i, statusentry in enumerate(q.applied): if statusentry.node in rootnodes: # if one of the stripped roots is an applied # patch, only part of the queue is stripped start = i break del q.applied[start:end] q.savedirty() revs = sorted(rootnodes) if update and opts.get('keep'): urev, p2 = repo.changelog.parents(revs[0]) if (util.safehasattr(repo, 'mq') and p2 != nullid and p2 in [x.node for x in repo.mq.applied]): urev = p2 uctx = repo[urev] # only reset the dirstate for files that would actually change # between the working context and uctx descendantrevs = repo.revs("%s::." % uctx.rev()) changedfiles = [] for rev in descendantrevs: # blindly reset the files, regardless of what actually changed changedfiles.extend(repo[rev].files()) # reset files that only changed in the dirstate too dirstate = repo.dirstate dirchanges = [f for f in dirstate if dirstate[f] != 'n'] changedfiles.extend(dirchanges) repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles) repo.dirstate.write(repo.currenttransaction()) # clear resolve state ms = merge.mergestate(repo) ms.reset(repo['.'].node()) update = False strip(ui, repo, revs, backup=backup, update=update, force=opts.get('force'), bookmark=opts.get('bookmark')) finally: wlock.release() return 0
def prompt(ui, repo, **opts): cx = repo[None] parents = cx.parents() p0 = parents[0] node = p0.node() branch = cx.branch() heads = repo.branchheads(branch) tags = sum([p.tags() for p in parents], []) bookmarks = sum([p.bookmarks() for p in parents], []) bookmark = repo._bookmarkcurrent if bookmark in bookmarks: bookmarks.remove(bookmark) else: bookmark = None if len(parents) > 1: headstate = '(merge)' elif branch != p0.branch(): headstate = '(new branch)' elif (p0.extra().get('close') and node in repo.branchheads(branch, closed=True)): headstate = '(head closed)' elif node not in heads: headstate = '(new head)' else: headstate = '(head)' new = [0] * len(repo) cl = repo.changelog hrevs = [cl.rev(x) for x in heads] prevs = [p.rev() for p in parents] for i in hrevs: new[i] = 1 for i in cl.ancestors(hrevs): new[i] = 1 for i in prevs: if i >= 0: new[i] = 0 for i in cl.ancestors(prevs): new[i] = 0 new = sum(new) if not new: upstate = '' elif node not in heads: upstate = 'new:%d' % new else: upstate = 'new:%d heads:%d' % (new, len(heads)) # working status mods, adds, rems, dels, unk = repo.status(unknown=True)[:5] # merge conflicts from mercurial import merge ms = merge.mergestate(repo) unr = [f for f in ms if ms[f] == 'u'] # subrepos sub = [s for s in cx.substate if cx.sub(s).dirty()] pad = [False] def wr(m, l=''): if pad[0]: ui.write(' ') pad[0] = True return ui.write(m, label=l) ps = [('%d:%s' % (p.rev(), p)) for p in parents] wr(','.join(ps), 'log.changeset') wr(branch, 'log.branch') if bookmark: wr(bookmark, 'bookmarks.current') if bookmarks: wr(','.join(bookmarks), 'log.bookmark') if tags: wr(','.join(tags), 'log.tag') if mods: wr('%dM' % len(mods), 'status.modified') if adds: wr('%dA' % len(adds), 'status.added') if rems: wr('%dR' % len(rems), 'status.removed') if dels: wr('%d!' % len(dels), 'status.deleted') if unk: wr('%d?' % len(unk), 'status.unknown') if unr: wr('%d>' % len(unr), 'resolve.unresolved') if sub: wr('/M', 'status.modified') wr(headstate, 'log.changeset') wr(upstate) wr('\n')
repo.addchangegroup(gen, 'unshelve', 'bundle:' + fp.name) nodes = [ctx.node() for ctx in repo.set('%d:', oldtiprev)] phases.retractboundary(repo, phases.secret, nodes) tr.close() finally: fp.close() tip = repo['tip'] wctx = repo['.'] ancestor = tip.ancestor(wctx) wlock = repo.wlock() if ancestor.node() != wctx.node(): conflicts = hg.merge(repo, tip.node(), force=True, remind=False) ms = merge.mergestate(repo) stripnodes = [repo.changelog.node(rev) for rev in xrange(oldtiprev, len(repo))] if conflicts: shelvedstate.save(repo, basename, stripnodes) # Fix up the dirstate entries of files from the second # parent as if we were not merging, except for those # with unresolved conflicts. parents = repo.parents() revertfiles = set(parents[1].files()).difference(ms) cmdutil.revert(ui, repo, parents[1], (parents[0].node(), nullid), *revertfiles, **{'no_backup': True}) raise error.InterventionRequired( _("unresolved conflicts (see 'hg resolve', then " "'hg unshelve --continue')"))
def mark(menuitem, files): ms = merge_.mergestate(self.repo) for wfile in files: ms.mark(wfile, "r") ms.commit() self.reload_status()