--- a/Makefile Sun Nov 25 20:39:37 2012 +0100
+++ b/Makefile Wed Nov 28 16:15:05 2012 -0600
@@ -34,7 +34,7 @@
local:
$(PYTHON) setup.py $(PURE) build_py -c -d . build_ext -i build_hgexe -i build_mo
- $(PYTHON) hg version
+ env HGRCPATH= $(PYTHON) hg version
build:
$(PYTHON) setup.py $(PURE) build
--- a/contrib/check-code.py Sun Nov 25 20:39:37 2012 +0100
+++ b/contrib/check-code.py Wed Nov 28 16:15:05 2012 -0600
@@ -211,11 +211,11 @@
(r'\.strip\(\)\.split\(\)', "no need to strip before splitting"),
(r'^\s*except\s*:', "warning: naked except clause", r'#.*re-raises'),
(r':\n( )*( ){1,3}[^ ]', "must indent 4 spaces"),
+ (r'ui\.(status|progress|write|note|warn)\([\'\"]x',
+ "missing _() in ui message (use () to hide false-positives)"),
],
# warnings
[
- (r'ui\.(status|progress|write|note|warn)\([\'\"]x',
- "warning: unwrapped ui message"),
]
]
--- a/contrib/hgk Sun Nov 25 20:39:37 2012 +0100
+++ b/contrib/hgk Wed Nov 28 16:15:05 2012 -0600
@@ -15,8 +15,43 @@
# The whole snipped is activated only under windows, mouse wheel
# bindings working already under MacOSX and Linux.
+if {[catch {package require Ttk}]} {
+ # use a shim
+ namespace eval ttk {
+ proc style args {}
+
+ proc entry args {
+ eval [linsert $args 0 ::entry] -relief flat
+ }
+ }
+
+ interp alias {} ttk::button {} button
+ interp alias {} ttk::frame {} frame
+ interp alias {} ttk::label {} label
+ interp alias {} ttk::scrollbar {} scrollbar
+ interp alias {} ttk::optionMenu {} tk_optionMenu
+} else {
+ proc ::ttk::optionMenu {w varName firstValue args} {
+ upvar #0 $varName var
+
+ if {![info exists var]} {
+ set var $firstValue
+ }
+ ttk::menubutton $w -textvariable $varName -menu $w.menu \
+ -direction flush
+ menu $w.menu -tearoff 0
+ $w.menu add radiobutton -label $firstValue -variable $varName
+ foreach i $args {
+ $w.menu add radiobutton -label $i -variable $varName
+ }
+ return $w.menu
+ }
+}
+
if {[tk windowingsystem] eq "win32"} {
+ttk::style theme use xpnative
+
set mw_classes [list Text Listbox Table TreeCtrl]
foreach class $mw_classes { bind $class <MouseWheel> {} }
@@ -72,6 +107,12 @@
bind all <MouseWheel> [list ::tk::MouseWheel %W %X %Y %D 0]
# end of win32 section
+} else {
+
+if {[ttk::style theme use] eq "default"} {
+ ttk::style theme use clam
+}
+
}
@@ -480,7 +521,7 @@
wm transient $w .
message $w.m -text $msg -justify center -aspect 400
pack $w.m -side top -fill x -padx 20 -pady 20
- button $w.ok -text OK -command "destroy $w"
+ ttk::button $w.ok -text OK -command "destroy $w"
pack $w.ok -side bottom -fill x
bind $w <Visibility> "grab $w; focus $w"
tkwait window $w
@@ -526,11 +567,11 @@
set geometry(ctexth) [expr {($texth - 8) /
[font metrics $textfont -linespace]}]
}
- frame .ctop.top
- frame .ctop.top.bar
+ ttk::frame .ctop.top
+ ttk::frame .ctop.top.bar
pack .ctop.top.bar -side bottom -fill x
set cscroll .ctop.top.csb
- scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
+ ttk::scrollbar $cscroll -command {allcanvs yview}
pack $cscroll -side right -fill y
panedwindow .ctop.top.clist -orient horizontal -sashpad 0 -handlesize 4
pack .ctop.top.clist -side top -fill both -expand 1
@@ -538,15 +579,15 @@
set canv .ctop.top.clist.canv
canvas $canv -height $geometry(canvh) -width $geometry(canv1) \
-bg $bgcolor -bd 0 \
- -yscrollincr $linespc -yscrollcommand "$cscroll set" -selectbackground grey
+ -yscrollincr $linespc -yscrollcommand "$cscroll set" -selectbackground "#c0c0c0"
.ctop.top.clist add $canv
set canv2 .ctop.top.clist.canv2
canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \
- -bg $bgcolor -bd 0 -yscrollincr $linespc -selectbackground grey
+ -bg $bgcolor -bd 0 -yscrollincr $linespc -selectbackground "#c0c0c0"
.ctop.top.clist add $canv2
set canv3 .ctop.top.clist.canv3
canvas $canv3 -height $geometry(canvh) -width $geometry(canv3) \
- -bg $bgcolor -bd 0 -yscrollincr $linespc -selectbackground grey
+ -bg $bgcolor -bd 0 -yscrollincr $linespc -selectbackground "#c0c0c0"
.ctop.top.clist add $canv3
bind .ctop.top.clist <Configure> {resizeclistpanes %W %w}
@@ -557,7 +598,7 @@
-command gotocommit -width 8
$sha1but conf -disabledforeground [$sha1but cget -foreground]
pack .ctop.top.bar.sha1label -side left
- entry $sha1entry -width 40 -font $textfont -textvariable sha1string
+ ttk::entry $sha1entry -width 40 -font $textfont -textvariable sha1string
trace add variable sha1string write sha1change
pack $sha1entry -side left -pady 2
@@ -577,25 +618,25 @@
0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
}
- button .ctop.top.bar.leftbut -image bm-left -command goback \
+ ttk::button .ctop.top.bar.leftbut -image bm-left -command goback \
-state disabled -width 26
pack .ctop.top.bar.leftbut -side left -fill y
- button .ctop.top.bar.rightbut -image bm-right -command goforw \
+ ttk::button .ctop.top.bar.rightbut -image bm-right -command goforw \
-state disabled -width 26
pack .ctop.top.bar.rightbut -side left -fill y
- button .ctop.top.bar.findbut -text "Find" -command dofind
+ ttk::button .ctop.top.bar.findbut -text "Find" -command dofind
pack .ctop.top.bar.findbut -side left
set findstring {}
set fstring .ctop.top.bar.findstring
lappend entries $fstring
- entry $fstring -width 30 -font $textfont -textvariable findstring
+ ttk::entry $fstring -width 30 -font $textfont -textvariable findstring
pack $fstring -side left -expand 1 -fill x
set findtype Exact
- set findtypemenu [tk_optionMenu .ctop.top.bar.findtype \
+ set findtypemenu [ttk::optionMenu .ctop.top.bar.findtype \
findtype Exact IgnCase Regexp]
set findloc "All fields"
- tk_optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \
+ ttk::optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \
Comments Author Committer Files Pickaxe
pack .ctop.top.bar.findloc -side right
pack .ctop.top.bar.findtype -side right
@@ -604,14 +645,14 @@
panedwindow .ctop.cdet -orient horizontal
.ctop add .ctop.cdet
- frame .ctop.cdet.left
+ ttk::frame .ctop.cdet.left
set ctext .ctop.cdet.left.ctext
text $ctext -fg $fgcolor -bg $bgcolor -state disabled -font $textfont \
-width $geometry(ctextw) -height $geometry(ctexth) \
-yscrollcommand ".ctop.cdet.left.sb set" \
-xscrollcommand ".ctop.cdet.left.hb set" -wrap none
- scrollbar .ctop.cdet.left.sb -command "$ctext yview"
- scrollbar .ctop.cdet.left.hb -orient horizontal -command "$ctext xview"
+ ttk::scrollbar .ctop.cdet.left.sb -command "$ctext yview"
+ ttk::scrollbar .ctop.cdet.left.hb -orient horizontal -command "$ctext xview"
pack .ctop.cdet.left.sb -side right -fill y
pack .ctop.cdet.left.hb -side bottom -fill x
pack $ctext -side left -fill both -expand 1
@@ -643,12 +684,12 @@
$ctext tag conf found -back yellow
}
- frame .ctop.cdet.right
+ ttk::frame .ctop.cdet.right
set cflist .ctop.cdet.right.cfiles
listbox $cflist -fg $fgcolor -bg $bgcolor \
-selectmode extended -width $geometry(cflistw) \
-yscrollcommand ".ctop.cdet.right.sb set"
- scrollbar .ctop.cdet.right.sb -command "$cflist yview"
+ ttk::scrollbar .ctop.cdet.right.sb -command "$cflist yview"
pack .ctop.cdet.right.sb -side right -fill y
pack $cflist -side left -fill both -expand 1
.ctop.cdet add .ctop.cdet.right
@@ -901,7 +942,7 @@
Use and redistribute under the terms of the GNU General Public License} \
-justify center -aspect 400
pack $w.m -side top -fill x -padx 20 -pady 20
- button $w.ok -text Close -command "destroy $w"
+ ttk::button $w.ok -text Close -command "destroy $w"
pack $w.ok -side bottom
}
@@ -1219,7 +1260,7 @@
} else {
# draw a head or other ref
if {[incr nheads -1] >= 0} {
- set col green
+ set col "#00ff00"
} else {
set col "#ddddff"
}
@@ -2417,8 +2458,7 @@
set currentid $id
$sha1entry delete 0 end
$sha1entry insert 0 $id
- $sha1entry selection from 0
- $sha1entry selection to end
+ $sha1entry selection range 0 end
$ctext conf -state normal
$ctext delete 0.0 end
@@ -3675,36 +3715,36 @@
set patchtop $top
catch {destroy $top}
toplevel $top
- label $top.title -text "Generate patch"
+ ttk::label $top.title -text "Generate patch"
grid $top.title - -pady 10
- label $top.from -text "From:"
- entry $top.fromsha1 -width 40 -relief flat
+ ttk::label $top.from -text "From:"
+ ttk::entry $top.fromsha1 -width 40
$top.fromsha1 insert 0 $oldid
$top.fromsha1 conf -state readonly
grid $top.from $top.fromsha1 -sticky w
- entry $top.fromhead -width 60 -relief flat
+ ttk::entry $top.fromhead -width 60
$top.fromhead insert 0 $oldhead
$top.fromhead conf -state readonly
grid x $top.fromhead -sticky w
- label $top.to -text "To:"
- entry $top.tosha1 -width 40 -relief flat
+ ttk::label $top.to -text "To:"
+ ttk::entry $top.tosha1 -width 40
$top.tosha1 insert 0 $newid
$top.tosha1 conf -state readonly
grid $top.to $top.tosha1 -sticky w
- entry $top.tohead -width 60 -relief flat
+ ttk::entry $top.tohead -width 60
$top.tohead insert 0 $newhead
$top.tohead conf -state readonly
grid x $top.tohead -sticky w
- button $top.rev -text "Reverse" -command mkpatchrev -padx 5
+ ttk::button $top.rev -text "Reverse" -command mkpatchrev
grid $top.rev x -pady 10
- label $top.flab -text "Output file:"
- entry $top.fname -width 60
+ ttk::label $top.flab -text "Output file:"
+ ttk::entry $top.fname -width 60
$top.fname insert 0 [file normalize "patch$patchnum.patch"]
incr patchnum
grid $top.flab $top.fname -sticky w
- frame $top.buts
- button $top.buts.gen -text "Generate" -command mkpatchgo
- button $top.buts.can -text "Cancel" -command mkpatchcan
+ ttk::frame $top.buts
+ ttk::button $top.buts.gen -text "Generate" -command mkpatchgo
+ ttk::button $top.buts.can -text "Cancel" -command mkpatchcan
grid $top.buts.gen $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -3755,23 +3795,23 @@
set mktagtop $top
catch {destroy $top}
toplevel $top
- label $top.title -text "Create tag"
+ ttk::label $top.title -text "Create tag"
grid $top.title - -pady 10
- label $top.id -text "ID:"
- entry $top.sha1 -width 40 -relief flat
+ ttk::label $top.id -text "ID:"
+ ttk::entry $top.sha1 -width 40
$top.sha1 insert 0 $rowmenuid
$top.sha1 conf -state readonly
grid $top.id $top.sha1 -sticky w
- entry $top.head -width 60 -relief flat
+ ttk::entry $top.head -width 60
$top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
$top.head conf -state readonly
grid x $top.head -sticky w
- label $top.tlab -text "Tag name:"
- entry $top.tag -width 60
+ ttk::label $top.tlab -text "Tag name:"
+ ttk::entry $top.tag -width 60
grid $top.tlab $top.tag -sticky w
- frame $top.buts
- button $top.buts.gen -text "Create" -command mktaggo
- button $top.buts.can -text "Cancel" -command mktagcan
+ ttk::frame $top.buts
+ ttk::button $top.buts.gen -text "Create" -command mktaggo
+ ttk::button $top.buts.can -text "Cancel" -command mktagcan
grid $top.buts.gen $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -3835,27 +3875,27 @@
set wrcomtop $top
catch {destroy $top}
toplevel $top
- label $top.title -text "Write commit to file"
+ ttk::label $top.title -text "Write commit to file"
grid $top.title - -pady 10
- label $top.id -text "ID:"
- entry $top.sha1 -width 40 -relief flat
+ ttk::label $top.id -text "ID:"
+ ttk::entry $top.sha1 -width 40
$top.sha1 insert 0 $rowmenuid
$top.sha1 conf -state readonly
grid $top.id $top.sha1 -sticky w
- entry $top.head -width 60 -relief flat
+ ttk::entry $top.head -width 60
$top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
$top.head conf -state readonly
grid x $top.head -sticky w
- label $top.clab -text "Command:"
- entry $top.cmd -width 60 -textvariable wrcomcmd
+ ttk::label $top.clab -text "Command:"
+ ttk::entry $top.cmd -width 60 -textvariable wrcomcmd
grid $top.clab $top.cmd -sticky w -pady 10
- label $top.flab -text "Output file:"
- entry $top.fname -width 60
+ ttk::label $top.flab -text "Output file:"
+ ttk::entry $top.fname -width 60
$top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
grid $top.flab $top.fname -sticky w
- frame $top.buts
- button $top.buts.gen -text "Write" -command wrcomgo
- button $top.buts.can -text "Cancel" -command wrcomcan
+ ttk::frame $top.buts
+ ttk::button $top.buts.gen -text "Write" -command wrcomgo
+ ttk::button $top.buts.can -text "Cancel" -command wrcomcan
grid $top.buts.gen $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
--- a/hgext/convert/__init__.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/convert/__init__.py Wed Nov 28 16:15:05 2012 -0600
@@ -191,6 +191,10 @@
branch indicated in the regex as the second parent of the
changeset. Default is ``{{mergefrombranch ([-\\w]+)}}``
+ :convert.localtimezone: use local time (as determined by the TZ
+ environment variable) for changeset date/times. The default
+ is False (use UTC).
+
:hook.cvslog: Specify a Python function to be called at the end of
gathering the CVS log. The function is passed a list with the
log entries, and can modify the entries in-place, or add or
@@ -231,6 +235,10 @@
:convert.svn.trunk: specify the name of the trunk branch. The
default is ``trunk``.
+ :convert.localtimezone: use local time (as determined by the TZ
+ environment variable) for changeset date/times. The default
+ is False (use UTC).
+
Source history can be retrieved starting at a specific revision,
instead of being integrally converted. Only single branch
conversions are supported.
--- a/hgext/convert/common.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/convert/common.py Wed Nov 28 16:15:05 2012 -0600
@@ -5,7 +5,7 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
-import base64, errno, subprocess, os
+import base64, errno, subprocess, os, datetime
import cPickle as pickle
from mercurial import util
from mercurial.i18n import _
@@ -446,3 +446,10 @@
if e.errno != errno.ENOENT:
raise
return m
+
+def makedatetimestamp(t):
+ """Like util.makedate() but for time t instead of current time"""
+ delta = (datetime.datetime.utcfromtimestamp(t) -
+ datetime.datetime.fromtimestamp(t))
+ tz = delta.days * 86400 + delta.seconds
+ return t, tz
--- a/hgext/convert/cvs.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/convert/cvs.py Wed Nov 28 16:15:05 2012 -0600
@@ -11,6 +11,7 @@
from mercurial.i18n import _
from common import NoRepo, commit, converter_source, checktool
+from common import makedatetimestamp
import cvsps
class convert_cvs(converter_source):
@@ -70,6 +71,8 @@
cs.author = self.recode(cs.author)
self.lastbranch[cs.branch] = id
cs.comment = self.recode(cs.comment)
+ if self.ui.configbool('convert', 'localtimezone'):
+ cs.date = makedatetimestamp(cs.date[0])
date = util.datestr(cs.date, '%Y-%m-%d %H:%M:%S %1%2')
self.tags.update(dict.fromkeys(cs.tags, id))
--- a/hgext/convert/cvsps.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/convert/cvsps.py Wed Nov 28 16:15:05 2012 -0600
@@ -801,22 +801,22 @@
# Note: trailing spaces on several lines here are needed to have
# bug-for-bug compatibility with cvsps.
ui.write('---------------------\n')
- ui.write('PatchSet %d \n' % cs.id)
- ui.write('Date: %s\n' % util.datestr(cs.date,
- '%Y/%m/%d %H:%M:%S %1%2'))
- ui.write('Author: %s\n' % cs.author)
- ui.write('Branch: %s\n' % (cs.branch or 'HEAD'))
- ui.write('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1],
- ','.join(cs.tags) or '(none)'))
+ ui.write(('PatchSet %d \n' % cs.id))
+ ui.write(('Date: %s\n' % util.datestr(cs.date,
+ '%Y/%m/%d %H:%M:%S %1%2')))
+ ui.write(('Author: %s\n' % cs.author))
+ ui.write(('Branch: %s\n' % (cs.branch or 'HEAD')))
+ ui.write(('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1],
+ ','.join(cs.tags) or '(none)')))
branchpoints = getattr(cs, 'branchpoints', None)
if branchpoints:
- ui.write('Branchpoints: %s \n' % ', '.join(branchpoints))
+ ui.write(('Branchpoints: %s \n' % ', '.join(branchpoints)))
if opts["parents"] and cs.parents:
if len(cs.parents) > 1:
- ui.write('Parents: %s\n' %
- (','.join([str(p.id) for p in cs.parents])))
+ ui.write(('Parents: %s\n' %
+ (','.join([str(p.id) for p in cs.parents]))))
else:
- ui.write('Parent: %d\n' % cs.parents[0].id)
+ ui.write(('Parent: %d\n' % cs.parents[0].id))
if opts["ancestors"]:
b = cs.branch
@@ -825,11 +825,11 @@
b, c = ancestors[b]
r.append('%s:%d:%d' % (b or "HEAD", c, branches[b]))
if r:
- ui.write('Ancestors: %s\n' % (','.join(r)))
+ ui.write(('Ancestors: %s\n' % (','.join(r))))
- ui.write('Log:\n')
+ ui.write(('Log:\n'))
ui.write('%s\n\n' % cs.comment)
- ui.write('Members: \n')
+ ui.write(('Members: \n'))
for f in cs.entries:
fn = f.file
if fn.startswith(opts["prefix"]):
--- a/hgext/convert/git.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/convert/git.py Wed Nov 28 16:15:05 2012 -0600
@@ -6,12 +6,24 @@
# GNU General Public License version 2 or any later version.
import os
-from mercurial import util
+from mercurial import util, config
from mercurial.node import hex, nullid
from mercurial.i18n import _
from common import NoRepo, commit, converter_source, checktool
+class submodule(object):
+ def __init__(self, path, node, url):
+ self.path = path
+ self.node = node
+ self.url = url
+
+ def hgsub(self):
+ return "%s = [git]%s" % (self.path, self.url)
+
+ def hgsubstate(self):
+ return "%s %s" % (self.node, self.path)
+
class convert_git(converter_source):
# Windows does not support GIT_DIR= construct while other systems
# cannot remove environment variable. Just assume none have
@@ -55,6 +67,7 @@
checktool('git', 'git')
self.path = path
+ self.submodules = []
def getheads(self):
if not self.rev:
@@ -76,16 +89,57 @@
return data
def getfile(self, name, rev):
- data = self.catfile(rev, "blob")
- mode = self.modecache[(name, rev)]
+ if name == '.hgsub':
+ data = '\n'.join([m.hgsub() for m in self.submoditer()])
+ mode = ''
+ elif name == '.hgsubstate':
+ data = '\n'.join([m.hgsubstate() for m in self.submoditer()])
+ mode = ''
+ else:
+ data = self.catfile(rev, "blob")
+ mode = self.modecache[(name, rev)]
return data, mode
+ def submoditer(self):
+ null = hex(nullid)
+ for m in sorted(self.submodules, key=lambda p: p.path):
+ if m.node != null:
+ yield m
+
+ def parsegitmodules(self, content):
+ """Parse the formatted .gitmodules file, example file format:
+ [submodule "sub"]\n
+ \tpath = sub\n
+ \turl = git://giturl\n
+ """
+ self.submodules = []
+ c = config.config()
+ # Each item in .gitmodules starts with \t that cant be parsed
+ c.parse('.gitmodules', content.replace('\t',''))
+ for sec in c.sections():
+ s = c[sec]
+ if 'url' in s and 'path' in s:
+ self.submodules.append(submodule(s['path'], '', s['url']))
+
+ def retrievegitmodules(self, version):
+ modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules'))
+ if ret:
+ raise util.Abort(_('cannot read submodules config file in %s') %
+ version)
+ self.parsegitmodules(modules)
+ for m in self.submodules:
+ node, ret = self.gitread("git rev-parse %s:%s" % (version, m.path))
+ if ret:
+ continue
+ m.node = node.strip()
+
def getchanges(self, version):
self.modecache = {}
fh = self.gitopen("git diff-tree -z --root -m -r %s" % version)
changes = []
seen = set()
entry = None
+ subexists = False
for l in fh.read().split('\x00'):
if not entry:
if not l.startswith(':'):
@@ -97,15 +151,24 @@
seen.add(f)
entry = entry.split()
h = entry[3]
- if entry[1] == '160000':
- raise util.Abort('git submodules are not supported!')
p = (entry[1] == "100755")
s = (entry[1] == "120000")
- self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
- changes.append((f, h))
+
+ if f == '.gitmodules':
+ subexists = True
+ changes.append(('.hgsub', ''))
+ elif entry[1] == '160000' or entry[0] == ':160000':
+ subexists = True
+ else:
+ self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
+ changes.append((f, h))
entry = None
if fh.close():
raise util.Abort(_('cannot read changes in %s') % version)
+
+ if subexists:
+ self.retrievegitmodules(version)
+ changes.append(('.hgsubstate', ''))
return (changes, {})
def getcommit(self, version):
--- a/hgext/convert/hg.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/convert/hg.py Wed Nov 28 16:15:05 2012 -0600
@@ -219,9 +219,10 @@
return
self.ui.status(_("updating bookmarks\n"))
+ destmarks = self.repo._bookmarks
for bookmark in updatedbookmark:
- self.repo._bookmarks[bookmark] = bin(updatedbookmark[bookmark])
- bookmarks.write(self.repo)
+ destmarks[bookmark] = bin(updatedbookmark[bookmark])
+ destmarks.write()
def hascommit(self, rev):
if rev not in self.repo and self.clonebranches:
--- a/hgext/convert/subversion.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/convert/subversion.py Wed Nov 28 16:15:05 2012 -0600
@@ -18,6 +18,7 @@
from common import NoRepo, MissingTool, commit, encodeargs, decodeargs
from common import commandline, converter_source, converter_sink, mapfile
+from common import makedatetimestamp
try:
from svn.core import SubversionException, Pool
@@ -802,6 +803,8 @@
# ISO-8601 conformant
# '2007-01-04T17:35:00.902377Z'
date = util.parsedate(date[:19] + " UTC", ["%Y-%m-%dT%H:%M:%S"])
+ if self.ui.configbool('convert', 'localtimezone'):
+ date = makedatetimestamp(date[0])
log = message and self.recode(message) or ''
author = author and self.recode(author) or ''
--- a/hgext/eol.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/eol.py Wed Nov 28 16:15:05 2012 -0600
@@ -307,7 +307,7 @@
eolmtime = 0
if eolmtime > cachemtime:
- ui.debug("eol: detected change in .hgeol\n")
+ self.ui.debug("eol: detected change in .hgeol\n")
wlock = None
try:
wlock = self.wlock()
--- a/hgext/hgk.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/hgk.py Wed Nov 28 16:15:05 2012 -0600
@@ -98,9 +98,9 @@
if ctx is None:
ctx = repo[n]
# use ctx.node() instead ??
- ui.write("tree %s\n" % short(ctx.changeset()[0]))
+ ui.write(("tree %s\n" % short(ctx.changeset()[0])))
for p in ctx.parents():
- ui.write("parent %s\n" % p)
+ ui.write(("parent %s\n" % p))
date = ctx.date()
description = ctx.description().replace("\0", "")
@@ -108,12 +108,13 @@
if lines and lines[-1].startswith('committer:'):
committer = lines[-1].split(': ')[1].rstrip()
else:
- committer = ctx.user()
+ committer = ""
- ui.write("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1]))
- ui.write("committer %s %s %s\n" % (committer, int(date[0]), date[1]))
- ui.write("revision %d\n" % ctx.rev())
- ui.write("branch %s\n\n" % ctx.branch())
+ ui.write(("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1])))
+ if committer != '':
+ ui.write(("committer %s %s %s\n" % (committer, int(date[0]), date[1])))
+ ui.write(("revision %d\n" % ctx.rev()))
+ ui.write(("branch %s\n\n" % ctx.branch()))
if prefix != "":
ui.write("%s%s\n" % (prefix,
@@ -302,7 +303,7 @@
def config(ui, repo, **opts):
"""print extension options"""
def writeopt(name, value):
- ui.write('k=%s\nv=%s\n' % (name, value))
+ ui.write(('k=%s\nv=%s\n' % (name, value)))
writeopt('vdiff', ui.config('hgk', 'vdiff', ''))
--- a/hgext/histedit.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/histedit.py Wed Nov 28 16:15:05 2012 -0600
@@ -144,7 +144,6 @@
import pickle
import os
-from mercurial import bookmarks
from mercurial import cmdutil
from mercurial import discovery
from mercurial import error
@@ -740,12 +739,13 @@
# nothing to move
moves.append((bk, new[-1]))
if moves:
+ marks = repo._bookmarks
for mark, new in moves:
- old = repo._bookmarks[mark]
+ old = marks[mark]
ui.note(_('histedit: moving bookmarks %s from %s to %s\n')
% (mark, node.short(old), node.short(new)))
- repo._bookmarks[mark] = new
- bookmarks.write(repo)
+ marks[mark] = new
+ marks.write()
def cleanupnode(ui, repo, name, nodes):
"""strip a group of nodes from the repository
--- a/hgext/mq.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/mq.py Wed Nov 28 16:15:05 2012 -0600
@@ -63,7 +63,7 @@
from mercurial.node import bin, hex, short, nullid, nullrev
from mercurial.lock import release
from mercurial import commands, cmdutil, hg, scmutil, util, revset
-from mercurial import repair, extensions, error, phases, bookmarks
+from mercurial import repair, extensions, error, phases
from mercurial import patch as patchmod
import os, re, errno, shutil
@@ -1675,9 +1675,10 @@
patchf.write(chunk)
patchf.close()
+ marks = repo._bookmarks
for bm in bmlist:
- repo._bookmarks[bm] = n
- bookmarks.write(repo)
+ marks[bm] = n
+ marks.write()
self.applied.append(statusentry(n, patchfn))
except: # re-raises
@@ -2999,7 +3000,7 @@
revs.update(set(rsrevs))
if not revs:
del marks[mark]
- repo._writebookmarks(mark)
+ marks.write()
ui.write(_("bookmark '%s' deleted\n") % mark)
if not revs:
@@ -3049,7 +3050,7 @@
if opts.get('bookmark'):
del marks[mark]
- repo._writebookmarks(marks)
+ marks.write()
ui.write(_("bookmark '%s' deleted\n") % mark)
repo.mq.strip(repo, revs, backup=backup, update=update,
@@ -3435,7 +3436,7 @@
outapplied.pop()
# looking for pushed and shared changeset
for node in outapplied:
- if repo[node].phase() < phases.secret:
+ if self[node].phase() < phases.secret:
raise util.Abort(_('source has mq patches applied'))
# no non-secret patches pushed
super(mqrepo, self).checkpush(force, revs)
--- a/hgext/patchbomb.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/patchbomb.py Wed Nov 28 16:15:05 2012 -0600
@@ -474,11 +474,11 @@
if opts.get('diffstat') or opts.get('confirm'):
ui.write(_('\nFinal summary:\n\n'))
- ui.write('From: %s\n' % sender)
+ ui.write(('From: %s\n' % sender))
for addr in showaddrs:
ui.write('%s\n' % addr)
for m, subj, ds in msgs:
- ui.write('Subject: %s\n' % subj)
+ ui.write(('Subject: %s\n' % subj))
if ds:
ui.write(ds)
ui.write('\n')
--- a/hgext/rebase.py Sun Nov 25 20:39:37 2012 +0100
+++ b/hgext/rebase.py Wed Nov 28 16:15:05 2012 -0600
@@ -479,13 +479,14 @@
def updatebookmarks(repo, nstate, originalbookmarks, **opts):
'Move bookmarks to their correct changesets'
+ marks = repo._bookmarks
for k, v in originalbookmarks.iteritems():
if v in nstate:
if nstate[v] != nullmerge:
# update the bookmarks for revs that have moved
- repo._bookmarks[k] = nstate[v]
+ marks[k] = nstate[v]
- bookmarks.write(repo)
+ marks.write()
def storestatus(repo, originalwd, target, state, collapse, keep, keepbranches,
external):
@@ -655,9 +656,12 @@
#
# The actual abort is handled by `defineparents`
if len(root.parents()) <= 1:
- # (strict) ancestors of <root> not ancestors of <dest>
- detachset = repo.revs('::%d - ::%d - %d', root, commonbase, root)
+ # ancestors of <root> not ancestors of <dest>
+ detachset = repo.changelog.findmissingrevs([commonbase.rev()],
+ [root.rev()])
state.update(dict.fromkeys(detachset, nullmerge))
+ # detachset can have root, and we definitely want to rebase that
+ state[root.rev()] = nullrev
return repo['.'].rev(), dest.rev(), state
def clearrebased(ui, repo, state, collapsedas=None):
--- a/mercurial/ancestor.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/ancestor.py Wed Nov 28 16:15:05 2012 -0600
@@ -6,6 +6,7 @@
# GNU General Public License version 2 or any later version.
import heapq
+from node import nullrev
def ancestor(a, b, pfunc):
"""
@@ -89,3 +90,166 @@
gx = x.next()
except StopIteration:
return None
+
+def missingancestors(revs, bases, pfunc):
+ """Return all the ancestors of revs that are not ancestors of bases.
+
+ This may include elements from revs.
+
+ Equivalent to the revset (::revs - ::bases). Revs are returned in
+ revision number order, which is a topological order.
+
+ revs and bases should both be iterables. pfunc must return a list of
+ parent revs for a given revs.
+
+ graph is a dict of child->parent adjacency lists for this graph:
+ o 13
+ |
+ | o 12
+ | |
+ | | o 11
+ | | |\
+ | | | | o 10
+ | | | | |
+ | o---+ | 9
+ | | | | |
+ o | | | | 8
+ / / / /
+ | | o | 7
+ | | | |
+ o---+ | 6
+ / / /
+ | | o 5
+ | |/
+ | o 4
+ | |
+ o | 3
+ | |
+ | o 2
+ |/
+ o 1
+ |
+ o 0
+ >>> graph = {0: [-1], 1: [0], 2: [1], 3: [1], 4: [2], 5: [4], 6: [4],
+ ... 7: [4], 8: [-1], 9: [6, 7], 10: [5], 11: [3, 7], 12: [9],
+ ... 13: [8]}
+ >>> pfunc = graph.get
+
+ Empty revs
+ >>> missingancestors([], [1], pfunc)
+ []
+ >>> missingancestors([], [], pfunc)
+ []
+
+ If bases is empty, it's the same as if it were [nullrev]
+ >>> missingancestors([12], [], pfunc)
+ [0, 1, 2, 4, 6, 7, 9, 12]
+
+ Trivial case: revs == bases
+ >>> missingancestors([0], [0], pfunc)
+ []
+ >>> missingancestors([4, 5, 6], [6, 5, 4], pfunc)
+ []
+
+ With nullrev
+ >>> missingancestors([-1], [12], pfunc)
+ []
+ >>> missingancestors([12], [-1], pfunc)
+ [0, 1, 2, 4, 6, 7, 9, 12]
+
+ 9 is a parent of 12. 7 is a parent of 9, so an ancestor of 12. 6 is an
+ ancestor of 12 but not of 7.
+ >>> missingancestors([12], [9], pfunc)
+ [12]
+ >>> missingancestors([9], [12], pfunc)
+ []
+ >>> missingancestors([12, 9], [7], pfunc)
+ [6, 9, 12]
+ >>> missingancestors([7, 6], [12], pfunc)
+ []
+
+ More complex cases
+ >>> missingancestors([10], [11, 12], pfunc)
+ [5, 10]
+ >>> missingancestors([11], [10], pfunc)
+ [3, 7, 11]
+ >>> missingancestors([11], [10, 12], pfunc)
+ [3, 11]
+ >>> missingancestors([12], [10], pfunc)
+ [6, 7, 9, 12]
+ >>> missingancestors([12], [11], pfunc)
+ [6, 9, 12]
+ >>> missingancestors([10, 11, 12], [13], pfunc)
+ [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12]
+ >>> missingancestors([13], [10, 11, 12], pfunc)
+ [8, 13]
+ """
+
+ revsvisit = set(revs)
+ basesvisit = set(bases)
+ if not revsvisit:
+ return []
+ if not basesvisit:
+ basesvisit.add(nullrev)
+ start = max(max(revsvisit), max(basesvisit))
+ bothvisit = revsvisit.intersection(basesvisit)
+ revsvisit.difference_update(bothvisit)
+ basesvisit.difference_update(bothvisit)
+ # At this point, we hold the invariants that:
+ # - revsvisit is the set of nodes we know are an ancestor of at least one
+ # of the nodes in revs
+ # - basesvisit is the same for bases
+ # - bothvisit is the set of nodes we know are ancestors of at least one of
+ # the nodes in revs and one of the nodes in bases
+ # - a node may be in none or one, but not more, of revsvisit, basesvisit
+ # and bothvisit at any given time
+ # Now we walk down in reverse topo order, adding parents of nodes already
+ # visited to the sets while maintaining the invariants. When a node is
+ # found in both revsvisit and basesvisit, it is removed from them and
+ # added to bothvisit instead. When revsvisit becomes empty, there are no
+ # more ancestors of revs that aren't also ancestors of bases, so exit.
+
+ missing = []
+ for curr in xrange(start, nullrev, -1):
+ if not revsvisit:
+ break
+
+ if curr in bothvisit:
+ bothvisit.remove(curr)
+ # curr's parents might have made it into revsvisit or basesvisit
+ # through another path
+ for p in pfunc(curr):
+ revsvisit.discard(p)
+ basesvisit.discard(p)
+ bothvisit.add(p)
+ continue
+
+ # curr will never be in both revsvisit and basesvisit, since if it
+ # were it'd have been pushed to bothvisit
+ if curr in revsvisit:
+ missing.append(curr)
+ thisvisit = revsvisit
+ othervisit = basesvisit
+ elif curr in basesvisit:
+ thisvisit = basesvisit
+ othervisit = revsvisit
+ else:
+ # not an ancestor of revs or bases: ignore
+ continue
+
+ thisvisit.remove(curr)
+ for p in pfunc(curr):
+ if p == nullrev:
+ pass
+ elif p in othervisit or p in bothvisit:
+ # p is implicitly in thisvisit. This means p is or should be
+ # in bothvisit
+ revsvisit.discard(p)
+ basesvisit.discard(p)
+ bothvisit.add(p)
+ else:
+ # visit later
+ thisvisit.add(p)
+
+ missing.reverse()
+ return missing
--- a/mercurial/bookmarks.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/bookmarks.py Wed Nov 28 16:15:05 2012 -0600
@@ -7,35 +7,75 @@
from mercurial.i18n import _
from mercurial.node import hex
-from mercurial import encoding, error, util, obsolete, phases
+from mercurial import encoding, error, util, obsolete
import errno, os
-def read(repo):
- '''Parse .hg/bookmarks file and return a dictionary
+class bmstore(dict):
+ """Storage for bookmarks.
+
+ This object should do all bookmark reads and writes, so that it's
+ fairly simple to replace the storage underlying bookmarks without
+ having to clone the logic surrounding bookmarks.
+
+ This particular bmstore implementation stores bookmarks as
+ {hash}\s{name}\n (the same format as localtags) in
+ .hg/bookmarks. The mapping is stored as {name: nodeid}.
+
+ This class does NOT handle the "current" bookmark state at this
+ time.
+ """
- Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values
- in the .hg/bookmarks file.
- Read the file and return a (name=>nodeid) dictionary
- '''
- bookmarks = {}
- try:
- for line in repo.opener('bookmarks'):
- line = line.strip()
- if not line:
- continue
- if ' ' not in line:
- repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n') % line)
- continue
- sha, refspec = line.split(' ', 1)
- refspec = encoding.tolocal(refspec)
+ def __init__(self, repo):
+ dict.__init__(self)
+ self._repo = repo
+ try:
+ for line in repo.vfs('bookmarks'):
+ line = line.strip()
+ if not line:
+ continue
+ if ' ' not in line:
+ repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n')
+ % line)
+ continue
+ sha, refspec = line.split(' ', 1)
+ refspec = encoding.tolocal(refspec)
+ try:
+ self[refspec] = repo.changelog.lookup(sha)
+ except LookupError:
+ pass
+ except IOError, inst:
+ if inst.errno != errno.ENOENT:
+ raise
+
+ def write(self):
+ '''Write bookmarks
+
+ Write the given bookmark => hash dictionary to the .hg/bookmarks file
+ in a format equal to those of localtags.
+
+ We also store a backup of the previous state in undo.bookmarks that
+ can be copied back on rollback.
+ '''
+ repo = self._repo
+ if repo._bookmarkcurrent not in self:
+ setcurrent(repo, None)
+
+ wlock = repo.wlock()
+ try:
+
+ file = repo.vfs('bookmarks', 'w', atomictemp=True)
+ for name, node in self.iteritems():
+ file.write("%s %s\n" % (hex(node), encoding.fromlocal(name)))
+ file.close()
+
+ # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
try:
- bookmarks[refspec] = repo.changelog.lookup(sha)
- except LookupError:
+ os.utime(repo.sjoin('00changelog.i'), None)
+ except OSError:
pass
- except IOError, inst:
- if inst.errno != errno.ENOENT:
- raise
- return bookmarks
+
+ finally:
+ wlock.release()
def readcurrent(repo):
'''Get the current bookmark
@@ -60,37 +100,6 @@
file.close()
return mark
-def write(repo):
- '''Write bookmarks
-
- Write the given bookmark => hash dictionary to the .hg/bookmarks file
- in a format equal to those of localtags.
-
- We also store a backup of the previous state in undo.bookmarks that
- can be copied back on rollback.
- '''
- refs = repo._bookmarks
-
- if repo._bookmarkcurrent not in refs:
- setcurrent(repo, None)
-
- wlock = repo.wlock()
- try:
-
- file = repo.opener('bookmarks', 'w', atomictemp=True)
- for refspec, node in refs.iteritems():
- file.write("%s %s\n" % (hex(node), encoding.fromlocal(refspec)))
- file.close()
-
- # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
- try:
- os.utime(repo.sjoin('00changelog.i'), None)
- except OSError:
- pass
-
- finally:
- wlock.release()
-
def setcurrent(repo, mark):
'''Set the name of the bookmark that we are currently on
@@ -152,7 +161,7 @@
if mark != cur:
del marks[mark]
if update:
- repo._writebookmarks(marks)
+ marks.write()
return update
def listbookmarks(repo):
@@ -179,7 +188,7 @@
if new not in repo:
return False
marks[key] = repo[new].node()
- write(repo)
+ marks.write()
return True
finally:
w.release()
@@ -188,16 +197,17 @@
ui.debug("checking for updated bookmarks\n")
rb = remote.listkeys('bookmarks')
changed = False
+ localmarks = repo._bookmarks
for k in rb.keys():
- if k in repo._bookmarks:
- nr, nl = rb[k], repo._bookmarks[k]
+ if k in localmarks:
+ nr, nl = rb[k], localmarks[k]
if nr in repo:
cr = repo[nr]
cl = repo[nl]
if cl.rev() >= cr.rev():
continue
if validdest(repo, cl, cr):
- repo._bookmarks[k] = cr.node()
+ localmarks[k] = cr.node()
changed = True
ui.status(_("updating bookmark %s\n") % k)
else:
@@ -208,7 +218,7 @@
# find a unique @ suffix
for x in range(1, 100):
n = '%s@%d' % (kd, x)
- if n not in repo._bookmarks:
+ if n not in localmarks:
break
# try to use an @pathalias suffix
# if an @pathalias already exists, we overwrite (update) it
@@ -216,17 +226,17 @@
if path == u:
n = '%s@%s' % (kd, p)
- repo._bookmarks[n] = cr.node()
+ localmarks[n] = cr.node()
changed = True
ui.warn(_("divergent bookmark %s stored as %s\n") % (k, n))
elif rb[k] in repo:
# add remote bookmarks for changes we already have
- repo._bookmarks[k] = repo[rb[k]].node()
+ localmarks[k] = repo[rb[k]].node()
changed = True
ui.status(_("adding remote bookmark %s\n") % k)
if changed:
- write(repo)
+ localmarks.write()
def diff(ui, dst, src):
ui.status(_("searching for changed bookmarks\n"))
@@ -263,14 +273,10 @@
while len(validdests) != plen:
plen = len(validdests)
succs = set(c.node() for c in validdests)
- for c in validdests:
- if c.phase() > phases.public:
- # obsolescence marker does not apply to public changeset
- succs.update(obsolete.allsuccessors(repo.obsstore,
- [c.node()]))
+ mutable = [c.node() for c in validdests if c.mutable()]
+ succs.update(obsolete.allsuccessors(repo.obsstore, mutable))
known = (n for n in succs if n in nm)
validdests = set(repo.set('%ln::', known))
- validdests.remove(old)
return new in validdests
else:
return old.descendant(new)
--- a/mercurial/bundlerepo.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/bundlerepo.py Wed Nov 28 16:15:05 2012 -0600
@@ -33,6 +33,7 @@
self.basemap = {}
n = len(self)
chain = None
+ self.bundlenodes = []
while True:
chunkdata = bundle.deltachunk(chain)
if not chunkdata:
@@ -48,6 +49,7 @@
start = bundle.tell() - size
link = linkmapper(cs)
+ self.bundlenodes.append(node)
if node in self.nodemap:
# this can happen if two branches make the same change
chain = node
--- a/mercurial/cmdutil.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/cmdutil.py Wed Nov 28 16:15:05 2012 -0600
@@ -10,7 +10,7 @@
import os, sys, errno, re, tempfile
import util, scmutil, templater, patch, error, templatekw, revlog, copies
import match as matchmod
-import subrepo, context, repair, bookmarks, graphmod, revset, phases, obsolete
+import subrepo, context, repair, graphmod, revset, phases, obsolete
import changelog
import lock as lockmod
@@ -1759,9 +1759,10 @@
# Move bookmarks from old parent to amend commit
bms = repo.nodebookmarks(old.node())
if bms:
+ marks = repo._bookmarks
for bm in bms:
- repo._bookmarks[bm] = newid
- bookmarks.write(repo)
+ marks[bm] = newid
+ marks.write()
#commit the whole amend process
if obsolete._enabled and newid != old.node():
# mark the new changeset as successor of the rewritten one
--- a/mercurial/commands.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/commands.py Wed Nov 28 16:15:05 2012 -0600
@@ -549,6 +549,10 @@
hg bisect --skip
hg bisect --skip 23
+ - skip all revisions that do not touch directories ``foo`` or ``bar``
+
+ hg bisect --skip '!( file("path:foo") & file("path:bar") )'
+
- forget the current bisection::
hg bisect --reset
@@ -821,7 +825,7 @@
if mark == repo._bookmarkcurrent:
bookmarks.setcurrent(repo, None)
del marks[mark]
- bookmarks.write(repo)
+ marks.write()
elif rename:
if mark is None:
@@ -834,7 +838,7 @@
if repo._bookmarkcurrent == rename and not inactive:
bookmarks.setcurrent(repo, mark)
del marks[rename]
- bookmarks.write(repo)
+ marks.write()
elif mark is not None:
mark = checkformat(mark)
@@ -848,7 +852,7 @@
marks[mark] = cur
if not inactive and cur == marks[mark]:
bookmarks.setcurrent(repo, mark)
- bookmarks.write(repo)
+ marks.write()
# Same message whether trying to deactivate the current bookmark (-i
# with no NAME) or listing bookmarks
@@ -1321,11 +1325,12 @@
elif marks:
ui.debug('moving bookmarks %r from %s to %s\n' %
(marks, old.hex(), hex(node)))
+ newmarks = repo._bookmarks
for bm in marks:
- repo._bookmarks[bm] = node
+ newmarks[bm] = node
if bm == current:
bookmarks.setcurrent(repo, bm)
- bookmarks.write(repo)
+ newmarks.write()
else:
e = cmdutil.commiteditor
if opts.get('force_editor'):
@@ -1512,7 +1517,7 @@
ui.progress(_('building'), id, unit=_('revisions'), total=total)
for type, data in dagparser.parsedag(text):
if type == 'n':
- ui.note('node %s\n' % str(data))
+ ui.note(('node %s\n' % str(data)))
id, ps = data
files = []
@@ -1573,10 +1578,10 @@
at = id
elif type == 'l':
id, name = data
- ui.note('tag %s\n' % name)
+ ui.note(('tag %s\n' % name))
tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
elif type == 'a':
- ui.note('branch %s\n' % data)
+ ui.note(('branch %s\n' % data))
atbranch = data
ui.progress(_('building'), id, unit=_('revisions'), total=total)
tr.close()
@@ -1594,7 +1599,7 @@
try:
gen = changegroup.readbundle(f, bundlepath)
if all:
- ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
+ ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
def showchunks(named):
ui.write("\n%s\n" % named)
@@ -1786,11 +1791,11 @@
d = util.parsedate(date, util.extendeddateformats)
else:
d = util.parsedate(date)
- ui.write("internal: %s %s\n" % d)
- ui.write("standard: %s\n" % util.datestr(d))
+ ui.write(("internal: %s %s\n") % d)
+ ui.write(("standard: %s\n") % util.datestr(d))
if range:
m = util.matchdate(range)
- ui.write("match: %s\n" % m(d[0]))
+ ui.write(("match: %s\n") % m(d[0]))
@command('debugdiscovery',
[('', 'old', None, _('use old-style discovery')),
@@ -1820,7 +1825,7 @@
force=True)
common = set(common)
if not opts.get('nonheads'):
- ui.write("unpruned common: %s\n" % " ".join([short(n)
+ ui.write(("unpruned common: %s\n") % " ".join([short(n)
for n in common]))
dag = dagutil.revlogdag(repo.changelog)
all = dag.ancestorset(dag.internalizeall(common))
@@ -1830,11 +1835,11 @@
common = set(common)
rheads = set(hds)
lheads = set(repo.heads())
- ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
+ ui.write(("common heads: %s\n") % " ".join([short(n) for n in common]))
if lheads <= common:
- ui.write("local is subset\n")
+ ui.write(("local is subset\n"))
elif rheads <= common:
- ui.write("remote is subset\n")
+ ui.write(("remote is subset\n"))
serverlogs = opts.get('serverlog')
if serverlogs:
@@ -1878,9 +1883,9 @@
def debugfsinfo(ui, path = "."):
"""show information detected about current filesystem"""
util.writefile('.debugfsinfo', '')
- ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
- ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
- ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
+ ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
+ ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
+ ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
and 'yes' or 'no'))
os.unlink('.debugfsinfo')
@@ -1978,7 +1983,7 @@
r = filelog
if not r:
r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
- ui.write("digraph G {\n")
+ ui.write(("digraph G {\n"))
for i in r:
node = r.node(i)
pp = r.parents(node)
@@ -2324,52 +2329,54 @@
def pcfmt(value, total):
return (value, 100 * float(value) / total)
- ui.write('format : %d\n' % format)
- ui.write('flags : %s\n' % ', '.join(flags))
+ ui.write(('format : %d\n') % format)
+ ui.write(('flags : %s\n') % ', '.join(flags))
ui.write('\n')
fmt = pcfmtstr(totalsize)
fmt2 = dfmtstr(totalsize)
- ui.write('revisions : ' + fmt2 % numrevs)
- ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
- ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
- ui.write('revisions : ' + fmt2 % numrevs)
- ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
- ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
- ui.write('revision size : ' + fmt2 % totalsize)
- ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
- ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
+ ui.write(('revisions : ') + fmt2 % numrevs)
+ ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
+ ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
+ ui.write(('revisions : ') + fmt2 % numrevs)
+ ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
+ ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
+ ui.write(('revision size : ') + fmt2 % totalsize)
+ ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
+ ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
ui.write('\n')
fmt = dfmtstr(max(avgchainlen, compratio))
- ui.write('avg chain length : ' + fmt % avgchainlen)
- ui.write('compression ratio : ' + fmt % compratio)
+ ui.write(('avg chain length : ') + fmt % avgchainlen)
+ ui.write(('compression ratio : ') + fmt % compratio)
if format > 0:
ui.write('\n')
- ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
+ ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
% tuple(datasize))
- ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
+ ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
% tuple(fullsize))
- ui.write('delta size (min/max/avg) : %d / %d / %d\n'
+ ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
% tuple(deltasize))
if numdeltas > 0:
ui.write('\n')
fmt = pcfmtstr(numdeltas)
fmt2 = pcfmtstr(numdeltas, 4)
- ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
+ ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
if numprev > 0:
- ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
+ ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
numprev))
- ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
+ ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
numprev))
- ui.write(' other : ' + fmt2 % pcfmt(numoprev,
+ ui.write((' other : ') + fmt2 % pcfmt(numoprev,
numprev))
if gdelta:
- ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
- ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
- ui.write('deltas against other : ' + fmt % pcfmt(numother,
+ ui.write(('deltas against p1 : ')
+ + fmt % pcfmt(nump1, numdeltas))
+ ui.write(('deltas against p2 : ')
+ + fmt % pcfmt(nump2, numdeltas))
+ ui.write(('deltas against other : ') + fmt % pcfmt(numother,
numdeltas))
@command('debugrevspec', [], ('REVSPEC'))
@@ -2447,9 +2454,9 @@
def debugsub(ui, repo, rev=None):
ctx = scmutil.revsingle(repo, rev, None)
for k, v in sorted(ctx.substate.items()):
- ui.write('path %s\n' % k)
- ui.write(' source %s\n' % v[0])
- ui.write(' revision %s\n' % v[1])
+ ui.write(('path %s\n') % k)
+ ui.write((' source %s\n') % v[0])
+ ui.write((' revision %s\n') % v[1])
@command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
def debugwalk(ui, repo, *pats, **opts):
@@ -4206,6 +4213,9 @@
Returns 0 on success.
"""
+
+ fm = ui.formatter('manifest', opts)
+
if opts.get('all'):
if rev or node:
raise util.Abort(_("can't specify a revision with --all"))
@@ -4223,7 +4233,9 @@
finally:
lock.release()
for f in res:
- ui.write("%s\n" % f)
+ fm.startitem()
+ fm.write("path", '%s\n', f)
+ fm.end()
return
if rev and node:
@@ -4232,14 +4244,17 @@
if not node:
node = rev
- decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
+ char = {'l': '@', 'x': '*', '': ''}
+ mode = {'l': '644', 'x': '755', '': '644'}
ctx = scmutil.revsingle(repo, node)
+ mf = ctx.manifest()
for f in ctx:
- if ui.debugflag:
- ui.write("%40s " % hex(ctx.manifest()[f]))
- if ui.verbose:
- ui.write(decor[ctx.flags(f)])
- ui.write("%s\n" % f)
+ fm.startitem()
+ fl = ctx[f].flags()
+ fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
+ fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
+ fm.write('path', '%s\n', f)
+ fm.end()
@command('^merge',
[('f', 'force', None, _('force a merge with outstanding changes')),
@@ -4665,11 +4680,12 @@
# update specified bookmarks
if opts.get('bookmark'):
+ marks = repo._bookmarks
for b in opts['bookmark']:
# explicit pull overrides local bookmark if any
ui.status(_("importing bookmark %s\n") % b)
- repo._bookmarks[b] = repo[rb[b]].node()
- bookmarks.write(repo)
+ marks[b] = repo[rb[b]].node()
+ marks.write()
return ret
@@ -5426,17 +5442,16 @@
copy = copies.pathcopies(repo[node1], repo[node2])
fm = ui.formatter('status', opts)
- format = '%s %s' + end
- if opts.get('no_status'):
- format = '%.0s%s' + end
+ fmt = '%s' + end
+ showchar = not opts.get('no_status')
for state, char, files in changestates:
if state in show:
label = 'status.' + state
for f in files:
fm.startitem()
- fm.write("status path", format, char,
- repo.pathto(f, cwd), label=label)
+ fm.condwrite(showchar, 'status', '%s ', char, label=label)
+ fm.write('path', fmt, repo.pathto(f, cwd), label=label)
if f in copy:
fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
label='status.copied')
@@ -5742,7 +5757,7 @@
release(lock, wlock)
@command('tags', [], '')
-def tags(ui, repo):
+def tags(ui, repo, **opts):
"""list repository tags
This lists both regular and local tags. When the -v/--verbose
@@ -5751,27 +5766,27 @@
Returns 0 on success.
"""
+ fm = ui.formatter('tags', opts)
hexfunc = ui.debugflag and hex or short
tagtype = ""
for t, n in reversed(repo.tagslist()):
- if ui.quiet:
- ui.write("%s\n" % t, label='tags.normal')
- continue
-
hn = hexfunc(n)
- r = "%5d:%s" % (repo.changelog.rev(n), hn)
- rev = ui.label(r, 'log.changeset changeset.%s' % repo[n].phasestr())
- spaces = " " * (30 - encoding.colwidth(t))
-
- tag = ui.label(t, 'tags.normal')
- if ui.verbose:
- if repo.tagtype(t) == 'local':
- tagtype = " local"
- tag = ui.label(t, 'tags.local')
- else:
- tagtype = ""
- ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
+ label = 'tags.normal'
+ tagtype = ''
+ if repo.tagtype(t) == 'local':
+ label = 'tags.local'
+ tagtype = 'local'
+
+ fm.startitem()
+ fm.write('tag', '%s', t, label=label)
+ fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
+ fm.condwrite(not ui.quiet, 'rev id', fmt,
+ repo.changelog.rev(n), hn, label=label)
+ fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
+ tagtype, label=label)
+ fm.plain('\n')
+ fm.end()
@command('tip',
[('p', 'patch', None, _('show patch')),
--- a/mercurial/formatter.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/formatter.py Wed Nov 28 16:15:05 2012 -0600
@@ -31,6 +31,10 @@
'''do default text output while assigning data to item'''
for k, v in zip(fields.split(), fielddata):
self._item[k] = v
+ def condwrite(self, cond, fields, deftext, *fielddata, **opts):
+ '''do conditional write (primarily for plain formatter)'''
+ for k, v in zip(fields.split(), fielddata):
+ self._item[k] = v
def plain(self, text, **opts):
'''show raw text for non-templated mode'''
pass
@@ -51,6 +55,10 @@
pass
def write(self, fields, deftext, *fielddata, **opts):
self._ui.write(deftext % fielddata, **opts)
+ def condwrite(self, cond, fields, deftext, *fielddata, **opts):
+ '''do conditional write'''
+ if cond:
+ self._ui.write(deftext % fielddata, **opts)
def plain(self, text, **opts):
self._ui.write(text, **opts)
def end(self):
--- a/mercurial/help/config.txt Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/help/config.txt Wed Nov 28 16:15:05 2012 -0600
@@ -1295,6 +1295,10 @@
(DEPRECATED) Whether to allow .zip downloading of repository
revisions. Default is False. This feature creates temporary files.
+``archivesubrepos``
+ Whether to recurse into subrepositories when archiving. Default is
+ False.
+
``baseurl``
Base URL to use when publishing URLs in other locations, so
third-party tools like email notification hooks can construct
--- a/mercurial/hg.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/hg.py Wed Nov 28 16:15:05 2012 -0600
@@ -171,11 +171,14 @@
r = repository(ui, root)
default = srcrepo.ui.config('paths', 'default')
- if default:
- fp = r.opener("hgrc", "w", text=True)
- fp.write("[paths]\n")
- fp.write("default = %s\n" % default)
- fp.close()
+ if not default:
+ # set default to source for being able to clone subrepos
+ default = os.path.abspath(util.urllocalpath(origsource))
+ fp = r.opener("hgrc", "w", text=True)
+ fp.write("[paths]\n")
+ fp.write("default = %s\n" % default)
+ fp.close()
+ r.ui.setconfig('paths', 'default', default)
if update:
r.ui.status(_("updating working directory\n"))
@@ -391,14 +394,15 @@
destrepo = destpeer.local()
if destrepo and srcpeer.capable("pushkey"):
rb = srcpeer.listkeys('bookmarks')
+ marks = destrepo._bookmarks
for k, n in rb.iteritems():
try:
m = destrepo.lookup(n)
- destrepo._bookmarks[k] = m
+ marks[k] = m
except error.RepoLookupError:
pass
if rb:
- bookmarks.write(destrepo)
+ marks.write()
elif srcrepo and destpeer.capable("pushkey"):
for k, n in srcrepo._bookmarks.iteritems():
destpeer.pushkey('bookmarks', k, '', hex(n))
--- a/mercurial/hgweb/webcommands.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/hgweb/webcommands.py Wed Nov 28 16:15:05 2012 -0600
@@ -14,6 +14,7 @@
from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND
from mercurial import graphmod, patch
from mercurial import help as helpmod
+from mercurial import scmutil
from mercurial.i18n import _
# __all__ is populated with the allowed commands. Be sure to add to it if
@@ -799,7 +800,11 @@
headers.append(('Content-Encoding', encoding))
req.header(headers)
req.respond(HTTP_OK)
- archival.archive(web.repo, req, cnode, artype, prefix=name)
+
+ ctx = webutil.changectx(web.repo, req)
+ archival.archive(web.repo, req, cnode, artype, prefix=name,
+ matchfn=scmutil.match(ctx, []),
+ subrepos=web.configbool("web", "archivesubrepos"))
return []
--- a/mercurial/localrepo.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/localrepo.py Wed Nov 28 16:15:05 2012 -0600
@@ -265,15 +265,12 @@
@filecache('bookmarks')
def _bookmarks(self):
- return bookmarks.read(self)
+ return bookmarks.bmstore(self)
@filecache('bookmarks.current')
def _bookmarkcurrent(self):
return bookmarks.readcurrent(self)
- def _writebookmarks(self, marks):
- bookmarks.write(self)
-
def bookmarkheads(self, bookmark):
name = bookmark.split('@', 1)[0]
heads = []
--- a/mercurial/mdiff.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/mdiff.py Wed Nov 28 16:15:05 2012 -0600
@@ -7,7 +7,7 @@
from i18n import _
import bdiff, mpatch, util
-import re, struct
+import re, struct, base85, zlib
def splitnewlines(text):
'''like str.splitlines, but only split on newlines.'''
@@ -142,20 +142,7 @@
yield s, type
yield s1, '='
-def diffline(revs, a, b, opts):
- parts = ['diff']
- if opts.git:
- parts.append('--git')
- if revs and not opts.git:
- parts.append(' '.join(["-r %s" % rev for rev in revs]))
- if opts.git:
- parts.append('a/%s' % a)
- parts.append('b/%s' % b)
- else:
- parts.append(a)
- return ' '.join(parts) + '\n'
-
-def unidiff(a, ad, b, bd, fn1, fn2, r=None, opts=defaultopts):
+def unidiff(a, ad, b, bd, fn1, fn2, opts=defaultopts):
def datetag(date, fn=None):
if not opts.git and not opts.nodates:
return '\t%s\n' % date
@@ -206,9 +193,6 @@
if l[ln][-1] != '\n':
l[ln] += "\n\ No newline at end of file\n"
- if r:
- l.insert(0, diffline(r, fn1, fn2, opts))
-
return "".join(l)
# creates a headerless unified diff
@@ -314,6 +298,41 @@
for x in yieldhunk(hunk):
yield x
+def b85diff(to, tn):
+ '''print base85-encoded binary diff'''
+ def fmtline(line):
+ l = len(line)
+ if l <= 26:
+ l = chr(ord('A') + l - 1)
+ else:
+ l = chr(l - 26 + ord('a') - 1)
+ return '%c%s\n' % (l, base85.b85encode(line, True))
+
+ def chunk(text, csize=52):
+ l = len(text)
+ i = 0
+ while i < l:
+ yield text[i:i + csize]
+ i += csize
+
+ if to is None:
+ to = ''
+ if tn is None:
+ tn = ''
+
+ if to == tn:
+ return ''
+
+ # TODO: deltas
+ ret = []
+ ret.append('GIT binary patch\n')
+ ret.append('literal %s\n' % len(tn))
+ for l in chunk(zlib.compress(tn)):
+ ret.append(fmtline(l))
+ ret.append('\n')
+
+ return ''.join(ret)
+
def patchtext(bin):
pos = 0
t = []
--- a/mercurial/patch.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/patch.py Wed Nov 28 16:15:05 2012 -0600
@@ -6,7 +6,7 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
-import cStringIO, email.Parser, os, errno, re
+import cStringIO, email.Parser, os, errno, re, posixpath
import tempfile, zlib, shutil
from i18n import _
@@ -1514,44 +1514,6 @@
finally:
fp.close()
-def b85diff(to, tn):
- '''print base85-encoded binary diff'''
- def gitindex(text):
- if not text:
- return hex(nullid)
- l = len(text)
- s = util.sha1('blob %d\0' % l)
- s.update(text)
- return s.hexdigest()
-
- def fmtline(line):
- l = len(line)
- if l <= 26:
- l = chr(ord('A') + l - 1)
- else:
- l = chr(l - 26 + ord('a') - 1)
- return '%c%s\n' % (l, base85.b85encode(line, True))
-
- def chunk(text, csize=52):
- l = len(text)
- i = 0
- while i < l:
- yield text[i:i + csize]
- i += csize
-
- tohash = gitindex(to)
- tnhash = gitindex(tn)
- if tohash == tnhash:
- return ""
-
- # TODO: deltas
- ret = ['index %s..%s\nGIT binary patch\nliteral %s\n' %
- (tohash, tnhash, len(tn))]
- for l in chunk(zlib.compress(tn)):
- ret.append(fmtline(l))
- ret.append('\n')
- return ''.join(ret)
-
class GitDiffRequired(Exception):
pass
@@ -1622,9 +1584,8 @@
return []
revs = None
- if not repo.ui.quiet:
- hexfunc = repo.ui.debugflag and hex or short
- revs = [hexfunc(node) for node in [node1, node2] if node]
+ hexfunc = repo.ui.debugflag and hex or short
+ revs = [hexfunc(node) for node in [node1, node2] if node]
copy = {}
if opts.git or opts.upgrade:
@@ -1690,17 +1651,45 @@
'''like diff(), but yields 2-tuples of (output, label) for ui.write()'''
return difflabel(diff, *args, **kw)
-
-def _addmodehdr(header, omode, nmode):
- if omode != nmode:
- header.append('old mode %s\n' % omode)
- header.append('new mode %s\n' % nmode)
-
def trydiff(repo, revs, ctx1, ctx2, modified, added, removed,
copy, getfilectx, opts, losedatafn, prefix):
def join(f):
- return os.path.join(prefix, f)
+ return posixpath.join(prefix, f)
+
+ def addmodehdr(header, omode, nmode):
+ if omode != nmode:
+ header.append('old mode %s\n' % omode)
+ header.append('new mode %s\n' % nmode)
+
+ def addindexmeta(meta, revs):
+ if opts.git:
+ i = len(revs)
+ if i==2:
+ meta.append('index %s..%s\n' % tuple(revs))
+ elif i==3:
+ meta.append('index %s,%s..%s\n' % tuple(revs))
+
+ def gitindex(text):
+ if not text:
+ return hex(nullid)
+ l = len(text)
+ s = util.sha1('blob %d\0' % l)
+ s.update(text)
+ return s.hexdigest()
+
+ def diffline(a, b, revs):
+ if opts.git:
+ line = 'diff --git a/%s b/%s\n' % (a, b)
+ elif not repo.ui.quiet:
+ if revs:
+ revinfo = ' '.join(["-r %s" % rev for rev in revs])
+ line = 'diff %s %s\n' % (revinfo, a)
+ else:
+ line = 'diff %s\n' % a
+ else:
+ line = ''
+ return line
date1 = util.datestr(ctx1.date())
man1 = ctx1.manifest()
@@ -1733,7 +1722,7 @@
else:
a = copyto[f]
omode = gitmode[man1.flags(a)]
- _addmodehdr(header, omode, mode)
+ addmodehdr(header, omode, mode)
if a in removed and a not in gone:
op = 'rename'
gone.add(a)
@@ -1779,22 +1768,24 @@
nflag = ctx2.flags(f)
binary = util.binary(to) or util.binary(tn)
if opts.git:
- _addmodehdr(header, gitmode[oflag], gitmode[nflag])
+ addmodehdr(header, gitmode[oflag], gitmode[nflag])
if binary:
dodiff = 'binary'
elif binary or nflag != oflag:
losedatafn(f)
- if opts.git:
- header.insert(0, mdiff.diffline(revs, join(a), join(b), opts))
if dodiff:
+ if opts.git or revs:
+ header.insert(0, diffline(join(a), join(b), revs))
if dodiff == 'binary':
- text = b85diff(to, tn)
+ text = mdiff.b85diff(to, tn)
+ if text:
+ addindexmeta(header, [gitindex(to), gitindex(tn)])
else:
text = mdiff.unidiff(to, date1,
# ctx2 date may be dynamic
tn, util.datestr(ctx2.date()),
- join(a), join(b), revs, opts=opts)
+ join(a), join(b), opts=opts)
if header and (text or len(header) > 1):
yield ''.join(header)
if text:
--- a/mercurial/repair.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/repair.py Wed Nov 28 16:15:05 2012 -0600
@@ -6,7 +6,7 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
-from mercurial import changegroup, bookmarks
+from mercurial import changegroup
from mercurial.node import short
from mercurial.i18n import _
import os
@@ -181,7 +181,7 @@
for m in updatebm:
bm[m] = repo[newbmtarget].node()
- bookmarks.write(repo)
+ bm.write()
except: # re-raises
if backupfile:
ui.warn(_("strip failed, full bundle stored in '%s'\n")
--- a/mercurial/revlog.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/revlog.py Wed Nov 28 16:15:05 2012 -0600
@@ -257,11 +257,14 @@
return iter(xrange(len(self)))
def revs(self, start=0, stop=None):
"""iterate over all rev in this revlog (from start to stop)"""
- if stop is None:
- stop = len(self)
+ step = 1
+ if stop is not None:
+ if start > stop:
+ step = -1
+ stop += step
else:
- stop += 1
- return xrange(start, stop)
+ stop = len(self)
+ return xrange(start, stop, step)
@util.propertycache
def nodemap(self):
@@ -429,6 +432,29 @@
missing.sort()
return has, [self.node(r) for r in missing]
+ def findmissingrevs(self, common=None, heads=None):
+ """Return the revision numbers of the ancestors of heads that
+ are not ancestors of common.
+
+ More specifically, return a list of revision numbers corresponding to
+ nodes N such that every N satisfies the following constraints:
+
+ 1. N is an ancestor of some node in 'heads'
+ 2. N is not an ancestor of any node in 'common'
+
+ The list is sorted by revision number, meaning it is
+ topologically sorted.
+
+ 'heads' and 'common' are both lists of revision numbers. If heads is
+ not supplied, uses all of the revlog's heads. If common is not
+ supplied, uses nullid."""
+ if common is None:
+ common = [nullrev]
+ if heads is None:
+ heads = self.headrevs()
+
+ return ancestor.missingancestors(heads, common, self.parentrevs)
+
def findmissing(self, common=None, heads=None):
"""Return the ancestors of heads that are not ancestors of common.
@@ -444,8 +470,16 @@
'heads' and 'common' are both lists of node IDs. If heads is
not supplied, uses all of the revlog's heads. If common is not
supplied, uses nullid."""
- _common, missing = self.findcommonmissing(common, heads)
- return missing
+ if common is None:
+ common = [nullid]
+ if heads is None:
+ heads = self.heads()
+
+ common = [self.rev(n) for n in common]
+ heads = [self.rev(n) for n in heads]
+
+ return [self.node(r) for r in
+ ancestor.missingancestors(heads, common, self.parentrevs)]
def nodesbetween(self, roots=None, heads=None):
"""Return a topological path from 'roots' to 'heads'.
--- a/mercurial/revset.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/revset.py Wed Nov 28 16:15:05 2012 -0600
@@ -442,6 +442,19 @@
bumped = obsmod.getrevs(repo, 'bumped')
return [r for r in subset if r in bumped]
+def bundle(repo, subset, x):
+ """``bundle()``
+ Changesets in the bundle.
+
+ Bundle must be specified by the -R option."""
+
+ try:
+ bundlenodes = repo.changelog.bundlenodes
+ except AttributeError:
+ raise util.Abort(_("no bundle provided - specify with -R"))
+ revs = set(repo[n].rev() for n in bundlenodes)
+ return [r for r in subset if r in revs]
+
def checkstatus(repo, subset, pat, field):
m = None
s = []
@@ -1513,6 +1526,7 @@
"branch": branch,
"branchpoint": branchpoint,
"bumped": bumped,
+ "bundle": bundle,
"children": children,
"closed": closed,
"contains": contains,
--- a/mercurial/scmutil.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/scmutil.py Wed Nov 28 16:15:05 2012 -0600
@@ -279,37 +279,38 @@
mode += "b" # for that other OS
nlink = -1
- dirname, basename = util.split(f)
- # If basename is empty, then the path is malformed because it points
- # to a directory. Let the posixfile() call below raise IOError.
- if basename and mode not in ('r', 'rb'):
- if atomictemp:
- if not os.path.isdir(dirname):
- util.makedirs(dirname, self.createmode)
- return util.atomictempfile(f, mode, self.createmode)
- try:
- if 'w' in mode:
- util.unlink(f)
+ if mode not in ('r', 'rb'):
+ dirname, basename = util.split(f)
+ # If basename is empty, then the path is malformed because it points
+ # to a directory. Let the posixfile() call below raise IOError.
+ if basename:
+ if atomictemp:
+ if not os.path.isdir(dirname):
+ util.makedirs(dirname, self.createmode)
+ return util.atomictempfile(f, mode, self.createmode)
+ try:
+ if 'w' in mode:
+ util.unlink(f)
+ nlink = 0
+ else:
+ # nlinks() may behave differently for files on Windows
+ # shares if the file is open.
+ fd = util.posixfile(f)
+ nlink = util.nlinks(f)
+ if nlink < 1:
+ nlink = 2 # force mktempcopy (issue1922)
+ fd.close()
+ except (OSError, IOError), e:
+ if e.errno != errno.ENOENT:
+ raise
nlink = 0
- else:
- # nlinks() may behave differently for files on Windows
- # shares if the file is open.
- fd = util.posixfile(f)
- nlink = util.nlinks(f)
- if nlink < 1:
- nlink = 2 # force mktempcopy (issue1922)
- fd.close()
- except (OSError, IOError), e:
- if e.errno != errno.ENOENT:
- raise
- nlink = 0
- if not os.path.isdir(dirname):
- util.makedirs(dirname, self.createmode)
- if nlink > 0:
- if self._trustnlink is None:
- self._trustnlink = nlink > 1 or util.checknlink(f)
- if nlink > 1 or not self._trustnlink:
- util.rename(util.mktempcopy(f), f)
+ if not os.path.isdir(dirname):
+ util.makedirs(dirname, self.createmode)
+ if nlink > 0:
+ if self._trustnlink is None:
+ self._trustnlink = nlink > 1 or util.checknlink(f)
+ if nlink > 1 or not self._trustnlink:
+ util.rename(util.mktempcopy(f), f)
fp = util.posixfile(f, mode)
if nlink == 0:
self._fixfilemode(f)
--- a/mercurial/subrepo.py Sun Nov 25 20:39:37 2012 +0100
+++ b/mercurial/subrepo.py Wed Nov 28 16:15:05 2012 -0600
@@ -446,7 +446,7 @@
node2 = node.bin(node2)
cmdutil.diffordiffstat(self._repo.ui, self._repo, diffopts,
node1, node2, match,
- prefix=os.path.join(prefix, self._path),
+ prefix=posixpath.join(prefix, self._path),
listsubrepos=True, **opts)
except error.RepoLookupError, inst:
self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
--- a/setup.py Sun Nov 25 20:39:37 2012 +0100
+++ b/setup.py Wed Nov 28 16:15:05 2012 -0600
@@ -151,6 +151,8 @@
if not e.startswith(b('Not trusting file')) \
and not e.startswith(b('warning: Not importing'))]
if err:
+ print >> sys.stderr, "stderr from '%s':" % (' '.join(cmd))
+ print >> sys.stderr, '\n'.join([' ' + e for e in err])
return ''
return out
--- a/tests/autodiff.py Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/autodiff.py Wed Nov 28 16:15:05 2012 -0600
@@ -35,7 +35,7 @@
for chunk in it:
ui.write(chunk)
for fn in sorted(brokenfiles):
- ui.write('data lost for: %s\n' % fn)
+ ui.write(('data lost for: %s\n' % fn))
cmdtable = {
"autodiff":
--- a/tests/run-tests.py Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/run-tests.py Wed Nov 28 16:15:05 2012 -0600
@@ -55,6 +55,7 @@
import re
import threading
import killdaemons as killmod
+import cPickle as pickle
processlock = threading.Lock()
@@ -162,6 +163,8 @@
parser.add_option("-p", "--port", type="int",
help="port on which servers should listen"
" (default: $%s or %d)" % defaults['port'])
+ parser.add_option("--compiler", type="string",
+ help="compiler to build with")
parser.add_option("--pure", action="store_true",
help="use pure Python code instead of C extensions")
parser.add_option("-R", "--restart", action="store_true",
@@ -175,6 +178,8 @@
parser.add_option("-t", "--timeout", type="int",
help="kill errant tests after TIMEOUT seconds"
" (default: $%s or %d)" % defaults['timeout'])
+ parser.add_option("--time", action="store_true",
+ help="time how long each test takes")
parser.add_option("--tmpdir", type="string",
help="run tests in the given temporary directory"
" (implies --keep-tmpdir)")
@@ -263,6 +268,10 @@
sys.stderr.write(
'warning: --timeout option ignored with --debug\n')
options.timeout = 0
+ if options.time:
+ sys.stderr.write(
+ 'warning: --time option ignored with --debug\n')
+ options.time = False
if options.py3k_warnings:
if sys.version_info[:2] < (2, 6) or sys.version_info[:2] >= (3, 0):
parser.error('--py3k-warnings can only be used on Python 2.6+')
@@ -364,6 +373,9 @@
def installhg(options):
vlog("# Performing temporary installation of HG")
installerrs = os.path.join("tests", "install.err")
+ compiler = ''
+ if options.compiler:
+ compiler = '--compiler ' + options.compiler
pure = options.pure and "--pure" or ""
# Run installer in hg root
@@ -377,12 +389,14 @@
# least on Windows for now, deal with .pydistutils.cfg bugs
# when they happen.
nohome = ''
- cmd = ('%s setup.py %s clean --all'
- ' build --build-base="%s"'
- ' install --force --prefix="%s" --install-lib="%s"'
- ' --install-scripts="%s" %s >%s 2>&1'
- % (sys.executable, pure, os.path.join(HGTMP, "build"),
- INST, PYTHONDIR, BINDIR, nohome, installerrs))
+ cmd = ('%(exe)s setup.py %(pure)s clean --all'
+ ' build %(compiler)s --build-base="%(base)s"'
+ ' install --force --prefix="%(prefix)s" --install-lib="%(libdir)s"'
+ ' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1'
+ % dict(exe=sys.executable, pure=pure, compiler=compiler,
+ base=os.path.join(HGTMP, "build"),
+ prefix=INST, libdir=PYTHONDIR, bindir=BINDIR,
+ nohome=nohome, logfile=installerrs))
vlog("# Running", cmd)
if os.system(cmd) == 0:
if not options.verbose:
@@ -447,6 +461,14 @@
fn = os.path.join(INST, '..', '.coverage')
os.environ['COVERAGE_FILE'] = fn
+def outputtimes(options):
+ vlog('# Producing time report')
+ times.sort(key=lambda t: (t[1], t[0]), reverse=True)
+ cols = '%7.3f %s'
+ print '\n%-7s %s' % ('Time', 'Test')
+ for test, timetaken in times:
+ print cols % (timetaken, test)
+
def outputcoverage(options):
vlog('# Producing coverage report')
@@ -891,7 +913,12 @@
replacements.append((re.escape(testtmp), '$TESTTMP'))
os.mkdir(testtmp)
+ if options.time:
+ starttime = time.time()
ret, out = runner(testpath, testtmp, options, replacements)
+ if options.time:
+ endtime = time.time()
+ times.append((test, endtime - starttime))
vlog("# Ret was:", ret)
mark = '.'
@@ -1056,29 +1083,30 @@
childopts += ['--tmpdir', childtmp]
cmdline = [PYTHON, sys.argv[0]] + opts + childopts + job
vlog(' '.join(cmdline))
- fps[os.spawnvp(os.P_NOWAIT, cmdline[0], cmdline)] = os.fdopen(rfd, 'r')
+ fps[os.spawnvp(os.P_NOWAIT, cmdline[0], cmdline)] = os.fdopen(rfd, 'rb')
os.close(wfd)
signal.signal(signal.SIGINT, signal.SIG_IGN)
failures = 0
- tested, skipped, failed = 0, 0, 0
+ passed, skipped, failed = 0, 0, 0
skips = []
fails = []
while fps:
pid, status = os.wait()
fp = fps.pop(pid)
- l = fp.read().splitlines()
try:
- test, skip, fail = map(int, l[:3])
- except ValueError:
- test, skip, fail = 0, 0, 0
- split = -fail or len(l)
- for s in l[3:split]:
- skips.append(s.split(" ", 1))
- for s in l[split:]:
- fails.append(s.split(" ", 1))
- tested += test
- skipped += skip
- failed += fail
+ childresults = pickle.load(fp)
+ except pickle.UnpicklingError:
+ pass
+ else:
+ passed += len(childresults['p'])
+ skipped += len(childresults['s'])
+ failed += len(childresults['f'])
+ skips.extend(childresults['s'])
+ fails.extend(childresults['f'])
+ if options.time:
+ childtimes = pickle.load(fp)
+ times.extend(childtimes)
+
vlog('pid %d exited, status %d' % (pid, status))
failures |= status
print
@@ -1093,17 +1121,20 @@
_checkhglib("Tested")
print "# Ran %d tests, %d skipped, %d failed." % (
- tested, skipped, failed)
+ passed + failed, skipped, failed)
+ if options.time:
+ outputtimes(options)
if options.anycoverage:
outputcoverage(options)
sys.exit(failures != 0)
results = dict(p=[], f=[], s=[], i=[])
resultslock = threading.Lock()
+times = []
iolock = threading.Lock()
-def runqueue(options, tests, results):
+def runqueue(options, tests):
for test in tests:
ret = runone(options, test)
if options.first and ret is not None and not ret:
@@ -1129,7 +1160,7 @@
print "running all tests"
tests = orig
- runqueue(options, tests, results)
+ runqueue(options, tests)
failed = len(results['f'])
tested = len(results['p']) + failed
@@ -1137,12 +1168,10 @@
ignored = len(results['i'])
if options.child:
- fp = os.fdopen(options.child, 'w')
- fp.write('%d\n%d\n%d\n' % (tested, skipped, failed))
- for s in results['s']:
- fp.write("%s %s\n" % s)
- for s in results['f']:
- fp.write("%s %s\n" % s)
+ fp = os.fdopen(options.child, 'wb')
+ pickle.dump(results, fp, pickle.HIGHEST_PROTOCOL)
+ if options.time:
+ pickle.dump(times, fp, pickle.HIGHEST_PROTOCOL)
fp.close()
else:
print
@@ -1153,6 +1182,8 @@
_checkhglib("Tested")
print "# Ran %d tests, %d skipped, %d failed." % (
tested, skipped + ignored, failed)
+ if options.time:
+ outputtimes(options)
if options.anycoverage:
outputcoverage(options)
@@ -1170,9 +1201,9 @@
checktools()
- if len(args) == 0:
- args = os.listdir(".")
- args.sort()
+ if len(args) == 0:
+ args = os.listdir(".")
+ args.sort()
tests = args
--- a/tests/test-bundle.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-bundle.t Wed Nov 28 16:15:05 2012 -0600
@@ -444,6 +444,33 @@
added 1 changesets with 1 changes to 1 files
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+View full contents of the bundle
+ $ hg -R test bundle --base null -r 3 ../partial.hg
+ 4 changesets found
+ $ cd test
+ $ hg -R ../../partial.hg log -r "bundle()"
+ changeset: 0:f9ee2f85a263
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: 0.0
+
+ changeset: 1:34c2bf6b0626
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: 0.1
+
+ changeset: 2:e38ba6f5b7e0
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: 0.2
+
+ changeset: 3:eebf5a27f8ca
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: 0.3
+
+ $ cd ..
+
test for 540d1059c802
test for 540d1059c802
--- a/tests/test-check-code-hg.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-check-code-hg.t Wed Nov 28 16:15:05 2012 -0600
@@ -5,163 +5,7 @@
> echo "skipped: not a Mercurial working dir" >&2
> exit 80
> fi
- $ hg manifest | xargs "$check_code" || echo 'FAILURE IS NOT AN OPTION!!!'
- $ hg manifest | xargs "$check_code" --warnings --nolineno --per-file=0 || true
- hgext/convert/cvsps.py:0:
- > ui.write('Ancestors: %s\n' % (','.join(r)))
- warning: unwrapped ui message
- hgext/convert/cvsps.py:0:
- > ui.write('Parent: %d\n' % cs.parents[0].id)
- warning: unwrapped ui message
- hgext/convert/cvsps.py:0:
- > ui.write('Parents: %s\n' %
- warning: unwrapped ui message
- hgext/convert/cvsps.py:0:
- > ui.write('Branchpoints: %s \n' % ', '.join(branchpoints))
- warning: unwrapped ui message
- hgext/convert/cvsps.py:0:
- > ui.write('Author: %s\n' % cs.author)
- warning: unwrapped ui message
- hgext/convert/cvsps.py:0:
- > ui.write('Branch: %s\n' % (cs.branch or 'HEAD'))
- warning: unwrapped ui message
- hgext/convert/cvsps.py:0:
- > ui.write('Date: %s\n' % util.datestr(cs.date,
- warning: unwrapped ui message
- hgext/convert/cvsps.py:0:
- > ui.write('Log:\n')
- warning: unwrapped ui message
- hgext/convert/cvsps.py:0:
- > ui.write('Members: \n')
- warning: unwrapped ui message
- hgext/convert/cvsps.py:0:
- > ui.write('PatchSet %d \n' % cs.id)
- warning: unwrapped ui message
- hgext/convert/cvsps.py:0:
- > ui.write('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1],
- warning: unwrapped ui message
- hgext/hgk.py:0:
- > ui.write("parent %s\n" % p)
- warning: unwrapped ui message
- hgext/hgk.py:0:
- > ui.write('k=%s\nv=%s\n' % (name, value))
- warning: unwrapped ui message
- hgext/hgk.py:0:
- > ui.write("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1]))
- warning: unwrapped ui message
- hgext/hgk.py:0:
- > ui.write("branch %s\n\n" % ctx.branch())
- warning: unwrapped ui message
- hgext/hgk.py:0:
- > ui.write("committer %s %s %s\n" % (committer, int(date[0]), date[1]))
- warning: unwrapped ui message
- hgext/hgk.py:0:
- > ui.write("revision %d\n" % ctx.rev())
- warning: unwrapped ui message
- hgext/hgk.py:0:
- > ui.write("tree %s\n" % short(ctx.changeset()[0]))
- warning: unwrapped ui message
- hgext/patchbomb.py:0:
- > ui.write('Subject: %s\n' % subj)
- warning: unwrapped ui message
- hgext/patchbomb.py:0:
- > ui.write('From: %s\n' % sender)
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.note('branch %s\n' % data)
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.note('node %s\n' % str(data))
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.note('tag %s\n' % name)
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write("unpruned common: %s\n" % " ".join([short(n)
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write("local is subset\n")
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write("remote is subset\n")
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('deltas against other : ' + fmt % pcfmt(numother,
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write("match: %s\n" % m(d[0]))
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('path %s\n' % k)
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write("digraph G {\n")
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write("internal: %s %s\n" % d)
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write("standard: %s\n" % util.datestr(d))
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('avg chain length : ' + fmt % avgchainlen)
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('compression ratio : ' + fmt % compratio)
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('delta size (min/max/avg) : %d / %d / %d\n'
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('flags : %s\n' % ', '.join(flags))
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('format : %d\n' % format)
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('revision size : ' + fmt2 % totalsize)
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('revisions : ' + fmt2 % numrevs)
- warning: unwrapped ui message
- warning: unwrapped ui message
- mercurial/commands.py:0:
- > ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
- warning: unwrapped ui message
- tests/autodiff.py:0:
- > ui.write('data lost for: %s\n' % fn)
- warning: unwrapped ui message
- tests/test-ui-color.py:0:
- > testui.warn('warning\n')
- warning: unwrapped ui message
- tests/test-ui-color.py:0:
- > testui.write('buffered\n')
- warning: unwrapped ui message
+New errors are not allowed. Warnings are strongly discouraged.
+
+ $ hg manifest | xargs "$check_code" --warnings --nolineno --per-file=0
--- a/tests/test-convert-cvs.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-convert-cvs.t Wed Nov 28 16:15:05 2012 -0600
@@ -69,9 +69,16 @@
$TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
$ cd ..
-convert fresh repo
+convert fresh repo and also check localtimezone option
+
+NOTE: This doesn't check all time zones -- it merely determines that
+the configuration option is taking effect.
- $ hg convert src src-hg
+An arbitrary (U.S.) time zone is used here. TZ=US/Hawaii is selected
+since it does not use DST (unlike other U.S. time zones) and is always
+a fixed difference from UTC.
+
+ $ TZ=US/Hawaii hg convert --config convert.localtimezone=True src src-hg
initializing destination src-hg repository
connecting to $TESTTMP/cvsrepo
scanning source...
@@ -161,7 +168,7 @@
convert again
- $ hg convert src src-hg
+ $ TZ=US/Hawaii hg convert --config convert.localtimezone=True src src-hg
connecting to $TESTTMP/cvsrepo
scanning source...
collecting CVS rlog
@@ -221,7 +228,7 @@
convert again
- $ hg convert src src-hg
+ $ TZ=US/Hawaii hg convert --config convert.localtimezone=True src src-hg
connecting to $TESTTMP/cvsrepo
scanning source...
collecting CVS rlog
@@ -239,7 +246,7 @@
convert again with --filemap
- $ hg convert --filemap filemap src src-filemap
+ $ TZ=US/Hawaii hg convert --config convert.localtimezone=True --filemap filemap src src-filemap
connecting to $TESTTMP/cvsrepo
scanning source...
collecting CVS rlog
@@ -286,7 +293,7 @@
convert again
- $ hg convert --config convert.cvsps.fuzz=2 src src-hg
+ $ TZ=US/Hawaii hg convert --config convert.cvsps.fuzz=2 --config convert.localtimezone=True src src-hg
connecting to $TESTTMP/cvsrepo
scanning source...
collecting CVS rlog
@@ -300,25 +307,25 @@
2 funny
1 fuzzy
0 fuzzy
- $ hg -R src-hg glog --template '{rev} ({branches}) {desc} files: {files}\n'
- o 8 (branch) fuzzy files: b/c
+ $ hg -R src-hg glog --template '{rev} ({branches}) {desc} date: {date|date} files: {files}\n'
+ o 8 (branch) fuzzy date: * -1000 files: b/c (glob)
|
- o 7 (branch) fuzzy files: a
+ o 7 (branch) fuzzy date: * -1000 files: a (glob)
|
o 6 (branch) funny
| ----------------------------
- | log message files: a
- o 5 (branch) ci2 files: b/c
+ | log message date: * -1000 files: a (glob)
+ o 5 (branch) ci2 date: * -1000 files: b/c (glob)
- o 4 () ci1 files: a b/c
+ o 4 () ci1 date: * -1000 files: a b/c (glob)
|
- o 3 () update tags files: .hgtags
+ o 3 () update tags date: * +0000 files: .hgtags (glob)
|
- o 2 () ci0 files: b/c
+ o 2 () ci0 date: * -1000 files: b/c (glob)
|
- | o 1 (INITIAL) import files:
+ | o 1 (INITIAL) import date: * -1000 files: (glob)
|/
- o 0 () Initial revision files: a b/c
+ o 0 () Initial revision date: * -1000 files: a b/c (glob)
testing debugcvsps
--- a/tests/test-convert-git.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-convert-git.t Wed Nov 28 16:15:05 2012 -0600
@@ -298,3 +298,50 @@
$ hg convert git-repo4 git-repo4-broken-hg 2>&1 | \
> grep 'abort:' | sed 's/abort:.*/abort:/g'
abort:
+
+test sub modules
+
+ $ mkdir git-repo5
+ $ cd git-repo5
+ $ git init-db >/dev/null 2>/dev/null
+ $ echo 'sub' >> foo
+ $ git add foo
+ $ commit -a -m 'addfoo'
+ $ BASE=${PWD}
+ $ cd ..
+ $ mkdir git-repo6
+ $ cd git-repo6
+ $ git init-db >/dev/null 2>/dev/null
+ $ git submodule add ${BASE} >/dev/null 2>/dev/null
+ $ commit -a -m 'addsubmodule' >/dev/null 2>/dev/null
+ $ cd ..
+
+convert sub modules
+ $ hg convert git-repo6 git-repo6-hg
+ initializing destination git-repo6-hg repository
+ scanning source...
+ sorting...
+ converting...
+ 0 addsubmodule
+ updating bookmarks
+ $ hg -R git-repo6-hg log -v
+ changeset: 0:* (glob)
+ bookmark: master
+ tag: tip
+ user: nottest <test@example.org>
+ date: Mon Jan 01 00:00:23 2007 +0000
+ files: .hgsub .hgsubstate
+ description:
+ addsubmodule
+
+ committer: test <test@example.org>
+
+
+
+ $ cd git-repo6-hg
+ $ hg up >/dev/null 2>/dev/null
+ $ cat .hgsubstate
+ * git-repo5 (glob)
+ $ cd git-repo5
+ $ cat foo
+ sub
--- a/tests/test-convert-svn-source.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-convert-svn-source.t Wed Nov 28 16:15:05 2012 -0600
@@ -63,9 +63,16 @@
Committed revision 5.
$ cd ..
-Convert to hg once
+Convert to hg once and also test localtimezone option
+
+NOTE: This doesn't check all time zones -- it merely determines that
+the configuration option is taking effect.
- $ hg convert "$SVNREPOURL/proj%20B" B-hg
+An arbitrary (U.S.) time zone is used here. TZ=US/Hawaii is selected
+since it does not use DST (unlike other U.S. time zones) and is always
+a fixed difference from UTC.
+
+ $ TZ=US/Hawaii hg convert --config convert.localtimezone=True "$SVNREPOURL/proj%20B" B-hg
initializing destination B-hg repository
scanning source...
sorting...
@@ -109,7 +116,7 @@
Test incremental conversion
- $ hg convert "$SVNREPOURL/proj%20B" B-hg
+ $ TZ=US/Hawaii hg convert --config convert.localtimezone=True "$SVNREPOURL/proj%20B" B-hg
scanning source...
sorting...
converting...
@@ -118,22 +125,22 @@
updating tags
$ cd B-hg
- $ hg glog --template '{rev} {desc|firstline} files: {files}\n'
- o 7 update tags files: .hgtags
+ $ hg glog --template '{rev} {desc|firstline} date: {date|date} files: {files}\n'
+ o 7 update tags date: * +0000 files: .hgtags (glob)
|
- o 6 work in progress files: letter2.txt
+ o 6 work in progress date: * -1000 files: letter2.txt (glob)
|
- o 5 second letter files: letter .txt letter2.txt
+ o 5 second letter date: * -1000 files: letter .txt letter2.txt (glob)
|
- o 4 update tags files: .hgtags
+ o 4 update tags date: * +0000 files: .hgtags (glob)
|
- o 3 nice day files: letter .txt
+ o 3 nice day date: * -1000 files: letter .txt (glob)
|
- o 2 world files: letter .txt
+ o 2 world date: * -1000 files: letter .txt (glob)
|
- o 1 hello files: letter .txt
+ o 1 hello date: * -1000 files: letter .txt (glob)
|
- o 0 init projB files:
+ o 0 init projB date: * -1000 files: (glob)
$ hg tags -q
tip
--- a/tests/test-convert.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-convert.t Wed Nov 28 16:15:05 2012 -0600
@@ -172,6 +172,10 @@
will add the most recent revision on the branch indicated in
the regex as the second parent of the changeset. Default is
"{{mergefrombranch ([-\w]+)}}"
+ convert.localtimezone
+ use local time (as determined by the TZ environment
+ variable) for changeset date/times. The default is False
+ (use UTC).
hook.cvslog Specify a Python function to be called at the end of
gathering the CVS log. The function is passed a list with
the log entries, and can modify the entries in-place, or add
@@ -211,6 +215,10 @@
convert.svn.trunk
specify the name of the trunk branch. The default is
"trunk".
+ convert.localtimezone
+ use local time (as determined by the TZ environment
+ variable) for changeset date/times. The default is False
+ (use UTC).
Source history can be retrieved starting at a specific revision, instead
of being integrally converted. Only single branch conversions are
--- a/tests/test-eolfilename.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-eolfilename.t Wed Nov 28 16:15:05 2012 -0600
@@ -68,9 +68,9 @@
$ touch "$A"
$ touch "$B"
$ hg status --color=always
- \x1b[0;35;1;4m? foo\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mfoo\x1b[0m (esc)
\x1b[0;35;1;4mbar\x1b[0m (esc)
- \x1b[0;35;1;4m? foo\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mfoo\x1b[0m (esc)
\x1b[0;35;1;4mbar.baz\x1b[0m (esc)
$ cd ..
--- a/tests/test-hgk.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-hgk.t Wed Nov 28 16:15:05 2012 -0600
@@ -11,7 +11,6 @@
tree a0c8bcbbb45c
parent 000000000000
author test 0 0
- committer test 0 0
revision 0
branch default
--- a/tests/test-mq-qrefresh.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-mq-qrefresh.t Wed Nov 28 16:15:05 2012 -0600
@@ -209,6 +209,7 @@
$ hg add orphanchild
$ hg qrefresh nonexistentfilename # clear patch
nonexistentfilename: * (glob)
+ $ hg diff -c qtip
$ hg qrefresh --short 1/base
$ hg qrefresh --short 2/base
--- a/tests/test-mq.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-mq.t Wed Nov 28 16:15:05 2012 -0600
@@ -198,11 +198,11 @@
status --mq with color (issue2096)
$ hg status --mq --config extensions.color= --config color.mode=ansi --color=always
- \x1b[0;32;1mA .hgignore\x1b[0m (esc)
- \x1b[0;32;1mA A\x1b[0m (esc)
- \x1b[0;32;1mA B\x1b[0m (esc)
- \x1b[0;32;1mA series\x1b[0m (esc)
- \x1b[0;35;1;4m? flaf\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1m.hgignore\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mA\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mB\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mseries\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mflaf\x1b[0m (esc)
try the --mq option on a command provided by an extension
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-pathencode.py Wed Nov 28 16:15:05 2012 -0600
@@ -0,0 +1,193 @@
+# This is a randomized test that generates different pathnames every
+# time it is invoked, and tests the encoding of those pathnames.
+#
+# It uses a simple probabilistic model to generate valid pathnames
+# that have proven likely to expose bugs and divergent behaviour in
+# different encoding implementations.
+
+from mercurial import parsers
+from mercurial import store
+import binascii, itertools, math, os, random, sys, time
+import collections
+
+if sys.version_info[:2] < (2, 6):
+ sys.exit(0)
+
+def hybridencode(path):
+ return store._hybridencode(path, True)
+
+validchars = set(map(chr, range(0, 256)))
+alphanum = range(ord('A'), ord('Z'))
+
+for c in '\0/':
+ validchars.remove(c)
+
+winreserved = ('aux con prn nul'.split() +
+ ['com%d' % i for i in xrange(1, 10)] +
+ ['lpt%d' % i for i in xrange(1, 10)])
+
+def casecombinations(names):
+ '''Build all case-diddled combinations of names.'''
+
+ combos = set()
+
+ for r in names:
+ for i in xrange(len(r) + 1):
+ for c in itertools.combinations(xrange(len(r)), i):
+ d = r
+ for j in c:
+ d = ''.join((d[:j], d[j].upper(), d[j + 1:]))
+ combos.add(d)
+ return sorted(combos)
+
+def buildprobtable(fp, cmd='hg manifest tip'):
+ '''Construct and print a table of probabilities for path name
+ components. The numbers are percentages.'''
+
+ counts = collections.defaultdict(lambda: 0)
+ for line in os.popen(cmd).read().splitlines():
+ if line[-2:] in ('.i', '.d'):
+ line = line[:-2]
+ if line.startswith('data/'):
+ line = line[5:]
+ for c in line:
+ counts[c] += 1
+ for c in '\r/\n':
+ counts.pop(c, None)
+ t = sum(counts.itervalues()) / 100.0
+ fp.write('probtable = (')
+ for i, (k, v) in enumerate(sorted(counts.iteritems(), key=lambda x: x[1],
+ reverse=True)):
+ if (i % 5) == 0:
+ fp.write('\n ')
+ vt = v / t
+ if vt < 0.0005:
+ break
+ fp.write('(%r, %.03f), ' % (k, vt))
+ fp.write('\n )\n')
+
+# A table of character frequencies (as percentages), gleaned by
+# looking at filelog names from a real-world, very large repo.
+
+probtable = (
+ ('t', 9.828), ('e', 9.042), ('s', 8.011), ('a', 6.801), ('i', 6.618),
+ ('g', 5.053), ('r', 5.030), ('o', 4.887), ('p', 4.363), ('n', 4.258),
+ ('l', 3.830), ('h', 3.693), ('_', 3.659), ('.', 3.377), ('m', 3.194),
+ ('u', 2.364), ('d', 2.296), ('c', 2.163), ('b', 1.739), ('f', 1.625),
+ ('6', 0.666), ('j', 0.610), ('y', 0.554), ('x', 0.487), ('w', 0.477),
+ ('k', 0.476), ('v', 0.473), ('3', 0.336), ('1', 0.335), ('2', 0.326),
+ ('4', 0.310), ('5', 0.305), ('9', 0.302), ('8', 0.300), ('7', 0.299),
+ ('q', 0.298), ('0', 0.250), ('z', 0.223), ('-', 0.118), ('C', 0.095),
+ ('T', 0.087), ('F', 0.085), ('B', 0.077), ('S', 0.076), ('P', 0.076),
+ ('L', 0.059), ('A', 0.058), ('N', 0.051), ('D', 0.049), ('M', 0.046),
+ ('E', 0.039), ('I', 0.035), ('R', 0.035), ('G', 0.028), ('U', 0.026),
+ ('W', 0.025), ('O', 0.017), ('V', 0.015), ('H', 0.013), ('Q', 0.011),
+ ('J', 0.007), ('K', 0.005), ('+', 0.004), ('X', 0.003), ('Y', 0.001),
+ )
+
+for c, _ in probtable:
+ validchars.remove(c)
+validchars = list(validchars)
+
+def pickfrom(rng, table):
+ c = 0
+ r = rng.random() * sum(i[1] for i in table)
+ for i, p in table:
+ c += p
+ if c >= r:
+ return i
+
+reservedcombos = casecombinations(winreserved)
+
+# The first component of a name following a slash.
+
+firsttable = (
+ (lambda rng: pickfrom(rng, probtable), 90),
+ (lambda rng: rng.choice(validchars), 5),
+ (lambda rng: rng.choice(reservedcombos), 5),
+ )
+
+# Components of a name following the first.
+
+resttable = firsttable[:-1]
+
+# Special suffixes.
+
+internalsuffixcombos = casecombinations('.hg .i .d'.split())
+
+# The last component of a path, before a slash or at the end of a name.
+
+lasttable = resttable + (
+ (lambda rng: '', 95),
+ (lambda rng: rng.choice(internalsuffixcombos), 5),
+ )
+
+def makepart(rng, k):
+ '''Construct a part of a pathname, without slashes.'''
+
+ p = pickfrom(rng, firsttable)(rng)
+ l = len(p)
+ ps = [p]
+ while l <= k:
+ p = pickfrom(rng, resttable)(rng)
+ l += len(p)
+ ps.append(p)
+ ps.append(pickfrom(rng, lasttable)(rng))
+ return ''.join(ps)
+
+def makepath(rng, j, k):
+ '''Construct a complete pathname.'''
+
+ return ('data/' + '/'.join(makepart(rng, k) for _ in xrange(j)) +
+ rng.choice(['.d', '.i']))
+
+def genpath(rng, count):
+ '''Generate random pathnames with gradually increasing lengths.'''
+
+ mink, maxk = 1, 4096
+ def steps():
+ x, k = 0, mink
+ for i in xrange(count):
+ yield mink + int(round(math.sqrt((maxk - mink) * float(i) / count)))
+ for k in steps():
+ x = rng.randint(1, k)
+ y = rng.randint(1, k)
+ yield makepath(rng, x, y)
+
+def runtests(rng, seed, count):
+ nerrs = 0
+ for p in genpath(rng, count):
+ hybridencode(p)
+ return nerrs
+
+def main():
+ import getopt
+
+ # Empirically observed to take about a second to run
+ count = 100
+ seed = None
+ opts, args = getopt.getopt(sys.argv[1:], 'c:s:',
+ ['build', 'count=', 'seed='])
+ for o, a in opts:
+ if o in ('-c', '--count'):
+ count = int(a)
+ elif o in ('-s', '--seed'):
+ seed = long(a)
+ elif o == '--build':
+ buildprobtable(sys.stdout,
+ 'find .hg/store/data -type f && '
+ 'cat .hg/store/fncache 2>/dev/null')
+ sys.exit(0)
+
+ if seed is None:
+ try:
+ seed = long(binascii.hexlify(os.urandom(16)), 16)
+ except AttributeError:
+ seed = long(time.time() * 1000)
+
+ rng = random.Random(seed)
+ if runtests(rng, seed, count):
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main()
--- a/tests/test-status-color.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-status-color.t Wed Nov 28 16:15:05 2012 -0600
@@ -15,100 +15,100 @@
hg status in repo root:
$ hg status --color=always
- \x1b[0;35;1;4m? a/1/in_a_1\x1b[0m (esc)
- \x1b[0;35;1;4m? a/in_a\x1b[0m (esc)
- \x1b[0;35;1;4m? b/1/in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? b/2/in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? b/in_b\x1b[0m (esc)
- \x1b[0;35;1;4m? in_root\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
hg status . in repo root:
$ hg status --color=always .
- \x1b[0;35;1;4m? a/1/in_a_1\x1b[0m (esc)
- \x1b[0;35;1;4m? a/in_a\x1b[0m (esc)
- \x1b[0;35;1;4m? b/1/in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? b/2/in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? b/in_b\x1b[0m (esc)
- \x1b[0;35;1;4m? in_root\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
$ hg status --color=always --cwd a
- \x1b[0;35;1;4m? a/1/in_a_1\x1b[0m (esc)
- \x1b[0;35;1;4m? a/in_a\x1b[0m (esc)
- \x1b[0;35;1;4m? b/1/in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? b/2/in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? b/in_b\x1b[0m (esc)
- \x1b[0;35;1;4m? in_root\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
$ hg status --color=always --cwd a .
- \x1b[0;35;1;4m? 1/in_a_1\x1b[0m (esc)
- \x1b[0;35;1;4m? in_a\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a\x1b[0m (esc)
$ hg status --color=always --cwd a ..
- \x1b[0;35;1;4m? 1/in_a_1\x1b[0m (esc)
- \x1b[0;35;1;4m? in_a\x1b[0m (esc)
- \x1b[0;35;1;4m? ../b/1/in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? ../b/2/in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? ../b/in_b\x1b[0m (esc)
- \x1b[0;35;1;4m? ../in_root\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../b/1/in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../b/2/in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../b/in_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_root\x1b[0m (esc)
$ hg status --color=always --cwd b
- \x1b[0;35;1;4m? a/1/in_a_1\x1b[0m (esc)
- \x1b[0;35;1;4m? a/in_a\x1b[0m (esc)
- \x1b[0;35;1;4m? b/1/in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? b/2/in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? b/in_b\x1b[0m (esc)
- \x1b[0;35;1;4m? in_root\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
$ hg status --color=always --cwd b .
- \x1b[0;35;1;4m? 1/in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? 2/in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? in_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m2/in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b\x1b[0m (esc)
$ hg status --color=always --cwd b ..
- \x1b[0;35;1;4m? ../a/1/in_a_1\x1b[0m (esc)
- \x1b[0;35;1;4m? ../a/in_a\x1b[0m (esc)
- \x1b[0;35;1;4m? 1/in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? 2/in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? in_b\x1b[0m (esc)
- \x1b[0;35;1;4m? ../in_root\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../a/1/in_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../a/in_a\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m2/in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_root\x1b[0m (esc)
$ hg status --color=always --cwd a/1
- \x1b[0;35;1;4m? a/1/in_a_1\x1b[0m (esc)
- \x1b[0;35;1;4m? a/in_a\x1b[0m (esc)
- \x1b[0;35;1;4m? b/1/in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? b/2/in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? b/in_b\x1b[0m (esc)
- \x1b[0;35;1;4m? in_root\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
$ hg status --color=always --cwd a/1 .
- \x1b[0;35;1;4m? in_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a_1\x1b[0m (esc)
$ hg status --color=always --cwd a/1 ..
- \x1b[0;35;1;4m? in_a_1\x1b[0m (esc)
- \x1b[0;35;1;4m? ../in_a\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_a\x1b[0m (esc)
$ hg status --color=always --cwd b/1
- \x1b[0;35;1;4m? a/1/in_a_1\x1b[0m (esc)
- \x1b[0;35;1;4m? a/in_a\x1b[0m (esc)
- \x1b[0;35;1;4m? b/1/in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? b/2/in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? b/in_b\x1b[0m (esc)
- \x1b[0;35;1;4m? in_root\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
$ hg status --color=always --cwd b/1 .
- \x1b[0;35;1;4m? in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_1\x1b[0m (esc)
$ hg status --color=always --cwd b/1 ..
- \x1b[0;35;1;4m? in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? ../2/in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? ../in_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../2/in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_b\x1b[0m (esc)
$ hg status --color=always --cwd b/2
- \x1b[0;35;1;4m? a/1/in_a_1\x1b[0m (esc)
- \x1b[0;35;1;4m? a/in_a\x1b[0m (esc)
- \x1b[0;35;1;4m? b/1/in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? b/2/in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? b/in_b\x1b[0m (esc)
- \x1b[0;35;1;4m? in_root\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
$ hg status --color=always --cwd b/2 .
- \x1b[0;35;1;4m? in_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_2\x1b[0m (esc)
$ hg status --color=always --cwd b/2 ..
- \x1b[0;35;1;4m? ../1/in_b_1\x1b[0m (esc)
- \x1b[0;35;1;4m? in_b_2\x1b[0m (esc)
- \x1b[0;35;1;4m? ../in_b\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../1/in_b_1\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_2\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_b\x1b[0m (esc)
$ cd ..
$ hg init repo2
@@ -128,59 +128,59 @@
hg status:
$ hg status --color=always
- \x1b[0;32;1mA added\x1b[0m (esc)
- \x1b[0;31;1mR removed\x1b[0m (esc)
- \x1b[0;36;1;4m! deleted\x1b[0m (esc)
- \x1b[0;35;1;4m? unknown\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
+ \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
+ \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
hg status modified added removed deleted unknown never-existed ignored:
$ hg status --color=always modified added removed deleted unknown never-existed ignored
never-existed: * (glob)
- \x1b[0;32;1mA added\x1b[0m (esc)
- \x1b[0;31;1mR removed\x1b[0m (esc)
- \x1b[0;36;1;4m! deleted\x1b[0m (esc)
- \x1b[0;35;1;4m? unknown\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
+ \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
+ \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
$ hg copy modified copied
hg status -C:
$ hg status --color=always -C
- \x1b[0;32;1mA added\x1b[0m (esc)
- \x1b[0;32;1mA copied\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
\x1b[0;0m modified\x1b[0m (esc)
- \x1b[0;31;1mR removed\x1b[0m (esc)
- \x1b[0;36;1;4m! deleted\x1b[0m (esc)
- \x1b[0;35;1;4m? unknown\x1b[0m (esc)
+ \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
+ \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
hg status -A:
$ hg status --color=always -A
- \x1b[0;32;1mA added\x1b[0m (esc)
- \x1b[0;32;1mA copied\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
\x1b[0;0m modified\x1b[0m (esc)
- \x1b[0;31;1mR removed\x1b[0m (esc)
- \x1b[0;36;1;4m! deleted\x1b[0m (esc)
- \x1b[0;35;1;4m? unknown\x1b[0m (esc)
- \x1b[0;30;1mI ignored\x1b[0m (esc)
- \x1b[0;0mC .hgignore\x1b[0m (esc)
- \x1b[0;0mC modified\x1b[0m (esc)
+ \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
+ \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
+ \x1b[0;30;1mI \x1b[0m\x1b[0;30;1mignored\x1b[0m (esc)
+ \x1b[0;0mC \x1b[0m\x1b[0;0m.hgignore\x1b[0m (esc)
+ \x1b[0;0mC \x1b[0m\x1b[0;0mmodified\x1b[0m (esc)
hg status -A (with terminfo color):
$ mkdir "$TESTTMP/terminfo"
$ TERMINFO="$TESTTMP/terminfo" tic "$TESTDIR/hgterm.ti"
$ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status --config color.mode=terminfo --color=always -A
- \x1b[30m\x1b[32m\x1b[1mA added\x1b[30m (esc)
- \x1b[30m\x1b[32m\x1b[1mA copied\x1b[30m (esc)
+ \x1b[30m\x1b[32m\x1b[1mA \x1b[30m\x1b[30m\x1b[32m\x1b[1madded\x1b[30m (esc)
+ \x1b[30m\x1b[32m\x1b[1mA \x1b[30m\x1b[30m\x1b[32m\x1b[1mcopied\x1b[30m (esc)
\x1b[30m\x1b[30m modified\x1b[30m (esc)
- \x1b[30m\x1b[31m\x1b[1mR removed\x1b[30m (esc)
- \x1b[30m\x1b[36m\x1b[1m\x1b[4m! deleted\x1b[30m (esc)
- \x1b[30m\x1b[35m\x1b[1m\x1b[4m? unknown\x1b[30m (esc)
- \x1b[30m\x1b[30m\x1b[1mI ignored\x1b[30m (esc)
- \x1b[30m\x1b[30mC .hgignore\x1b[30m (esc)
- \x1b[30m\x1b[30mC modified\x1b[30m (esc)
+ \x1b[30m\x1b[31m\x1b[1mR \x1b[30m\x1b[30m\x1b[31m\x1b[1mremoved\x1b[30m (esc)
+ \x1b[30m\x1b[36m\x1b[1m\x1b[4m! \x1b[30m\x1b[30m\x1b[36m\x1b[1m\x1b[4mdeleted\x1b[30m (esc)
+ \x1b[30m\x1b[35m\x1b[1m\x1b[4m? \x1b[30m\x1b[30m\x1b[35m\x1b[1m\x1b[4munknown\x1b[30m (esc)
+ \x1b[30m\x1b[30m\x1b[1mI \x1b[30m\x1b[30m\x1b[30m\x1b[1mignored\x1b[30m (esc)
+ \x1b[30m\x1b[30mC \x1b[30m\x1b[30m\x1b[30m.hgignore\x1b[30m (esc)
+ \x1b[30m\x1b[30mC \x1b[30m\x1b[30m\x1b[30mmodified\x1b[30m (esc)
$ echo "^ignoreddir$" > .hgignore
@@ -194,7 +194,7 @@
hg status -i ignoreddir/file:
$ hg status --color=always -i ignoreddir/file
- \x1b[0;30;1mI ignoreddir/file\x1b[0m (esc)
+ \x1b[0;30;1mI \x1b[0m\x1b[0;30;1mignoreddir/file\x1b[0m (esc)
$ cd ..
check 'status -q' and some combinations
@@ -220,11 +220,11 @@
$ hg --config color.status.modified=periwinkle status --color=always
ignoring unknown color/effect 'periwinkle' (configured in color.status.modified)
M modified
- \x1b[0;32;1mA added\x1b[0m (esc)
- \x1b[0;32;1mA copied\x1b[0m (esc)
- \x1b[0;31;1mR removed\x1b[0m (esc)
- \x1b[0;36;1;4m! deleted\x1b[0m (esc)
- \x1b[0;35;1;4m? unknown\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
+ \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
+ \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
+ \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
+ \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
Run status with 2 different flags.
Check if result is the same or different.
--- a/tests/test-subrepo.t Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-subrepo.t Wed Nov 28 16:15:05 2012 -0600
@@ -718,6 +718,14 @@
committing subrepository subrepo-2
$ hg st subrepo-2/file
+Check that share works with subrepo
+ $ hg --config extensions.share= share . ../shared
+ updating working directory
+ cloning subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
+ 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ test -f ../shared/subrepo-1/.hg/sharedpath
+ [1]
+
Check hg update --clean
$ cd $TESTTMP/t
$ rm -r t/t.orig
--- a/tests/test-ui-color.py Sun Nov 25 20:39:37 2012 +0100
+++ b/tests/test-ui-color.py Wed Nov 28 16:15:05 2012 -0600
@@ -5,8 +5,8 @@
# ensure errors aren't buffered
testui = color.colorui()
testui.pushbuffer()
-testui.write('buffered\n')
-testui.warn('warning\n')
+testui.write(('buffered\n'))
+testui.warn(('warning\n'))
testui.write_err('error\n')
print repr(testui.popbuffer())