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