##// END OF EJS Templates
Merge with backout
Matt Mackall -
r3099:09e8aecd merge default
parent child Browse files
Show More
@@ -0,0 +1,179
1 # churn.py - create a graph showing who changed the most lines
2 #
3 # Copyright 2006 Josef "Jeff" Sipek <jeffpc@josefsipek.net>
4 #
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
7 #
8 #
9 # Aliases map file format is simple one alias per line in the following
10 # format:
11 #
12 # <alias email> <actual email>
13
14 from mercurial.demandload import *
15 from mercurial.i18n import gettext as _
16 demandload(globals(), 'time sys signal os')
17 demandload(globals(), 'mercurial:hg,mdiff,fancyopts,cmdutil,ui,util,templater,node')
18
19 def __gather(ui, repo, node1, node2):
20 def dirtywork(f, mmap1, mmap2):
21 lines = 0
22
23 to = mmap1 and repo.file(f).read(mmap1[f]) or None
24 tn = mmap2 and repo.file(f).read(mmap2[f]) or None
25
26 diff = mdiff.unidiff(to, "", tn, "", f).split("\n")
27
28 for line in diff:
29 if not line:
30 continue # skip EOF
31 if line.startswith(" "):
32 continue # context line
33 if line.startswith("--- ") or line.startswith("+++ "):
34 continue # begining of diff
35 if line.startswith("@@ "):
36 continue # info line
37
38 # changed lines
39 lines += 1
40
41 return lines
42
43 ##
44
45 lines = 0
46
47 changes = repo.status(node1, node2, None, util.always)[:5]
48
49 modified, added, removed, deleted, unknown = changes
50
51 who = repo.changelog.read(node2)[1]
52 who = templater.email(who) # get the email of the person
53
54 mmap1 = repo.manifest.read(repo.changelog.read(node1)[0])
55 mmap2 = repo.manifest.read(repo.changelog.read(node2)[0])
56 for f in modified:
57 lines += dirtywork(f, mmap1, mmap2)
58
59 for f in added:
60 lines += dirtywork(f, None, mmap2)
61
62 for f in removed:
63 lines += dirtywork(f, mmap1, None)
64
65 for f in deleted:
66 lines += dirtywork(f, mmap1, mmap2)
67
68 for f in unknown:
69 lines += dirtywork(f, mmap1, mmap2)
70
71 return (who, lines)
72
73 def gather_stats(ui, repo, amap, revs=None, progress=False):
74 stats = {}
75
76 cl = repo.changelog
77
78 if not revs:
79 revs = range(0, cl.count())
80
81 nr_revs = len(revs)
82 cur_rev = 0
83
84 for rev in revs:
85 cur_rev += 1 # next revision
86
87 node2 = cl.node(rev)
88 node1 = cl.parents(node2)[0]
89
90 if cl.parents(node2)[1] != node.nullid:
91 ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
92 continue
93
94 who, lines = __gather(ui, repo, node1, node2)
95
96 # remap the owner if possible
97 if amap.has_key(who):
98 ui.note("using '%s' alias for '%s'\n" % (amap[who], who))
99 who = amap[who]
100
101 if not stats.has_key(who):
102 stats[who] = 0
103 stats[who] += lines
104
105 ui.note("rev %d: %d lines by %s\n" % (rev, lines, who))
106
107 if progress:
108 if int(100.0*(cur_rev - 1)/nr_revs) < int(100.0*cur_rev/nr_revs):
109 ui.write("%d%%.." % (int(100.0*cur_rev/nr_revs),))
110 sys.stdout.flush()
111
112 if progress:
113 ui.write("done\n")
114 sys.stdout.flush()
115
116 return stats
117
118 def churn(ui, repo, **opts):
119 "Graphs the number of lines changed"
120
121 def pad(s, l):
122 if len(s) < l:
123 return s + " " * (l-len(s))
124 return s[0:l]
125
126 def graph(n, maximum, width, char):
127 n = int(n * width / float(maximum))
128
129 return char * (n)
130
131 def get_aliases(f):
132 aliases = {}
133
134 for l in f.readlines():
135 l = l.strip()
136 alias, actual = l.split(" ")
137 aliases[alias] = actual
138
139 return aliases
140
141 amap = {}
142 aliases = opts.get('aliases')
143 if aliases:
144 try:
145 f = open(aliases,"r")
146 except OSError, e:
147 print "Error: " + e
148 return
149
150 amap = get_aliases(f)
151 f.close()
152
153 revs = [int(r) for r in cmdutil.revrange(ui, repo, opts['rev'])]
154 revs.sort()
155 stats = gather_stats(ui, repo, amap, revs, opts.get('progress'))
156
157 # make a list of tuples (name, lines) and sort it in descending order
158 ordered = stats.items()
159 ordered.sort(lambda x, y: cmp(y[1], x[1]))
160
161 maximum = ordered[0][1]
162
163 ui.note("Assuming 80 character terminal\n")
164 width = 80 - 1
165
166 for i in ordered:
167 person = i[0]
168 lines = i[1]
169 print "%s %6d %s" % (pad(person, 20), lines,
170 graph(lines, maximum, width - 20 - 1 - 6 - 2 - 2, '*'))
171
172 cmdtable = {
173 "churn":
174 (churn,
175 [('r', 'rev', [], _('limit statistics to the specified revisions')),
176 ('', 'aliases', '', _('file with email aliases')),
177 ('', 'progress', None, _('show progress'))],
178 'hg churn [-r revision range] [-a file] [--progress]'),
179 }
@@ -0,0 +1,9
1 #!/bin/sh
2
3 echo 'syntax error' > badext.py
4 abspath=`pwd`/badext.py
5
6 echo '[extensions]' >> $HGRCPATH
7 echo "badext = $abspath" >> $HGRCPATH
8
9 hg -q help help
@@ -0,0 +1,4
1 *** failed to import extension badext: invalid syntax (badext.py, line 1)
2 hg help [COMMAND]
3
4 show help for a command, extension, or list of commands
@@ -0,0 +1,34
1 #!/bin/sh
2 #
3 # test for branch handling
4 #
5 # XXX: need more tests
6
7 hg init
8 echo a > a
9 echo b > b
10 hg ci -A -m 0 -d "1000000 0"
11 echo aa > a
12 echo bb > b
13 hg ci -m 1 -d "1000000 0"
14 hg tag -l foo
15 hg update 0
16 hg parents -b
17
18 # test update
19 hg update -b foo
20 hg parents
21
22 # test merge
23 hg update 0
24 echo c > c
25 hg ci -A -m 0.0 -d "1000000 0"
26 hg merge -b foo
27 hg parents -b
28
29 # re-test with more branches
30 hg update -C 0
31 echo d > d
32 hg ci -A -m 0.0 -d "1000000 0"
33 hg merge -b foo
34 hg parents -b
@@ -0,0 +1,55
1 adding a
2 adding b
3 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 changeset: 0:b544c4ac4389
5 user: test
6 date: Mon Jan 12 13:46:40 1970 +0000
7 summary: 0
8
9 Using head f4ac749470f2 for branch foo
10 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 changeset: 1:f4ac749470f2
12 tag: foo
13 tag: tip
14 user: test
15 date: Mon Jan 12 13:46:40 1970 +0000
16 summary: 1
17
18 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
19 adding c
20 Using head f4ac749470f2 for branch foo
21 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 (branch merge, don't forget to commit)
23 changeset: 2:1505d56ee00e
24 tag: tip
25 parent: 0:b544c4ac4389
26 user: test
27 date: Mon Jan 12 13:46:40 1970 +0000
28 summary: 0.0
29
30 changeset: 1:f4ac749470f2
31 tag: foo
32 branch: foo
33 user: test
34 date: Mon Jan 12 13:46:40 1970 +0000
35 summary: 1
36
37 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
38 adding d
39 Using head f4ac749470f2 for branch foo
40 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
41 (branch merge, don't forget to commit)
42 changeset: 3:53b72df12ae5
43 tag: tip
44 parent: 0:b544c4ac4389
45 user: test
46 date: Mon Jan 12 13:46:40 1970 +0000
47 summary: 0.0
48
49 changeset: 1:f4ac749470f2
50 tag: foo
51 branch: foo
52 user: test
53 date: Mon Jan 12 13:46:40 1970 +0000
54 summary: 1
55
@@ -0,0 +1,35
1 #!/bin/sh
2
3 echo "[extensions]" >> $HGRCPATH
4 echo "mq=" >> $HGRCPATH
5
6 hg init a
7 cd a
8
9 echo 'base' > base
10 hg ci -Ambase -d '1 0'
11
12 hg qnew a
13 hg qnew b
14 hg qnew c
15
16 hg qdel c
17 hg qpop
18 hg qdel c
19 hg qseries
20 ls .hg/patches
21 hg qpop
22 hg qdel -k b
23 ls .hg/patches
24 hg qdel -f a
25 hg qapplied
26 hg log --template '{rev} {desc}\n'
27
28 hg qnew d
29 hg qnew e
30 hg qnew f
31
32 hg qdel -f e
33 hg qdel -f d e
34 hg qapplied
35 hg log --template '{rev} {desc}\n'
@@ -0,0 +1,23
1 adding base
2 abort: cannot delete applied patch c
3 Now at: b
4 a
5 b
6 a
7 b
8 series
9 status
10 Now at: a
11 a
12 b
13 series
14 status
15 1 New patch: a
16 0 base
17 abort: patch e not at base
18 f
19 4 New patch: f
20 3 New patch: e
21 2 New patch: d
22 1 New patch: a
23 0 base
@@ -0,0 +1,25
1 #!/bin/sh
2
3 echo "[extensions]" >> $HGRCPATH
4 echo "mq=" >> $HGRCPATH
5
6 hg init a
7 cd a
8
9 echo 'base' > base
10 hg ci -Ambase -d '1 0'
11
12 hg qnew -mmqbase mqbase
13 hg qrename mqbase renamed
14 mkdir .hg/patches/foo
15 hg qrename renamed foo
16 hg qseries
17 ls .hg/patches/foo
18 mkdir .hg/patches/bar
19 hg qrename foo/renamed bar
20 hg qseries
21 ls .hg/patches/bar
22 hg qrename bar/renamed baz
23 hg qseries
24 ls .hg/patches/baz
25
@@ -0,0 +1,7
1 adding base
2 foo/renamed
3 renamed
4 bar/renamed
5 renamed
6 baz
7 .hg/patches/baz
@@ -30,15 +30,29 proc getcommits {rargs} {
30 30 set startmsecs [clock clicks -milliseconds]
31 31 set nextupdate [expr $startmsecs + 100]
32 32 set ncmupdate 1
33 set limit 0
34 set revargs {}
35 for {set i 0} {$i < [llength $rargs]} {incr i} {
36 set opt [lindex $rargs $i]
37 if {$opt == "--limit"} {
38 incr i
39 set limit [lindex $rargs $i]
40 } else {
41 lappend revargs $opt
42 }
43 }
33 44 if [catch {
34 set parse_args [concat --default HEAD $rargs]
45 set parse_args [concat --default HEAD $revargs]
35 46 set parsed_args [split [eval exec hg debug-rev-parse $parse_args] "\n"]
36 }] {
47 } err] {
37 48 # if git-rev-parse failed for some reason...
38 49 if {$rargs == {}} {
39 set rargs HEAD
40 }
41 set parsed_args $rargs
50 set revargs HEAD
51 }
52 set parsed_args $revargs
53 }
54 if {$limit > 0} {
55 set parsed_args [concat -n $limit $parsed_args]
42 56 }
43 57 if [catch {
44 58 set commfd [open "|hg debug-rev-list --header --topo-order --parents $parsed_args" r]
@@ -100,7 +114,7 to allow selection of commits to be disp
100 114 set ids [string range $cmit 0 [expr {$j - 1}]]
101 115 set ok 1
102 116 foreach id $ids {
103 if {![regexp {^[0-9a-f]{40}$} $id]} {
117 if {![regexp {^[0-9a-f]{12}$} $id]} {
104 118 set ok 0
105 119 break
106 120 }
@@ -176,6 +190,7 proc parsecommit {id contents listed old
176 190 set audate {}
177 191 set comname {}
178 192 set comdate {}
193 set rev {}
179 194 if {![info exists nchildren($id)]} {
180 195 set children($id) {}
181 196 set nchildren($id) 0
@@ -209,6 +224,8 proc parsecommit {id contents listed old
209 224 set x [expr {[llength $line] - 2}]
210 225 set comdate [lindex $line $x]
211 226 set comname [join [lrange $line 1 [expr {$x - 1}]]]
227 } elseif {$tag == "revision"} {
228 set rev [lindex $line 1]
212 229 }
213 230 }
214 231 } else {
@@ -233,7 +250,7 proc parsecommit {id contents listed old
233 250 set comdate [clock format $comdate -format "%Y-%m-%d %H:%M:%S"]
234 251 }
235 252 set commitinfo($id) [list $headline $auname $audate \
236 $comname $comdate $comment]
253 $comname $comdate $comment $rev]
237 254 }
238 255
239 256 proc readrefs {} {
@@ -261,7 +278,7 proc readotherrefs {base dname excl} {
261 278 catch {
262 279 set fd [open $f r]
263 280 set line [read $fd 40]
264 if {[regexp {^[0-9a-f]{40}} $line id]} {
281 if {[regexp {^[0-9a-f]{12}} $line id]} {
265 282 set name "$dname[file tail $f]"
266 283 set otherrefids($name) $id
267 284 lappend idotherrefs($id) $name
@@ -1743,7 +1760,7 proc readfindproc {} {
1743 1760 }
1744 1761 return
1745 1762 }
1746 if {![regexp {^[0-9a-f]{40}} $line id]} {
1763 if {![regexp {^[0-9a-f]{12}} $line id]} {
1747 1764 error_popup "Can't parse git-diff-tree output: $line"
1748 1765 stopfindproc
1749 1766 return
@@ -1856,7 +1873,7 proc readfilediffs {df} {
1856 1873 }
1857 1874 return
1858 1875 }
1859 if {[regexp {^([0-9a-f]{40}) \(from ([0-9a-f]{40})\)} $line match id p]} {
1876 if {[regexp {^([0-9a-f]{12}) \(from ([0-9a-f]{12})\)} $line match id p]} {
1860 1877 # start of a new string of diffs
1861 1878 donefilediff
1862 1879 set fdiffids [list $id $p]
@@ -2002,8 +2019,9 proc commit_descriptor {p} {
2002 2019 set l "..."
2003 2020 if {[info exists commitinfo($p)]} {
2004 2021 set l [lindex $commitinfo($p) 0]
2005 }
2006 return "$p ($l)"
2022 set r [lindex $commitinfo($p) 6]
2023 }
2024 return "$r:$p ($l)"
2007 2025 }
2008 2026
2009 2027 # append some text to the ctext widget, and make any SHA1 ID
@@ -2014,7 +2032,7 proc appendwithlinks {text} {
2014 2032 set start [$ctext index "end - 1c"]
2015 2033 $ctext insert end $text
2016 2034 $ctext insert end "\n"
2017 set links [regexp -indices -all -inline {[0-9a-f]{40}} $text]
2035 set links [regexp -indices -all -inline {[0-9a-f]{12}} $text]
2018 2036 foreach l $links {
2019 2037 set s [lindex $l 0]
2020 2038 set e [lindex $l 1]
@@ -2107,6 +2125,7 proc selectline {l isnew} {
2107 2125 $ctext mark set fmark.0 0.0
2108 2126 $ctext mark gravity fmark.0 left
2109 2127 set info $commitinfo($id)
2128 $ctext insert end "Revision: [lindex $info 6]\n"
2110 2129 $ctext insert end "Author: [lindex $info 1] [lindex $info 2]\n"
2111 2130 $ctext insert end "Committer: [lindex $info 3] [lindex $info 4]\n"
2112 2131 if {[info exists idtags($id)]} {
@@ -193,6 +193,10 FILES
193 193 global /etc/mercurial/hgrc configuration. See hgrc(5) for details of
194 194 the contents and format of these files.
195 195
196 Some commands (e.g. revert) produce backup files ending in .orig, if
197 the .orig file already exists and is not tracked by Mercurial, it
198 will be overwritten.
199
196 200 BUGS
197 201 ----
198 202 Probably lots, please post them to the mailing list (See Resources below)
@@ -133,6 +133,21 decode/encode::
133 133 # them to the working dir
134 134 **.txt = tempfile: unix2dos -n INFILE OUTFILE
135 135
136 defaults::
137 Use the [defaults] section to define command defaults, i.e. the
138 default options/arguments to pass to the specified commands.
139
140 The following example makes 'hg log' run in verbose mode, and
141 'hg status' show only the modified files, by default.
142
143 [defaults]
144 log = -v
145 status = -m
146
147 The actual commands, instead of their aliases, must be used when
148 defining command defaults. The command defaults will also be
149 applied to the aliases of the commands defined.
150
136 151 email::
137 152 Settings for extensions that send email messages.
138 153 from;;
@@ -41,13 +41,15 HGTMP="${TMPDIR-/tmp}/hgeditor.$RANDOM.$
41 41
42 42 cat "$1" > "$HGTMP/msg"
43 43
44 CHECKSUM=`md5sum "$HGTMP/msg"`
44 MD5=$(which md5sum 2>/dev/null) || \
45 MD5=$(which md5 2>/dev/null)
46 [ -x "${MD5}" ] && CHECKSUM=`${MD5} "$HGTMP/msg"`
45 47 if [ -s "$HGTMP/diff" ]; then
46 48 $EDITOR "$HGTMP/msg" "$HGTMP/diff" || exit $?
47 49 else
48 50 $EDITOR "$HGTMP/msg" || exit $?
49 51 fi
50 echo "$CHECKSUM" | md5sum -c >/dev/null 2>&1 && exit 13
52 [ -x "${MD5}" ] && (echo "$CHECKSUM" | ${MD5} -c >/dev/null 2>&1 && exit 13)
51 53
52 54 mv "$HGTMP/msg" "$1"
53 55
@@ -60,8 +60,8 class checker(object):
60 60 return None, False
61 61
62 62 thisuser = self.getuser()
63 pats = [pat for pat, user in self.ui.configitems(key)
64 if user == thisuser]
63 pats = [pat for pat, users in self.ui.configitems(key)
64 if thisuser in users.replace(',', ' ').split()]
65 65 self.ui.debug(_('acl: %s enabled, %d entries for user %s\n') %
66 66 (key, len(pats), thisuser))
67 67 if pats:
@@ -45,7 +45,7
45 45 from mercurial.demandload import demandload
46 46 from mercurial.i18n import gettext as _
47 47 from mercurial.node import *
48 demandload(globals(), 'mercurial:commands,cmdutil,util os shutil tempfile')
48 demandload(globals(), 'mercurial:cmdutil,util os shutil tempfile')
49 49
50 50 def dodiff(ui, repo, diffcmd, diffopts, pats, opts):
51 51 def snapshot_node(files, node):
@@ -90,7 +90,7 def dodiff(ui, repo, diffcmd, diffopts,
90 90 fp.write(chunk)
91 91 return dirname
92 92
93 node1, node2 = commands.revpair(ui, repo, opts['rev'])
93 node1, node2 = cmdutil.revpair(ui, repo, opts['rev'])
94 94 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
95 95 modified, added, removed, deleted, unknown = repo.status(
96 96 node1, node2, files, match=matchfn)[:5]
@@ -105,8 +105,7 def dodiff(ui, repo, diffcmd, diffopts,
105 105 else:
106 106 dir2 = snapshot_wdir(modified + added)
107 107 cmdline = ('%s %s %s %s' %
108 (util.shellquote(diffcmd),
109 ' '.join(map(util.shellquote, diffopts)),
108 (util.shellquote(diffcmd), ' '.join(diffopts),
110 109 util.shellquote(dir1), util.shellquote(dir2)))
111 110 ui.debug('running %r in %s\n' % (cmdline, tmproot))
112 111 util.system(cmdline, cwd=tmproot)
@@ -7,92 +7,39
7 7
8 8 from mercurial.demandload import *
9 9 demandload(globals(), 'time sys signal os')
10 demandload(globals(), 'mercurial:hg,mdiff,fancyopts,commands,ui,util')
11
12 def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
13 changes=None, text=False):
14 def date(c):
15 return time.asctime(time.gmtime(c[2][0]))
10 demandload(globals(), 'mercurial:hg,fancyopts,commands,ui,util,patch,revlog')
16 11
17 if not changes:
18 changes = repo.status(node1, node2, files, match=match)[:5]
19 modified, added, removed, deleted, unknown = changes
20 if files:
21 modified, added, removed = map(lambda x: filterfiles(files, x),
22 (modified, added, removed))
23
24 if not modified and not added and not removed:
25 return
26
12 def difftree(ui, repo, node1=None, node2=None, *files, **opts):
13 """diff trees from two commits"""
14 def __difftree(repo, node1, node2, files=[]):
27 15 if node2:
28 16 change = repo.changelog.read(node2)
29 17 mmap2 = repo.manifest.read(change[0])
30 date2 = date(change)
31 def read(f):
32 return repo.file(f).read(mmap2[f])
18 status = repo.status(node1, node2, files=files)[:5]
19 modified, added, removed, deleted, unknown = status
33 20 else:
34 date2 = time.asctime()
21 status = repo.status(node1, files=files)[:5]
22 modified, added, removed, deleted, unknown = status
35 23 if not node1:
36 24 node1 = repo.dirstate.parents()[0]
37 def read(f):
38 return repo.wfile(f).read()
39 25
40 26 change = repo.changelog.read(node1)
41 27 mmap = repo.manifest.read(change[0])
42 date1 = date(change)
43
44 for f in modified:
45 to = None
46 if f in mmap:
47 to = repo.file(f).read(mmap[f])
48 tn = read(f)
49 opts = mdiff.diffopts()
50 opts.text = text
51 fp.write("diff --git a/%s b/%s\n" % (f, f))
52 fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, opts=opts))
53 for f in added:
54 to = None
55 tn = read(f)
56 fp.write("diff --git /dev/null b/%s\n" % (f))
57 fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, opts=opts))
58 for f in removed:
59 to = repo.file(f).read(mmap[f])
60 tn = None
61 fp.write("diff --git a/%s /dev/null\n" % (f))
62 fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, opts=opts))
63
64 def difftree(ui, repo, node1=None, node2=None, **opts):
65 """diff trees from two commits"""
66 def __difftree(repo, node1, node2):
67 def date(c):
68 return time.asctime(time.gmtime(c[2][0]))
69
70 if node2:
71 change = repo.changelog.read(node2)
72 mmap2 = repo.manifest.read(change[0])
73 modified, added, removed, deleted, unknown = repo.status(node1, node2)[:5]
74 def read(f): return repo.file(f).read(mmap2[f])
75 date2 = date(change)
76 else:
77 date2 = time.asctime()
78 modified, added, removed, deleted, unknown = repo.status(node1)[:5]
79 if not node1:
80 node1 = repo.dirstate.parents()[0]
81 def read(f): return file(os.path.join(repo.root, f)).read()
82
83 change = repo.changelog.read(node1)
84 mmap = repo.manifest.read(change[0])
85 date1 = date(change)
86 empty = "0" * 40;
28 empty = hg.short(hg.nullid)
87 29
88 30 for f in modified:
89 31 # TODO get file permissions
90 print ":100664 100664 %s %s M\t%s\t%s" % (hg.hex(mmap[f]),
91 hg.hex(mmap2[f]), f, f)
32 print ":100664 100664 %s %s M\t%s\t%s" % (hg.short(mmap[f]),
33 hg.short(mmap2[f]),
34 f, f)
92 35 for f in added:
93 print ":000000 100664 %s %s N\t%s\t%s" % (empty, hg.hex(mmap2[f]), f, f)
36 print ":000000 100664 %s %s N\t%s\t%s" % (empty,
37 hg.short(mmap2[f]),
38 f, f)
94 39 for f in removed:
95 print ":100664 000000 %s %s D\t%s\t%s" % (hg.hex(mmap[f]), empty, f, f)
40 print ":100664 000000 %s %s D\t%s\t%s" % (hg.short(mmap[f]),
41 empty,
42 f, f)
96 43 ##
97 44
98 45 while True:
@@ -115,20 +62,22 def difftree(ui, repo, node1=None, node2
115 62 if opts['patch']:
116 63 if opts['pretty']:
117 64 catcommit(repo, node2, "")
118 dodiff(sys.stdout, ui, repo, node1, node2)
65 patch.diff(repo, node1, node2,
66 files=files,
67 opts=patch.diffopts(ui, {'git': True}))
119 68 else:
120 __difftree(repo, node1, node2)
69 __difftree(repo, node1, node2, files=files)
121 70 if not opts['stdin']:
122 71 break
123 72
124 73 def catcommit(repo, n, prefix, changes=None):
125 74 nlprefix = '\n' + prefix;
126 75 (p1, p2) = repo.changelog.parents(n)
127 (h, h1, h2) = map(hg.hex, (n, p1, p2))
76 (h, h1, h2) = map(hg.short, (n, p1, p2))
128 77 (i1, i2) = map(repo.changelog.rev, (p1, p2))
129 78 if not changes:
130 79 changes = repo.changelog.read(n)
131 print "tree %s" % (hg.hex(changes[0]))
80 print "tree %s" % (hg.short(changes[0]))
132 81 if i1 != -1: print "parent %s" % (h1)
133 82 if i2 != -1: print "parent %s" % (h2)
134 83 date_ar = changes[2]
@@ -141,6 +90,7 def catcommit(repo, n, prefix, changes=N
141 90
142 91 print "author %s %s %s" % (changes[1], date, date_ar[1])
143 92 print "committer %s %s %s" % (committer, date, date_ar[1])
93 print "revision %d" % repo.changelog.rev(n)
144 94 print ""
145 95 if prefix != "":
146 96 print "%s%s" % (prefix, changes[4].replace('\n', nlprefix).strip())
@@ -154,7 +104,7 def base(ui, repo, node1, node2):
154 104 node1 = repo.lookup(node1)
155 105 node2 = repo.lookup(node2)
156 106 n = repo.changelog.ancestor(node1, node2)
157 print hg.hex(n)
107 print hg.short(n)
158 108
159 109 def catfile(ui, repo, type=None, r=None, **opts):
160 110 """cat a specific revision"""
@@ -267,7 +217,6 def revtree(args, repo, full="tree", max
267 217
268 218 # walk the repository looking for commits that are in our
269 219 # reachability graph
270 #for i in range(repo.changelog.count()-1, -1, -1):
271 220 for i, changes in chlogwalk():
272 221 n = repo.changelog.node(i)
273 222 mask = is_reachable(want_sha1, reachable, n)
@@ -276,17 +225,17 def revtree(args, repo, full="tree", max
276 225 if parents:
277 226 pp = repo.changelog.parents(n)
278 227 if pp[0] != hg.nullid:
279 parentstr += " " + hg.hex(pp[0])
228 parentstr += " " + hg.short(pp[0])
280 229 if pp[1] != hg.nullid:
281 parentstr += " " + hg.hex(pp[1])
230 parentstr += " " + hg.short(pp[1])
282 231 if not full:
283 print hg.hex(n) + parentstr
284 elif full is "commit":
285 print hg.hex(n) + parentstr
232 print hg.short(n) + parentstr
233 elif full == "commit":
234 print hg.short(n) + parentstr
286 235 catcommit(repo, n, ' ', changes)
287 236 else:
288 237 (p1, p2) = repo.changelog.parents(n)
289 (h, h1, h2) = map(hg.hex, (n, p1, p2))
238 (h, h1, h2) = map(hg.short, (n, p1, p2))
290 239 (i1, i2) = map(repo.changelog.rev, (p1, p2))
291 240
292 241 date = changes[2][0]
@@ -302,6 +251,19 def revtree(args, repo, full="tree", max
302 251 break
303 252 count += 1
304 253
254 def revparse(ui, repo, *revs, **opts):
255 """Parse given revisions"""
256 def revstr(rev):
257 if rev == 'HEAD':
258 rev = 'tip'
259 return revlog.hex(repo.lookup(rev))
260
261 for r in revs:
262 revrange = r.split(':', 1)
263 ui.write('%s\n' % revstr(revrange[0]))
264 if len(revrange) == 2:
265 ui.write('^%s\n' % revstr(revrange[1]))
266
305 267 # git rev-list tries to order things by date, and has the ability to stop
306 268 # at a given commit without walking the whole repo. TODO add the stop
307 269 # parameter
@@ -314,23 +276,29 def revlist(ui, repo, *revs, **opts):
314 276 copy = [x for x in revs]
315 277 revtree(copy, repo, full, opts['max_count'], opts['parents'])
316 278
317 def view(ui, repo, *etc):
279 def view(ui, repo, *etc, **opts):
318 280 "start interactive history viewer"
319 281 os.chdir(repo.root)
320 os.system(ui.config("hgk", "path", "hgk") + " " + " ".join(etc))
282 optstr = ' '.join(['--%s %s' % (k, v) for k, v in opts.iteritems()])
283 os.system(ui.config("hgk", "path", "hgk") + " %s %s" % (optstr, " ".join(etc)))
321 284
322 285 cmdtable = {
323 "view": (view, [], 'hg view'),
286 "view": (view,
287 [('l', 'limit', '', 'limit number of changes displayed')],
288 'hg view [-l LIMIT] [REVRANGE]'),
324 289 "debug-diff-tree": (difftree, [('p', 'patch', None, 'generate patch'),
325 290 ('r', 'recursive', None, 'recursive'),
326 291 ('P', 'pretty', None, 'pretty'),
327 292 ('s', 'stdin', None, 'stdin'),
328 293 ('C', 'copy', None, 'detect copies'),
329 294 ('S', 'search', "", 'search')],
330 "hg git-diff-tree [options] node1 node2"),
295 "hg git-diff-tree [options] node1 node2 [files...]"),
331 296 "debug-cat-file": (catfile, [('s', 'stdin', None, 'stdin')],
332 297 "hg debug-cat-file [options] type file"),
333 298 "debug-merge-base": (base, [], "hg debug-merge-base node node"),
299 'debug-rev-parse': (revparse,
300 [('', 'default', '', 'ignored')],
301 "hg debug-rev-parse rev"),
334 302 "debug-rev-list": (revlist, [('H', 'header', None, 'header'),
335 303 ('t', 'topo-order', None, 'topo-order'),
336 304 ('p', 'parents', None, 'parents'),
@@ -40,7 +40,7 commands.norepo += " qclone qversion"
40 40 class statusentry:
41 41 def __init__(self, rev, name=None):
42 42 if not name:
43 fields = rev.split(':')
43 fields = rev.split(':', 1)
44 44 if len(fields) == 2:
45 45 self.rev, self.name = fields
46 46 else:
@@ -483,24 +483,35 class queue:
483 483 tr.close()
484 484 return (err, n)
485 485
486 def delete(self, repo, patches, keep=False):
486 def delete(self, repo, patches, opts):
487 487 realpatches = []
488 appliedbase = 0
489 forget = opts.get('forget')
488 490 for patch in patches:
489 491 patch = self.lookup(patch, strict=True)
490 492 info = self.isapplied(patch)
491 if info:
493 if info and not forget:
492 494 raise util.Abort(_("cannot delete applied patch %s") % patch)
493 495 if patch not in self.series:
494 496 raise util.Abort(_("patch %s not in series file") % patch)
497 if forget:
498 if not info:
499 raise util.Abort(_("cannot forget unapplied patch %s") % patch)
500 if info[0] != appliedbase:
501 raise util.Abort(_("patch %s not at base") % patch)
502 appliedbase += 1
495 503 realpatches.append(patch)
496 504
497 if not keep:
505 if not opts.get('keep'):
498 506 r = self.qrepo()
499 507 if r:
500 508 r.remove(realpatches, True)
501 509 else:
502 510 os.unlink(self.join(patch))
503 511
512 if forget:
513 del self.applied[:appliedbase]
514 self.applied_dirty = 1
504 515 indices = [self.find_series(p) for p in realpatches]
505 516 indices.sort()
506 517 for i in indices[-1::-1]:
@@ -694,8 +705,8 class queue:
694 705 stripall(rev, revnum)
695 706
696 707 change = chlog.read(rev)
708 chlog.strip(revnum, revnum)
697 709 repo.manifest.strip(repo.manifest.rev(change[0]), revnum)
698 chlog.strip(revnum, revnum)
699 710 if saveheads:
700 711 self.ui.status("adding branch\n")
701 712 commands.unbundle(self.ui, repo, chgrpfile, update=False)
@@ -757,25 +768,25 class queue:
757 768 # return any partial match made above
758 769 if res:
759 770 return res
760 minus = patch.rsplit('-', 1)
761 if len(minus) > 1:
762 res = partial_name(minus[0])
771 minus = patch.rfind('-')
772 if minus >= 0:
773 res = partial_name(patch[:minus])
763 774 if res:
764 775 i = self.series.index(res)
765 776 try:
766 off = int(minus[1] or 1)
777 off = int(patch[minus+1:] or 1)
767 778 except(ValueError, OverflowError):
768 779 pass
769 780 else:
770 781 if i - off >= 0:
771 782 return self.series[i - off]
772 plus = patch.rsplit('+', 1)
773 if len(plus) > 1:
774 res = partial_name(plus[0])
783 plus = patch.rfind('+')
784 if plus >= 0:
785 res = partial_name(patch[:plus])
775 786 if res:
776 787 i = self.series.index(res)
777 788 try:
778 off = int(plus[1] or 1)
789 off = int(patch[plus+1:] or 1)
779 790 except(ValueError, OverflowError):
780 791 pass
781 792 else:
@@ -919,13 +930,13 class queue:
919 930 return 1
920 931 wlock = repo.wlock()
921 932 self.check_toppatch(repo)
922 (top, patch) = (self.applied[-1].rev, self.applied[-1].name)
933 (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name)
923 934 top = revlog.bin(top)
924 935 cparents = repo.changelog.parents(top)
925 936 patchparent = self.qparents(repo, top)
926 message, comments, user, date, patchfound = self.readheaders(patch)
937 message, comments, user, date, patchfound = self.readheaders(patchfn)
927 938
928 patchf = self.opener(patch, "w")
939 patchf = self.opener(patchfn, "w")
929 940 msg = opts.get('msg', '').rstrip()
930 941 if msg:
931 942 if comments:
@@ -995,8 +1006,11 class queue:
995 1006 r = list(util.unique(dd))
996 1007 a = list(util.unique(aa))
997 1008 filelist = filter(matchfn, util.unique(m + r + a))
998 self.printdiff(repo, patchparent, files=filelist,
999 changes=(m, a, r, [], u), fp=patchf)
1009 if opts.get('git'):
1010 self.diffopts().git = True
1011 patch.diff(repo, patchparent, files=filelist, match=matchfn,
1012 fp=patchf, changes=(m, a, r, [], u),
1013 opts=self.diffopts())
1000 1014 patchf.close()
1001 1015
1002 1016 changes = repo.changelog.read(tip)
@@ -1019,7 +1033,7 class queue:
1019 1033
1020 1034 if not msg:
1021 1035 if not message:
1022 message = "patch queue: %s\n" % patch
1036 message = "patch queue: %s\n" % patchfn
1023 1037 else:
1024 1038 message = "\n".join(message)
1025 1039 else:
@@ -1027,7 +1041,7 class queue:
1027 1041
1028 1042 self.strip(repo, top, update=False, backup='strip', wlock=wlock)
1029 1043 n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock)
1030 self.applied[-1] = statusentry(revlog.hex(n), patch)
1044 self.applied[-1] = statusentry(revlog.hex(n), patchfn)
1031 1045 self.applied_dirty = 1
1032 1046 else:
1033 1047 self.printdiff(repo, patchparent, fp=patchf)
@@ -1303,10 +1317,15 class queue:
1303 1317 def delete(ui, repo, patch, *patches, **opts):
1304 1318 """remove patches from queue
1305 1319
1306 The patches must not be applied.
1307 With -k, the patch files are preserved in the patch directory."""
1320 With --forget, mq will stop managing the named patches. The
1321 patches must be applied and at the base of the stack. This option
1322 is useful when the patches have been applied upstream.
1323
1324 Otherwise, the patches must not be applied.
1325
1326 With --keep, the patch files are preserved in the patch directory."""
1308 1327 q = repo.mq
1309 q.delete(repo, (patch,) + patches, keep=opts.get('keep'))
1328 q.delete(repo, (patch,) + patches, opts)
1310 1329 q.save_dirty()
1311 1330 return 0
1312 1331
@@ -1478,7 +1497,7 def fold(ui, repo, *files, **opts):
1478 1497 if not files:
1479 1498 raise util.Abort(_('qfold requires at least one patch name'))
1480 1499 if not q.check_toppatch(repo):
1481 raise util.Abort(_('No patches applied\n'))
1500 raise util.Abort(_('No patches applied'))
1482 1501
1483 1502 message = commands.logmessage(opts)
1484 1503 if opts['edit']:
@@ -1650,13 +1669,6 def rename(ui, repo, patch, name=None, *
1650 1669 name = patch
1651 1670 patch = None
1652 1671
1653 if name in q.series:
1654 raise util.Abort(_('A patch named %s already exists in the series file') % name)
1655
1656 absdest = q.join(name)
1657 if os.path.exists(absdest):
1658 raise util.Abort(_('%s already exists') % absdest)
1659
1660 1672 if patch:
1661 1673 patch = q.lookup(patch)
1662 1674 else:
@@ -1664,6 +1676,15 def rename(ui, repo, patch, name=None, *
1664 1676 ui.write(_('No patches applied\n'))
1665 1677 return
1666 1678 patch = q.lookup('qtip')
1679 absdest = q.join(name)
1680 if os.path.isdir(absdest):
1681 name = os.path.join(name, os.path.basename(patch))
1682 absdest = q.join(name)
1683 if os.path.exists(absdest):
1684 raise util.Abort(_('%s already exists') % absdest)
1685
1686 if name in q.series:
1687 raise util.Abort(_('A patch named %s already exists in the series file') % name)
1667 1688
1668 1689 if ui.verbose:
1669 1690 ui.write('Renaming %s to %s\n' % (patch, name))
@@ -1735,7 +1756,8 def strip(ui, repo, rev, **opts):
1735 1756 backup = 'strip'
1736 1757 elif opts['nobackup']:
1737 1758 backup = 'none'
1738 repo.mq.strip(repo, rev, backup=backup)
1759 update = repo.dirstate.parents()[0] != revlog.nullid
1760 repo.mq.strip(repo, rev, backup=backup, update=update)
1739 1761 return 0
1740 1762
1741 1763 def select(ui, repo, *args, **opts):
@@ -1911,8 +1933,9 cmdtable = {
1911 1933 'hg qdiff [-I] [-X] [FILE]...'),
1912 1934 "qdelete|qremove|qrm":
1913 1935 (delete,
1914 [('k', 'keep', None, _('keep patch file'))],
1915 'hg qdelete [-k] PATCH'),
1936 [('f', 'forget', None, _('stop managing an applied patch')),
1937 ('k', 'keep', None, _('keep patch file'))],
1938 'hg qdelete [-f] [-k] PATCH'),
1916 1939 'qfold':
1917 1940 (fold,
1918 1941 [('e', 'edit', None, _('edit patch header')),
@@ -1963,6 +1986,7 cmdtable = {
1963 1986 [('e', 'edit', None, _('edit commit message')),
1964 1987 ('m', 'message', '', _('change commit message with <text>')),
1965 1988 ('l', 'logfile', '', _('change commit message with <file> content')),
1989 ('g', 'git', None, _('use git extended diff format')),
1966 1990 ('s', 'short', None, 'short refresh'),
1967 1991 ('I', 'include', [], _('include names matching the given patterns')),
1968 1992 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
@@ -1994,7 +2018,7 cmdtable = {
1994 2018 (series,
1995 2019 [('m', 'missing', None, 'print patches not in series'),
1996 2020 ('s', 'summary', None, _('print first line of patch header'))],
1997 'hg qseries [-m]'),
2021 'hg qseries [-ms]'),
1998 2022 "^strip":
1999 2023 (strip,
2000 2024 [('f', 'force', None, 'force multi-head removal'),
@@ -238,8 +238,11 class notifier(object):
238 238 return
239 239 fp = templater.stringio()
240 240 prev = self.repo.changelog.parents(node)[0]
241 patch.diff(self.repo, fp, prev, ref)
241 patch.diff(self.repo, prev, ref, fp=fp)
242 242 difflines = fp.getvalue().splitlines(1)
243 if self.ui.configbool('notify', 'diffstat', True):
244 s = patch.diffstat(difflines)
245 self.sio.write('\ndiffstat:\n\n' + s)
243 246 if maxdiff > 0 and len(difflines) > maxdiff:
244 247 self.sio.write(_('\ndiffs (truncated from %d to %d lines):\n\n') %
245 248 (len(difflines), maxdiff))
@@ -65,7 +65,7
65 65
66 66 from mercurial.demandload import *
67 67 demandload(globals(), '''email.MIMEMultipart email.MIMEText email.Utils
68 mercurial:commands,hg,mail,ui
68 mercurial:commands,hg,mail,ui,patch
69 69 os errno popen2 socket sys tempfile time''')
70 70 from mercurial.i18n import gettext as _
71 71 from mercurial.node import *
@@ -76,27 +76,6 try:
76 76 import readline
77 77 except ImportError: pass
78 78
79 def diffstat(patch):
80 fd, name = tempfile.mkstemp(prefix="hg-patchbomb-", suffix=".txt")
81 try:
82 p = popen2.Popen3('diffstat -p1 -w79 2>/dev/null > ' + name)
83 try:
84 for line in patch: print >> p.tochild, line
85 p.tochild.close()
86 if p.wait(): return
87 fp = os.fdopen(fd, 'r')
88 stat = []
89 for line in fp: stat.append(line.lstrip())
90 last = stat.pop()
91 stat.insert(0, last)
92 stat = ''.join(stat)
93 if stat.startswith('0 files'): raise ValueError
94 return stat
95 except: raise
96 finally:
97 try: os.unlink(name)
98 except: pass
99
100 79 def patchbomb(ui, repo, *revs, **opts):
101 80 '''send changesets as a series of patch emails
102 81
@@ -123,8 +102,8 def patchbomb(ui, repo, *revs, **opts):
123 102 if not prompt(s, default = 'y', rest = '? ').lower().startswith('y'):
124 103 raise ValueError
125 104
126 def cdiffstat(summary, patch):
127 s = diffstat(patch)
105 def cdiffstat(summary, patchlines):
106 s = patch.diffstat(patchlines)
128 107 if s:
129 108 if summary:
130 109 ui.write(summary, '\n')
@@ -140,7 +119,9 def patchbomb(ui, repo, *revs, **opts):
140 119 if line.startswith('#'):
141 120 if line.startswith('# Node ID'): node = line.split()[-1]
142 121 continue
143 if line.startswith('diff -r'): break
122 if (line.startswith('diff -r')
123 or line.startswith('diff --git')):
124 break
144 125 desc.append(line)
145 126 if not node: raise ValueError
146 127
@@ -205,7 +186,8 def patchbomb(ui, repo, *revs, **opts):
205 186
206 187 commands.export(ui, repo, *revs, **{'output': exportee(patches),
207 188 'switch_parent': False,
208 'text': None})
189 'text': None,
190 'git': opts.get('git')})
209 191
210 192 jumbo = []
211 193 msgs = []
@@ -322,6 +304,7 cmdtable = {
322 304 ('', 'bcc', [], 'email addresses of blind copy recipients'),
323 305 ('c', 'cc', [], 'email addresses of copy recipients'),
324 306 ('d', 'diffstat', None, 'add diffstat output to messages'),
307 ('g', 'git', None, _('use git extended diff format')),
325 308 ('f', 'from', '', 'email address of sender'),
326 309 ('', 'plain', None, 'omit hg patch header'),
327 310 ('n', 'test', None, 'print messages that would be sent'),
@@ -16,6 +16,14 class changelog(revlog):
16 16 defversion)
17 17
18 18 def extract(self, text):
19 """
20 format used:
21 nodeid\n : manifest node in ascii
22 user\n : user, no \n or \r allowed
23 time tz\n : date (time is int or float, timezone is int)
24 files\n\n : files modified by the cset, no \n or \r allowed
25 (.*) : comment (free text, ideally utf-8)
26 """
19 27 if not text:
20 28 return (nullid, "", (0, 0), [], "")
21 29 last = text.index("\n\n")
@@ -11,6 +11,76 from i18n import gettext as _
11 11 demandload(globals(), 'mdiff util')
12 12 demandload(globals(), 'os sys')
13 13
14 revrangesep = ':'
15
16 def revfix(repo, val, defval):
17 '''turn user-level id of changeset into rev number.
18 user-level id can be tag, changeset, rev number, or negative rev
19 number relative to number of revs (-1 is tip, etc).'''
20 if not val:
21 return defval
22 try:
23 num = int(val)
24 if str(num) != val:
25 raise ValueError
26 if num < 0:
27 num += repo.changelog.count()
28 if num < 0:
29 num = 0
30 elif num >= repo.changelog.count():
31 raise ValueError
32 except ValueError:
33 try:
34 num = repo.changelog.rev(repo.lookup(val))
35 except KeyError:
36 raise util.Abort(_('invalid revision identifier %s') % val)
37 return num
38
39 def revpair(ui, repo, revs):
40 '''return pair of nodes, given list of revisions. second item can
41 be None, meaning use working dir.'''
42 if not revs:
43 return repo.dirstate.parents()[0], None
44 end = None
45 if len(revs) == 1:
46 start = revs[0]
47 if revrangesep in start:
48 start, end = start.split(revrangesep, 1)
49 start = revfix(repo, start, 0)
50 end = revfix(repo, end, repo.changelog.count() - 1)
51 else:
52 start = revfix(repo, start, None)
53 elif len(revs) == 2:
54 if revrangesep in revs[0] or revrangesep in revs[1]:
55 raise util.Abort(_('too many revisions specified'))
56 start = revfix(repo, revs[0], None)
57 end = revfix(repo, revs[1], None)
58 else:
59 raise util.Abort(_('too many revisions specified'))
60 if end is not None: end = repo.lookup(str(end))
61 return repo.lookup(str(start)), end
62
63 def revrange(ui, repo, revs):
64 """Yield revision as strings from a list of revision specifications."""
65 seen = {}
66 for spec in revs:
67 if revrangesep in spec:
68 start, end = spec.split(revrangesep, 1)
69 start = revfix(repo, start, 0)
70 end = revfix(repo, end, repo.changelog.count() - 1)
71 step = start > end and -1 or 1
72 for rev in xrange(start, end+step, step):
73 if rev in seen:
74 continue
75 seen[rev] = 1
76 yield str(rev)
77 else:
78 rev = revfix(repo, spec, None)
79 if rev in seen:
80 continue
81 seen[rev] = 1
82 yield str(rev)
83
14 84 def make_filename(repo, pat, node,
15 85 total=None, seqno=None, revwidth=None, pathname=None):
16 86 node_expander = {
@@ -53,7 +123,7 def make_filename(repo, pat, node,
53 123 i += 1
54 124 return ''.join(newname)
55 125 except KeyError, inst:
56 raise util.Abort(_("invalid format spec '%%%s' in output file name"),
126 raise util.Abort(_("invalid format spec '%%%s' in output file name") %
57 127 inst.args[0])
58 128
59 129 def make_file(repo, pat, node=None,
@@ -8,7 +8,7
8 8 from demandload import demandload
9 9 from node import *
10 10 from i18n import gettext as _
11 demandload(globals(), "os re sys signal shutil imp urllib pdb")
11 demandload(globals(), "os re sys signal shutil imp urllib pdb shlex")
12 12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
13 13 demandload(globals(), "fnmatch difflib patch random signal tempfile time")
14 14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
@@ -50,6 +50,21 def logmessage(opts):
50 50 (logfile, inst.strerror))
51 51 return message
52 52
53 def defaultrev(repo, rev=None, default='tip'):
54 """returns rev if it is specified, otherwise the working dir
55 parent if there is only one, or tip if there is no working
56 dir"""
57 if rev:
58 return rev
59
60 p1, p2 = repo.dirstate.parents()
61 if p2 != nullid:
62 raise util.Abort(_('uncommitted merge - please provide a '
63 'specific revision'))
64 if p1 != nullid:
65 return hex(p1)
66 return default
67
53 68 def walkchangerevs(ui, repo, pats, opts):
54 69 '''Iterate over files and the revs they changed in.
55 70
@@ -99,16 +114,10 def walkchangerevs(ui, repo, pats, opts)
99 114 return [], False, matchfn
100 115
101 116 if follow:
102 p = repo.dirstate.parents()[0]
103 if p == nullid:
104 ui.warn(_('No working directory revision; defaulting to tip\n'))
105 start = 'tip'
106 else:
107 start = repo.changelog.rev(p)
108 defrange = '%s:0' % start
117 defrange = '%s:0' % defaultrev(repo)
109 118 else:
110 119 defrange = 'tip:0'
111 revs = map(int, revrange(ui, repo, opts['rev'] or [defrange]))
120 revs = map(int, cmdutil.revrange(ui, repo, opts['rev'] or [defrange]))
112 121 wanted = {}
113 122 slowpath = anypats
114 123 fncache = {}
@@ -252,76 +261,6 def walkchangerevs(ui, repo, pats, opts)
252 261 yield 'iter', rev, None
253 262 return iterate(), getchange, matchfn
254 263
255 revrangesep = ':'
256
257 def revfix(repo, val, defval):
258 '''turn user-level id of changeset into rev number.
259 user-level id can be tag, changeset, rev number, or negative rev
260 number relative to number of revs (-1 is tip, etc).'''
261 if not val:
262 return defval
263 try:
264 num = int(val)
265 if str(num) != val:
266 raise ValueError
267 if num < 0:
268 num += repo.changelog.count()
269 if num < 0:
270 num = 0
271 elif num >= repo.changelog.count():
272 raise ValueError
273 except ValueError:
274 try:
275 num = repo.changelog.rev(repo.lookup(val))
276 except KeyError:
277 raise util.Abort(_('invalid revision identifier %s'), val)
278 return num
279
280 def revpair(ui, repo, revs):
281 '''return pair of nodes, given list of revisions. second item can
282 be None, meaning use working dir.'''
283 if not revs:
284 return repo.dirstate.parents()[0], None
285 end = None
286 if len(revs) == 1:
287 start = revs[0]
288 if revrangesep in start:
289 start, end = start.split(revrangesep, 1)
290 start = revfix(repo, start, 0)
291 end = revfix(repo, end, repo.changelog.count() - 1)
292 else:
293 start = revfix(repo, start, None)
294 elif len(revs) == 2:
295 if revrangesep in revs[0] or revrangesep in revs[1]:
296 raise util.Abort(_('too many revisions specified'))
297 start = revfix(repo, revs[0], None)
298 end = revfix(repo, revs[1], None)
299 else:
300 raise util.Abort(_('too many revisions specified'))
301 if end is not None: end = repo.lookup(str(end))
302 return repo.lookup(str(start)), end
303
304 def revrange(ui, repo, revs):
305 """Yield revision as strings from a list of revision specifications."""
306 seen = {}
307 for spec in revs:
308 if revrangesep in spec:
309 start, end = spec.split(revrangesep, 1)
310 start = revfix(repo, start, 0)
311 end = revfix(repo, end, repo.changelog.count() - 1)
312 step = start > end and -1 or 1
313 for rev in xrange(start, end+step, step):
314 if rev in seen:
315 continue
316 seen[rev] = 1
317 yield str(rev)
318 else:
319 rev = revfix(repo, spec, None)
320 if rev in seen:
321 continue
322 seen[rev] = 1
323 yield str(rev)
324
325 264 def write_bundle(cg, filename=None, compress=True):
326 265 """Write a bundle file and return its filename.
327 266
@@ -341,7 +280,7 def write_bundle(cg, filename=None, comp
341 280 try:
342 281 if filename:
343 282 if os.path.exists(filename):
344 raise util.Abort(_("file '%s' already exists"), filename)
283 raise util.Abort(_("file '%s' already exists") % filename)
345 284 fh = open(filename, "wb")
346 285 else:
347 286 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
@@ -707,7 +646,7 def annotate(ui, repo, *pats, **opts):
707 646 if not opts['user'] and not opts['changeset'] and not opts['date']:
708 647 opts['number'] = 1
709 648
710 ctx = repo.changectx(opts['rev'] or repo.dirstate.parents()[0])
649 ctx = repo.changectx(defaultrev(repo, opts['rev']))
711 650
712 651 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
713 652 node=ctx.node()):
@@ -754,14 +693,7 def archive(ui, repo, dest, **opts):
754 693 The default is the basename of the archive, with suffixes removed.
755 694 '''
756 695
757 if opts['rev']:
758 node = repo.lookup(opts['rev'])
759 else:
760 node, p2 = repo.dirstate.parents()
761 if p2 != nullid:
762 raise util.Abort(_('uncommitted merge - please provide a '
763 'specific revision'))
764
696 node = repo.lookup(defaultrev(repo, opts['rev']))
765 697 dest = cmdutil.make_filename(repo, dest, node)
766 698 if os.path.realpath(dest) == repo.root:
767 699 raise util.Abort(_('repository root cannot be destination'))
@@ -867,7 +799,8 def cat(ui, repo, file1, *pats, **opts):
867 799 """output the latest or given revisions of files
868 800
869 801 Print the specified files as they were at the given revision.
870 If no revision is given then the tip is used.
802 If no revision is given then working dir parent is used, or tip
803 if no revision is checked out.
871 804
872 805 Output may be to a file, in which case the name of the file is
873 806 given using a format string. The formatting rules are the same as
@@ -877,7 +810,7 def cat(ui, repo, file1, *pats, **opts):
877 810 %d dirname of file being printed, or '.' if in repo root
878 811 %p root-relative path name of file being printed
879 812 """
880 ctx = repo.changectx(opts['rev'] or "-1")
813 ctx = repo.changectx(defaultrev(repo, opts['rev']))
881 814 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
882 815 ctx.node()):
883 816 fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs)
@@ -1269,7 +1202,7 def debugdata(ui, file_, rev):
1269 1202 try:
1270 1203 ui.write(r.revision(r.lookup(rev)))
1271 1204 except KeyError:
1272 raise util.Abort(_('invalid revision identifier %s'), rev)
1205 raise util.Abort(_('invalid revision identifier %s') % rev)
1273 1206
1274 1207 def debugindex(ui, file_):
1275 1208 """dump the contents of an index file"""
@@ -1344,7 +1277,7 def diff(ui, repo, *pats, **opts):
1344 1277 it detects as binary. With -a, diff will generate a diff anyway,
1345 1278 probably with undesirable results.
1346 1279 """
1347 node1, node2 = revpair(ui, repo, opts['rev'])
1280 node1, node2 = cmdutil.revpair(ui, repo, opts['rev'])
1348 1281
1349 1282 fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
1350 1283
@@ -1380,7 +1313,7 def export(ui, repo, *changesets, **opts
1380 1313 """
1381 1314 if not changesets:
1382 1315 raise util.Abort(_("export requires at least one changeset"))
1383 revs = list(revrange(ui, repo, changesets))
1316 revs = list(cmdutil.revrange(ui, repo, changesets))
1384 1317 if len(revs) > 1:
1385 1318 ui.note(_('exporting patches:\n'))
1386 1319 else:
@@ -1940,7 +1873,7 def merge(ui, repo, node=None, force=Non
1940 1873 revision to merge with must be provided.
1941 1874 """
1942 1875
1943 if node:
1876 if node or branch:
1944 1877 node = _lookup(repo, node, branch)
1945 1878 else:
1946 1879 heads = repo.heads()
@@ -2272,8 +2205,8 def revert(ui, repo, *pats, **opts):
2272 2205 Modified files are saved with a .orig suffix before reverting.
2273 2206 To disable these backups, use --no-backup.
2274 2207
2275 Using the -r option, revert the given files or directories to
2276 their contents as of a specific revision. This can be helpful to"roll
2208 Using the -r option, revert the given files or directories to their
2209 contents as of a specific revision. This can be helpful to "roll
2277 2210 back" some or all of a change that should not have been committed.
2278 2211
2279 2212 Revert modifies the working directory. It does not commit any
@@ -2291,16 +2224,11 def revert(ui, repo, *pats, **opts):
2291 2224 """
2292 2225
2293 2226 if not pats and not opts['all']:
2294 raise util.Abort(_('no files or directories specified'))
2227 raise util.Abort(_('no files or directories specified; '
2228 'use --all to revert the whole repo'))
2295 2229
2296 2230 parent, p2 = repo.dirstate.parents()
2297 if opts['rev']:
2298 node = repo.lookup(opts['rev'])
2299 elif p2 != nullid:
2300 raise util.Abort(_('working dir has two parents; '
2301 'you must specify the revision to revert to'))
2302 else:
2303 node = parent
2231 node = repo.lookup(defaultrev(repo, opts['rev']))
2304 2232 mf = repo.manifest.read(repo.changelog.read(node)[0])
2305 2233 if node == parent:
2306 2234 pmf = mf
@@ -2457,7 +2385,8 def serve(ui, repo, **opts):
2457 2385
2458 2386 if opts["stdio"]:
2459 2387 if repo is None:
2460 raise hg.RepoError(_('no repo found'))
2388 raise hg.RepoError(_("There is no Mercurial repository here"
2389 " (.hg not found)"))
2461 2390 s = sshserver.sshserver(ui, repo)
2462 2391 s.serve_forever()
2463 2392
@@ -2468,7 +2397,8 def serve(ui, repo, **opts):
2468 2397 ui.setconfig("web", o, opts[o])
2469 2398
2470 2399 if repo is None and not ui.config("web", "webdir_conf"):
2471 raise hg.RepoError(_('no repo found'))
2400 raise hg.RepoError(_("There is no Mercurial repository here"
2401 " (.hg not found)"))
2472 2402
2473 2403 if opts['daemon'] and not opts['daemon_pipefds']:
2474 2404 rfd, wfd = os.pipe()
@@ -2483,7 +2413,7 def serve(ui, repo, **opts):
2483 2413 try:
2484 2414 httpd = hgweb.server.create_server(ui, repo)
2485 2415 except socket.error, inst:
2486 raise util.Abort(_('cannot start server: ') + inst.args[1])
2416 raise util.Abort(_('cannot start server: %s') % inst.args[1])
2487 2417
2488 2418 if ui.verbose:
2489 2419 addr, port = httpd.socket.getsockname()
@@ -2598,15 +2528,10 def tag(ui, repo, name, rev_=None, **opt
2598 2528 raise util.Abort(_("use only one form to specify the revision"))
2599 2529 if opts['rev']:
2600 2530 rev_ = opts['rev']
2601 if rev_:
2602 r = repo.lookup(rev_)
2603 else:
2604 p1, p2 = repo.dirstate.parents()
2605 if p1 == nullid:
2531 r = defaultrev(repo, rev_, nullid)
2532 if r == nullid:
2606 2533 raise util.Abort(_('no revision to tag'))
2607 if p2 != nullid:
2608 raise util.Abort(_('outstanding uncommitted merges'))
2609 r = p1
2534 r = repo.lookup(r)
2610 2535
2611 2536 message = opts['message']
2612 2537 if not message:
@@ -2733,7 +2658,7 def _lookup(repo, node, branch=None):
2733 2658 repo.ui.warn(_("Using head %s for branch %s\n")
2734 2659 % (short(node), branch))
2735 2660 else:
2736 raise util.Abort(_("branch %s not found\n") % (branch))
2661 raise util.Abort(_("branch %s not found") % branch)
2737 2662 else:
2738 2663 node = node and repo.lookup(node) or repo.changelog.tip()
2739 2664 return node
@@ -2886,6 +2811,7 table = {
2886 2811 (export,
2887 2812 [('o', 'output', '', _('print output to file with formatted name')),
2888 2813 ('a', 'text', None, _('treat all files as text')),
2814 ('g', 'git', None, _('use git extended diff format')),
2889 2815 ('', 'switch-parent', None, _('diff against the second parent'))],
2890 2816 _('hg export [-a] [-o OUTFILESPEC] REV...')),
2891 2817 "debugforget|forget":
@@ -3221,7 +3147,7 def parse(ui, args):
3221 3147 cmd = aliases[0]
3222 3148 defaults = ui.config("defaults", cmd)
3223 3149 if defaults:
3224 args = defaults.split() + args
3150 args = shlex.split(defaults) + args
3225 3151 c = list(i[1])
3226 3152 else:
3227 3153 cmd = None
@@ -3305,12 +3231,14 def dispatch(args):
3305 3231 if num: signal.signal(num, catchterm)
3306 3232
3307 3233 try:
3308 u = ui.ui(traceback='--traceback' in sys.argv[1:],
3309 readhooks=[load_extensions])
3234 u = ui.ui(traceback='--traceback' in sys.argv[1:])
3310 3235 except util.Abort, inst:
3311 3236 sys.stderr.write(_("abort: %s\n") % inst)
3312 3237 return -1
3313 3238
3239 load_extensions(u)
3240 u.addreadhook(load_extensions)
3241
3314 3242 try:
3315 3243 cmd, func, args, options, cmdoptions = parse(u, args)
3316 3244 if options["time"]:
@@ -3445,7 +3373,7 def dispatch(args):
3445 3373 u.warn(_("abort: could not lock %s: %s\n") %
3446 3374 (inst.desc or inst.filename, inst.strerror))
3447 3375 except revlog.RevlogError, inst:
3448 u.warn(_("abort: "), inst, "!\n")
3376 u.warn(_("abort: %s!\n") % inst)
3449 3377 except util.SignalInterrupt:
3450 3378 u.warn(_("killed!\n"))
3451 3379 except KeyboardInterrupt:
@@ -3467,18 +3395,18 def dispatch(args):
3467 3395 u.warn(_("broken pipe\n"))
3468 3396 elif getattr(inst, "strerror", None):
3469 3397 if getattr(inst, "filename", None):
3470 u.warn(_("abort: %s - %s\n") % (inst.strerror, inst.filename))
3398 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
3471 3399 else:
3472 3400 u.warn(_("abort: %s\n") % inst.strerror)
3473 3401 else:
3474 3402 raise
3475 3403 except OSError, inst:
3476 if hasattr(inst, "filename"):
3404 if getattr(inst, "filename", None):
3477 3405 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
3478 3406 else:
3479 3407 u.warn(_("abort: %s\n") % inst.strerror)
3480 3408 except util.Abort, inst:
3481 u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
3409 u.warn(_("abort: %s\n") % inst)
3482 3410 except TypeError, inst:
3483 3411 # was this an argument error?
3484 3412 tb = traceback.extract_tb(sys.exc_info()[2])
@@ -115,7 +115,7 def clone(ui, source, dest=None, pull=Fa
115 115 source = localpath(source)
116 116
117 117 if os.path.exists(dest):
118 raise util.Abort(_("destination '%s' already exists"), dest)
118 raise util.Abort(_("destination '%s' already exists") % dest)
119 119
120 120 class DirCleanup(object):
121 121 def __init__(self, dir_):
@@ -127,11 +127,6 def clone(ui, source, dest=None, pull=Fa
127 127 if self.dir_:
128 128 self.rmtree(self.dir_, True)
129 129
130 dest_repo = None
131 try:
132 dest_repo = repository(ui, dest)
133 raise util.Abort(_("destination '%s' already exists." % dest))
134 except RepoError:
135 130 dest_repo = repository(ui, dest, create=True)
136 131
137 132 dest_path = None
@@ -207,7 +207,8 def create_server(ui, repo):
207 207 hgwebobj = self.repoviewmaker(repo.__class__(repo.ui,
208 208 repo.origroot))
209 209 else:
210 raise hg.RepoError(_('no repo found'))
210 raise hg.RepoError(_("There is no Mercurial repository here"
211 " (.hg not found)"))
211 212 return hgwebobj
212 213
213 214 class IPv6HTTPServer(MercurialHTTPServer):
@@ -325,7 +325,7 class httprepository(remoterepository):
325 325 rfp.close()
326 326 except socket.error, err:
327 327 if err[0] in (errno.ECONNRESET, errno.EPIPE):
328 raise util.Abort(_('push failed: %s'), err[1])
328 raise util.Abort(_('push failed: %s') % err[1])
329 329 raise util.Abort(err[1])
330 330 finally:
331 331 fp.close()
@@ -27,12 +27,21 class localrepository(repo.repository):
27 27 oldp = p
28 28 p = os.path.dirname(p)
29 29 if p == oldp:
30 raise repo.RepoError(_("no repo found"))
30 raise repo.RepoError(_("There is no Mercurial repository"
31 " here (.hg not found)"))
31 32 path = p
32 33 self.path = os.path.join(path, ".hg")
33 34
34 if not create and not os.path.isdir(self.path):
35 if not os.path.isdir(self.path):
36 if create:
37 if not os.path.exists(path):
38 os.mkdir(path)
39 os.mkdir(self.path)
40 os.mkdir(self.join("data"))
41 else:
35 42 raise repo.RepoError(_("repository %s not found") % path)
43 elif create:
44 raise repo.RepoError(_("repository %s already exists") % path)
36 45
37 46 self.root = os.path.abspath(path)
38 47 self.origroot = path
@@ -75,12 +84,6 class localrepository(repo.repository):
75 84 self.decodepats = None
76 85 self.transhandle = None
77 86
78 if create:
79 if not os.path.exists(path):
80 os.mkdir(path)
81 os.mkdir(self.path)
82 os.mkdir(self.join("data"))
83
84 87 self.dirstate = dirstate.dirstate(self.opener, self.ui, self.root)
85 88
86 89 def url(self):
@@ -131,7 +134,7 class localrepository(repo.repository):
131 134 except Exception, exc:
132 135 if isinstance(exc, util.Abort):
133 136 self.ui.warn(_('error: %s hook failed: %s\n') %
134 (hname, exc.args[0] % exc.args[1:]))
137 (hname, exc.args[0]))
135 138 else:
136 139 self.ui.warn(_('error: %s hook raised an exception: '
137 140 '%s\n') % (hname, exc))
@@ -641,7 +644,11 class localrepository(repo.repository):
641 644 if node:
642 645 fdict = dict.fromkeys(files)
643 646 for fn in self.manifest.read(self.changelog.read(node)[0]):
644 fdict.pop(fn, None)
647 for ffn in fdict:
648 # match if the file is the exact name or a directory
649 if ffn == fn or fn.startswith("%s/" % ffn):
650 del fdict[ffn]
651 break
645 652 if match(fn):
646 653 yield 'm', fn
647 654 for fn in fdict:
@@ -50,6 +50,9 class diffopts(object):
50 50 defaultopts = diffopts()
51 51
52 52 def unidiff(a, ad, b, bd, fn, r=None, opts=defaultopts):
53 def datetag(date):
54 return opts.git and '\n' or '\t%s\n' % date
55
53 56 if not a and not b: return ""
54 57 epoch = util.datestr((0, 0))
55 58
@@ -58,19 +61,19 def unidiff(a, ad, b, bd, fn, r=None, op
58 61 elif not a:
59 62 b = splitnewlines(b)
60 63 if a is None:
61 l1 = "--- %s\t%s\n" % ("/dev/null", epoch)
64 l1 = '--- /dev/null%s' % datetag(epoch)
62 65 else:
63 l1 = "--- %s\t%s\n" % ("a/" + fn, ad)
64 l2 = "+++ %s\t%s\n" % ("b/" + fn, bd)
66 l1 = "--- %s%s" % ("a/" + fn, datetag(ad))
67 l2 = "+++ %s%s" % ("b/" + fn, datetag(bd))
65 68 l3 = "@@ -0,0 +1,%d @@\n" % len(b)
66 69 l = [l1, l2, l3] + ["+" + e for e in b]
67 70 elif not b:
68 71 a = splitnewlines(a)
69 l1 = "--- %s\t%s\n" % ("a/" + fn, ad)
72 l1 = "--- %s%s" % ("a/" + fn, datetag(ad))
70 73 if b is None:
71 l2 = "+++ %s\t%s\n" % ("/dev/null", epoch)
74 l2 = '+++ /dev/null%s' % datetag(epoch)
72 75 else:
73 l2 = "+++ %s\t%s\n" % ("b/" + fn, bd)
76 l2 = "+++ %s%s" % ("b/" + fn, datetag(bd))
74 77 l3 = "@@ -1,%d +0,0 @@\n" % len(a)
75 78 l = [l1, l2, l3] + ["-" + e for e in a]
76 79 else:
@@ -79,8 +82,8 def unidiff(a, ad, b, bd, fn, r=None, op
79 82 l = list(bunidiff(a, b, al, bl, "a/" + fn, "b/" + fn, opts=opts))
80 83 if not l: return ""
81 84 # difflib uses a space, rather than a tab
82 l[0] = "%s\t%s\n" % (l[0][:-2], ad)
83 l[1] = "%s\t%s\n" % (l[1][:-2], bd)
85 l[0] = "%s%s" % (l[0][:-2], datetag(ad))
86 l[1] = "%s%s" % (l[1][:-2], datetag(bd))
84 87
85 88 for ln in xrange(len(l)):
86 89 if l[ln][-1] != '\n':
@@ -8,7 +8,7
8 8 from node import *
9 9 from i18n import gettext as _
10 10 from demandload import *
11 demandload(globals(), "util os tempfile")
11 demandload(globals(), "errno util os tempfile")
12 12
13 13 def fmerge(f, local, other, ancestor):
14 14 """merge executable flags"""
@@ -88,12 +88,9 def update(repo, node, branchmerge=False
88 88 if modified or added or removed:
89 89 raise util.Abort(_("outstanding uncommitted changes"))
90 90
91 m1n = repo.changelog.read(p1)[0]
92 m2n = repo.changelog.read(p2)[0]
93 man = repo.manifest.ancestor(m1n, m2n)
94 m1 = repo.manifest.read(m1n).copy()
95 m2 = repo.manifest.read(m2n).copy()
96 ma = repo.manifest.read(man)
91 m1 = repo.changectx(p1).manifest().copy()
92 m2 = repo.changectx(p2).manifest().copy()
93 ma = repo.changectx(pa).manifest()
97 94
98 95 if not force:
99 96 for f in unknown:
@@ -108,7 +105,7 def update(repo, node, branchmerge=False
108 105 repo.ui.debug(_(" overwrite %s branchmerge %s partial %s linear %s\n") %
109 106 (overwrite, branchmerge, bool(partial), linear_path))
110 107 repo.ui.debug(_(" ancestor %s local %s remote %s\n") %
111 (short(man), short(m1n), short(m2n)))
108 (short(p1), short(p2), short(pa)))
112 109
113 110 action = {}
114 111 forget = []
@@ -116,8 +113,9 def update(repo, node, branchmerge=False
116 113 # update m1 from working dir
117 114 umap = dict.fromkeys(unknown)
118 115
119 for f in added + modified + unknown:
120 m1[f] = m1.get(f, nullid) + "+"
116 for i,l in (("a", added), ("m", modified), ("u", unknown)):
117 for f in l:
118 m1[f] = m1.get(f, nullid) + i
121 119 m1.set(f, util.is_exec(repo.wjoin(f), m1.execf(f)))
122 120
123 121 for f in deleted + removed:
@@ -157,7 +155,7 def update(repo, node, branchmerge=False
157 155 repo.ui.debug(_(" remote %s is newer, get\n") % f)
158 156 action[f] = (m2.execf(f), m2[f], None)
159 157 queued = 1
160 elif f in umap or f in added:
158 elif n[20:] in ("u","a"):
161 159 # this unknown file is the same as the checkout
162 160 # we need to reset the dirstate if the file was added
163 161 action[f] = (m2.execf(f), m2[f], None)
@@ -168,7 +166,8 def update(repo, node, branchmerge=False
168 166 repo.ui.debug(_(" updating permissions for %s\n") % f)
169 167 util.set_exec(repo.wjoin(f), m2.execf(f))
170 168 else:
171 if fmerge(f, m1, m2, ma) != m1.execf(f):
169 mode = fmerge(f, m1, m2, ma)
170 if mode != m1.execf(f):
172 171 repo.ui.debug(_(" updating permissions for %s\n")
173 172 % f)
174 173 util.set_exec(repo.wjoin(f), mode)
@@ -187,7 +186,7 def update(repo, node, branchmerge=False
187 186 action[f] = (None, None, None)
188 187 else:
189 188 # file is created on branch or in working directory
190 if overwrite and f not in umap:
189 if overwrite and n[20:] != "u":
191 190 repo.ui.debug(_("remote deleted %s, clobbering\n") % f)
192 191 action[f] = (None, None, None)
193 192 elif not n[20:]: # same as parent
@@ -236,8 +235,7 def update(repo, node, branchmerge=False
236 235 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xxp2)
237 236
238 237 # update files
239 unresolved = []
240 updated, merged, removed = 0, 0, 0
238 updated, merged, removed, unresolved = 0, 0, 0, 0
241 239 files = action.keys()
242 240 files.sort()
243 241 for f in files:
@@ -257,7 +255,7 def update(repo, node, branchmerge=False
257 255 elif other:
258 256 repo.ui.status(_("merging %s\n") % f)
259 257 if merge3(repo, f, my, other, xp1, xp2):
260 unresolved.append(f)
258 unresolved += 1
261 259 util.set_exec(repo.wjoin(f), flag)
262 260 merged += 1
263 261 else:
@@ -302,9 +300,9 def update(repo, node, branchmerge=False
302 300
303 301 if show_stats:
304 302 stats = ((updated, _("updated")),
305 (merged - len(unresolved), _("merged")),
303 (merged - unresolved, _("merged")),
306 304 (removed, _("removed")),
307 (len(unresolved), _("unresolved")))
305 (unresolved, _("unresolved")))
308 306 note = ", ".join([_("%d files %s") % s for s in stats])
309 307 repo.ui.status("%s\n" % note)
310 308 if not partial:
@@ -322,6 +320,6 def update(repo, node, branchmerge=False
322 320 repo.ui.status(_("There are unresolved merges with"
323 321 " locally modified files.\n"))
324 322
325 repo.hook('update', parent1=xp1, parent2=xxp2, error=len(unresolved))
326 return len(unresolved)
323 repo.hook('update', parent1=xp1, parent2=xxp2, error=unresolved)
324 return unresolved
327 325
@@ -9,7 +9,8 from demandload import demandload
9 9 from i18n import gettext as _
10 10 from node import *
11 11 demandload(globals(), "cmdutil mdiff util")
12 demandload(globals(), "cStringIO email.Parser errno os re shutil sys tempfile")
12 demandload(globals(), '''cStringIO email.Parser errno os re shutil sys tempfile
13 popen2''')
13 14
14 15 # helper functions
15 16
@@ -182,7 +183,7 def readgitpatch(patchname):
182 183
183 184 return (dopatch, gitpatches)
184 185
185 def dogitpatch(patchname, gitpatches):
186 def dogitpatch(patchname, gitpatches, cwd=None):
186 187 """Preprocess git patch so that vanilla patch can handle it"""
187 188 pf = file(patchname)
188 189 pfline = 1
@@ -196,7 +197,7 def dogitpatch(patchname, gitpatches):
196 197 if not p.copymod:
197 198 continue
198 199
199 copyfile(p.oldpath, p.path)
200 copyfile(p.oldpath, p.path, basedir=cwd)
200 201
201 202 # rewrite patch hunk
202 203 while pfline < p.lineno:
@@ -227,23 +228,20 def patch(patchname, ui, strip=1, cwd=No
227 228 """apply the patch <patchname> to the working directory.
228 229 a list of patched files is returned"""
229 230
230 (dopatch, gitpatches) = readgitpatch(patchname)
231
231 # helper function
232 def __patch(patchname):
233 """patch and updates the files and fuzz variables"""
232 234 files = {}
233 235 fuzz = False
234 if dopatch:
235 if dopatch == 'filter':
236 patchname = dogitpatch(patchname, gitpatches)
237 patcher = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch')
236
237 patcher = util.find_in_path('gpatch', os.environ.get('PATH', ''),
238 'patch')
238 239 args = []
239 240 if cwd:
240 241 args.append('-d %s' % util.shellquote(cwd))
241 242 fp = os.popen('%s %s -p%d < %s' % (patcher, ' '.join(args), strip,
242 243 util.shellquote(patchname)))
243 244
244 if dopatch == 'filter':
245 False and os.unlink(patchname)
246
247 245 for line in fp:
248 246 line = line.rstrip()
249 247 ui.note(line + '\n')
@@ -264,11 +262,24 def patch(patchname, ui, strip=1, cwd=No
264 262 ui.warn(pf + '\n')
265 263 printed_file = True
266 264 ui.warn(line + '\n')
267
268 265 code = fp.close()
269 266 if code:
270 267 raise util.Abort(_("patch command failed: %s") %
271 268 util.explain_exit(code)[0])
269 return files, fuzz
270
271 (dopatch, gitpatches) = readgitpatch(patchname)
272
273 if dopatch:
274 if dopatch == 'filter':
275 patchname = dogitpatch(patchname, gitpatches, cwd=cwd)
276 try:
277 files, fuzz = __patch(patchname)
278 finally:
279 if dopatch == 'filter':
280 os.unlink(patchname)
281 else:
282 files, fuzz = {}, False
272 283
273 284 for gp in gitpatches:
274 285 files[gp.path] = (gp.op, gp)
@@ -492,6 +503,9 def diff(repo, node1=None, node2=None, f
492 503 header.append('deleted file mode %s\n' % mode)
493 504 else:
494 505 omode = gitmode(mmap.execf(f))
506 if node2:
507 nmode = gitmode(mmap2.execf(f))
508 else:
495 509 nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f)))
496 510 addmodehdr(header, omode, nmode)
497 511 r = None
@@ -537,3 +551,24 def export(repo, revs, template='hg-%h.p
537 551
538 552 for seqno, cset in enumerate(revs):
539 553 single(cset, seqno, fp)
554
555 def diffstat(patchlines):
556 fd, name = tempfile.mkstemp(prefix="hg-patchbomb-", suffix=".txt")
557 try:
558 p = popen2.Popen3('diffstat -p1 -w79 2>/dev/null > ' + name)
559 try:
560 for line in patchlines: print >> p.tochild, line
561 p.tochild.close()
562 if p.wait(): return
563 fp = os.fdopen(fd, 'r')
564 stat = []
565 for line in fp: stat.append(line.lstrip())
566 last = stat.pop()
567 stat.insert(0, last)
568 stat = ''.join(stat)
569 if stat.startswith('0 files'): raise ValueError
570 return stat
571 except: raise
572 finally:
573 try: os.unlink(name)
574 except: pass
@@ -139,6 +139,11 class lazyparser(object):
139 139 if self.all: return
140 140 if data is None:
141 141 self.dataf.seek(blockstart)
142 if blockstart + blocksize > self.datasize:
143 # the revlog may have grown since we've started running,
144 # but we don't have space in self.index for more entries.
145 # limit blocksize so that we don't get too much data.
146 blocksize = max(self.datasize - blockstart, 0)
142 147 data = self.dataf.read(blocksize)
143 148 lend = len(data) / self.s
144 149 i = blockstart / self.s
@@ -32,12 +32,6 class sshrepository(remoterepository):
32 32 remotecmd = self.ui.config("ui", "remotecmd", "hg")
33 33
34 34 if create:
35 try:
36 self.validate_repo(ui, sshcmd, args, remotecmd)
37 return # the repo is good, nothing more to do
38 except hg.RepoError:
39 pass
40
41 35 cmd = '%s %s "%s init %s"'
42 36 cmd = cmd % (sshcmd, args, remotecmd, self.path)
43 37
@@ -52,6 +46,9 class sshrepository(remoterepository):
52 46 return self._url
53 47
54 48 def validate_repo(self, ui, sshcmd, args, remotecmd):
49 # cleanup up previous run
50 self.cleanup()
51
55 52 cmd = '%s %s "%s -R %s serve --stdio"'
56 53 cmd = cmd % (sshcmd, args, remotecmd, self.path)
57 54
@@ -90,7 +87,7 class sshrepository(remoterepository):
90 87 if not l: break
91 88 self.ui.status(_("remote: "), l)
92 89
93 def __del__(self):
90 def cleanup(self):
94 91 try:
95 92 self.pipeo.close()
96 93 self.pipei.close()
@@ -101,6 +98,8 class sshrepository(remoterepository):
101 98 except:
102 99 pass
103 100
101 __del__ = cleanup
102
104 103 def do_cmd(self, cmd, **args):
105 104 self.ui.debug(_("sending %s command\n") % cmd)
106 105 self.pipeo.write("%s\n" % cmd)
@@ -12,13 +12,12 demandload(globals(), "ConfigParser mdif
12 12
13 13 class ui(object):
14 14 def __init__(self, verbose=False, debug=False, quiet=False,
15 interactive=True, traceback=False, parentui=None,
16 readhooks=[]):
15 interactive=True, traceback=False, parentui=None):
17 16 self.overlay = {}
18 17 if parentui is None:
19 18 # this is the parent of all ui children
20 19 self.parentui = None
21 self.readhooks = list(readhooks)
20 self.readhooks = []
22 21 self.cdata = ConfigParser.SafeConfigParser()
23 22 self.readconfig(util.rcpath())
24 23
@@ -36,7 +35,7 class ui(object):
36 35 else:
37 36 # parentui may point to an ui object which is already a child
38 37 self.parentui = parentui.parentui or parentui
39 self.readhooks = list(parentui.readhooks or readhooks)
38 self.readhooks = parentui.readhooks[:]
40 39 parent_cdata = self.parentui.cdata
41 40 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
42 41 # make interpolation work
@@ -51,7 +50,7 class ui(object):
51 50 def updateopts(self, verbose=False, debug=False, quiet=False,
52 51 interactive=True, traceback=False, config=[]):
53 52 self.quiet = (self.quiet or quiet) and not verbose and not debug
54 self.verbose = (self.verbose or verbose) or debug
53 self.verbose = ((self.verbose or verbose) or debug) and not self.quiet
55 54 self.debugflag = (self.debugflag or debug)
56 55 self.interactive = (self.interactive and interactive)
57 56 self.traceback = self.traceback or traceback
@@ -84,6 +83,9 class ui(object):
84 83 for hook in self.readhooks:
85 84 hook(self)
86 85
86 def addreadhook(self, hook):
87 self.readhooks.append(hook)
88
87 89 def setconfig(self, section, name, val):
88 90 self.overlay[(section, name)] = val
89 91
@@ -94,7 +96,9 class ui(object):
94 96 try:
95 97 return self.cdata.get(section, name)
96 98 except ConfigParser.InterpolationError, inst:
97 raise util.Abort(_("Error in configuration:\n%s") % inst)
99 raise util.Abort(_("Error in configuration section [%s] "
100 "parameter '%s':\n%s")
101 % (section, name, inst))
98 102 if self.parentui is None:
99 103 return default
100 104 else:
@@ -116,7 +120,9 class ui(object):
116 120 try:
117 121 return self.cdata.getboolean(section, name)
118 122 except ConfigParser.InterpolationError, inst:
119 raise util.Abort(_("Error in configuration:\n%s") % inst)
123 raise util.Abort(_("Error in configuration section [%s] "
124 "parameter '%s':\n%s")
125 % (section, name, inst))
120 126 if self.parentui is None:
121 127 return default
122 128 else:
@@ -134,7 +140,8 class ui(object):
134 140 try:
135 141 items.update(dict(self.cdata.items(section)))
136 142 except ConfigParser.InterpolationError, inst:
137 raise util.Abort(_("Error in configuration:\n%s") % inst)
143 raise util.Abort(_("Error in configuration section [%s]:\n%s")
144 % (section, inst))
138 145 x = items.items()
139 146 x.sort()
140 147 return x
@@ -146,10 +153,14 class ui(object):
146 153 yield section, name, value
147 154 seen[section, name] = 1
148 155 for section in self.cdata.sections():
156 try:
149 157 for name, value in self.cdata.items(section):
150 158 if (section, name) in seen: continue
151 159 yield section, name, value.replace('\n', '\\n')
152 160 seen[section, name] = 1
161 except ConfigParser.InterpolationError, inst:
162 raise util.Abort(_("Error in configuration section [%s]:\n%s")
163 % (section, inst))
153 164 if self.parentui is not None:
154 165 for parent in self.parentui.walkconfig(seen):
155 166 yield parent
@@ -8,7 +8,7 error = error-gitweb.tmpl
8 8 naventry = '<a href="?cmd=changelog;rev=#rev#;style=gitweb">#label|escape#</a> '
9 9 navshortentry = '<a href="?cmd=shortlog;rev=#rev#;style=gitweb">#label|escape#</a> '
10 10 filedifflink = '<a href="?cmd=filediff;node=#node#;file=#file|urlescape#;style=gitweb">#file|escape#</a> '
11 filenodelink = '<tr class="light"><td><a class="list" href="">#file|escape#</a></td><td></td><td class="link"><a href="?cmd=file;filenode=#filenode#;file=#file|urlescape#;style=gitweb">file</a> | <!-- FIXME: <a href="?fd=#filenode|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?cmd=filelog;filenode=#filenode|short#;file=#file|urlescape#;style=gitweb">revisions</a></td></tr>'
11 filenodelink = '<tr class="light"><td><a class="list" href="">#file|escape#</a></td><td></td><td class="link"><a href="?cmd=file;filenode=#filenode#;file=#file|urlescape#;style=gitweb">file</a> | <a href="?fa=#filenode|short#;file=#file|urlescape#;style=gitweb">annotate</a> | <!-- FIXME: <a href="?fd=#filenode|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?cmd=filelog;filenode=#filenode|short#;file=#file|urlescape#;style=gitweb">revisions</a></td></tr>'
12 12 fileellipses = '...'
13 13 changelogentry = changelogentry-gitweb.tmpl
14 14 searchentry = changelogentry-gitweb.tmpl
@@ -19,12 +19,12 manifestfileentry = '<tr class="parity#p
19 19 filerevision = filerevision-gitweb.tmpl
20 20 fileannotate = fileannotate-gitweb.tmpl
21 21 filelog = filelog-gitweb.tmpl
22 fileline = '<div style="font-family:monospace; white-space: pre;" class="parity#parity#"><span class="linenr"> #linenumber#</span> #line|escape#</div>'
23 annotateline = '<tr style="font-family:monospace; white-space: pre;" class="parity#parity#"><td class="linenr" style="text-align: right;"><a href="?cs=#node|short#;style=gitweb">#author|obfuscate#@#rev#</a></td><td>#line|escape#</td></tr>'
24 difflineplus = '<div class="pre" style="color:#008800;">#line|escape#</div>'
25 difflineminus = '<div class="pre" style="color:#cc0000;">#line|escape#</div>'
26 difflineat = '<div class="pre" style="color:#990099;">#line|escape#</div>'
27 diffline = '<div class="pre">#line|escape#</div>'
22 fileline = '<div style="font-family:monospace" class="parity#parity#"><pre><span class="linenr"> #linenumber#</span> #line|escape#</pre></div>'
23 annotateline = '<tr style="font-family:monospace" class="parity#parity#"><td class="linenr" style="text-align: right;"><a href="?cs=#node|short#;style=gitweb">#author|obfuscate#@#rev#</a></td><td><pre>#line|escape#</pre></td></tr>'
24 difflineplus = '<div style="color:#008800;">#line|escape#</div>'
25 difflineminus = '<div style="color:#cc0000;">#line|escape#</div>'
26 difflineat = '<div style="color:#990099;">#line|escape#</div>'
27 diffline = '<div>#line|escape#</div>'
28 28 changelogparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
29 29 changesetparent = '<tr><td>parent</td><td style="font-family:monospace"><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb">#node|short#</a></td></tr>'
30 30 filerevparent = '<tr><td class="metatag">parent:</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
@@ -37,7 +37,7 filerevchild = '<tr><td class="metatag">
37 37 fileannotatechild = '<tr><td class="metatag">child:</td><td><a href="?cmd=annotate;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
38 38 tags = tags-gitweb.tmpl
39 39 tagentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#tag|escape#</b></a></td><td class="link"><a href="?cmd=changeset;node=#node|short#;style=gitweb">changeset</a> | <a href="?cmd=changelog;rev=#node|short#;style=gitweb">changelog</a> | <a href="?mf=#tagmanifest|short#;path=/;style=gitweb">manifest</a></td></tr>'
40 diffblock = '#lines#'
40 diffblock = '<pre>#lines#</pre>'
41 41 changelogtag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
42 42 changesettag = '<tr><td>tag</td><td>#tag|escape#</td></tr>'
43 43 filediffparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
@@ -46,5 +46,5 filediffchild = '<tr><th class="child">c
46 46 filelogchild = '<tr><td align="right">child #rev#:&nbsp;</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
47 47 shortlog = shortlog-gitweb.tmpl
48 48 shortlogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><i>#author#</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><a href="?cmd=changeset;node=#node|short#;style=gitweb">changeset</a> | <a href="?cmd=manifest;manifest=#manifest|short#;path=/;style=gitweb">manifest</a></td></tr>'
49 filelogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><!-- FIXME: <a href="?fd=#node|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?fa=#filenode|short#;file=#file|urlescape#;style=gitweb">annotate</a> #rename%filelogrename#</td></tr>'
49 filelogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">file</a> | <!-- FIXME: <a href="?fd=#node|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?fa=#filenode|short#;file=#file|urlescape#;style=gitweb">annotate</a> #rename%filelogrename#</td></tr>'
50 50 archiveentry = ' | <a href="?ca=#node|short#;type=#type|urlescape#">#type|escape#</a> '
@@ -47,3 +47,4 a.rss_logo {
47 47 text-align:center; text-decoration:none;
48 48 }
49 49 a.rss_logo:hover { background-color:#ee5500; }
50 pre { margin: 0; }
@@ -59,9 +59,9 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:4
59 59 line 1
60 60
61 61 # error if style not readable
62 abort: Permission denied - ./q
62 abort: Permission denied: ./q
63 63 # error if no style
64 abort: No such file or directory - notexist
64 abort: No such file or directory: notexist
65 65 # error if style missing key
66 66 abort: ./t: no key named 'changeset'
67 67 # error if include fails
@@ -17,7 +17,7 foo-b
17 17 A b
18 18 R a
19 19 %%% revert should fail
20 abort: working dir has two parents; you must specify the revision to revert to
20 abort: uncommitted merge - please provide a specific revision
21 21 %%% revert should be ok now
22 22 undeleting a
23 23 forgetting b
@@ -50,3 +50,7 hg ci -mrenamemod -d '0 0'
50 50 echo '% rename+mod+chmod'
51 51 hg diff --git -r 6:tip | sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \
52 52 -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/"
53
54 echo '% nonexistent in tip+chmod'
55 hg diff --git -r 5:6 | sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \
56 -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/"
@@ -40,3 +40,7 rename to dst
40 40 4
41 41 5
42 42 +a
43 % nonexistent in tip+chmod
44 diff --git a/src b/src
45 old mode 100644
46 new mode 100755
@@ -11,7 +11,7 cat hg1.pid hg2.pid >> $DAEMON_PIDS
11 11
12 12 echo % clone via stream
13 13 http_proxy= hg clone --uncompressed http://localhost:20059/ copy 2>&1 | \
14 sed -e 's/[0-9][0-9.]*/XXX/g' -e 's/.\(B\/sec\)/X\1/'
14 sed -e 's/[0-9][0-9.]*/XXX/g' -e 's/[KM]\(B\/sec\)/X\1/'
15 15 hg verify -R copy
16 16
17 17 echo % try to clone via stream, should use pull instead
@@ -15,7 +15,7 sleep 2
15 15
16 16 echo %% url for proxy, stream
17 17 http_proxy=http://localhost:20060/ hg --config http_proxy.always=True clone --uncompressed http://localhost:20059/ b | \
18 sed -e 's/[0-9][0-9.]*/XXX/g'
18 sed -e 's/[0-9][0-9.]*/XXX/g' -e 's/[KM]\(B\/sec\)/X\1/'
19 19 cd b
20 20 hg verify
21 21 cd ..
@@ -2,7 +2,7 adding a
2 2 %% url for proxy, stream
3 3 streaming all changes
4 4 XXX files to transfer, XXX bytes of data
5 transferred XXX bytes in XXX seconds (XXX KB/sec)
5 transferred XXX bytes in XXX seconds (XXX XB/sec)
6 6 XXX files updated, XXX files merged, XXX files removed, XXX files unresolved
7 7 checking changesets
8 8 checking manifests
@@ -27,6 +27,9 hg init local
27 27 echo this > local/foo
28 28 hg ci --cwd local -A -m "init" -d "1000000 0"
29 29
30 echo "#test failure"
31 hg init local
32
30 33 echo "# init+push to remote2"
31 34 hg init -e ./dummyssh ssh://user@dummy/remote2
32 35 hg incoming -R remote2 local
@@ -35,6 +38,12 hg push -R local -e ./dummyssh ssh://use
35 38 echo "# clone to remote1"
36 39 hg clone -e ./dummyssh local ssh://user@dummy/remote1
37 40
41 echo "# init to existing repo"
42 hg init -e ./dummyssh ssh://user@dummy/remote1
43
44 echo "# clone to existing repo"
45 hg clone -e ./dummyssh local ssh://user@dummy/remote1
46
38 47 echo "# output of dummyssh"
39 48 cat dummylog
40 49
@@ -1,5 +1,7
1 1 # creating 'local'
2 2 adding foo
3 #test failure
4 abort: repository local already exists!
3 5 # init+push to remote2
4 6 changeset: 0:c4e059d443be
5 7 tag: tip
@@ -15,20 +17,24 remote: adding file changes
15 17 remote: added 1 changesets with 1 changes to 1 files
16 18 # clone to remote1
17 19 searching for changes
18 remote: abort: repository remote1 not found!
19 20 remote: adding changesets
20 21 remote: adding manifests
21 22 remote: adding file changes
22 23 remote: added 1 changesets with 1 changes to 1 files
24 # init to existing repo
25 abort: repository remote1 already exists!
26 abort: could not create remote repo!
27 # clone to existing repo
28 abort: repository remote1 already exists!
29 abort: could not create remote repo!
23 30 # output of dummyssh
24 Got arguments 1:user@dummy 2:hg -R remote2 serve --stdio 3: 4: 5:
25 31 Got arguments 1:user@dummy 2:hg init remote2 3: 4: 5:
26 32 Got arguments 1:user@dummy 2:hg -R remote2 serve --stdio 3: 4: 5:
27 33 Got arguments 1:user@dummy 2:hg -R remote2 serve --stdio 3: 4: 5:
28 Got arguments 1:user@dummy 2:hg -R remote1 serve --stdio 3: 4: 5:
34 Got arguments 1:user@dummy 2:hg init remote1 3: 4: 5:
29 35 Got arguments 1:user@dummy 2:hg -R remote1 serve --stdio 3: 4: 5:
30 36 Got arguments 1:user@dummy 2:hg init remote1 3: 4: 5:
31 Got arguments 1:user@dummy 2:hg -R remote1 serve --stdio 3: 4: 5:
37 Got arguments 1:user@dummy 2:hg init remote1 3: 4: 5:
32 38 # comparing repositories
33 39 0:c4e059d443be
34 40 0:c4e059d443be
@@ -23,7 +23,7 added 1 changesets with 1 changes to 1 f
23 23 merge: warning: conflicts during merge
24 24 resolving manifests
25 25 overwrite None branchmerge True partial False linear False
26 ancestor 055d847dd401 local 2eded9ab0a5c remote 84cf5750dd20
26 ancestor 451c744aabcc local a070d41e8360 remote faaea63e63a9
27 27 test.txt versions differ, resolve
28 28 merging test.txt
29 29 resolving test.txt
@@ -115,6 +115,19 hg push ../../k
115 115 echo % qunapplied
116 116 hg qunapplied
117 117
118 echo % qpush/qpop with index
119 hg qnew test1b.patch
120 echo 1b > 1b
121 hg add 1b
122 hg qrefresh
123 hg qpush 2
124 hg qpop 0
125 hg qpush test.patch+1
126 hg qpush test.patch+2
127 hg qpop test2.patch-1
128 hg qpop test2.patch-2
129 hg qpush test1b.patch+1
130
118 131 echo % push should succeed
119 132 hg qpop -a
120 133 hg push ../../k
@@ -126,6 +139,27 hg ci -Ama
126 139 hg strip tip 2>&1 | sed 's/\(saving bundle to \).*/\1/'
127 140 hg unbundle .hg/strip-backup/*
128 141
142 echo '% cd b; hg qrefresh'
143 hg init refresh
144 cd refresh
145 echo a > a
146 hg ci -Ama -d'0 0'
147 hg qnew -mfoo foo
148 echo a >> a
149 hg qrefresh
150 mkdir b
151 cd b
152 echo f > f
153 hg add f
154 hg qrefresh
155 sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \
156 -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/" ../.hg/patches/foo
157 echo % hg qrefresh .
158 hg qrefresh .
159 sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \
160 -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/" ../.hg/patches/foo
161 hg status
162
129 163 cat >>$HGRCPATH <<EOF
130 164 [diff]
131 165 git = True
@@ -110,6 +110,19 pushing to ../../k
110 110 abort: source has mq patches applied
111 111 % qunapplied
112 112 test2.patch
113 % qpush/qpop with index
114 applying test2.patch
115 Now at: test2.patch
116 Now at: test.patch
117 applying test1b.patch
118 Now at: test1b.patch
119 applying test2.patch
120 Now at: test2.patch
121 Now at: test1b.patch
122 Now at: test.patch
123 applying test1b.patch
124 applying test2.patch
125 Now at: test2.patch
113 126 % push should succeed
114 127 Patch queue now empty
115 128 pushing to ../../k
@@ -127,6 +140,30 adding manifests
127 140 adding file changes
128 141 added 1 changesets with 1 changes to 1 files
129 142 (run 'hg update' to get a working copy)
143 % cd b; hg qrefresh
144 adding a
145 foo
146
147 diff -r cb9a9f314b8b a
148 --- a/a
149 +++ b/a
150 @@ -1,1 +1,2 @@ a
151 a
152 +a
153 diff -r cb9a9f314b8b b/f
154 --- /dev/null
155 +++ b/b/f
156 @@ -0,0 +1,1 @@
157 +f
158 % hg qrefresh .
159 foo
160
161 diff -r cb9a9f314b8b b/f
162 --- /dev/null
163 +++ b/b/f
164 @@ -0,0 +1,1 @@
165 +f
166 M a
130 167 new file
131 168
132 169 diff --git a/new b/new
@@ -85,4 +85,8 hg revert -rtip
85 85 echo % should succeed
86 86 hg revert --all -rtip
87 87
88 echo %% issue332
89 hg ci -A -m b -d '1000001 0'
90 echo foobar > b/b
91 hg revert b
88 92 true
@@ -55,6 +55,9 executable
55 55 adding a
56 56 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
57 57 % should fail - no arguments
58 abort: no files or directories specified
58 abort: no files or directories specified; use --all to revert the whole repo
59 59 % should succeed
60 60 reverting a
61 %% issue332
62 adding b/b
63 reverting b/b
@@ -1,3 +1,3
1 1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 2 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 abort: Permission denied - test-ro-message/b/vehicle
3 abort: Permission denied: test-ro-message/b/vehicle
@@ -38,7 +38,7 cd ..
38 38
39 39 echo "# clone remote via stream"
40 40 hg clone -e ./dummyssh --uncompressed ssh://user@dummy/remote local-stream 2>&1 | \
41 sed -e 's/[0-9][0-9.]*/XXX/g'
41 sed -e 's/[0-9][0-9.]*/XXX/g' -e 's/[KM]\(B\/sec\)/X\1/'
42 42 cd local-stream
43 43 hg verify
44 44 cd ..
@@ -80,7 +80,7 cd ../remote
80 80 echo "# check remote tip"
81 81 hg tip
82 82 hg verify
83 hg cat foo
83 hg cat -r tip foo
84 84
85 85 echo z > z
86 86 hg ci -A -m z -d '1000001 0' z
@@ -2,7 +2,7
2 2 # clone remote via stream
3 3 streaming all changes
4 4 XXX files to transfer, XXX bytes of data
5 transferred XXX bytes in XXX seconds (XXX KB/sec)
5 transferred XXX bytes in XXX seconds (XXX XB/sec)
6 6 XXX files updated, XXX files merged, XXX files removed, XXX files unresolved
7 7 checking changesets
8 8 checking manifests
@@ -1,6 +1,6
1 1 #!/usr/bin/env python
2 2
3 from mercurial import ui
3 from mercurial import ui, util
4 4
5 5 testui = ui.ui()
6 6 testui.updateopts(config=[
@@ -11,10 +11,19 testui.updateopts(config=[
11 11 'lists.list2=foo bar baz',
12 12 'lists.list3=alice, bob',
13 13 'lists.list4=foo bar baz alice, bob',
14 'interpolation.value1=hallo',
15 'interpolation.value2=%(value1)s world',
16 'interpolation.value3=%(novalue)s',
17 'interpolation.value4=%(bad)1',
18 'interpolation.value5=%bad2',
14 19 ])
15 20
16 21 print repr(testui.configitems('values'))
17 22 print repr(testui.configitems('lists'))
23 try:
24 print repr(testui.configitems('interpolation'))
25 except util.Abort, inst:
26 print inst
18 27 print "---"
19 28 print repr(testui.config('values', 'string'))
20 29 print repr(testui.config('values', 'bool1'))
@@ -45,3 +54,18 print repr(testui.configlist('lists', 'u
45 54 print repr(testui.configlist('lists', 'unknown', ['foo bar']))
46 55 print repr(testui.configlist('lists', 'unknown', ['foo', 'bar']))
47 56 print "---"
57 print repr(testui.config('interpolation', 'value1'))
58 print repr(testui.config('interpolation', 'value2'))
59 try:
60 print repr(testui.config('interpolation', 'value3'))
61 except util.Abort, inst:
62 print inst
63 try:
64 print repr(testui.config('interpolation', 'value4'))
65 except util.Abort, inst:
66 print inst
67 try:
68 print repr(testui.config('interpolation', 'value5'))
69 except util.Abort, inst:
70 print inst
71 print "---"
@@ -1,5 +1,7
1 1 [('bool1', 'true'), ('bool2', 'false'), ('string', 'string value')]
2 2 [('list1', 'foo'), ('list2', 'foo bar baz'), ('list3', 'alice, bob'), ('list4', 'foo bar baz alice, bob')]
3 Error in configuration section [interpolation]:
4 '%' must be followed by '%' or '(', found: '%bad2'
3 5 ---
4 6 'string value'
5 7 'true'
@@ -27,3 +29,17 True
27 29 ['foo bar']
28 30 ['foo', 'bar']
29 31 ---
32 'hallo'
33 'hallo world'
34 Error in configuration section [interpolation] parameter 'value3':
35 Bad value substitution:
36 section: [interpolation]
37 option : value3
38 key : novalue
39 rawval :
40
41 Error in configuration section [interpolation] parameter 'value4':
42 bad interpolation variable reference '%(bad)1'
43 Error in configuration section [interpolation] parameter 'value5':
44 '%' must be followed by '%' or '(', found: '%bad2'
45 ---
@@ -16,7 +16,7 summary: 1
16 16
17 17 resolving manifests
18 18 overwrite False branchmerge False partial False linear True
19 ancestor a0c8bcbbb45c local a0c8bcbbb45c remote 1165e8bd193e
19 ancestor 33aaa84a386b local 802f095af299 remote 33aaa84a386b
20 20 a versions differ, resolve
21 21 remote created b
22 22 merging a
@@ -32,7 +32,7 summary: 2
32 32
33 33 resolving manifests
34 34 overwrite False branchmerge False partial False linear True
35 ancestor a0c8bcbbb45c local 1165e8bd193e remote a0c8bcbbb45c
35 ancestor 802f095af299 local 33aaa84a386b remote 33aaa84a386b
36 36 remote deleted b
37 37 removing b
38 38 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
@@ -50,7 +50,7 summary: 1
50 50
51 51 resolving manifests
52 52 overwrite False branchmerge False partial False linear True
53 ancestor a0c8bcbbb45c local a0c8bcbbb45c remote 1165e8bd193e
53 ancestor 33aaa84a386b local 802f095af299 remote 33aaa84a386b
54 54 a versions differ, resolve
55 55 remote created b
56 56 merging a
@@ -101,7 +101,7 abort: outstanding uncommitted changes
101 101 failed
102 102 resolving manifests
103 103 overwrite False branchmerge True partial False linear False
104 ancestor a0c8bcbbb45c local 1165e8bd193e remote 4096f2872392
104 ancestor 802f095af299 local 030602aee63d remote 33aaa84a386b
105 105 a versions differ, resolve
106 106 b versions differ, resolve
107 107 merging a
@@ -41,7 +41,7 side1
41 41 side2
42 42 resolving manifests
43 43 overwrite True branchmerge False partial False linear False
44 ancestor 8515d4bfda76 local 1c0f48f8ece6 remote 0594b9004bae
44 ancestor ded32b0db104 local 221226fb2bd8 remote 537353581d3d
45 45 remote deleted side2, clobbering
46 46 remote deleted side1, clobbering
47 47 remote created main
General Comments 0
You need to be logged in to leave comments. Login now