# HG changeset patch # User Vadim Gelfer # Date 1155750384 25200 # Node ID ef8ee4477019da03a39add4be5a471b3b7263600 # Parent b70740aefa4df12bd0c86d7093c39c139171ba82# Parent 8743188f4d2ed4ef5f2329ff0eaf3d30f6802b7c merge with mpm. diff -r b70740aefa4d -r ef8ee4477019 hgext/mq.py --- a/hgext/mq.py Tue Aug 15 11:28:50 2006 -0700 +++ b/hgext/mq.py Wed Aug 16 10:46:24 2006 -0700 @@ -77,7 +77,7 @@ def diffopts(self): if self._diffopts is None: - self._diffopts = self.ui.diffopts() + self._diffopts = patch.diffopts(self.ui) return self._diffopts def join(self, *p): @@ -400,15 +400,39 @@ '''Apply patchfile to the working directory. patchfile: file name of patch''' try: - (files, fuzz) = patch.patch(patchfile, self.ui, strip=1, - cwd=repo.root) - except Exception, inst: - self.ui.note(str(inst) + '\n') - if not self.ui.verbose: - self.ui.warn("patch failed, unable to continue (try -v)\n") - return (False, [], False) + pp = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') + f = os.popen("%s -d %s -p1 --no-backup-if-mismatch < %s" % + (pp, util.shellquote(repo.root), util.shellquote(patchfile))) + except: + self.ui.warn("patch failed, unable to continue (try -v)\n") + return (None, [], False) + files = [] + fuzz = False + for l in f: + l = l.rstrip('\r\n'); + if self.ui.verbose: + self.ui.warn(l + "\n") + if l[:14] == 'patching file ': + pf = os.path.normpath(util.parse_patch_output(l)) + if pf not in files: + files.append(pf) + printed_file = False + file_str = l + elif l.find('with fuzz') >= 0: + if not printed_file: + self.ui.warn(file_str + '\n') + printed_file = True + self.ui.warn(l + '\n') + fuzz = True + elif l.find('saving rejects to file') >= 0: + self.ui.warn(l + '\n') + elif l.find('FAILED') >= 0: + if not printed_file: + self.ui.warn(file_str + '\n') + printed_file = True + self.ui.warn(l + '\n') - return (True, files.keys(), fuzz) + return (not f.close(), files, fuzz) def apply(self, repo, series, list=False, update_status=True, strict=False, patchdir=None, merge=None, wlock=None): @@ -482,28 +506,21 @@ tr.close() return (err, n) - def delete(self, repo, patches, keep=False): - realpatches = [] - for patch in patches: - patch = self.lookup(patch, strict=True) - info = self.isapplied(patch) - if info: - raise util.Abort(_("cannot delete applied patch %s") % patch) - if patch not in self.series: - raise util.Abort(_("patch %s not in series file") % patch) - realpatches.append(patch) - - if not keep: + def delete(self, repo, patch, force=False): + patch = self.lookup(patch, strict=True) + info = self.isapplied(patch) + if info: + raise util.Abort(_("cannot delete applied patch %s") % patch) + if patch not in self.series: + raise util.Abort(_("patch %s not in series file") % patch) + if force: r = self.qrepo() if r: - r.remove(realpatches, True) + r.remove([patch], True) else: os.unlink(self.join(patch)) - - indices = [self.find_series(p) for p in realpatches] - indices.sort() - for i in indices[-1::-1]: - del self.full_series[i] + i = self.find_series(patch) + del self.full_series[i] self.parse_series() self.series_dirty = 1 @@ -1283,13 +1300,13 @@ if qrepo: qrepo.add(added) -def delete(ui, repo, patch, *patches, **opts): - """remove patches from queue +def delete(ui, repo, patch, **opts): + """remove a patch from the series file - The patches must not be applied. - With -k, the patch files are preserved in the patch directory.""" + The patch must not be applied. + With -f, deletes the patch file as well as the series entry.""" q = repo.mq - q.delete(repo, (patch,) + patches, keep=opts.get('keep')) + q.delete(repo, patch, force=opts.get('force')) q.save_dirty() return 0 @@ -1447,7 +1464,7 @@ applied to the current patch in the order given. If all the patches apply successfully, the current patch will be refreshed with the new cumulative patch, and the folded patches will - be deleted. With -k/--keep, the folded patch files will not + be deleted. With -f/--force, the folded patch files will be removed afterwards. The header for each folded patch will be concatenated with @@ -1497,7 +1514,7 @@ q.refresh(repo, msg=message) for patch in patches: - q.delete(repo, patch, keep=opts['keep']) + q.delete(repo, patch, force=opts['force']) q.save_dirty() @@ -1886,14 +1903,14 @@ commands.table["^commit|ci"][1], 'hg qcommit [OPTION]... [FILE]...'), "^qdiff": (diff, [], 'hg qdiff [FILE]...'), - "qdelete|qremove|qrm": + "qdelete": (delete, - [('k', 'keep', None, _('keep patch file'))], - 'hg qdelete [-k] PATCH'), + [('f', 'force', None, _('delete patch file'))], + 'hg qdelete [-f] PATCH'), 'qfold': (fold, [('e', 'edit', None, _('edit patch header')), - ('k', 'keep', None, _('keep folded patch files')), + ('f', 'force', None, _('delete folded patch files')), ('m', 'message', '', _('set patch header to ')), ('l', 'logfile', '', _('set patch header to contents of '))], 'hg qfold [-e] [-m ] [-l self.startrev: + # forward: all descendants + if not self.roots: + self.roots.append(self.startrev) + for parent in realparents(rev): + if parent in self.roots: + self.roots.append(rev) + return True else: - return filter(lambda x: x != -1, repo.changelog.parentrevs(rev)) - - if self.startrev == -1: - self.startrev = rev - return True - - if rev > self.startrev: - # forward: all descendants - if not self.roots: - self.roots.append(self.startrev) - for parent in realparents(rev): - if parent in self.roots: - self.roots.append(rev) + # backwards: all parents + if not self.roots: + self.roots.extend(realparents(self.startrev)) + if rev in self.roots: + self.roots.remove(rev) + self.roots.extend(realparents(rev)) return True - else: - # backwards: all parents - if not self.roots: - self.roots.extend(realparents(self.startrev)) - if rev in self.roots: - self.roots.remove(rev) - self.roots.extend(realparents(rev)) - return True - - return False - - # it might be worthwhile to do this in the iterator if the rev range - # is descending and the prune args are all within that range - for rev in opts.get('prune', ()): - rev = repo.changelog.rev(repo.lookup(rev)) - ff = followfilter() - stop = min(revs[0], revs[-1]) - for x in range(rev, stop-1, -1): - if ff.match(x) and wanted.has_key(x): - del wanted[x] - - def iterate(): + + return False + if follow and not files: ff = followfilter(onlyfirst=opts.get('follow_first')) def want(rev): - if ff.match(rev) and rev in wanted: - return True - return False + if rev not in wanted: + return False + return ff.match(rev) else: def want(rev): return rev in wanted @@ -1347,7 +1337,7 @@ fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts) patch.diff(repo, node1, node2, fns, match=matchfn, - opts=ui.diffopts(opts)) + opts=patch.diffopts(ui, opts)) def export(ui, repo, *changesets, **opts): """dump the header and diffs for one or more changesets @@ -1384,7 +1374,8 @@ else: ui.note(_('exporting patch:\n')) patch.export(repo, map(repo.lookup, revs), template=opts['output'], - switch_parent=opts['switch_parent'], opts=ui.diffopts(opts)) + switch_parent=opts['switch_parent'], + opts=patch.diffopts(ui, opts)) def forget(ui, repo, *pats, **opts): """don't add the specified files on the next commit (DEPRECATED) @@ -1681,7 +1672,7 @@ message = None ui.debug(_('message:\n%s\n') % message) - files, fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root) + files = patch.patch(strip, tmpname, ui, cwd=repo.root) removes = [] if len(files) > 0: cfiles = files.keys() @@ -1969,29 +1960,9 @@ requested revision. Files that changed between either parent are marked as changed for the next commit and a commit must be performed before any further updates are allowed. - - If no revision is specified, the working directory's parent is a - head revision, and the repository contains exactly one other head, - the other head is merged with by default. Otherwise, an explicit - revision to merge with must be provided. """ - if node: - node = _lookup(repo, node, branch) - else: - heads = repo.heads() - if len(heads) > 2: - raise util.Abort(_('repo has %d heads - ' - 'please merge with an explicit rev') % - len(heads)) - if len(heads) == 1: - raise util.Abort(_('there is nothing to merge - ' - 'use "hg update" instead')) - parent = repo.dirstate.parents()[0] - if parent not in heads: - raise util.Abort(_('working dir not at a head rev - ' - 'use "hg update" or merge with an explicit rev')) - node = parent == heads[0] and heads[-1] or heads[0] + node = _lookup(repo, node, branch) return hg.merge(repo, node, force=force) def outgoing(ui, repo, dest=None, **opts): @@ -2897,7 +2868,6 @@ ('a', 'text', None, _('treat all files as text')), ('p', 'show-function', None, _('show which function each change is in')), - ('g', 'git', None, _('use git extended diff format')), ('w', 'ignore-all-space', None, _('ignore white space when comparing lines')), ('b', 'ignore-space-change', None, @@ -2997,7 +2967,6 @@ ('', 'style', '', _('display using template map file')), ('m', 'only-merges', None, _('show only merges')), ('p', 'patch', None, _('show patch')), - ('P', 'prune', [], _('do not display revision or any of its ancestors')), ('', 'template', '', _('display with template')), ('I', 'include', [], _('include names matching the given patterns')), ('X', 'exclude', [], _('exclude names matching the given patterns'))], diff -r b70740aefa4d -r ef8ee4477019 mercurial/filelog.py --- a/mercurial/filelog.py Tue Aug 15 11:28:50 2006 -0700 +++ b/mercurial/filelog.py Wed Aug 16 10:46:24 2006 -0700 @@ -65,26 +65,25 @@ return (m["copy"], bin(m["copyrev"])) return False + def size(self, rev): + """return the size of a given revision""" + + # for revisions with renames, we have to go the slow way + node = self.node(rev) + if self.renamed(node): + return len(self.read(node)) + + return revlog.size(self, rev) + def cmp(self, node, text): """compare text with a given file revision""" # for renames, we have to go the slow way if self.renamed(node): t2 = self.read(node) - return t2 == text - - p1, p2 = self.parents(node) - h = hash(text, p1, p2) - - return h != node + return t2 != text - def makenode(self, node, text): - """calculate a file nodeid for text, descended or possibly - unchanged from node""" - - if self.cmp(node, text): - return hash(text, node, nullid) - return node + return revlog.cmp(self, node, text) def annotate(self, node): diff -r b70740aefa4d -r ef8ee4477019 mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py Tue Aug 15 11:28:50 2006 -0700 +++ b/mercurial/hgweb/hgweb_mod.py Wed Aug 16 10:46:24 2006 -0700 @@ -11,7 +11,7 @@ import mimetypes from mercurial.demandload import demandload demandload(globals(), "re zlib ConfigParser mimetools cStringIO sys tempfile") -demandload(globals(), "mercurial:mdiff,ui,hg,util,archival,streamclone") +demandload(globals(), "mercurial:mdiff,ui,hg,util,archival,streamclone,patch") demandload(globals(), "mercurial:templater") demandload(globals(), "mercurial.hgweb.common:get_mtime,staticfile") from mercurial.node import * @@ -134,7 +134,7 @@ modified, added, removed = map(lambda x: filterfiles(files, x), (modified, added, removed)) - diffopts = self.repo.ui.diffopts() + diffopts = patch.diffopts(ui) for f in modified: to = r.file(f).read(mmap1[f]) tn = r.file(f).read(mmap2[f]) diff -r b70740aefa4d -r ef8ee4477019 mercurial/mail.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/mail.py Wed Aug 16 10:46:24 2006 -0700 @@ -0,0 +1,68 @@ +# mail.py - mail sending bits for mercurial +# +# Copyright 2006 Matt Mackall +# +# This software may be used and distributed according to the terms +# of the GNU General Public License, incorporated herein by reference. + +from i18n import gettext as _ +from demandload import * +demandload(globals(), "os re smtplib templater util") + +def _smtp(ui): + '''send mail using smtp.''' + + local_hostname = ui.config('smtp', 'local_hostname') + s = smtplib.SMTP(local_hostname=local_hostname) + mailhost = ui.config('smtp', 'host') + if not mailhost: + raise util.Abort(_('no [smtp]host in hgrc - cannot send mail')) + mailport = int(ui.config('smtp', 'port', 25)) + self.note(_('sending mail: smtp host %s, port %s\n') % + (mailhost, mailport)) + s.connect(host=mailhost, port=mailport) + if ui.configbool('smtp', 'tls'): + ui.note(_('(using tls)\n')) + s.ehlo() + s.starttls() + s.ehlo() + username = ui.config('smtp', 'username') + password = ui.config('smtp', 'password') + if username and password: + ui.note(_('(authenticating to mail server as %s)\n') % + (username)) + s.login(username, password) + return s + +class _sendmail(object): + '''send mail using sendmail.''' + + def __init__(self, ui, program): + self.ui = ui + self.program = program + + def sendmail(self, sender, recipients, msg): + cmdline = '%s -f %s %s' % ( + self.program, templater.email(sender), + ' '.join(map(templater.email, recipients))) + self.ui.note(_('sending mail: %s\n') % cmdline) + fp = os.popen(cmdline, 'w') + fp.write(msg) + ret = fp.close() + if ret: + raise util.Abort('%s %s' % ( + os.path.basename(self.program.split(None, 1)[0]), + util.explain_exit(ret)[0])) + +def connect(ui): + '''make a mail connection. object returned has one method, sendmail. + call as sendmail(sender, list-of-recipients, msg).''' + + method = ui.config('email', 'method', 'smtp') + if method == 'smtp': + return smtp(ui) + + return sendmail(ui, method) + +def sendmail(ui, sender, recipients, msg): + return connect(ui).sendmail(sender, recipients, msg) diff -r b70740aefa4d -r ef8ee4477019 mercurial/merge.py --- a/mercurial/merge.py Tue Aug 15 11:28:50 2006 -0700 +++ b/mercurial/merge.py Wed Aug 16 10:46:24 2006 -0700 @@ -10,6 +10,11 @@ from demandload import * demandload(globals(), "util os tempfile") +def fmerge(f, local, other, ancestor): + """merge executable flags""" + a, b, c = ancestor.execf(f), local.execf(f), other.execf(f) + return ((a^b) | (a^c)) ^ a + def merge3(repo, fn, my, other, p1, p2): """perform a 3-way merge in the working directory""" @@ -90,9 +95,7 @@ if not force: for f in unknown: if f in m2: - t1 = repo.wread(f) - t2 = repo.file(f).read(m2[f]) - if cmp(t1, t2) != 0: + if repo.file(f).cmp(m2[f], repo.wread(f)): raise util.Abort(_("'%s' already exists in the working" " dir and differs from remote") % f) @@ -100,13 +103,14 @@ # we care about merging repo.ui.note(_("resolving manifests\n")) repo.ui.debug(_(" overwrite %s branchmerge %s partial %s linear %s\n") % - (overwrite, branchmerge, partial and True or False, linear_path)) + (overwrite, branchmerge, bool(partial), linear_path)) repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (short(man), short(m1n), short(m2n))) merge = {} get = {} remove = [] + forget = [] # construct a working dir manifest mw = m1.copy() @@ -114,6 +118,11 @@ for f in added + modified + unknown: mw[f] = "" + # is the wfile new and matches m2? + if (f not in m1 and f in m2 and + not repo.file(f).cmp(m2[f], repo.wread(f))): + mw[f] = m2[f] + mw.set(f, util.is_exec(repo.wjoin(f), mw.execf(f))) for f in deleted + removed: @@ -125,8 +134,8 @@ # the file, then we need to remove it from the dirstate, to # prevent the dirstate from listing the file when it is no # longer in the manifest. - if not partial and linear_path and f not in m2: - repo.dirstate.forget((f,)) + if linear_path and f not in m2: + forget.append(f) # Compare manifests for f, n in mw.iteritems(): @@ -135,25 +144,13 @@ if f in m2: s = 0 - # is the wfile new since m1, and match m2? - if f not in m1: - t1 = repo.wread(f) - t2 = repo.file(f).read(m2[f]) - if cmp(t1, t2) == 0: - n = m2[f] - del t1, t2 - # are files different? if n != m2[f]: a = ma.get(f, nullid) # are both different from the ancestor? if n != a and m2[f] != a: repo.ui.debug(_(" %s versions differ, resolve\n") % f) - # merge executable bits - # "if we changed or they changed, change in merge" - a, b, c = ma.execf(f), mw.execf(f), m2.execf(f) - mode = ((a^b) | (a^c)) ^ a - merge[f] = (mode, m1.get(f, nullid), m2[f]) + merge[f] = (fmerge(f, mw, m2, ma), m1.get(f, nullid), m2[f]) s = 1 # are we clobbering? # is remote's version newer? @@ -172,9 +169,7 @@ repo.ui.debug(_(" updating permissions for %s\n") % f) util.set_exec(repo.wjoin(f), m2.execf(f)) else: - a, b, c = ma.execf(f), mw.execf(f), m2.execf(f) - mode = ((a^b) | (a^c)) ^ a - if mode != b: + if fmerge(f, mw, m2, ma) != mw.execf(f): repo.ui.debug(_(" updating permissions for %s\n") % f) util.set_exec(repo.wjoin(f), mode) @@ -230,6 +225,8 @@ del mw, m1, m2, ma + ### apply phase + if overwrite: for f in merge: get[f] = merge[f][:2] @@ -257,11 +254,6 @@ t = repo.file(f).read(node) repo.wwrite(f, t) util.set_exec(repo.wjoin(f), flag) - if not partial: - if branchmerge: - repo.dirstate.update([f], 'n', st_mtime=-1) - else: - repo.dirstate.update([f], 'n') # merge the tricky bits unresolved = [] @@ -274,19 +266,6 @@ if ret: unresolved.append(f) util.set_exec(repo.wjoin(f), flag) - if not partial: - if branchmerge: - # We've done a branch merge, mark this file as merged - # so that we properly record the merger later - repo.dirstate.update([f], 'm') - else: - # We've update-merged a locally modified file, so - # we set the dirstate to emulate a normal checkout - # of that file some time in the past. Thus our - # merge will appear as a normal local file - # modification. - f_len = len(repo.file(f).read(other)) - repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1) remove.sort() for f in remove: @@ -298,14 +277,40 @@ if inst.errno != errno.ENOENT: repo.ui.warn(_("update failed to remove %s: %s!\n") % (f, inst.strerror)) + + # update dirstate if not partial: + repo.dirstate.setparents(p1, p2) + repo.dirstate.forget(forget) if branchmerge: repo.dirstate.update(remove, 'r') else: repo.dirstate.forget(remove) - if not partial: - repo.dirstate.setparents(p1, p2) + files = get.keys() + files.sort() + for f in files: + if branchmerge: + repo.dirstate.update([f], 'n', st_mtime=-1) + else: + repo.dirstate.update([f], 'n') + + files = merge.keys() + files.sort() + for f in files: + if branchmerge: + # We've done a branch merge, mark this file as merged + # so that we properly record the merger later + repo.dirstate.update([f], 'm') + else: + # We've update-merged a locally modified file, so + # we set the dirstate to emulate a normal checkout + # of that file some time in the past. Thus our + # merge will appear as a normal local file + # modification. + fl = repo.file(f) + f_len = fl.size(fl.rev(other)) + repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1) if show_stats: stats = ((len(get), _("updated")), diff -r b70740aefa4d -r ef8ee4477019 mercurial/patch.py --- a/mercurial/patch.py Tue Aug 15 11:28:50 2006 -0700 +++ b/mercurial/patch.py Wed Aug 16 10:46:24 2006 -0700 @@ -215,14 +215,13 @@ tmpfp.close() return patchname -def patch(patchname, ui, strip=1, cwd=None): +def patch(strip, patchname, ui, cwd=None): """apply the patch to the working directory. a list of patched files is returned""" (dopatch, gitpatches) = readgitpatch(patchname) files = {} - fuzz = False if dopatch: if dopatch == 'filter': patchname = dogitpatch(patchname, gitpatches) @@ -238,25 +237,10 @@ for line in fp: line = line.rstrip() - ui.note(line + '\n') + ui.status("%s\n" % line) if line.startswith('patching file '): pf = util.parse_patch_output(line) - printed_file = False files.setdefault(pf, (None, None)) - elif line.find('with fuzz') >= 0: - fuzz = True - if not printed_file: - ui.warn(pf + '\n') - printed_file = True - ui.warn(line + '\n') - elif line.find('saving rejects to file') >= 0: - ui.warn(line + '\n') - elif line.find('FAILED') >= 0: - if not printed_file: - ui.warn(pf + '\n') - printed_file = True - ui.warn(line + '\n') - code = fp.close() if code: raise util.Abort(_("patch command failed: %s") % @@ -265,7 +249,19 @@ for gp in gitpatches: files[gp.path] = (gp.op, gp) - return (files, fuzz) + return files + +def diffopts(ui, opts={}): + return mdiff.diffopts( + text=opts.get('text'), + showfunc=(opts.get('show_function') or + ui.configbool('diff', 'showfunc', None)), + ignorews=(opts.get('ignore_all_space') or + ui.configbool('diff', 'ignorews', None)), + ignorewsamount=(opts.get('ignore_space_change') or + ui.configbool('diff', 'ignorewsamount', None)), + ignoreblanklines=(opts.get('ignore_blank_lines') or + ui.configbool('diff', 'ignoreblanklines', None))) def diff(repo, node1=None, node2=None, files=None, match=util.always, fp=None, changes=None, opts=None): @@ -314,9 +310,6 @@ return _date2 def read(f): return repo.file(f).read(mmap2[f]) - def renamed(f): - src = repo.file(f).renamed(mmap2[f]) - return src and src[0] or None else: tz = util.makedate()[1] _date2 = util.datestr() @@ -328,8 +321,6 @@ return _date2 def read(f): return repo.wread(f) - def renamed(f): - return repo.dirstate.copies.get(f) if repo.ui.quiet: r = None @@ -337,65 +328,16 @@ hexfunc = repo.ui.verbose and hex or short r = [hexfunc(node) for node in [node1, node2] if node] - if opts.git: - copied = {} - for f in added: - src = renamed(f) - if src: - copied[f] = src - srcs = [x[1] for x in copied.items()] - all = modified + added + removed all.sort() for f in all: to = None tn = None - dodiff = True if f in mmap: to = repo.file(f).read(mmap[f]) if f not in removed: tn = read(f) - if opts.git: - def gitmode(x): - return x and '100755' or '100644' - def addmodehdr(header, omode, nmode): - if omode != nmode: - header.append('old mode %s\n' % omode) - header.append('new mode %s\n' % nmode) - - a, b = f, f - header = [] - if f in added: - if node2: - mode = gitmode(mmap2.execf(f)) - else: - mode = gitmode(util.is_exec(repo.wjoin(f), None)) - if f in copied: - a = copied[f] - omode = gitmode(mmap.execf(a)) - addmodehdr(header, omode, mode) - op = a in removed and 'rename' or 'copy' - header.append('%s from %s\n' % (op, a)) - header.append('%s to %s\n' % (op, f)) - to = repo.file(a).read(mmap[a]) - else: - header.append('new file mode %s\n' % mode) - elif f in removed: - if f in srcs: - dodiff = False - else: - mode = gitmode(mmap.execf(f)) - header.append('deleted file mode %s\n' % mode) - else: - omode = gitmode(mmap.execf(f)) - nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f))) - addmodehdr(header, omode, nmode) - r = None - if dodiff: - header.insert(0, 'diff --git a/%s b/%s\n' % (a, b)) - fp.write(''.join(header)) - if dodiff: - fp.write(mdiff.unidiff(to, date1, tn, date2(f), f, r, opts=opts)) + fp.write(mdiff.unidiff(to, date1, tn, date2(f), f, r, opts=opts)) def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False, opts=None): diff -r b70740aefa4d -r ef8ee4477019 mercurial/revlog.py --- a/mercurial/revlog.py Tue Aug 15 11:28:50 2006 -0700 +++ b/mercurial/revlog.py Wed Aug 16 10:46:24 2006 -0700 @@ -766,6 +766,19 @@ raise RevlogError(_("No match found")) + def cmp(self, node, text): + """compare text with a given file revision""" + p1, p2 = self.parents(node) + return hash(text, p1, p2) != node + + def makenode(self, node, text): + """calculate a file nodeid for text, descended or possibly + unchanged from node""" + + if self.cmp(node, text): + return hash(text, node, nullid) + return node + def diff(self, a, b): """return a delta between two revisions""" return mdiff.textdiff(a, b) diff -r b70740aefa4d -r ef8ee4477019 mercurial/ui.py --- a/mercurial/ui.py Tue Aug 15 11:28:50 2006 -0700 +++ b/mercurial/ui.py Wed Aug 16 10:46:24 2006 -0700 @@ -7,7 +7,7 @@ from i18n import gettext as _ from demandload import * -demandload(globals(), "errno getpass os re smtplib socket sys tempfile") +demandload(globals(), "errno getpass os re socket sys tempfile") demandload(globals(), "ConfigParser mdiff templater traceback util") class ui(object): @@ -169,20 +169,6 @@ result[key.lower()] = value return result - def diffopts(self, opts={}): - return mdiff.diffopts( - text=opts.get('text'), - showfunc=(opts.get('show_function') or - self.configbool('diff', 'showfunc', None)), - git=(opts.get('git') or - self.configbool('diff', 'git', None)), - ignorews=(opts.get('ignore_all_space') or - self.configbool('diff', 'ignorews', None)), - ignorewsamount=(opts.get('ignore_space_change') or - self.configbool('diff', 'ignorewsamount', None)), - ignoreblanklines=(opts.get('ignore_blank_lines') or - self.configbool('diff', 'ignoreblanklines', None))) - def username(self): """Return default username to be used in commits. @@ -295,62 +281,6 @@ return t - def sendmail(self): - '''send mail message. object returned has one method, sendmail. - call as sendmail(sender, list-of-recipients, msg).''' - - def smtp(): - '''send mail using smtp.''' - - local_hostname = self.config('smtp', 'local_hostname') - s = smtplib.SMTP(local_hostname=local_hostname) - mailhost = self.config('smtp', 'host') - if not mailhost: - raise util.Abort(_('no [smtp]host in hgrc - cannot send mail')) - mailport = int(self.config('smtp', 'port', 25)) - self.note(_('sending mail: smtp host %s, port %s\n') % - (mailhost, mailport)) - s.connect(host=mailhost, port=mailport) - if self.configbool('smtp', 'tls'): - self.note(_('(using tls)\n')) - s.ehlo() - s.starttls() - s.ehlo() - username = self.config('smtp', 'username') - password = self.config('smtp', 'password') - if username and password: - self.note(_('(authenticating to mail server as %s)\n') % - (username)) - s.login(username, password) - return s - - class sendmail(object): - '''send mail using sendmail.''' - - def __init__(self, ui, program): - self.ui = ui - self.program = program - - def sendmail(self, sender, recipients, msg): - cmdline = '%s -f %s %s' % ( - self.program, templater.email(sender), - ' '.join(map(templater.email, recipients))) - self.ui.note(_('sending mail: %s\n') % cmdline) - fp = os.popen(cmdline, 'w') - fp.write(msg) - ret = fp.close() - if ret: - raise util.Abort('%s %s' % ( - os.path.basename(self.program.split(None, 1)[0]), - util.explain_exit(ret)[0])) - - method = self.config('email', 'method', 'smtp') - if method == 'smtp': - mail = smtp() - else: - mail = sendmail(self, method) - return mail - def print_exc(self): '''print exception traceback if traceback printing enabled. only to call in exception handler. returns true if traceback