def filter(self, filter, node, changelog, patchfile): """arbitrarily rewrite changeset before applying it""" self.ui.status(_("filtering %s\n") % patchfile) user, date, msg = (changelog[1], changelog[2], changelog[4]) fd, headerfile = tempfile.mkstemp(prefix="hg-transplant-") fp = os.fdopen(fd, "w") fp.write("# HG changeset patch\n") fp.write("# User %s\n" % user) fp.write("# Date %d %d\n" % date) fp.write(msg + "\n") fp.close() try: util.system( "%s %s %s" % (filter, util.shellquote(headerfile), util.shellquote(patchfile)), environ={"HGUSER": changelog[1], "HGREVISION": revlog.hex(node)}, onerr=util.Abort, errprefix=_("filter failed"), out=self.ui.fout, ) user, date, msg = self.parselog(file(headerfile))[1:4] finally: os.unlink(headerfile) return (user, date, msg)
def filter(self, filter, changelog, patchfile): '''arbitrarily rewrite changeset before applying it''' self.ui.status('filtering %s\n' % patchfile) user, date, msg = (changelog[1], changelog[2], changelog[4]) fd, headerfile = tempfile.mkstemp(prefix='hg-transplant-') fp = os.fdopen(fd, 'w') fp.write("# HG changeset patch\n") fp.write("# User %s\n" % user) fp.write("# Date %d %d\n" % date) fp.write(changelog[4]) fp.close() try: util.system('%s %s %s' % (filter, util.shellquote(headerfile), util.shellquote(patchfile)), environ={'HGUSER': changelog[1]}, onerr=util.Abort, errprefix=_('filter failed')) user, date, msg = self.parselog(file(headerfile))[1:4] finally: os.unlink(headerfile) return (user, date, msg)
def view(ui, repo, *etc, **opts): "start interactive history viewer" os.chdir(repo.root) optstr = ' '.join(['--%s %s' % (k, v) for k, v in opts.iteritems() if v]) cmd = ui.config("hgk", "path", "hgk") + " %s %s" % (optstr, " ".join(etc)) ui.debug("running %s\n" % cmd) util.system(cmd)
def filter(self, filter, node, changelog, patchfile): '''arbitrarily rewrite changeset before applying it''' self.ui.status(_('filtering %s\n') % patchfile) user, date, msg = (changelog[1], changelog[2], changelog[4]) fd, headerfile = tempfile.mkstemp(prefix='hg-transplant-') fp = os.fdopen(fd, 'w') fp.write("# HG changeset patch\n") fp.write("# User %s\n" % user) fp.write("# Date %d %d\n" % date) fp.write(msg + '\n') fp.close() try: util.system('%s %s %s' % (filter, util.shellquote(headerfile), util.shellquote(patchfile)), environ={'HGUSER': changelog[1], 'HGREVISION': revlog.hex(node), }, onerr=util.Abort, errprefix=_('filter failed'), out=self.ui.fout) user, date, msg = self.parselog(file(headerfile))[1:4] finally: os.unlink(headerfile) return (user, date, msg)
def execCmd(sub, cmd, kind): """if sub == None, cmd is executed inside repo; else, inside sub. If cmd == None, do nothing. If cmd == '', do only the print0 (if needed). Else, do either print0 or the debugging message, then execute the command. kind is the type of the (sub)repo. """ if sub == None: envargdict = dict(HG_SUBPATH='.', HG_SUBURL='.', HG_SUBSTATE=repo['.'].hex(), HG_REPO=repo.root, HG_SUBTYPE=kind) relpath = '.' cmdwd = repo.root else: # subrepo.relpath was renamed to subrepo.subrelpath in # 18b5b6392fcf. if hasattr(subrepo, 'relpath'): relpath = subrepo.relpath(sub) else: relpath = subrepo.subrelpath(sub) envargdict = dict(HG_SUBPATH=relpath, HG_SUBURL=sub._path, HG_SUBSTATE=sub._state[1], HG_REPO=repo.root, HG_SUBTYPE=kind) cmdwd = os.path.join(repo.root, relpath) if cmd != None and (repotypefilter == '' or repotypefilter == kind): if print0: ui.write(relpath, "\0") if cmd != '': if not print0: ui.note(_("executing '%s' in %s\n") % (cmd, relpath)) util.system(cmd, environ=envargdict, cwd=cmdwd, onerr=onerr, errprefix=_('terminated onsub in %s') % relpath)
def view(ui, repo, *etc, **opts): "start interactive history viewer" os.chdir(repo.root) optstr = ' '.join(['--%s %s' % (k, v) for k, v in opts.iteritems() if v]) cmd = ui.config("hgk", "path", "hgk") + " %s %s" % (optstr, " ".join(etc)) ui.debug(_("running %s\n") % cmd) util.system(cmd)
def foreach(ui, repo, cmd, depthfirst, maxdepth, print0, ignoreerrors): """execute cmd in repo.root and in each subrepository""" ctx = repo['.'] work = [(1, ctx.sub(subpath)) for subpath in sorted(ctx.substate)] if depthfirst: work.reverse() while work: if depthfirst: (depth, sub) = work.pop() else: (depth, sub) = work.pop(0) if depth > maxdepth >= 0: continue # subrepo.relpath was renamed to subrepo.subrelpath in # 18b5b6392fcf. if hasattr(subrepo, 'relpath'): relpath = subrepo.relpath(sub) else: relpath = subrepo.subrelpath(sub) if print0: ui.write(relpath, "\0") else: ui.note(_("executing '%s' in %s\n") % (cmd, relpath)) if ignoreerrors: onerr = None else: onerr = util.Abort util.system(cmd, environ=dict(HG_SUBPATH=relpath, HG_SUBURL=sub._path, HG_SUBSTATE=sub._state[1], HG_REPO=repo.root), cwd=os.path.join(repo.root, relpath), onerr=onerr, errprefix=_('terminated onsub in %s') % relpath) if isinstance(sub, subrepo.hgsubrepo): rev = sub._state[1] ctx = sub._repo[rev] w = [(depth + 1, ctx.sub(subpath)) for subpath in sorted(ctx.substate)] if depthfirst: w.reverse() work.extend(w)
def doedit(): pathroot = self.repo.root copynode = None # if we aren't looking at the wc, copy the node... if otherparent: copynode = self._node1 elif self._node2: copynode = self._node2 if copynode: pf = [util.pconvert(f) for f in files] copydir = snapshot_node(self.ui, self.repo, pf, copynode, self.tmproot) pathroot = os.path.join(self.tmproot, copydir) paths = ['"%s"' % os.path.join(pathroot, f) for f in files] command = '%s %s' % (editor, ' '.join(paths)) util.system(command, onerr=self.ui, errprefix=_('edit failed'))
def doedit(): pathroot = self.repo.root copynode = None # if we aren't looking at the wc, copy the node... if stat in "R!" or force_left: copynode = self._node1 elif self._node2: copynode = self._node2 if copynode: copydir = snapshot_node(self.ui, self.repo, [util.pconvert(file)], copynode, self.tmproot) pathroot = os.path.join(self.tmproot, copydir) file_path = os.path.join(pathroot, file) util.system( '%s "%s"' % (editor, file_path), environ={"HGUSER": self.ui.username()}, onerr=util.Abort, errprefix=_("edit failed"), )
def execCmd(sub, cmd, kind): """if sub == None, cmd is executed inside repo; else, inside sub. If cmd == None, do nothing. If cmd == '', do only the print0 (if needed). Else, do either print0 or the debugging message, then execute the command. kind is the type of the (sub)repo. """ if sub == None: envargdict = dict(HG_SUBPATH='.', HG_SUBURL='.', HG_SUBSTATE=repo['.'].hex(), HG_REPO=repo.root, HG_SUBTYPE=kind) relpath = '.' cmdwd = repo.root else: # subrepo.relpath was renamed to subrepo.subrelpath in # 18b5b6392fcf. if hasattr(subrepo, 'relpath'): relpath = subrepo.relpath(sub) else: relpath = subrepo.subrelpath(sub) envargdict = dict(HG_SUBPATH=relpath, HG_SUBURL=sub._path, HG_SUBSTATE=sub._state[1], HG_REPO=repo.root, HG_SUBTYPE=kind) cmdwd = os.path.join(repo.root, relpath) if cmd != None and (repotypefilter == '' or repotypefilter == kind): if print0: ui.write(relpath, "\0") if cmd != '': if not print0: ui.write(_("executing '%s' in %s\n") % (cmd, relpath)) util.system(cmd, environ=envargdict, cwd=cmdwd, onerr=onerr, errprefix=_('terminated onsub in %s') % relpath)
def dodiff(ui, repo, diffcmd, diffopts, pats, opts): '''Do the actuall diff: - copy to a temp structure if diffing 2 internal revisions - copy to a temp structure if diffing working revision with another one and more than 1 file is changed - just invoke the diff for a single file in the working dir ''' node1, node2 = cmdutil.revpair(repo, opts['rev']) files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts) modified, added, removed, deleted, unknown = repo.status( node1, node2, files, match=matchfn)[:5] if not (modified or added or removed): return 0 tmproot = tempfile.mkdtemp(prefix='extdiff.') dir2root = '' try: # Always make a copy of node1 dir1 = snapshot_node(ui, repo, modified + removed, node1, tmproot) changes = len(modified) + len(removed) + len(added) fns_and_mtime = [] # If node2 in not the wc or there is >1 change, copy it if node2: dir2 = snapshot_node(ui, repo, modified + added, node2, tmproot) elif changes > 1: #we only actually need to get the files to copy back to the working #dir in this case (because the other cases are: diffing 2 revisions #or single file -- in which case the file is already directly passed #to the diff tool). dir2, fns_and_mtime = snapshot_wdir(ui, repo, modified + added, tmproot) else: # This lets the diff tool open the changed file directly dir2 = '' dir2root = repo.root # If only one change, diff the files instead of the directories if changes == 1 : if len(modified): dir1 = os.path.join(dir1, util.localpath(modified[0])) dir2 = os.path.join(dir2root, dir2, util.localpath(modified[0])) elif len(removed) : dir1 = os.path.join(dir1, util.localpath(removed[0])) dir2 = os.devnull else: dir1 = os.devnull dir2 = os.path.join(dir2root, dir2, util.localpath(added[0])) cmdline = ('%s %s %s %s' % (util.shellquote(diffcmd), ' '.join(diffopts), util.shellquote(dir1), util.shellquote(dir2))) ui.debug('running %r in %s\n' % (cmdline, tmproot)) util.system(cmdline, cwd=tmproot) for copy_fn, working_fn, mtime in fns_and_mtime: if os.path.getmtime(copy_fn) != mtime: ui.debug('File changed while diffing. ' 'Overwriting: %s (src: %s)\n' % (working_fn, copy_fn)) util.copyfile(copy_fn, working_fn) return 1 finally: ui.note(_('cleaning up temp directory\n')) shutil.rmtree(tmproot)
def prompt(skipfile, skipall, query, chunk): """prompt query, and process base inputs - y/n for the rest of file - y/n for the rest - ? (help) - q (quit) Return True/False and possibly updated skipfile and skipall. """ newpatches = None if skipall is not None: return skipall, skipfile, skipall, newpatches if skipfile is not None: return skipfile, skipfile, skipall, newpatches while True: resps = _( "[Ynesfdaq?]" "$$ &Yes, record this change" "$$ &No, skip this change" "$$ &Edit the change manually" "$$ &Skip remaining changes to this file" "$$ Record remaining changes to this &file" "$$ &Done, skip remaining changes and files" "$$ Record &all changes to all remaining files" "$$ &Quit, recording no changes" "$$ &?" ) r = ui.promptchoice("%s %s" % (query, resps)) ui.write("\n") if r == 8: # ? doc = gettext(record.__doc__) c = doc.find("::") + 2 for l in doc[c:].splitlines(): if l.startswith(" "): ui.write(l.strip(), "\n") continue elif r == 0: # yes ret = True elif r == 1: # no ret = False elif r == 2: # Edit patch if chunk is None: ui.write(_("cannot edit patch for whole file")) ui.write("\n") continue if chunk.header.binary(): ui.write(_("cannot edit patch for binary file")) ui.write("\n") continue # Patch comment based on the Git one (based on comment at end of # http://mercurial.selenic.com/wiki/RecordExtension) phelp = "---" + _( """ To remove '-' lines, make them ' ' lines (context). To remove '+' lines, delete them. Lines starting with # will be removed from the patch. If the patch applies cleanly, the edited hunk will immediately be added to the record list. If it does not apply cleanly, a rejects file will be generated: you can use that when you try again. If all lines of the hunk are removed, then the edit is aborted and the hunk is left unchanged. """ ) (patchfd, patchfn) = tempfile.mkstemp(prefix="hg-editor-", suffix=".diff", text=True) ncpatchfp = None try: # Write the initial patch f = os.fdopen(patchfd, "w") chunk.header.write(f) chunk.write(f) f.write("\n".join(["# " + i for i in phelp.splitlines()])) f.close() # Start the editor and wait for it to complete editor = ui.geteditor() util.system( '%s "%s"' % (editor, patchfn), environ={"HGUSER": ui.username()}, onerr=util.Abort, errprefix=_("edit failed"), out=ui.fout, ) # Remove comment lines patchfp = open(patchfn) ncpatchfp = cStringIO.StringIO() for line in patchfp: if not line.startswith("#"): ncpatchfp.write(line) patchfp.close() ncpatchfp.seek(0) newpatches = parsepatch(ncpatchfp) finally: os.unlink(patchfn) del ncpatchfp # Signal that the chunk shouldn't be applied as-is, but # provide the new patch to be used instead. ret = False elif r == 3: # Skip ret = skipfile = False elif r == 4: # file (Record remaining) ret = skipfile = True elif r == 5: # done, skip remaining ret = skipall = False elif r == 6: # all ret = skipall = True elif r == 7: # quit raise util.Abort(_("user quit")) return ret, skipfile, skipall, newpatches
def dodiff(ui, repo, diffcmd, diffopts, pats, opts): '''Do the actuall diff: - copy to a temp structure if diffing 2 internal revisions - copy to a temp structure if diffing working revision with another one and more than 1 file is changed - just invoke the diff for a single file in the working dir ''' revs = opts.get('rev') change = opts.get('change') if revs and change: msg = _('cannot specify --rev and --change at the same time') raise util.Abort(msg) elif change: node2 = repo.lookup(change) node1 = repo[node2].parents()[0].node() else: node1, node2 = cmdutil.revpair(repo, revs) matcher = cmdutil.match(repo, pats, opts) modified, added, removed = repo.status(node1, node2, matcher)[:3] if not (modified or added or removed): return 0 tmproot = tempfile.mkdtemp(prefix='extdiff.') dir2root = '' try: # Always make a copy of node1 dir1 = snapshot(ui, repo, modified + removed, node1, tmproot)[0] changes = len(modified) + len(removed) + len(added) # If node2 in not the wc or there is >1 change, copy it if node2 or changes > 1: dir2, fns_and_mtime = snapshot(ui, repo, modified + added, node2, tmproot) else: # This lets the diff tool open the changed file directly dir2 = '' dir2root = repo.root fns_and_mtime = [] # If only one change, diff the files instead of the directories if changes == 1: if len(modified): dir1 = os.path.join(dir1, util.localpath(modified[0])) dir2 = os.path.join(dir2root, dir2, util.localpath(modified[0])) elif len(removed): dir1 = os.path.join(dir1, util.localpath(removed[0])) dir2 = os.devnull else: dir1 = os.devnull dir2 = os.path.join(dir2root, dir2, util.localpath(added[0])) cmdline = ('%s %s %s %s' % (util.shellquote(diffcmd), ' '.join(diffopts), util.shellquote(dir1), util.shellquote(dir2))) ui.debug(_('running %r in %s\n') % (cmdline, tmproot)) util.system(cmdline, cwd=tmproot) for copy_fn, working_fn, mtime in fns_and_mtime: if os.path.getmtime(copy_fn) != mtime: ui.debug( _('file changed while diffing. ' 'Overwriting: %s (src: %s)\n') % (working_fn, copy_fn)) util.copyfile(copy_fn, working_fn) return 1 finally: ui.note(_('cleaning up temp directory\n')) shutil.rmtree(tmproot)
def dodiff(ui, repo, diffcmd, diffopts, pats, opts): '''Do the actuall diff: - copy to a temp structure if diffing 2 internal revisions - copy to a temp structure if diffing working revision with another one and more than 1 file is changed - just invoke the diff for a single file in the working dir ''' revs = opts.get('rev') change = opts.get('change') if revs and change: msg = _('cannot specify --rev and --change at the same time') raise util.Abort(msg) elif change: node2 = repo.lookup(change) node1 = repo[node2].parents()[0].node() else: node1, node2 = cmdutil.revpair(repo, revs) matcher = cmdutil.match(repo, pats, opts) modified, added, removed = repo.status(node1, node2, matcher)[:3] if not (modified or added or removed): return 0 tmproot = tempfile.mkdtemp(prefix='extdiff.') dir2root = '' try: # Always make a copy of node1 dir1 = snapshot(ui, repo, modified + removed, node1, tmproot)[0] changes = len(modified) + len(removed) + len(added) # If node2 in not the wc or there is >1 change, copy it if node2 or changes > 1: dir2, fns_and_mtime = snapshot(ui, repo, modified + added, node2, tmproot) else: # This lets the diff tool open the changed file directly dir2 = '' dir2root = repo.root fns_and_mtime = [] # If only one change, diff the files instead of the directories if changes == 1 : if len(modified): dir1 = os.path.join(dir1, util.localpath(modified[0])) dir2 = os.path.join(dir2root, dir2, util.localpath(modified[0])) elif len(removed) : dir1 = os.path.join(dir1, util.localpath(removed[0])) dir2 = os.devnull else: dir1 = os.devnull dir2 = os.path.join(dir2root, dir2, util.localpath(added[0])) cmdline = ('%s %s %s %s' % (util.shellquote(diffcmd), ' '.join(diffopts), util.shellquote(dir1), util.shellquote(dir2))) ui.debug(_('running %r in %s\n') % (cmdline, tmproot)) util.system(cmdline, cwd=tmproot) for copy_fn, working_fn, mtime in fns_and_mtime: if os.path.getmtime(copy_fn) != mtime: ui.debug(_('file changed while diffing. ' 'Overwriting: %s (src: %s)\n') % (working_fn, copy_fn)) util.copyfile(copy_fn, working_fn) return 1 finally: ui.note(_('cleaning up temp directory\n')) shutil.rmtree(tmproot)
def dodiff(ui, repo, diffcmd, diffopts, pats, opts): '''Do the actuall diff: - copy to a temp structure if diffing 2 internal revisions - copy to a temp structure if diffing working revision with another one and more than 1 file is changed - just invoke the diff for a single file in the working dir ''' revs = opts.get('rev') change = opts.get('change') args = ' '.join(diffopts) do3way = '$parent2' in args if revs and change: msg = _('cannot specify --rev and --change at the same time') raise util.Abort(msg) elif change: node2 = repo.lookup(change) node1a, node1b = repo.changelog.parents(node2) else: node1a, node2 = cmdutil.revpair(repo, revs) if not revs: node1b = repo.dirstate.parents()[1] else: node1b = nullid # Disable 3-way merge if there is only one parent if do3way: if node1b == nullid: do3way = False matcher = cmdutil.match(repo, pats, opts) mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3]) if do3way: mod_b, add_b, rem_b = map(set, repo.status(node1b, node2, matcher)[:3]) else: mod_b, add_b, rem_b = set(), set(), set() modadd = mod_a | add_a | mod_b | add_b common = modadd | rem_a | rem_b if not common: return 0 tmproot = tempfile.mkdtemp(prefix='extdiff.') try: # Always make a copy of node1a (and node1b, if applicable) dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a) dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot)[0] if do3way: dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b) dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot)[0] else: dir1b = None fns_and_mtime = [] # If node2 in not the wc or there is >1 change, copy it dir2root = '' if node2: dir2 = snapshot(ui, repo, modadd, node2, tmproot)[0] elif len(common) > 1: #we only actually need to get the files to copy back to #the working dir in this case (because the other cases #are: diffing 2 revisions or single file -- in which case #the file is already directly passed to the diff tool). dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot) else: # This lets the diff tool open the changed file directly dir2 = '' dir2root = repo.root # If only one change, diff the files instead of the directories # Handle bogus modifies correctly by checking if the files exist if len(common) == 1: common_file = util.localpath(common.pop()) dir1a = os.path.join(dir1a, common_file) if not os.path.isfile(os.path.join(tmproot, dir1a)): dir1a = os.devnull if do3way: dir1b = os.path.join(dir1b, common_file) if not os.path.isfile(os.path.join(tmproot, dir1b)): dir1b = os.devnull dir2 = os.path.join(dir2root, dir2, common_file) # Function to quote file/dir names in the argument string. # When not operating in 3-way mode, an empty string is # returned for parent2 replace = dict(parent=dir1a, parent1=dir1a, parent2=dir1b, child=dir2) def quote(match): key = match.group()[1:] if not do3way and key == 'parent2': return '' return util.shellquote(replace[key]) # Match parent2 first, so 'parent1?' will match both parent1 and parent regex = '\$(parent2|parent1?|child)' if not do3way and not re.search(regex, args): args += ' $parent1 $child' args = re.sub(regex, quote, args) cmdline = util.shellquote(diffcmd) + ' ' + args ui.debug('running %r in %s\n' % (cmdline, tmproot)) util.system(cmdline, cwd=tmproot) for copy_fn, working_fn, mtime in fns_and_mtime: if os.path.getmtime(copy_fn) != mtime: ui.debug('file changed while diffing. ' 'Overwriting: %s (src: %s)\n' % (working_fn, copy_fn)) util.copyfile(copy_fn, working_fn) return 1 finally: ui.note(_('cleaning up temp directory\n')) shutil.rmtree(tmproot)
def dodiff(ui, repo, diffcmd, diffopts, pats, opts): """Do the actual diff: - copy to a temp structure if diffing 2 internal revisions - copy to a temp structure if diffing working revision with another one and more than 1 file is changed - just invoke the diff for a single file in the working dir """ revs = opts.get("rev") change = opts.get("change") args = " ".join(map(util.shellquote, diffopts)) do3way = "$parent2" in args if revs and change: msg = _("cannot specify --rev and --change at the same time") raise util.Abort(msg) elif change: node2 = scmutil.revsingle(repo, change, None).node() node1a, node1b = repo.changelog.parents(node2) else: node1a, node2 = scmutil.revpair(repo, revs) if not revs: node1b = repo.dirstate.p2() else: node1b = nullid # Disable 3-way merge if there is only one parent if do3way: if node1b == nullid: do3way = False matcher = scmutil.match(repo[node2], pats, opts) mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3]) if do3way: mod_b, add_b, rem_b = map(set, repo.status(node1b, node2, matcher)[:3]) else: mod_b, add_b, rem_b = set(), set(), set() modadd = mod_a | add_a | mod_b | add_b common = modadd | rem_a | rem_b if not common: return 0 tmproot = tempfile.mkdtemp(prefix="extdiff.") try: # Always make a copy of node1a (and node1b, if applicable) dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a) dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot)[0] rev1a = "@%d" % repo[node1a].rev() if do3way: dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b) dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot)[0] rev1b = "@%d" % repo[node1b].rev() else: dir1b = None rev1b = "" fns_and_mtime = [] # If node2 in not the wc or there is >1 change, copy it dir2root = "" rev2 = "" if node2: dir2 = snapshot(ui, repo, modadd, node2, tmproot)[0] rev2 = "@%d" % repo[node2].rev() elif len(common) > 1: # we only actually need to get the files to copy back to # the working dir in this case (because the other cases # are: diffing 2 revisions or single file -- in which case # the file is already directly passed to the diff tool). dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot) else: # This lets the diff tool open the changed file directly dir2 = "" dir2root = repo.root label1a = rev1a label1b = rev1b label2 = rev2 # If only one change, diff the files instead of the directories # Handle bogus modifies correctly by checking if the files exist if len(common) == 1: common_file = util.localpath(common.pop()) dir1a = os.path.join(tmproot, dir1a, common_file) label1a = common_file + rev1a if not os.path.isfile(dir1a): dir1a = os.devnull if do3way: dir1b = os.path.join(tmproot, dir1b, common_file) label1b = common_file + rev1b if not os.path.isfile(dir1b): dir1b = os.devnull dir2 = os.path.join(dir2root, dir2, common_file) label2 = common_file + rev2 # Function to quote file/dir names in the argument string. # When not operating in 3-way mode, an empty string is # returned for parent2 replace = { "parent": dir1a, "parent1": dir1a, "parent2": dir1b, "plabel1": label1a, "plabel2": label1b, "clabel": label2, "child": dir2, "root": repo.root, } def quote(match): key = match.group()[1:] if not do3way and key == "parent2": return "" return util.shellquote(replace[key]) # Match parent2 first, so 'parent1?' will match both parent1 and parent regex = "\$(parent2|parent1?|child|plabel1|plabel2|clabel|root)" if not do3way and not re.search(regex, args): args += " $parent1 $child" args = re.sub(regex, quote, args) cmdline = util.shellquote(diffcmd) + " " + args ui.debug("running %r in %s\n" % (cmdline, tmproot)) util.system(cmdline, cwd=tmproot, out=ui.fout) for copy_fn, working_fn, mtime in fns_and_mtime: if os.lstat(copy_fn).st_mtime != mtime: ui.debug("file changed while diffing. " "Overwriting: %s (src: %s)\n" % (working_fn, copy_fn)) util.copyfile(copy_fn, working_fn) return 1 finally: ui.note(_("cleaning up temp directory\n")) shutil.rmtree(tmproot)
def doedit(): util.system('%s "%s"' % (editor, file))
def prompt(skipfile, skipall, query, chunk): """prompt query, and process base inputs - y/n for the rest of file - y/n for the rest - ? (help) - q (quit) Return True/False and possibly updated skipfile and skipall. """ newpatches = None if skipall is not None: return skipall, skipfile, skipall, newpatches if skipfile is not None: return skipfile, skipfile, skipall, newpatches while True: resps = _('[Ynesfdaq?]' '$$ &Yes, record this change' '$$ &No, skip this change' '$$ &Edit this change manually' '$$ &Skip remaining changes to this file' '$$ Record remaining changes to this &file' '$$ &Done, skip remaining changes and files' '$$ Record &all changes to all remaining files' '$$ &Quit, recording no changes' '$$ &? (display help)') r = ui.promptchoice("%s %s" % (query, resps)) ui.write("\n") if r == 8: # ? for c, t in ui.extractchoices(resps)[1]: ui.write('%s - %s\n' % (c, t.lower())) continue elif r == 0: # yes ret = True elif r == 1: # no ret = False elif r == 2: # Edit patch if chunk is None: ui.write(_('cannot edit patch for whole file')) ui.write("\n") continue if chunk.header.binary(): ui.write(_('cannot edit patch for binary file')) ui.write("\n") continue # Patch comment based on the Git one (based on comment at end of # http://mercurial.selenic.com/wiki/RecordExtension) phelp = '---' + _(""" To remove '-' lines, make them ' ' lines (context). To remove '+' lines, delete them. Lines starting with # will be removed from the patch. If the patch applies cleanly, the edited hunk will immediately be added to the record list. If it does not apply cleanly, a rejects file will be generated: you can use that when you try again. If all lines of the hunk are removed, then the edit is aborted and the hunk is left unchanged. """) (patchfd, patchfn) = tempfile.mkstemp(prefix="hg-editor-", suffix=".diff", text=True) ncpatchfp = None try: # Write the initial patch f = os.fdopen(patchfd, "w") chunk.header.write(f) chunk.write(f) f.write('\n'.join(['# ' + i for i in phelp.splitlines()])) f.close() # Start the editor and wait for it to complete editor = ui.geteditor() util.system("%s \"%s\"" % (editor, patchfn), environ={'HGUSER': ui.username()}, onerr=util.Abort, errprefix=_("edit failed"), out=ui.fout) # Remove comment lines patchfp = open(patchfn) ncpatchfp = cStringIO.StringIO() for line in patchfp: if not line.startswith('#'): ncpatchfp.write(line) patchfp.close() ncpatchfp.seek(0) newpatches = parsepatch(ncpatchfp) finally: os.unlink(patchfn) del ncpatchfp # Signal that the chunk shouldn't be applied as-is, but # provide the new patch to be used instead. ret = False elif r == 3: # Skip ret = skipfile = False elif r == 4: # file (Record remaining) ret = skipfile = True elif r == 5: # done, skip remaining ret = skipall = False elif r == 6: # all ret = skipall = True elif r == 7: # quit raise util.Abort(_('user quit')) return ret, skipfile, skipall, newpatches