Show More
@@ -0,0 +1,108 b'' | |||
|
1 | #!/bin/sh | |
|
2 | ||
|
3 | echo "[extensions]" >> $HGRCPATH | |
|
4 | echo "mq=" >> $HGRCPATH | |
|
5 | echo "[diff]" >> $HGRCPATH | |
|
6 | echo "nodates=true" >> $HGRCPATH | |
|
7 | ||
|
8 | ||
|
9 | catlog() { | |
|
10 | cat .hg/patches/$1.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /" | |
|
11 | hg log --template "{rev}: {desc} - {author}\n" | |
|
12 | } | |
|
13 | ||
|
14 | ||
|
15 | echo ==== init | |
|
16 | hg init a | |
|
17 | cd a | |
|
18 | hg qinit | |
|
19 | ||
|
20 | ||
|
21 | echo ==== qnew -U | |
|
22 | hg qnew -U 1.patch | |
|
23 | catlog 1 | |
|
24 | ||
|
25 | echo ==== qref | |
|
26 | echo "1" >1 | |
|
27 | hg add | |
|
28 | hg qref | |
|
29 | catlog 1 | |
|
30 | ||
|
31 | echo ==== qref -u | |
|
32 | hg qref -u mary | |
|
33 | catlog 1 | |
|
34 | ||
|
35 | echo ==== qnew | |
|
36 | hg qnew 2.patch | |
|
37 | echo "2" >2 | |
|
38 | hg add | |
|
39 | hg qref | |
|
40 | catlog 2 | |
|
41 | ||
|
42 | echo ==== qref -u | |
|
43 | hg qref -u jane | |
|
44 | catlog 2 | |
|
45 | ||
|
46 | ||
|
47 | echo ==== qnew -U -m | |
|
48 | hg qnew -U -m "Three" 3.patch | |
|
49 | catlog 3 | |
|
50 | ||
|
51 | echo ==== qref | |
|
52 | echo "3" >3 | |
|
53 | hg add | |
|
54 | hg qref | |
|
55 | catlog 3 | |
|
56 | ||
|
57 | echo ==== qref -m | |
|
58 | hg qref -m "Drei" | |
|
59 | catlog 3 | |
|
60 | ||
|
61 | echo ==== qref -u | |
|
62 | hg qref -u mary | |
|
63 | catlog 3 | |
|
64 | ||
|
65 | echo ==== qref -u -m | |
|
66 | hg qref -u maria -m "Three (again)" | |
|
67 | catlog 3 | |
|
68 | ||
|
69 | echo ==== qnew -m | |
|
70 | hg qnew -m "Four" 4.patch | |
|
71 | echo "4" >4 | |
|
72 | hg add | |
|
73 | hg qref | |
|
74 | catlog 4 | |
|
75 | ||
|
76 | echo ==== qref -u | |
|
77 | hg qref -u jane | |
|
78 | catlog 4 | |
|
79 | ||
|
80 | ||
|
81 | echo ==== qnew with HG header | |
|
82 | hg qnew 5.patch | |
|
83 | hg qpop | |
|
84 | echo "# HG changeset patch" >>.hg/patches/5.patch | |
|
85 | echo "# User johndoe" >>.hg/patches/5.patch | |
|
86 | # Drop patch specific error line | |
|
87 | hg qpush 2>&1 | grep -v garbage | |
|
88 | catlog 5 | |
|
89 | ||
|
90 | echo ==== hg qref | |
|
91 | echo "5" >5 | |
|
92 | hg add | |
|
93 | hg qref | |
|
94 | catlog 5 | |
|
95 | ||
|
96 | echo ==== hg qref -U | |
|
97 | hg qref -U | |
|
98 | catlog 5 | |
|
99 | ||
|
100 | echo ==== hg qref -u | |
|
101 | hg qref -u johndeere | |
|
102 | catlog 5 | |
|
103 | ||
|
104 | ||
|
105 | echo ==== "qpop -a / qpush -a" | |
|
106 | hg qpop -a | |
|
107 | hg qpush -a | |
|
108 | hg log --template "{rev}: {desc} - {author}\n" |
@@ -0,0 +1,200 b'' | |||
|
1 | ==== init | |
|
2 | ==== qnew -U | |
|
3 | From: test | |
|
4 | ||
|
5 | 0: [mq]: 1.patch - test | |
|
6 | ==== qref | |
|
7 | adding 1 | |
|
8 | From: test | |
|
9 | ||
|
10 | diff -r ... 1 | |
|
11 | --- /dev/null | |
|
12 | +++ b/1 | |
|
13 | @@ -0,0 +1,1 @@ | |
|
14 | +1 | |
|
15 | 0: [mq]: 1.patch - test | |
|
16 | ==== qref -u | |
|
17 | From: mary | |
|
18 | ||
|
19 | diff -r ... 1 | |
|
20 | --- /dev/null | |
|
21 | +++ b/1 | |
|
22 | @@ -0,0 +1,1 @@ | |
|
23 | +1 | |
|
24 | 0: [mq]: 1.patch - mary | |
|
25 | ==== qnew | |
|
26 | adding 2 | |
|
27 | diff -r ... 2 | |
|
28 | --- /dev/null | |
|
29 | +++ b/2 | |
|
30 | @@ -0,0 +1,1 @@ | |
|
31 | +2 | |
|
32 | 1: [mq]: 2.patch - test | |
|
33 | 0: [mq]: 1.patch - mary | |
|
34 | ==== qref -u | |
|
35 | From: jane | |
|
36 | ||
|
37 | ||
|
38 | diff -r ... 2 | |
|
39 | --- /dev/null | |
|
40 | +++ b/2 | |
|
41 | @@ -0,0 +1,1 @@ | |
|
42 | +2 | |
|
43 | 1: [mq]: 2.patch - jane | |
|
44 | 0: [mq]: 1.patch - mary | |
|
45 | ==== qnew -U -m | |
|
46 | From: test | |
|
47 | ||
|
48 | Three | |
|
49 | 2: Three - test | |
|
50 | 1: [mq]: 2.patch - jane | |
|
51 | 0: [mq]: 1.patch - mary | |
|
52 | ==== qref | |
|
53 | adding 3 | |
|
54 | From: test | |
|
55 | ||
|
56 | Three | |
|
57 | ||
|
58 | diff -r ... 3 | |
|
59 | --- /dev/null | |
|
60 | +++ b/3 | |
|
61 | @@ -0,0 +1,1 @@ | |
|
62 | +3 | |
|
63 | 2: Three - test | |
|
64 | 1: [mq]: 2.patch - jane | |
|
65 | 0: [mq]: 1.patch - mary | |
|
66 | ==== qref -m | |
|
67 | From: test | |
|
68 | ||
|
69 | Drei | |
|
70 | ||
|
71 | diff -r ... 3 | |
|
72 | --- /dev/null | |
|
73 | +++ b/3 | |
|
74 | @@ -0,0 +1,1 @@ | |
|
75 | +3 | |
|
76 | 2: Drei - test | |
|
77 | 1: [mq]: 2.patch - jane | |
|
78 | 0: [mq]: 1.patch - mary | |
|
79 | ==== qref -u | |
|
80 | From: mary | |
|
81 | ||
|
82 | Drei | |
|
83 | ||
|
84 | diff -r ... 3 | |
|
85 | --- /dev/null | |
|
86 | +++ b/3 | |
|
87 | @@ -0,0 +1,1 @@ | |
|
88 | +3 | |
|
89 | 2: Drei - mary | |
|
90 | 1: [mq]: 2.patch - jane | |
|
91 | 0: [mq]: 1.patch - mary | |
|
92 | ==== qref -u -m | |
|
93 | From: maria | |
|
94 | ||
|
95 | Three (again) | |
|
96 | ||
|
97 | diff -r ... 3 | |
|
98 | --- /dev/null | |
|
99 | +++ b/3 | |
|
100 | @@ -0,0 +1,1 @@ | |
|
101 | +3 | |
|
102 | 2: Three (again) - maria | |
|
103 | 1: [mq]: 2.patch - jane | |
|
104 | 0: [mq]: 1.patch - mary | |
|
105 | ==== qnew -m | |
|
106 | adding 4 | |
|
107 | Four | |
|
108 | ||
|
109 | diff -r ... 4 | |
|
110 | --- /dev/null | |
|
111 | +++ b/4 | |
|
112 | @@ -0,0 +1,1 @@ | |
|
113 | +4 | |
|
114 | 3: Four - test | |
|
115 | 2: Three (again) - maria | |
|
116 | 1: [mq]: 2.patch - jane | |
|
117 | 0: [mq]: 1.patch - mary | |
|
118 | ==== qref -u | |
|
119 | From: jane | |
|
120 | ||
|
121 | Four | |
|
122 | ||
|
123 | diff -r ... 4 | |
|
124 | --- /dev/null | |
|
125 | +++ b/4 | |
|
126 | @@ -0,0 +1,1 @@ | |
|
127 | +4 | |
|
128 | 3: Four - jane | |
|
129 | 2: Three (again) - maria | |
|
130 | 1: [mq]: 2.patch - jane | |
|
131 | 0: [mq]: 1.patch - mary | |
|
132 | ==== qnew with HG header | |
|
133 | Now at: 4.patch | |
|
134 | applying 5.patch | |
|
135 | patch failed, unable to continue (try -v) | |
|
136 | patch 5.patch is empty | |
|
137 | Now at: 5.patch | |
|
138 | # HG changeset patch | |
|
139 | # User johndoe | |
|
140 | 4: imported patch 5.patch - johndoe | |
|
141 | 3: Four - jane | |
|
142 | 2: Three (again) - maria | |
|
143 | 1: [mq]: 2.patch - jane | |
|
144 | 0: [mq]: 1.patch - mary | |
|
145 | ==== hg qref | |
|
146 | adding 5 | |
|
147 | # HG changeset patch | |
|
148 | # User johndoe | |
|
149 | ||
|
150 | diff -r ... 5 | |
|
151 | --- /dev/null | |
|
152 | +++ b/5 | |
|
153 | @@ -0,0 +1,1 @@ | |
|
154 | +5 | |
|
155 | 4: [mq]: 5.patch - johndoe | |
|
156 | 3: Four - jane | |
|
157 | 2: Three (again) - maria | |
|
158 | 1: [mq]: 2.patch - jane | |
|
159 | 0: [mq]: 1.patch - mary | |
|
160 | ==== hg qref -U | |
|
161 | # HG changeset patch | |
|
162 | # User test | |
|
163 | ||
|
164 | diff -r ... 5 | |
|
165 | --- /dev/null | |
|
166 | +++ b/5 | |
|
167 | @@ -0,0 +1,1 @@ | |
|
168 | +5 | |
|
169 | 4: [mq]: 5.patch - test | |
|
170 | 3: Four - jane | |
|
171 | 2: Three (again) - maria | |
|
172 | 1: [mq]: 2.patch - jane | |
|
173 | 0: [mq]: 1.patch - mary | |
|
174 | ==== hg qref -u | |
|
175 | # HG changeset patch | |
|
176 | # User johndeere | |
|
177 | ||
|
178 | diff -r ... 5 | |
|
179 | --- /dev/null | |
|
180 | +++ b/5 | |
|
181 | @@ -0,0 +1,1 @@ | |
|
182 | +5 | |
|
183 | 4: [mq]: 5.patch - johndeere | |
|
184 | 3: Four - jane | |
|
185 | 2: Three (again) - maria | |
|
186 | 1: [mq]: 2.patch - jane | |
|
187 | 0: [mq]: 1.patch - mary | |
|
188 | ==== qpop -a / qpush -a | |
|
189 | Patch queue now empty | |
|
190 | applying 1.patch | |
|
191 | applying 2.patch | |
|
192 | applying 3.patch | |
|
193 | applying 4.patch | |
|
194 | applying 5.patch | |
|
195 | Now at: 5.patch | |
|
196 | 4: imported patch 5.patch - johndeere | |
|
197 | 3: Four - jane | |
|
198 | 2: Three (again) - maria | |
|
199 | 1: imported patch 2.patch - jane | |
|
200 | 0: imported patch 1.patch - mary |
@@ -281,7 +281,7 b' hooks::' | |||
|
281 | 281 | commit to proceed. Non-zero status will cause the commit to fail. |
|
282 | 282 | Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2. |
|
283 | 283 | preoutgoing;; |
|
284 |
Run before co |
|
|
284 | Run before collecting changes to send from the local repository to | |
|
285 | 285 | another. Non-zero status will cause failure. This lets you |
|
286 | 286 | prevent pull over http or ssh. Also prevents against local pull, |
|
287 | 287 | push (outbound) or bundle commands, but not effective, since you |
@@ -603,6 +603,7 b' class queue:' | |||
|
603 | 603 | def new(self, repo, patch, *pats, **opts): |
|
604 | 604 | msg = opts.get('msg') |
|
605 | 605 | force = opts.get('force') |
|
606 | user = opts.get('user') | |
|
606 | 607 | if os.path.exists(self.join(patch)): |
|
607 | 608 | raise util.Abort(_('patch "%s" already exists') % patch) |
|
608 | 609 | if opts.get('include') or opts.get('exclude') or pats: |
@@ -617,7 +618,7 b' class queue:' | |||
|
617 | 618 | try: |
|
618 | 619 | insert = self.full_series_end() |
|
619 | 620 | commitmsg = msg and msg or ("[mq]: %s" % patch) |
|
620 | n = repo.commit(commitfiles, commitmsg, match=match, force=True) | |
|
621 | n = repo.commit(commitfiles, commitmsg, user, match=match, force=True) | |
|
621 | 622 | if n == None: |
|
622 | 623 | raise util.Abort(_("repo commit failed")) |
|
623 | 624 | self.full_series[insert:insert] = [patch] |
@@ -626,6 +627,8 b' class queue:' | |||
|
626 | 627 | self.series_dirty = 1 |
|
627 | 628 | self.applied_dirty = 1 |
|
628 | 629 | p = self.opener(patch, "w") |
|
630 | if user: | |
|
631 | p.write("From: " + user + "\n\n") | |
|
629 | 632 | if msg: |
|
630 | 633 | msg = msg + "\n" |
|
631 | 634 | p.write(msg) |
@@ -945,6 +948,22 b' class queue:' | |||
|
945 | 948 | while message[mi] != comments[ci]: |
|
946 | 949 | ci += 1 |
|
947 | 950 | del comments[ci] |
|
951 | ||
|
952 | newuser = opts.get('user') | |
|
953 | if newuser: | |
|
954 | # Update all references to a user in the patch header. | |
|
955 | # If none found, add "From: " header. | |
|
956 | needfrom = True | |
|
957 | for prefix in ['# User ', 'From: ']: | |
|
958 | for i in xrange(len(comments)): | |
|
959 | if comments[i].startswith(prefix): | |
|
960 | comments[i] = prefix + newuser | |
|
961 | needfrom = False | |
|
962 | break | |
|
963 | if needfrom: | |
|
964 | comments = ['From: ' + newuser, ''] + comments | |
|
965 | user = newuser | |
|
966 | ||
|
948 | 967 | if msg: |
|
949 | 968 | comments.append(msg) |
|
950 | 969 | |
@@ -1070,9 +1089,12 b' class queue:' | |||
|
1070 | 1089 | else: |
|
1071 | 1090 | message = msg |
|
1072 | 1091 | |
|
1092 | if not user: | |
|
1093 | user = changes[1] | |
|
1094 | ||
|
1073 | 1095 | self.strip(repo, top, update=False, |
|
1074 | 1096 | backup='strip') |
|
1075 |
n = repo.commit(filelist, message, |
|
|
1097 | n = repo.commit(filelist, message, user, match=matchfn, | |
|
1076 | 1098 | force=1) |
|
1077 | 1099 | self.applied[-1] = statusentry(revlog.hex(n), patchfn) |
|
1078 | 1100 | self.applied_dirty = 1 |
@@ -1605,6 +1627,12 b' def prev(ui, repo, **opts):' | |||
|
1605 | 1627 | return q.qseries(repo, start=l-2, length=1, status='A', |
|
1606 | 1628 | summary=opts.get('summary')) |
|
1607 | 1629 | |
|
1630 | def setupheaderopts(ui, opts): | |
|
1631 | def do(opt,val): | |
|
1632 | if not opts[opt] and opts['current' + opt]: | |
|
1633 | opts[opt] = val | |
|
1634 | do('user', ui.username()) | |
|
1635 | ||
|
1608 | 1636 | def new(ui, repo, patch, *args, **opts): |
|
1609 | 1637 | """create a new patch |
|
1610 | 1638 | |
@@ -1623,6 +1651,7 b' def new(ui, repo, patch, *args, **opts):' | |||
|
1623 | 1651 | if opts['edit']: |
|
1624 | 1652 | message = ui.edit(message, ui.username()) |
|
1625 | 1653 | opts['msg'] = message |
|
1654 | setupheaderopts(ui, opts) | |
|
1626 | 1655 | q.new(repo, patch, *args, **opts) |
|
1627 | 1656 | q.save_dirty() |
|
1628 | 1657 | return 0 |
@@ -1648,6 +1677,7 b' def refresh(ui, repo, *pats, **opts):' | |||
|
1648 | 1677 | patch = q.applied[-1].name |
|
1649 | 1678 | (message, comment, user, date, hasdiff) = q.readheaders(patch) |
|
1650 | 1679 | message = ui.edit('\n'.join(message), user or ui.username()) |
|
1680 | setupheaderopts(ui, opts) | |
|
1651 | 1681 | ret = q.refresh(repo, pats, msg=message, **opts) |
|
1652 | 1682 | q.save_dirty() |
|
1653 | 1683 | return ret |
@@ -2138,6 +2168,10 b' def reposetup(ui, repo):' | |||
|
2138 | 2168 | |
|
2139 | 2169 | seriesopts = [('s', 'summary', None, _('print first line of patch header'))] |
|
2140 | 2170 | |
|
2171 | headeropts = [ | |
|
2172 | ('U', 'currentuser', None, _('add "From: <current user>" to patch')), | |
|
2173 | ('u', 'user', '', _('add "From: <given user>" to patch'))] | |
|
2174 | ||
|
2141 | 2175 | cmdtable = { |
|
2142 | 2176 | "qapplied": (applied, [] + seriesopts, _('hg qapplied [-s] [PATCH]')), |
|
2143 | 2177 | "qclone": |
@@ -2196,7 +2230,7 b' cmdtable = {' | |||
|
2196 | 2230 | [('e', 'edit', None, _('edit commit message')), |
|
2197 | 2231 | ('f', 'force', None, _('import uncommitted changes into patch')), |
|
2198 | 2232 | ('g', 'git', None, _('use git extended diff format')), |
|
2199 | ] + commands.walkopts + commands.commitopts, | |
|
2233 | ] + commands.walkopts + commands.commitopts + headeropts, | |
|
2200 | 2234 | _('hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH [FILE]...')), |
|
2201 | 2235 | "qnext": (next, [] + seriesopts, _('hg qnext [-s]')), |
|
2202 | 2236 | "qprev": (prev, [] + seriesopts, _('hg qprev [-s]')), |
@@ -2219,7 +2253,7 b' cmdtable = {' | |||
|
2219 | 2253 | [('e', 'edit', None, _('edit commit message')), |
|
2220 | 2254 | ('g', 'git', None, _('use git extended diff format')), |
|
2221 | 2255 | ('s', 'short', None, _('refresh only files already in the patch')), |
|
2222 | ] + commands.walkopts + commands.commitopts, | |
|
2256 | ] + commands.walkopts + commands.commitopts + headeropts, | |
|
2223 | 2257 | _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...')), |
|
2224 | 2258 | 'qrename|qmv': |
|
2225 | 2259 | (rename, [], _('hg qrename PATCH1 [PATCH2]')), |
@@ -2029,6 +2029,7 b' def remove(ui, repo, *pats, **opts):' | |||
|
2029 | 2029 | forget.append(abs) |
|
2030 | 2030 | continue |
|
2031 | 2031 | reason = _('has been marked for add (use -f to force removal)') |
|
2032 | exact = 1 # force the message | |
|
2032 | 2033 | elif abs not in repo.dirstate: |
|
2033 | 2034 | reason = _('is not managed') |
|
2034 | 2035 | elif opts['after'] and not exact and abs not in deleted: |
@@ -67,7 +67,7 b' class _demandmod(object):' | |||
|
67 | 67 | return "<proxied module '%s'>" % self._data[0] |
|
68 | 68 | return "<unloaded module '%s'>" % self._data[0] |
|
69 | 69 | def __call__(self, *args, **kwargs): |
|
70 |
raise TypeError(" |
|
|
70 | raise TypeError("%s object is not callable" % repr(self)) | |
|
71 | 71 | def __getattribute__(self, attr): |
|
72 | 72 | if attr in ('_data', '_extend', '_load', '_module'): |
|
73 | 73 | return object.__getattribute__(self, attr) |
@@ -133,6 +133,8 b' def _runcatch(ui, args):' | |||
|
133 | 133 | |
|
134 | 134 | except util.Abort, inst: |
|
135 | 135 | ui.warn(_("abort: %s\n") % inst) |
|
136 | except MemoryError: | |
|
137 | ui.warn(_("abort: out of memory\n")) | |
|
136 | 138 | except SystemExit, inst: |
|
137 | 139 | # Commands shouldn't sys.exit directly, but give a return code. |
|
138 | 140 | # Just in case catch this and and pass exit code to caller. |
@@ -1,35 +1,74 b'' | |||
|
1 | 1 | import getopt |
|
2 | 2 | |
|
3 | 3 | def fancyopts(args, options, state): |
|
4 | long = [] | |
|
5 | short = '' | |
|
6 | map = {} | |
|
7 | dt = {} | |
|
4 | """ | |
|
5 | read args, parse options, and store options in state | |
|
6 | ||
|
7 | each option is a tuple of: | |
|
8 | ||
|
9 | short option or '' | |
|
10 | long option | |
|
11 | default value | |
|
12 | description | |
|
13 | ||
|
14 | option types include: | |
|
15 | ||
|
16 | boolean or none - option sets variable in state to true | |
|
17 | string - parameter string is stored in state | |
|
18 | list - parameter string is added to a list | |
|
19 | integer - parameter strings is stored as int | |
|
20 | function - call function with parameter | |
|
8 | 21 |
|
|
9 | for s, l, d, c in options: | |
|
10 | pl = l.replace('-', '_') | |
|
11 | map['-'+s] = map['--'+l] = pl | |
|
12 | if isinstance(d, list): | |
|
13 | state[pl] = d[:] | |
|
22 | non-option args are returned | |
|
23 | """ | |
|
24 | namelist = [] | |
|
25 | shortlist = '' | |
|
26 | argmap = {} | |
|
27 | defmap = {} | |
|
28 | ||
|
29 | for short, name, default, comment in options: | |
|
30 | # convert opts to getopt format | |
|
31 | oname = name | |
|
32 | name = name.replace('-', '_') | |
|
33 | ||
|
34 | argmap['-' + short] = argmap['--' + oname] = name | |
|
35 | defmap[name] = default | |
|
36 | ||
|
37 | # copy defaults to state | |
|
38 | if isinstance(default, list): | |
|
39 | state[name] = default[:] | |
|
40 | elif callable(default): | |
|
41 | print "whoa", name, default | |
|
42 | state[name] = None | |
|
14 | 43 | else: |
|
15 |
state[ |
|
|
16 | dt[pl] = type(d) | |
|
17 | if (d is not None and d is not True and d is not False and | |
|
18 | not callable(d)): | |
|
19 | if s: s += ':' | |
|
20 | if l: l += '=' | |
|
21 | if s: short = short + s | |
|
22 | if l: long.append(l) | |
|
44 | state[name] = default | |
|
23 | 45 | |
|
24 | opts, args = getopt.getopt(args, short, long) | |
|
46 | # does it take a parameter? | |
|
47 | if not (default is None or default is True or default is False): | |
|
48 | if short: short += ':' | |
|
49 | if oname: oname += '=' | |
|
50 | if short: | |
|
51 | shortlist += short | |
|
52 | if name: | |
|
53 | namelist.append(oname) | |
|
54 | ||
|
55 | # parse arguments | |
|
56 | opts, args = getopt.getopt(args, shortlist, namelist) | |
|
25 | 57 | |
|
26 | for opt, arg in opts: | |
|
27 | if dt[map[opt]] is type(fancyopts): state[map[opt]](state, map[opt], arg) | |
|
28 | elif dt[map[opt]] is type(1): state[map[opt]] = int(arg) | |
|
29 | elif dt[map[opt]] is type(''): state[map[opt]] = arg | |
|
30 | elif dt[map[opt]] is type([]): state[map[opt]].append(arg) | |
|
31 | elif dt[map[opt]] is type(None): state[map[opt]] = True | |
|
32 | elif dt[map[opt]] is type(False): state[map[opt]] = True | |
|
58 | # transfer result to state | |
|
59 | for opt, val in opts: | |
|
60 | name = argmap[opt] | |
|
61 | t = type(defmap[name]) | |
|
62 | if t is type(fancyopts): | |
|
63 | state[name] = defmap[name](val) | |
|
64 | elif t is type(1): | |
|
65 | state[name] = int(val) | |
|
66 | elif t is type(''): | |
|
67 | state[name] = val | |
|
68 | elif t is type([]): | |
|
69 | state[name].append(val) | |
|
70 | elif t is type(None) or t is type(False): | |
|
71 | state[name] = True | |
|
33 | 72 | |
|
73 | # return unparsed args | |
|
34 | 74 | return args |
|
35 |
@@ -280,13 +280,13 b' def update(repo, node):' | |||
|
280 | 280 | # len(pl)==1, otherwise _merge.update() would have raised util.Abort: |
|
281 | 281 | repo.ui.status(_(" hg update %s\n hg update %s\n") |
|
282 | 282 | % (pl[0].rev(), repo.changectx(node).rev())) |
|
283 | return stats[3] | |
|
283 | return stats[3] > 0 | |
|
284 | 284 | |
|
285 | 285 | def clean(repo, node, show_stats=True): |
|
286 | 286 | """forcibly switch the working directory to node, clobbering changes""" |
|
287 | 287 | stats = _merge.update(repo, node, False, True, None) |
|
288 | 288 | if show_stats: _showstats(repo, stats) |
|
289 | return stats[3] | |
|
289 | return stats[3] > 0 | |
|
290 | 290 | |
|
291 | 291 | def merge(repo, node, force=None, remind=True): |
|
292 | 292 | """branch merge with node, resolving changes""" |
@@ -301,11 +301,11 b' def merge(repo, node, force=None, remind' | |||
|
301 | 301 | % (pl[0].rev(), pl[1].rev())) |
|
302 | 302 | elif remind: |
|
303 | 303 | repo.ui.status(_("(branch merge, don't forget to commit)\n")) |
|
304 | return stats[3] | |
|
304 | return stats[3] > 0 | |
|
305 | 305 | |
|
306 | 306 | def revert(repo, node, choose): |
|
307 | 307 | """revert changes to revision in node without updating dirstate""" |
|
308 | return _merge.update(repo, node, False, True, choose)[3] | |
|
308 | return _merge.update(repo, node, False, True, choose)[3] > 0 | |
|
309 | 309 | |
|
310 | 310 | def verify(repo): |
|
311 | 311 | """verify the consistency of a repository""" |
@@ -6,18 +6,21 b'' | |||
|
6 | 6 | # of the GNU General Public License, incorporated herein by reference. |
|
7 | 7 | |
|
8 | 8 | from i18n import _ |
|
9 | import util | |
|
9 | import util, re | |
|
10 | ||
|
11 | _commentre = None | |
|
10 | 12 | |
|
11 | 13 | def _parselines(fp): |
|
12 | 14 | for line in fp: |
|
13 |
if n |
|
|
14 | line += '\n' | |
|
15 | escape = False | |
|
16 | for i in xrange(len(line)): | |
|
17 | if escape: escape = False | |
|
18 | elif line[i] == '\\': escape = True | |
|
19 | elif line[i] == '#': break | |
|
20 |
line = line |
|
|
15 | if "#" in line: | |
|
16 | global _commentre | |
|
17 | if not _commentre: | |
|
18 | _commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*') | |
|
19 | # remove comments prefixed by an even number of escapes | |
|
20 | line = _commentre.sub(r'\1', line) | |
|
21 | # fixup properly escaped comments that survived the above | |
|
22 | line = line.replace("\\#", "#") | |
|
23 | line = line.rstrip() | |
|
21 | 24 | if line: |
|
22 | 25 | yield line |
|
23 | 26 |
@@ -661,6 +661,7 b' class localrepository(repo.repository):' | |||
|
661 | 661 | match=util.always, force=False, force_editor=False, |
|
662 | 662 | p1=None, p2=None, extra={}, empty_ok=False): |
|
663 | 663 | wlock = lock = tr = None |
|
664 | valid = 0 # don't save the dirstate if this isn't set | |
|
664 | 665 | try: |
|
665 | 666 | commit = [] |
|
666 | 667 | remove = [] |
@@ -747,6 +748,9 b' class localrepository(repo.repository):' | |||
|
747 | 748 | if old_exec != new_exec or old_link != new_link: |
|
748 | 749 | changed.append(f) |
|
749 | 750 | m1.set(f, new_exec, new_link) |
|
751 | if use_dirstate: | |
|
752 | self.dirstate.normal(f) | |
|
753 | ||
|
750 | 754 | except (OSError, IOError): |
|
751 | 755 | if use_dirstate: |
|
752 | 756 | self.ui.warn(_("trouble committing %s!\n") % f) |
@@ -817,14 +821,15 b' class localrepository(repo.repository):' | |||
|
817 | 821 | if use_dirstate or update_dirstate: |
|
818 | 822 | self.dirstate.setparents(n) |
|
819 | 823 | if use_dirstate: |
|
820 | for f in new: | |
|
821 | self.dirstate.normal(f) | |
|
822 | 824 | for f in removed: |
|
823 | 825 | self.dirstate.forget(f) |
|
826 | valid = 1 # our dirstate updates are complete | |
|
824 | 827 | |
|
825 | 828 | self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2) |
|
826 | 829 | return n |
|
827 | 830 | finally: |
|
831 | if not valid: # don't save our updated dirstate | |
|
832 | self.dirstate.invalidate() | |
|
828 | 833 | del tr, lock, wlock |
|
829 | 834 | |
|
830 | 835 | def walk(self, node=None, files=[], match=util.always, badmatch=None): |
@@ -302,24 +302,26 b" unidesc = re.compile('@@ -(\\d+)(,(\\d+))?" | |||
|
302 | 302 | contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)') |
|
303 | 303 | |
|
304 | 304 | class patchfile: |
|
305 | def __init__(self, ui, fname): | |
|
305 | def __init__(self, ui, fname, missing=False): | |
|
306 | 306 | self.fname = fname |
|
307 | 307 | self.ui = ui |
|
308 | self.lines = [] | |
|
309 | self.exists = False | |
|
310 | self.missing = missing | |
|
311 | if not missing: | |
|
308 | 312 | try: |
|
309 | 313 | fp = file(fname, 'rb') |
|
310 | 314 | self.lines = fp.readlines() |
|
311 | 315 | self.exists = True |
|
312 | 316 | except IOError: |
|
317 | pass | |
|
318 | else: | |
|
319 | self.ui.warn(_("unable to find '%s' for patching\n") % self.fname) | |
|
320 | ||
|
321 | if not self.exists: | |
|
313 | 322 | dirname = os.path.dirname(fname) |
|
314 | 323 | if dirname and not os.path.isdir(dirname): |
|
315 |
|
|
|
316 | d = "" | |
|
317 | for x in dirs: | |
|
318 | d = os.path.join(d, x) | |
|
319 | if not os.path.isdir(d): | |
|
320 | os.mkdir(d) | |
|
321 | self.lines = [] | |
|
322 | self.exists = False | |
|
324 | os.makedirs(dirname) | |
|
323 | 325 | |
|
324 | 326 | self.hash = {} |
|
325 | 327 | self.dirty = 0 |
@@ -427,6 +429,10 b' class patchfile:' | |||
|
427 | 429 | if reverse: |
|
428 | 430 | h.reverse() |
|
429 | 431 | |
|
432 | if self.missing: | |
|
433 | self.rej.append(h) | |
|
434 | return -1 | |
|
435 | ||
|
430 | 436 | if self.exists and h.createfile(): |
|
431 | 437 | self.ui.warn(_("file %s already exists\n") % self.fname) |
|
432 | 438 | self.rej.append(h) |
@@ -796,31 +802,32 b' def selectfile(afile_orig, bfile_orig, h' | |||
|
796 | 802 | nulla = afile_orig == "/dev/null" |
|
797 | 803 | nullb = bfile_orig == "/dev/null" |
|
798 | 804 | afile = pathstrip(afile_orig, strip) |
|
799 |
gooda = os.path.exists(afile) |
|
|
805 | gooda = not nulla and os.path.exists(afile) | |
|
800 | 806 | bfile = pathstrip(bfile_orig, strip) |
|
801 | 807 | if afile == bfile: |
|
802 | 808 | goodb = gooda |
|
803 | 809 | else: |
|
804 |
goodb = os.path.exists(bfile) |
|
|
810 | goodb = not nullb and os.path.exists(bfile) | |
|
805 | 811 | createfunc = hunk.createfile |
|
806 | 812 | if reverse: |
|
807 | 813 | createfunc = hunk.rmfile |
|
808 |
|
|
|
809 | raise PatchError(_("unable to find %s or %s for patching") % | |
|
810 | (afile, bfile)) | |
|
814 | missing = not goodb and not gooda and not createfunc() | |
|
815 | fname = None | |
|
816 | if not missing: | |
|
811 | 817 | if gooda and goodb: |
|
812 | fname = bfile | |
|
813 | if afile in bfile: | |
|
814 | fname = afile | |
|
818 | fname = (afile in bfile) and afile or bfile | |
|
815 | 819 | elif gooda: |
|
816 | 820 | fname = afile |
|
817 | elif not nullb: | |
|
818 | fname = bfile | |
|
819 | if afile in bfile: | |
|
820 | fname = afile | |
|
821 | ||
|
822 | if not fname: | |
|
823 | if not nullb: | |
|
824 | fname = (afile in bfile) and afile or bfile | |
|
821 | 825 | elif not nulla: |
|
822 | 826 | fname = afile |
|
823 | return fname | |
|
827 | else: | |
|
828 | raise PatchError(_("undefined source and destination files")) | |
|
829 | ||
|
830 | return fname, missing | |
|
824 | 831 | |
|
825 | 832 | class linereader: |
|
826 | 833 | # simple class to allow pushing lines back into the input stream |
@@ -838,14 +845,16 b' class linereader:' | |||
|
838 | 845 | return l |
|
839 | 846 | return self.fp.readline() |
|
840 | 847 | |
|
841 | def applydiff(ui, fp, changed, strip=1, sourcefile=None, reverse=False, | |
|
842 | rejmerge=None, updatedir=None): | |
|
843 | """reads a patch from fp and tries to apply it. The dict 'changed' is | |
|
844 | filled in with all of the filenames changed by the patch. Returns 0 | |
|
845 | for a clean patch, -1 if any rejects were found and 1 if there was | |
|
846 | any fuzz.""" | |
|
848 | def iterhunks(ui, fp, sourcefile=None): | |
|
849 | """Read a patch and yield the following events: | |
|
850 | - ("file", afile, bfile, firsthunk): select a new target file. | |
|
851 | - ("hunk", hunk): a new hunk is ready to be applied, follows a | |
|
852 | "file" event. | |
|
853 | - ("git", gitchanges): current diff is in git format, gitchanges | |
|
854 | maps filenames to gitpatch records. Unique event. | |
|
855 | """ | |
|
847 | 856 | |
|
848 |
def scangitpatch(fp, firstline |
|
|
857 | def scangitpatch(fp, firstline): | |
|
849 | 858 | '''git patches can modify a file, then copy that file to |
|
850 | 859 | a new file, but expect the source to be the unmodified form. |
|
851 | 860 | So we scan the patch looking for that case so we can do |
@@ -858,46 +867,28 b' def applydiff(ui, fp, changed, strip=1, ' | |||
|
858 | 867 | fp = cStringIO.StringIO(fp.read()) |
|
859 | 868 | |
|
860 | 869 | (dopatch, gitpatches) = readgitpatch(fp, firstline) |
|
861 | for gp in gitpatches: | |
|
862 | if gp.op in ('COPY', 'RENAME'): | |
|
863 | copyfile(gp.oldpath, gp.path, basedir=cwd) | |
|
864 | ||
|
865 | 870 | fp.seek(pos) |
|
866 | 871 | |
|
867 | 872 | return fp, dopatch, gitpatches |
|
868 | 873 | |
|
874 | changed = {} | |
|
869 | 875 | current_hunk = None |
|
870 | current_file = None | |
|
871 | 876 | afile = "" |
|
872 | 877 | bfile = "" |
|
873 | 878 | state = None |
|
874 | 879 | hunknum = 0 |
|
875 | rejects = 0 | |
|
880 | emitfile = False | |
|
876 | 881 | |
|
877 | 882 | git = False |
|
878 | 883 | gitre = re.compile('diff --git (a/.*) (b/.*)') |
|
879 | 884 | |
|
880 | 885 | # our states |
|
881 | 886 | BFILE = 1 |
|
882 | err = 0 | |
|
883 | 887 | context = None |
|
884 | 888 | lr = linereader(fp) |
|
885 | 889 | dopatch = True |
|
886 | 890 | gitworkdone = False |
|
887 | 891 | |
|
888 | def getpatchfile(afile, bfile, hunk): | |
|
889 | try: | |
|
890 | if sourcefile: | |
|
891 | targetfile = patchfile(ui, sourcefile) | |
|
892 | else: | |
|
893 | targetfile = selectfile(afile, bfile, hunk, | |
|
894 | strip, reverse) | |
|
895 | targetfile = patchfile(ui, targetfile) | |
|
896 | return targetfile | |
|
897 | except PatchError, err: | |
|
898 | ui.warn(str(err) + '\n') | |
|
899 | return None | |
|
900 | ||
|
901 | 892 | while True: |
|
902 | 893 | newfile = False |
|
903 | 894 | x = lr.readline() |
@@ -906,11 +897,7 b' def applydiff(ui, fp, changed, strip=1, ' | |||
|
906 | 897 | if current_hunk: |
|
907 | 898 | if x.startswith('\ '): |
|
908 | 899 | current_hunk.fix_newline() |
|
909 | ret = current_file.apply(current_hunk, reverse) | |
|
910 | if ret >= 0: | |
|
911 | changed.setdefault(current_file.fname, (None, None)) | |
|
912 | if ret > 0: | |
|
913 | err = 1 | |
|
900 | yield 'hunk', current_hunk | |
|
914 | 901 | current_hunk = None |
|
915 | 902 | gitworkdone = False |
|
916 | 903 | if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or |
@@ -924,21 +911,15 b' def applydiff(ui, fp, changed, strip=1, ' | |||
|
924 | 911 | current_hunk = None |
|
925 | 912 | continue |
|
926 | 913 | hunknum += 1 |
|
927 |
if |
|
|
928 | current_file = getpatchfile(afile, bfile, current_hunk) | |
|
929 | if not current_file: | |
|
930 | current_file, current_hunk = None, None | |
|
931 | rejects += 1 | |
|
932 | continue | |
|
914 | if emitfile: | |
|
915 | emitfile = False | |
|
916 | yield 'file', (afile, bfile, current_hunk) | |
|
933 | 917 | elif state == BFILE and x.startswith('GIT binary patch'): |
|
934 | 918 | current_hunk = binhunk(changed[bfile[2:]][1]) |
|
935 | 919 | hunknum += 1 |
|
936 |
if |
|
|
937 | current_file = getpatchfile(afile, bfile, current_hunk) | |
|
938 | if not current_file: | |
|
939 | current_file, current_hunk = None, None | |
|
940 | rejects += 1 | |
|
941 | continue | |
|
920 | if emitfile: | |
|
921 | emitfile = False | |
|
922 | yield 'file', (afile, bfile, current_hunk) | |
|
942 | 923 | current_hunk.extract(fp) |
|
943 | 924 | elif x.startswith('diff --git'): |
|
944 | 925 | # check for git diff, scanning the whole patch file if needed |
@@ -948,6 +929,7 b' def applydiff(ui, fp, changed, strip=1, ' | |||
|
948 | 929 | if not git: |
|
949 | 930 | git = True |
|
950 | 931 | fp, dopatch, gitpatches = scangitpatch(fp, x) |
|
932 | yield 'git', gitpatches | |
|
951 | 933 | for gp in gitpatches: |
|
952 | 934 | changed[gp.path] = (gp.op, gp) |
|
953 | 935 | # else error? |
@@ -984,36 +966,79 b' def applydiff(ui, fp, changed, strip=1, ' | |||
|
984 | 966 | bfile = parsefilename(l2) |
|
985 | 967 | |
|
986 | 968 | if newfile: |
|
987 |
if |
|
|
969 | emitfile = True | |
|
970 | state = BFILE | |
|
971 | hunknum = 0 | |
|
972 | if current_hunk: | |
|
973 | if current_hunk.complete(): | |
|
974 | yield 'hunk', current_hunk | |
|
975 | else: | |
|
976 | raise PatchError(_("malformed patch %s %s") % (afile, | |
|
977 | current_hunk.desc)) | |
|
978 | ||
|
979 | if hunknum == 0 and dopatch and not gitworkdone: | |
|
980 | raise NoHunks | |
|
981 | ||
|
982 | def applydiff(ui, fp, changed, strip=1, sourcefile=None, reverse=False, | |
|
983 | rejmerge=None, updatedir=None): | |
|
984 | """reads a patch from fp and tries to apply it. The dict 'changed' is | |
|
985 | filled in with all of the filenames changed by the patch. Returns 0 | |
|
986 | for a clean patch, -1 if any rejects were found and 1 if there was | |
|
987 | any fuzz.""" | |
|
988 | ||
|
989 | rejects = 0 | |
|
990 | err = 0 | |
|
991 | current_file = None | |
|
992 | gitpatches = None | |
|
993 | ||
|
994 | def closefile(): | |
|
995 | if not current_file: | |
|
996 | return 0 | |
|
988 | 997 |
|
|
989 | 998 |
|
|
990 | 999 |
|
|
991 |
|
|
|
992 | state = BFILE | |
|
993 | current_file = None | |
|
994 |
|
|
|
995 |
if current_ |
|
|
996 | if current_hunk.complete(): | |
|
1000 | return len(current_file.rej) | |
|
1001 | ||
|
1002 | for state, values in iterhunks(ui, fp, sourcefile): | |
|
1003 | if state == 'hunk': | |
|
1004 | if not current_file: | |
|
1005 | continue | |
|
1006 | current_hunk = values | |
|
997 | 1007 | ret = current_file.apply(current_hunk, reverse) |
|
998 | 1008 | if ret >= 0: |
|
999 | 1009 | changed.setdefault(current_file.fname, (None, None)) |
|
1000 | 1010 | if ret > 0: |
|
1001 | 1011 | err = 1 |
|
1012 | elif state == 'file': | |
|
1013 | rejects += closefile() | |
|
1014 | afile, bfile, first_hunk = values | |
|
1015 | try: | |
|
1016 | if sourcefile: | |
|
1017 | current_file = patchfile(ui, sourcefile) | |
|
1002 | 1018 | else: |
|
1003 | fname = current_file and current_file.fname or None | |
|
1004 | raise PatchError(_("malformed patch %s %s") % (fname, | |
|
1005 | current_hunk.desc)) | |
|
1006 | if current_file: | |
|
1007 | current_file.close() | |
|
1008 | if rejmerge: | |
|
1009 | rejmerge(current_file) | |
|
1010 | rejects += len(current_file.rej) | |
|
1011 |
if |
|
|
1019 | current_file, missing = selectfile(afile, bfile, first_hunk, | |
|
1020 | strip, reverse) | |
|
1021 | current_file = patchfile(ui, current_file, missing) | |
|
1022 | except PatchError, err: | |
|
1023 | ui.warn(str(err) + '\n') | |
|
1024 | current_file, current_hunk = None, None | |
|
1025 | rejects += 1 | |
|
1026 | continue | |
|
1027 | elif state == 'git': | |
|
1028 | gitpatches = values | |
|
1029 | for gp in gitpatches: | |
|
1030 | if gp.op in ('COPY', 'RENAME'): | |
|
1031 | copyfile(gp.oldpath, gp.path) | |
|
1032 | changed[gp.path] = (gp.op, gp) | |
|
1033 | else: | |
|
1034 | raise util.Abort(_('unsupported parser state: %s') % state) | |
|
1035 | ||
|
1036 | rejects += closefile() | |
|
1037 | ||
|
1038 | if updatedir and gitpatches: | |
|
1012 | 1039 | updatedir(gitpatches) |
|
1013 | 1040 | if rejects: |
|
1014 | 1041 | return -1 |
|
1015 | if hunknum == 0 and dopatch and not gitworkdone: | |
|
1016 | raise NoHunks | |
|
1017 | 1042 | return err |
|
1018 | 1043 | |
|
1019 | 1044 | def diffopts(ui, opts={}, untrusted=False): |
@@ -919,7 +919,15 b" if os.name == 'nt':" | |||
|
919 | 919 | |
|
920 | 920 | def write(self, s): |
|
921 | 921 | try: |
|
922 | return self.fp.write(s) | |
|
922 | # This is workaround for "Not enough space" error on | |
|
923 | # writing large size of data to console. | |
|
924 | limit = 16000 | |
|
925 | l = len(s) | |
|
926 | start = 0 | |
|
927 | while start < l: | |
|
928 | end = start + limit | |
|
929 | self.fp.write(s[start:end]) | |
|
930 | start = end | |
|
923 | 931 | except IOError, inst: |
|
924 | 932 | if inst.errno != 0: raise |
|
925 | 933 | self.close() |
@@ -41,6 +41,8 b' hg qpush' | |||
|
41 | 41 | echo % display added files |
|
42 | 42 | cat a |
|
43 | 43 | cat c |
|
44 | echo % display rejections | |
|
45 | cat b.rej | |
|
44 | 46 | cd .. |
|
45 | 47 | |
|
46 | 48 | |
@@ -65,5 +67,7 b' hg st' | |||
|
65 | 67 | echo % display added files |
|
66 | 68 | cat a |
|
67 | 69 | cat c |
|
70 | echo % display rejections | |
|
71 | cat b.rej | |
|
68 | 72 | cd .. |
|
69 | 73 |
@@ -2,24 +2,48 b' adding b' | |||
|
2 | 2 | Patch queue now empty |
|
3 | 3 | % push patch with missing target |
|
4 | 4 | applying changeb |
|
5 |
unable to find |
|
|
6 | unable to find b or b for patching | |
|
5 | unable to find 'b' for patching | |
|
6 | 2 out of 2 hunks FAILED -- saving rejects to file b.rej | |
|
7 | 7 | patch failed, unable to continue (try -v) |
|
8 | 8 | patch failed, rejects left in working dir |
|
9 | 9 | Errors during apply, please fix and refresh changeb |
|
10 | 10 | % display added files |
|
11 | 11 | a |
|
12 | 12 | c |
|
13 | % display rejections | |
|
14 | --- b | |
|
15 | +++ b | |
|
16 | @@ -1,3 +1,5 @@ a | |
|
17 | +b | |
|
18 | +b | |
|
19 | a | |
|
20 | a | |
|
21 | a | |
|
22 | @@ -8,3 +10,5 @@ a | |
|
23 | a | |
|
24 | a | |
|
25 | a | |
|
26 | +c | |
|
27 | +c | |
|
13 | 28 | adding b |
|
14 | 29 | Patch queue now empty |
|
15 | 30 | % push git patch with missing target |
|
16 | 31 | applying changeb |
|
17 |
unable to find |
|
|
32 | unable to find 'b' for patching | |
|
33 | 1 out of 1 hunk FAILED -- saving rejects to file b.rej | |
|
18 | 34 | patch failed, unable to continue (try -v) |
|
19 | 35 | b: No such file or directory |
|
20 | 36 | b not tracked! |
|
21 | 37 | patch failed, rejects left in working dir |
|
22 | 38 | Errors during apply, please fix and refresh changeb |
|
39 | ? b.rej | |
|
23 | 40 | % display added files |
|
24 | 41 | a |
|
25 | 42 | c |
|
43 | % display rejections | |
|
44 | --- b | |
|
45 | +++ b | |
|
46 | GIT binary patch | |
|
47 | literal 2 | |
|
48 | Jc${No0000400IC2 | |
|
49 |
General Comments 0
You need to be logged in to leave comments.
Login now