redo merge with mpm.
previous merge at ef8ee4477019 was bad.
--- a/hgext/mq.py Tue Aug 15 11:28:50 2006 -0700
+++ b/hgext/mq.py Wed Aug 16 10:52:19 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):
--- a/hgext/notify.py Tue Aug 15 11:28:50 2006 -0700
+++ b/hgext/notify.py Wed Aug 16 10:52:19 2006 -0700
@@ -67,8 +67,8 @@
from mercurial.demandload import *
from mercurial.i18n import gettext as _
from mercurial.node import *
-demandload(globals(), 'email.Parser mercurial:commands,patch,templater,util')
-demandload(globals(), 'fnmatch socket time')
+demandload(globals(), 'mercurial:commands,patch,templater,util,mail')
+demandload(globals(), 'email.Parser fnmatch socket time')
# template for single changeset can include email headers.
single_template = '''
@@ -229,8 +229,8 @@
else:
self.ui.status(_('notify: sending %d subscribers %d changes\n') %
(len(self.subs), count))
- mail = self.ui.sendmail()
- mail.sendmail(templater.email(msg['From']), self.subs, msgtext)
+ mail.sendmail(self.ui, templater.email(msg['From']),
+ self.subs, msgtext)
def diff(self, node, ref):
maxdiff = int(self.ui.config('notify', 'maxdiff', 300))
--- a/hgext/patchbomb.py Tue Aug 15 11:28:50 2006 -0700
+++ b/hgext/patchbomb.py Wed Aug 16 10:52:19 2006 -0700
@@ -241,7 +241,7 @@
ui.write('\n')
if not opts['test'] and not opts['mbox']:
- mail = ui.sendmail()
+ mailer = mail.connect(ui)
parent = None
# Calculate UTC offset
@@ -290,7 +290,7 @@
ui.status('Sending ', m['Subject'], ' ...\n')
# Exim does not remove the Bcc field
del m['Bcc']
- mail.sendmail(sender, to + bcc + cc, m.as_string(0))
+ mailer.sendmail(sender, to + bcc + cc, m.as_string(0))
cmdtable = {
'email':
--- a/mercurial/commands.py Tue Aug 15 11:28:50 2006 -0700
+++ b/mercurial/commands.py Wed Aug 16 10:52:19 2006 -0700
@@ -1347,7 +1347,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 +1384,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)
--- a/mercurial/filelog.py Tue Aug 15 11:28:50 2006 -0700
+++ b/mercurial/filelog.py Wed Aug 16 10:52:19 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):
--- a/mercurial/hgweb/hgweb_mod.py Tue Aug 15 11:28:50 2006 -0700
+++ b/mercurial/hgweb/hgweb_mod.py Wed Aug 16 10:52:19 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])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/mail.py Wed Aug 16 10:52:19 2006 -0700
@@ -0,0 +1,68 @@
+# mail.py - mail sending bits for mercurial
+#
+# Copyright 2006 Matt Mackall <mpm@selenic.com>
+#
+# 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)
--- a/mercurial/merge.py Tue Aug 15 11:28:50 2006 -0700
+++ b/mercurial/merge.py Wed Aug 16 10:52:19 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")),
--- a/mercurial/patch.py Tue Aug 15 11:28:50 2006 -0700
+++ b/mercurial/patch.py Wed Aug 16 10:52:19 2006 -0700
@@ -267,6 +267,20 @@
return (files, fuzz)
+def diffopts(ui, opts={}):
+ return mdiff.diffopts(
+ text=opts.get('text'),
+ git=(opts.get('git') or
+ ui.configbool('diff', 'git', None)),
+ 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):
'''print diff of changes to files between two nodes, or node and
--- a/mercurial/revlog.py Tue Aug 15 11:28:50 2006 -0700
+++ b/mercurial/revlog.py Wed Aug 16 10:52:19 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)
--- a/mercurial/ui.py Tue Aug 15 11:28:50 2006 -0700
+++ b/mercurial/ui.py Wed Aug 16 10:52:19 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