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