Mercurial > hg > mercurial-crew-with-dirclash
annotate hgext/mq.py @ 2682:4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
This makes mq patch names visible in hg log and hg tags. It also
resolves the names only once, rather than on every lookup.
author | Brendan Cully <brendan@kublai.com> |
---|---|
date | Wed, 26 Jul 2006 12:22:04 -0700 |
parents | ec05ce9cbf47 |
children | 0fb28dbf0dc7 |
rev | line source |
---|---|
1808 | 1 # queue.py - patch queues for mercurial |
2 # | |
3 # Copyright 2005 Chris Mason <mason@suse.com> | |
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 | |
2554
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
8 '''patch management and development |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
9 |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
10 This extension lets you work with a stack of patches in a Mercurial |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
11 repository. It manages two stacks of patches - all known patches, and |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
12 applied patches (subset of known patches). |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
13 |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
14 Known patches are represented as patch files in the .hg/patches |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
15 directory. Applied patches are both patch files and changesets. |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
16 |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
17 Common tasks (use "hg help command" for more details): |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
18 |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
19 prepare repository to work with patches qinit |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
20 create new patch qnew |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
21 import existing patch qimport |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
22 |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
23 print patch series qseries |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
24 print applied patches qapplied |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
25 print name of top applied patch qtop |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
26 |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
27 add known patch to applied stack qpush |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
28 remove patch from applied stack qpop |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
29 refresh contents of top applied patch qrefresh |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
30 ''' |
8264c2034970
help: add help to mq extension
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2531
diff
changeset
|
31 |
1808 | 32 from mercurial.demandload import * |
33 demandload(globals(), "os sys re struct traceback errno bz2") | |
34 from mercurial.i18n import gettext as _ | |
35 from mercurial import ui, hg, revlog, commands, util | |
36 | |
37 versionstr = "0.45" | |
38 | |
39 repomap = {} | |
40 | |
2047
ebf1ecb5f4e8
Register qversion as a non repository related command
Edouard Gomez <ed.gomez@free.fr>
parents:
1863
diff
changeset
|
41 commands.norepo += " qversion" |
1808 | 42 class queue: |
43 def __init__(self, ui, path, patchdir=None): | |
44 self.basepath = path | |
45 if patchdir: | |
46 self.path = patchdir | |
47 else: | |
48 self.path = os.path.join(path, "patches") | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
49 self.opener = util.opener(self.path) |
1808 | 50 self.ui = ui |
51 self.applied = [] | |
52 self.full_series = [] | |
53 self.applied_dirty = 0 | |
54 self.series_dirty = 0 | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
55 self.series_path = "series" |
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
56 self.status_path = "status" |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
57 |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
58 if os.path.exists(os.path.join(self.path, self.series_path)): |
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
59 self.full_series = self.opener(self.series_path).read().splitlines() |
1808 | 60 self.read_series(self.full_series) |
61 | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
62 if os.path.exists(os.path.join(self.path, self.status_path)): |
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
63 self.applied = self.opener(self.status_path).read().splitlines() |
1808 | 64 |
65 def find_series(self, patch): | |
66 pre = re.compile("(\s*)([^#]+)") | |
67 index = 0 | |
68 for l in self.full_series: | |
69 m = pre.match(l) | |
70 if m: | |
71 s = m.group(2) | |
72 s = s.rstrip() | |
73 if s == patch: | |
74 return index | |
75 index += 1 | |
76 return None | |
77 | |
78 def read_series(self, list): | |
79 def matcher(list): | |
80 pre = re.compile("(\s*)([^#]+)") | |
81 for l in list: | |
82 m = pre.match(l) | |
83 if m: | |
84 s = m.group(2) | |
85 s = s.rstrip() | |
86 if len(s) > 0: | |
87 yield s | |
88 self.series = [] | |
89 self.series = [ x for x in matcher(list) ] | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
90 |
1808 | 91 def save_dirty(self): |
92 if self.applied_dirty: | |
93 if len(self.applied) > 0: | |
94 nl = "\n" | |
95 else: | |
96 nl = "" | |
97 f = self.opener(self.status_path, "w") | |
98 f.write("\n".join(self.applied) + nl) | |
99 if self.series_dirty: | |
100 if len(self.full_series) > 0: | |
101 nl = "\n" | |
102 else: | |
103 nl = "" | |
104 f = self.opener(self.series_path, "w") | |
105 f.write("\n".join(self.full_series) + nl) | |
106 | |
107 def readheaders(self, patch): | |
108 def eatdiff(lines): | |
109 while lines: | |
110 l = lines[-1] | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
111 if (l.startswith("diff -") or |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
112 l.startswith("Index:") or |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
113 l.startswith("===========")): |
1808 | 114 del lines[-1] |
115 else: | |
116 break | |
117 def eatempty(lines): | |
118 while lines: | |
119 l = lines[-1] | |
120 if re.match('\s*$', l): | |
121 del lines[-1] | |
122 else: | |
123 break | |
124 | |
125 pf = os.path.join(self.path, patch) | |
126 message = [] | |
127 comments = [] | |
128 user = None | |
2299
dacf718e1d48
Add timestamp field to export format. Make import and mq use it.
Danek Duvall <danek.duvall@sun.com>
parents:
2270
diff
changeset
|
129 date = None |
1808 | 130 format = None |
131 subject = None | |
132 diffstart = 0 | |
133 | |
134 for line in file(pf): | |
135 line = line.rstrip() | |
136 if diffstart: | |
137 if line.startswith('+++ '): | |
138 diffstart = 2 | |
139 break | |
140 if line.startswith("--- "): | |
141 diffstart = 1 | |
142 continue | |
143 elif format == "hgpatch": | |
144 # parse values when importing the result of an hg export | |
145 if line.startswith("# User "): | |
146 user = line[7:] | |
2300
52b9b6751b2c
Use "# Date" instead of "# Timestamp" for dated export/import of patches.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2299
diff
changeset
|
147 elif line.startswith("# Date "): |
52b9b6751b2c
Use "# Date" instead of "# Timestamp" for dated export/import of patches.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2299
diff
changeset
|
148 date = line[7:] |
1808 | 149 elif not line.startswith("# ") and line: |
150 message.append(line) | |
151 format = None | |
152 elif line == '# HG changeset patch': | |
153 format = "hgpatch" | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
154 elif (format != "tagdone" and (line.startswith("Subject: ") or |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
155 line.startswith("subject: "))): |
1808 | 156 subject = line[9:] |
157 format = "tag" | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
158 elif (format != "tagdone" and (line.startswith("From: ") or |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
159 line.startswith("from: "))): |
1808 | 160 user = line[6:] |
161 format = "tag" | |
162 elif format == "tag" and line == "": | |
163 # when looking for tags (subject: from: etc) they | |
164 # end once you find a blank line in the source | |
165 format = "tagdone" | |
2301
7c2623aedeb4
Strip empty lines and trailing spaces around commit messages.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2300
diff
changeset
|
166 elif message or line: |
1808 | 167 message.append(line) |
168 comments.append(line) | |
169 | |
170 eatdiff(message) | |
171 eatdiff(comments) | |
172 eatempty(message) | |
173 eatempty(comments) | |
174 | |
175 # make sure message isn't empty | |
176 if format and format.startswith("tag") and subject: | |
177 message.insert(0, "") | |
178 message.insert(0, subject) | |
2299
dacf718e1d48
Add timestamp field to export format. Make import and mq use it.
Danek Duvall <danek.duvall@sun.com>
parents:
2270
diff
changeset
|
179 return (message, comments, user, date, diffstart > 1) |
1808 | 180 |
181 def mergeone(self, repo, mergeq, head, patch, rev, wlock): | |
182 # first try just applying the patch | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
183 (err, n) = self.apply(repo, [ patch ], update_status=False, |
1808 | 184 strict=True, merge=rev, wlock=wlock) |
185 | |
186 if err == 0: | |
187 return (err, n) | |
188 | |
189 if n is None: | |
190 self.ui.warn("apply failed for patch %s\n" % patch) | |
191 sys.exit(1) | |
192 | |
193 self.ui.warn("patch didn't work out, merging %s\n" % patch) | |
194 | |
195 # apply failed, strip away that rev and merge. | |
196 repo.update(head, allow=False, force=True, wlock=wlock) | |
197 self.strip(repo, n, update=False, backup='strip', wlock=wlock) | |
198 | |
199 c = repo.changelog.read(rev) | |
200 ret = repo.update(rev, allow=True, wlock=wlock) | |
201 if ret: | |
202 self.ui.warn("update returned %d\n" % ret) | |
203 sys.exit(1) | |
204 n = repo.commit(None, c[4], c[1], force=1, wlock=wlock) | |
205 if n == None: | |
206 self.ui.warn("repo commit failed\n") | |
207 sys.exit(1) | |
208 try: | |
2299
dacf718e1d48
Add timestamp field to export format. Make import and mq use it.
Danek Duvall <danek.duvall@sun.com>
parents:
2270
diff
changeset
|
209 message, comments, user, date, patchfound = mergeq.readheaders(patch) |
1808 | 210 except: |
211 self.ui.warn("Unable to read %s\n" % patch) | |
212 sys.exit(1) | |
213 | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
214 patchf = self.opener(patch, "w") |
1808 | 215 if comments: |
216 comments = "\n".join(comments) + '\n\n' | |
217 patchf.write(comments) | |
218 commands.dodiff(patchf, self.ui, repo, head, n) | |
219 patchf.close() | |
220 return (0, n) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
221 |
1808 | 222 def qparents(self, repo, rev=None): |
223 if rev is None: | |
224 (p1, p2) = repo.dirstate.parents() | |
225 if p2 == revlog.nullid: | |
226 return p1 | |
227 if len(self.applied) == 0: | |
228 return None | |
229 (top, patch) = self.applied[-1].split(':') | |
230 top = revlog.bin(top) | |
231 return top | |
232 pp = repo.changelog.parents(rev) | |
233 if pp[1] != revlog.nullid: | |
234 arevs = [ x.split(':')[0] for x in self.applied ] | |
235 p0 = revlog.hex(pp[0]) | |
236 p1 = revlog.hex(pp[1]) | |
237 if p0 in arevs: | |
238 return pp[0] | |
239 if p1 in arevs: | |
240 return pp[1] | |
241 return pp[0] | |
242 | |
243 def mergepatch(self, repo, mergeq, series, wlock): | |
244 if len(self.applied) == 0: | |
245 # each of the patches merged in will have two parents. This | |
246 # can confuse the qrefresh, qdiff, and strip code because it | |
247 # needs to know which parent is actually in the patch queue. | |
248 # so, we insert a merge marker with only one parent. This way | |
249 # the first patch in the queue is never a merge patch | |
250 # | |
251 pname = ".hg.patches.merge.marker" | |
252 n = repo.commit(None, '[mq]: merge marker', user=None, force=1, | |
253 wlock=wlock) | |
254 self.applied.append(revlog.hex(n) + ":" + pname) | |
255 self.applied_dirty = 1 | |
256 | |
257 head = self.qparents(repo) | |
258 | |
259 for patch in series: | |
260 patch = mergeq.lookup(patch) | |
261 if not patch: | |
262 self.ui.warn("patch %s does not exist\n" % patch) | |
263 return (1, None) | |
264 | |
265 info = mergeq.isapplied(patch) | |
266 if not info: | |
267 self.ui.warn("patch %s is not applied\n" % patch) | |
268 return (1, None) | |
269 rev = revlog.bin(info[1]) | |
270 (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock) | |
271 if head: | |
272 self.applied.append(revlog.hex(head) + ":" + patch) | |
273 self.applied_dirty = 1 | |
274 if err: | |
275 return (err, head) | |
276 return (0, head) | |
277 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
278 def apply(self, repo, series, list=False, update_status=True, |
1808 | 279 strict=False, patchdir=None, merge=None, wlock=None): |
280 # TODO unify with commands.py | |
281 if not patchdir: | |
282 patchdir = self.path | |
283 pwd = os.getcwd() | |
284 os.chdir(repo.root) | |
285 err = 0 | |
286 if not wlock: | |
287 wlock = repo.wlock() | |
288 lock = repo.lock() | |
289 tr = repo.transaction() | |
290 n = None | |
291 for patch in series: | |
292 self.ui.warn("applying %s\n" % patch) | |
293 pf = os.path.join(patchdir, patch) | |
294 | |
295 try: | |
2299
dacf718e1d48
Add timestamp field to export format. Make import and mq use it.
Danek Duvall <danek.duvall@sun.com>
parents:
2270
diff
changeset
|
296 message, comments, user, date, patchfound = self.readheaders(patch) |
1808 | 297 except: |
298 self.ui.warn("Unable to read %s\n" % pf) | |
299 err = 1 | |
300 break | |
301 | |
302 if not message: | |
303 message = "imported patch %s\n" % patch | |
304 else: | |
305 if list: | |
306 message.append("\nimported patch %s" % patch) | |
307 message = '\n'.join(message) | |
308 | |
309 try: | |
2270
afd7c4ec000f
Fix issue240: mq: qpush fails on Solaris
Danek Duvall <danek.duvall@sun.com>
parents:
2185
diff
changeset
|
310 pp = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') |
afd7c4ec000f
Fix issue240: mq: qpush fails on Solaris
Danek Duvall <danek.duvall@sun.com>
parents:
2185
diff
changeset
|
311 f = os.popen("%s -p1 --no-backup-if-mismatch < '%s'" % (pp, pf)) |
1808 | 312 except: |
313 self.ui.warn("patch failed, unable to continue (try -v)\n") | |
314 err = 1 | |
315 break | |
316 files = [] | |
317 fuzz = False | |
318 for l in f: | |
319 l = l.rstrip('\r\n'); | |
320 if self.ui.verbose: | |
321 self.ui.warn(l + "\n") | |
322 if l[:14] == 'patching file ': | |
323 pf = os.path.normpath(l[14:]) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
324 # when patch finds a space in the file name, it puts |
1808 | 325 # single quotes around the filename. strip them off |
326 if pf[0] == "'" and pf[-1] == "'": | |
327 pf = pf[1:-1] | |
328 if pf not in files: | |
329 files.append(pf) | |
330 printed_file = False | |
331 file_str = l | |
332 elif l.find('with fuzz') >= 0: | |
333 if not printed_file: | |
334 self.ui.warn(file_str + '\n') | |
335 printed_file = True | |
336 self.ui.warn(l + '\n') | |
337 fuzz = True | |
338 elif l.find('saving rejects to file') >= 0: | |
339 self.ui.warn(l + '\n') | |
340 elif l.find('FAILED') >= 0: | |
341 if not printed_file: | |
342 self.ui.warn(file_str + '\n') | |
343 printed_file = True | |
344 self.ui.warn(l + '\n') | |
345 patcherr = f.close() | |
346 | |
347 if merge and len(files) > 0: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
348 # Mark as merged and update dirstate parent info |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
349 repo.dirstate.update(repo.dirstate.filterfiles(files), 'm') |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
350 p1, p2 = repo.dirstate.parents() |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
351 repo.dirstate.setparents(p1, merge) |
1808 | 352 if len(files) > 0: |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
353 commands.addremove_lock(self.ui, repo, files, |
1808 | 354 opts={}, wlock=wlock) |
2299
dacf718e1d48
Add timestamp field to export format. Make import and mq use it.
Danek Duvall <danek.duvall@sun.com>
parents:
2270
diff
changeset
|
355 n = repo.commit(files, message, user, date, force=1, lock=lock, |
1808 | 356 wlock=wlock) |
357 | |
358 if n == None: | |
359 self.ui.warn("repo commit failed\n") | |
360 sys.exit(1) | |
361 | |
362 if update_status: | |
363 self.applied.append(revlog.hex(n) + ":" + patch) | |
364 | |
365 if patcherr: | |
366 if not patchfound: | |
367 self.ui.warn("patch %s is empty\n" % patch) | |
368 err = 0 | |
369 else: | |
370 self.ui.warn("patch failed, rejects left in working dir\n") | |
371 err = 1 | |
372 break | |
373 | |
374 if fuzz and strict: | |
375 self.ui.warn("fuzz found when applying patch, stopping\n") | |
376 err = 1 | |
377 break | |
378 tr.close() | |
379 os.chdir(pwd) | |
380 return (err, n) | |
381 | |
382 def delete(self, repo, patch): | |
383 patch = self.lookup(patch) | |
384 info = self.isapplied(patch) | |
385 if info: | |
386 self.ui.warn("cannot delete applied patch %s\n" % patch) | |
387 sys.exit(1) | |
388 if patch not in self.series: | |
389 self.ui.warn("patch %s not in series file\n" % patch) | |
390 sys.exit(1) | |
391 i = self.find_series(patch) | |
392 del self.full_series[i] | |
393 self.read_series(self.full_series) | |
394 self.series_dirty = 1 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
395 |
1808 | 396 def check_toppatch(self, repo): |
397 if len(self.applied) > 0: | |
398 (top, patch) = self.applied[-1].split(':') | |
399 top = revlog.bin(top) | |
400 pp = repo.dirstate.parents() | |
401 if top not in pp: | |
402 self.ui.warn("queue top not at dirstate parents. top %s dirstate %s %s\n" %( revlog.short(top), revlog.short(pp[0]), revlog.short(pp[1]))) | |
403 sys.exit(1) | |
404 return top | |
405 return None | |
406 def check_localchanges(self, repo): | |
407 (c, a, r, d, u) = repo.changes(None, None) | |
408 if c or a or d or r: | |
409 self.ui.write("Local changes found, refresh first\n") | |
410 sys.exit(1) | |
411 def new(self, repo, patch, msg=None, force=None): | |
2511
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
412 commitfiles = [] |
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
413 (c, a, r, d, u) = repo.changes(None, None) |
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
414 if c or a or d or r: |
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
415 if not force: |
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
416 raise util.Abort(_("Local changes found, refresh first")) |
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
417 else: |
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
418 commitfiles = c + a + r |
1808 | 419 self.check_toppatch(repo) |
420 wlock = repo.wlock() | |
421 insert = self.series_end() | |
422 if msg: | |
2511
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
423 n = repo.commit(commitfiles, "[mq]: %s" % msg, force=True, |
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
424 wlock=wlock) |
1808 | 425 else: |
2511
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
426 n = repo.commit(commitfiles, |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
427 "New patch: %s" % patch, force=True, wlock=wlock) |
1808 | 428 if n == None: |
429 self.ui.warn("repo commit failed\n") | |
430 sys.exit(1) | |
431 self.full_series[insert:insert] = [patch] | |
432 self.applied.append(revlog.hex(n) + ":" + patch) | |
433 self.read_series(self.full_series) | |
434 self.series_dirty = 1 | |
435 self.applied_dirty = 1 | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
436 p = self.opener(patch, "w") |
1808 | 437 if msg: |
438 msg = msg + "\n" | |
439 p.write(msg) | |
440 p.close() | |
441 wlock = None | |
442 r = self.qrepo() | |
443 if r: r.add([patch]) | |
2511
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
444 if commitfiles: |
041d8f0a8437
mq: hg qnew -f should refresh the new patch
Chris Mason <mason@suse.com>
parents:
2488
diff
changeset
|
445 self.refresh(repo, short=True) |
1808 | 446 |
447 def strip(self, repo, rev, update=True, backup="all", wlock=None): | |
448 def limitheads(chlog, stop): | |
449 """return the list of all nodes that have no children""" | |
450 p = {} | |
451 h = [] | |
452 stoprev = 0 | |
453 if stop in chlog.nodemap: | |
454 stoprev = chlog.rev(stop) | |
455 | |
456 for r in range(chlog.count() - 1, -1, -1): | |
457 n = chlog.node(r) | |
458 if n not in p: | |
459 h.append(n) | |
460 if n == stop: | |
461 break | |
462 if r < stoprev: | |
463 break | |
464 for pn in chlog.parents(n): | |
465 p[pn] = 1 | |
466 return h | |
467 | |
468 def bundle(cg): | |
469 backupdir = repo.join("strip-backup") | |
470 if not os.path.isdir(backupdir): | |
471 os.mkdir(backupdir) | |
472 name = os.path.join(backupdir, "%s" % revlog.short(rev)) | |
473 name = savename(name) | |
474 self.ui.warn("saving bundle to %s\n" % name) | |
475 # TODO, exclusive open | |
476 f = open(name, "wb") | |
477 try: | |
478 f.write("HG10") | |
479 z = bz2.BZ2Compressor(9) | |
480 while 1: | |
481 chunk = cg.read(4096) | |
482 if not chunk: | |
483 break | |
484 f.write(z.compress(chunk)) | |
485 f.write(z.flush()) | |
486 except: | |
487 os.unlink(name) | |
488 raise | |
489 f.close() | |
490 return name | |
491 | |
492 def stripall(rev, revnum): | |
493 cl = repo.changelog | |
494 c = cl.read(rev) | |
495 mm = repo.manifest.read(c[0]) | |
496 seen = {} | |
497 | |
498 for x in xrange(revnum, cl.count()): | |
499 c = cl.read(cl.node(x)) | |
500 for f in c[3]: | |
501 if f in seen: | |
502 continue | |
503 seen[f] = 1 | |
504 if f in mm: | |
505 filerev = mm[f] | |
506 else: | |
507 filerev = 0 | |
508 seen[f] = filerev | |
509 # we go in two steps here so the strip loop happens in a | |
510 # sensible order. When stripping many files, this helps keep | |
511 # our disk access patterns under control. | |
512 list = seen.keys() | |
513 list.sort() | |
514 for f in list: | |
515 ff = repo.file(f) | |
516 filerev = seen[f] | |
517 if filerev != 0: | |
518 if filerev in ff.nodemap: | |
519 filerev = ff.rev(filerev) | |
520 else: | |
521 filerev = 0 | |
522 ff.strip(filerev, revnum) | |
523 | |
524 if not wlock: | |
525 wlock = repo.wlock() | |
526 lock = repo.lock() | |
527 chlog = repo.changelog | |
528 # TODO delete the undo files, and handle undo of merge sets | |
529 pp = chlog.parents(rev) | |
530 revnum = chlog.rev(rev) | |
531 | |
532 if update: | |
533 urev = self.qparents(repo, rev) | |
534 repo.update(urev, allow=False, force=True, wlock=wlock) | |
535 repo.dirstate.write() | |
536 | |
537 # save is a list of all the branches we are truncating away | |
538 # that we actually want to keep. changegroup will be used | |
539 # to preserve them and add them back after the truncate | |
540 saveheads = [] | |
541 savebases = {} | |
542 | |
543 tip = chlog.tip() | |
544 heads = limitheads(chlog, rev) | |
545 seen = {} | |
546 | |
547 # search through all the heads, finding those where the revision | |
548 # we want to strip away is an ancestor. Also look for merges | |
549 # that might be turned into new heads by the strip. | |
550 while heads: | |
551 h = heads.pop() | |
552 n = h | |
553 while True: | |
554 seen[n] = 1 | |
555 pp = chlog.parents(n) | |
556 if pp[1] != revlog.nullid and chlog.rev(pp[1]) > revnum: | |
557 if pp[1] not in seen: | |
558 heads.append(pp[1]) | |
559 if pp[0] == revlog.nullid: | |
560 break | |
561 if chlog.rev(pp[0]) < revnum: | |
562 break | |
563 n = pp[0] | |
564 if n == rev: | |
565 break | |
566 r = chlog.reachable(h, rev) | |
567 if rev not in r: | |
568 saveheads.append(h) | |
569 for x in r: | |
570 if chlog.rev(x) > revnum: | |
571 savebases[x] = 1 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
572 |
1808 | 573 # create a changegroup for all the branches we need to keep |
574 if backup is "all": | |
575 backupch = repo.changegroupsubset([rev], chlog.heads(), 'strip') | |
576 bundle(backupch) | |
577 if saveheads: | |
578 backupch = repo.changegroupsubset(savebases.keys(), saveheads, 'strip') | |
579 chgrpfile = bundle(backupch) | |
580 | |
581 stripall(rev, revnum) | |
582 | |
583 change = chlog.read(rev) | |
584 repo.manifest.strip(repo.manifest.rev(change[0]), revnum) | |
585 chlog.strip(revnum, revnum) | |
586 if saveheads: | |
587 self.ui.status("adding branch\n") | |
588 commands.unbundle(self.ui, repo, chgrpfile, update=False) | |
589 if backup is not "strip": | |
590 os.unlink(chgrpfile) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
591 |
1808 | 592 def isapplied(self, patch): |
593 """returns (index, rev, patch)""" | |
594 for i in xrange(len(self.applied)): | |
595 p = self.applied[i] | |
596 a = p.split(':') | |
597 if a[1] == patch: | |
598 return (i, a[0], a[1]) | |
599 return None | |
600 | |
601 def lookup(self, patch): | |
602 if patch == None: | |
603 return None | |
604 if patch in self.series: | |
605 return patch | |
606 if not os.path.isfile(os.path.join(self.path, patch)): | |
607 try: | |
608 sno = int(patch) | |
609 except(ValueError, OverflowError): | |
610 self.ui.warn("patch %s not in series\n" % patch) | |
611 sys.exit(1) | |
612 if sno >= len(self.series): | |
613 self.ui.warn("patch number %d is out of range\n" % sno) | |
614 sys.exit(1) | |
615 patch = self.series[sno] | |
616 else: | |
617 self.ui.warn("patch %s not in series\n" % patch) | |
618 sys.exit(1) | |
619 return patch | |
620 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
621 def push(self, repo, patch=None, force=False, list=False, |
1808 | 622 mergeq=None, wlock=None): |
623 if not wlock: | |
624 wlock = repo.wlock() | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
625 patch = self.lookup(patch) |
1808 | 626 if patch and self.isapplied(patch): |
627 self.ui.warn("patch %s is already applied\n" % patch) | |
628 sys.exit(1) | |
629 if self.series_end() == len(self.series): | |
630 self.ui.warn("File series fully applied\n") | |
631 sys.exit(1) | |
632 if not force: | |
633 self.check_localchanges(repo) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
634 |
1808 | 635 self.applied_dirty = 1; |
636 start = self.series_end() | |
637 if start > 0: | |
638 self.check_toppatch(repo) | |
639 if not patch: | |
640 patch = self.series[start] | |
641 end = start + 1 | |
642 else: | |
643 end = self.series.index(patch, start) + 1 | |
644 s = self.series[start:end] | |
645 if mergeq: | |
646 ret = self.mergepatch(repo, mergeq, s, wlock) | |
647 else: | |
648 ret = self.apply(repo, s, list, wlock=wlock) | |
649 top = self.applied[-1].split(':')[1] | |
650 if ret[0]: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
651 self.ui.write("Errors during apply, please fix and refresh %s\n" % |
1808 | 652 top) |
653 else: | |
654 self.ui.write("Now at: %s\n" % top) | |
655 return ret[0] | |
656 | |
657 def pop(self, repo, patch=None, force=False, update=True, wlock=None): | |
658 def getfile(f, rev): | |
659 t = repo.file(f).read(rev) | |
660 try: | |
661 repo.wfile(f, "w").write(t) | |
662 except IOError: | |
2086
8742352db413
mq: do not fail if directory to create exists
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2047
diff
changeset
|
663 try: |
8742352db413
mq: do not fail if directory to create exists
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2047
diff
changeset
|
664 os.makedirs(os.path.dirname(repo.wjoin(f))) |
8742352db413
mq: do not fail if directory to create exists
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2047
diff
changeset
|
665 except OSError, err: |
8742352db413
mq: do not fail if directory to create exists
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2047
diff
changeset
|
666 if err.errno != errno.EEXIST: raise |
1808 | 667 repo.wfile(f, "w").write(t) |
668 | |
669 if not wlock: | |
670 wlock = repo.wlock() | |
671 if patch: | |
672 # index, rev, patch | |
673 info = self.isapplied(patch) | |
674 if not info: | |
675 patch = self.lookup(patch) | |
676 info = self.isapplied(patch) | |
677 if not info: | |
678 self.ui.warn("patch %s is not applied\n" % patch) | |
679 sys.exit(1) | |
680 if len(self.applied) == 0: | |
681 self.ui.warn("No patches applied\n") | |
682 sys.exit(1) | |
683 | |
684 if not update: | |
685 parents = repo.dirstate.parents() | |
686 rr = [ revlog.bin(x.split(':')[0]) for x in self.applied ] | |
687 for p in parents: | |
688 if p in rr: | |
689 self.ui.warn("qpop: forcing dirstate update\n") | |
690 update = True | |
691 | |
692 if not force and update: | |
693 self.check_localchanges(repo) | |
694 | |
695 self.applied_dirty = 1; | |
696 end = len(self.applied) | |
697 if not patch: | |
698 info = [len(self.applied) - 1] + self.applied[-1].split(':') | |
699 start = info[0] | |
700 rev = revlog.bin(info[1]) | |
701 | |
702 # we know there are no local changes, so we can make a simplified | |
703 # form of hg.update. | |
704 if update: | |
705 top = self.check_toppatch(repo) | |
706 qp = self.qparents(repo, rev) | |
707 changes = repo.changelog.read(qp) | |
708 mf1 = repo.manifest.readflags(changes[0]) | |
709 mmap = repo.manifest.read(changes[0]) | |
710 (c, a, r, d, u) = repo.changes(qp, top) | |
711 if d: | |
712 raise util.Abort("deletions found between repo revs") | |
713 for f in c: | |
714 getfile(f, mmap[f]) | |
715 for f in r: | |
716 getfile(f, mmap[f]) | |
717 util.set_exec(repo.wjoin(f), mf1[f]) | |
718 repo.dirstate.update(c + r, 'n') | |
719 for f in a: | |
720 try: os.unlink(repo.wjoin(f)) | |
721 except: raise | |
722 try: os.removedirs(os.path.dirname(repo.wjoin(f))) | |
723 except: pass | |
724 if a: | |
725 repo.dirstate.forget(a) | |
726 repo.dirstate.setparents(qp, revlog.nullid) | |
727 self.strip(repo, rev, update=False, backup='strip', wlock=wlock) | |
728 del self.applied[start:end] | |
729 if len(self.applied): | |
730 self.ui.write("Now at: %s\n" % self.applied[-1].split(':')[1]) | |
731 else: | |
732 self.ui.write("Patch queue now empty\n") | |
733 | |
734 def diff(self, repo, files): | |
735 top = self.check_toppatch(repo) | |
736 if not top: | |
737 self.ui.write("No patches applied\n") | |
738 return | |
739 qp = self.qparents(repo, top) | |
740 commands.dodiff(sys.stdout, self.ui, repo, qp, None, files) | |
741 | |
742 def refresh(self, repo, short=False): | |
743 if len(self.applied) == 0: | |
744 self.ui.write("No patches applied\n") | |
745 return | |
746 wlock = repo.wlock() | |
747 self.check_toppatch(repo) | |
748 qp = self.qparents(repo) | |
749 (top, patch) = self.applied[-1].split(':') | |
750 top = revlog.bin(top) | |
751 cparents = repo.changelog.parents(top) | |
752 patchparent = self.qparents(repo, top) | |
2299
dacf718e1d48
Add timestamp field to export format. Make import and mq use it.
Danek Duvall <danek.duvall@sun.com>
parents:
2270
diff
changeset
|
753 message, comments, user, date, patchfound = self.readheaders(patch) |
1808 | 754 |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
755 patchf = self.opener(patch, "w") |
1808 | 756 if comments: |
757 comments = "\n".join(comments) + '\n\n' | |
758 patchf.write(comments) | |
759 | |
760 tip = repo.changelog.tip() | |
761 if top == tip: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
762 # if the top of our patch queue is also the tip, there is an |
1808 | 763 # optimization here. We update the dirstate in place and strip |
764 # off the tip commit. Then just commit the current directory | |
765 # tree. We can also send repo.commit the list of files | |
766 # changed to speed up the diff | |
767 # | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
768 # in short mode, we only diff the files included in the |
1808 | 769 # patch already |
770 # | |
771 # this should really read: | |
772 #(cc, dd, aa, aa2, uu) = repo.changes(tip, patchparent) | |
773 # but we do it backwards to take advantage of manifest/chlog | |
774 # caching against the next repo.changes call | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
775 # |
1808 | 776 (cc, aa, dd, aa2, uu) = repo.changes(patchparent, tip) |
777 if short: | |
778 filelist = cc + aa + dd | |
779 else: | |
780 filelist = None | |
781 (c, a, r, d, u) = repo.changes(None, None, filelist) | |
782 | |
783 # we might end up with files that were added between tip and | |
784 # the dirstate parent, but then changed in the local dirstate. | |
785 # in this case, we want them to only show up in the added section | |
786 for x in c: | |
787 if x not in aa: | |
788 cc.append(x) | |
789 # we might end up with files added by the local dirstate that | |
790 # were deleted by the patch. In this case, they should only | |
791 # show up in the changed section. | |
792 for x in a: | |
793 if x in dd: | |
794 del dd[dd.index(x)] | |
795 cc.append(x) | |
796 else: | |
797 aa.append(x) | |
798 # make sure any files deleted in the local dirstate | |
799 # are not in the add or change column of the patch | |
800 forget = [] | |
801 for x in d + r: | |
802 if x in aa: | |
803 del aa[aa.index(x)] | |
804 forget.append(x) | |
805 continue | |
806 elif x in cc: | |
807 del cc[cc.index(x)] | |
808 dd.append(x) | |
809 | |
810 c = list(util.unique(cc)) | |
811 r = list(util.unique(dd)) | |
812 a = list(util.unique(aa)) | |
813 filelist = list(util.unique(c + r + a )) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
814 commands.dodiff(patchf, self.ui, repo, patchparent, None, |
1808 | 815 filelist, changes=(c, a, r, [], u)) |
816 patchf.close() | |
817 | |
818 changes = repo.changelog.read(tip) | |
819 repo.dirstate.setparents(*cparents) | |
820 repo.dirstate.update(a, 'a') | |
821 repo.dirstate.update(r, 'r') | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
822 repo.dirstate.update(c, 'n') |
1808 | 823 repo.dirstate.forget(forget) |
824 | |
825 if not message: | |
826 message = "patch queue: %s\n" % patch | |
827 else: | |
828 message = "\n".join(message) | |
829 self.strip(repo, top, update=False, backup='strip', wlock=wlock) | |
830 n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock) | |
831 self.applied[-1] = revlog.hex(n) + ':' + patch | |
832 self.applied_dirty = 1 | |
833 else: | |
834 commands.dodiff(patchf, self.ui, repo, patchparent, None) | |
835 patchf.close() | |
836 self.pop(repo, force=True, wlock=wlock) | |
837 self.push(repo, force=True, wlock=wlock) | |
838 | |
839 def init(self, repo, create=False): | |
840 if os.path.isdir(self.path): | |
841 raise util.Abort("patch queue directory already exists") | |
842 os.mkdir(self.path) | |
843 if create: | |
844 return self.qrepo(create=True) | |
845 | |
846 def unapplied(self, repo, patch=None): | |
847 if patch and patch not in self.series: | |
848 self.ui.warn("%s not in the series file\n" % patch) | |
849 sys.exit(1) | |
850 if not patch: | |
851 start = self.series_end() | |
852 else: | |
853 start = self.series.index(patch) + 1 | |
854 for p in self.series[start:]: | |
2677
ec05ce9cbf47
mq: uniform verbose display of patche[s].
"Mathieu Clabaut <mathieu.clabaut@gmail.com>"
parents:
2664
diff
changeset
|
855 if self.ui.verbose: |
ec05ce9cbf47
mq: uniform verbose display of patche[s].
"Mathieu Clabaut <mathieu.clabaut@gmail.com>"
parents:
2664
diff
changeset
|
856 self.ui.write("%d " % self.series.index(p)) |
1808 | 857 self.ui.write("%s\n" % p) |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
858 |
1808 | 859 def qseries(self, repo, missing=None): |
860 start = self.series_end() | |
861 if not missing: | |
862 for p in self.series[:start]: | |
863 if self.ui.verbose: | |
864 self.ui.write("%d A " % self.series.index(p)) | |
865 self.ui.write("%s\n" % p) | |
866 for p in self.series[start:]: | |
867 if self.ui.verbose: | |
868 self.ui.write("%d U " % self.series.index(p)) | |
869 self.ui.write("%s\n" % p) | |
870 else: | |
871 list = [] | |
872 for root, dirs, files in os.walk(self.path): | |
873 d = root[len(self.path) + 1:] | |
874 for f in files: | |
875 fl = os.path.join(d, f) | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
876 if (fl not in self.series and |
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
877 fl not in (self.status_path, self.series_path) |
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
878 and not fl.startswith('.')): |
1808 | 879 list.append(fl) |
880 list.sort() | |
881 if list: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
882 for x in list: |
1808 | 883 if self.ui.verbose: |
884 self.ui.write("D ") | |
885 self.ui.write("%s\n" % x) | |
886 | |
887 def issaveline(self, l): | |
888 name = l.split(':')[1] | |
889 if name == '.hg.patches.save.line': | |
890 return True | |
891 | |
892 def qrepo(self, create=False): | |
893 if create or os.path.isdir(os.path.join(self.path, ".hg")): | |
1839
876e4e6ad82b
Create local ui object per repository, so .hg/hgrc don't get mixed.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1810
diff
changeset
|
894 return hg.repository(self.ui, path=self.path, create=create) |
1808 | 895 |
896 def restore(self, repo, rev, delete=None, qupdate=None): | |
897 c = repo.changelog.read(rev) | |
898 desc = c[4].strip() | |
899 lines = desc.splitlines() | |
900 i = 0 | |
901 datastart = None | |
902 series = [] | |
903 applied = [] | |
904 qpp = None | |
905 for i in xrange(0, len(lines)): | |
906 if lines[i] == 'Patch Data:': | |
907 datastart = i + 1 | |
908 elif lines[i].startswith('Dirstate:'): | |
909 l = lines[i].rstrip() | |
910 l = l[10:].split(' ') | |
911 qpp = [ hg.bin(x) for x in l ] | |
912 elif datastart != None: | |
913 l = lines[i].rstrip() | |
914 index = l.index(':') | |
915 id = l[:index] | |
916 file = l[index + 1:] | |
917 if id: | |
918 applied.append(l) | |
919 series.append(file) | |
920 if datastart == None: | |
921 self.ui.warn("No saved patch data found\n") | |
922 return 1 | |
923 self.ui.warn("restoring status: %s\n" % lines[0]) | |
924 self.full_series = series | |
925 self.applied = applied | |
926 self.read_series(self.full_series) | |
927 self.series_dirty = 1 | |
928 self.applied_dirty = 1 | |
929 heads = repo.changelog.heads() | |
930 if delete: | |
931 if rev not in heads: | |
932 self.ui.warn("save entry has children, leaving it alone\n") | |
933 else: | |
934 self.ui.warn("removing save entry %s\n" % hg.short(rev)) | |
935 pp = repo.dirstate.parents() | |
936 if rev in pp: | |
937 update = True | |
938 else: | |
939 update = False | |
940 self.strip(repo, rev, update=update, backup='strip') | |
941 if qpp: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
942 self.ui.warn("saved queue repository parents: %s %s\n" % |
1808 | 943 (hg.short(qpp[0]), hg.short(qpp[1]))) |
944 if qupdate: | |
945 print "queue directory updating" | |
946 r = self.qrepo() | |
947 if not r: | |
948 self.ui.warn("Unable to load queue repository\n") | |
949 return 1 | |
950 r.update(qpp[0], allow=False, force=True) | |
951 | |
952 def save(self, repo, msg=None): | |
953 if len(self.applied) == 0: | |
954 self.ui.warn("save: no patches applied, exiting\n") | |
955 return 1 | |
956 if self.issaveline(self.applied[-1]): | |
957 self.ui.warn("status is already saved\n") | |
958 return 1 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
959 |
1808 | 960 ar = [ ':' + x for x in self.full_series ] |
961 if not msg: | |
962 msg = "hg patches saved state" | |
963 else: | |
964 msg = "hg patches: " + msg.rstrip('\r\n') | |
965 r = self.qrepo() | |
966 if r: | |
967 pp = r.dirstate.parents() | |
968 msg += "\nDirstate: %s %s" % (hg.hex(pp[0]), hg.hex(pp[1])) | |
969 msg += "\n\nPatch Data:\n" | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
970 text = msg + "\n".join(self.applied) + '\n' + (ar and "\n".join(ar) |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
971 + '\n' or "") |
1808 | 972 n = repo.commit(None, text, user=None, force=1) |
973 if not n: | |
974 self.ui.warn("repo commit failed\n") | |
975 return 1 | |
976 self.applied.append(revlog.hex(n) + ":" + '.hg.patches.save.line') | |
977 self.applied_dirty = 1 | |
978 | |
979 def series_end(self): | |
980 end = 0 | |
981 if len(self.applied) > 0: | |
982 (top, p) = self.applied[-1].split(':') | |
983 try: | |
984 end = self.series.index(p) | |
985 except ValueError: | |
986 return 0 | |
987 return end + 1 | |
988 return end | |
989 | |
990 def qapplied(self, repo, patch=None): | |
991 if patch and patch not in self.series: | |
992 self.ui.warn("%s not in the series file\n" % patch) | |
993 sys.exit(1) | |
994 if not patch: | |
995 end = len(self.applied) | |
996 else: | |
997 end = self.series.index(patch) + 1 | |
998 for x in xrange(end): | |
999 p = self.appliedname(x) | |
1000 self.ui.write("%s\n" % p) | |
1001 | |
1002 def appliedname(self, index): | |
1003 p = self.applied[index] | |
2677
ec05ce9cbf47
mq: uniform verbose display of patche[s].
"Mathieu Clabaut <mathieu.clabaut@gmail.com>"
parents:
2664
diff
changeset
|
1004 pname = p.split(':')[1] |
1808 | 1005 if not self.ui.verbose: |
2677
ec05ce9cbf47
mq: uniform verbose display of patche[s].
"Mathieu Clabaut <mathieu.clabaut@gmail.com>"
parents:
2664
diff
changeset
|
1006 p = pname |
ec05ce9cbf47
mq: uniform verbose display of patche[s].
"Mathieu Clabaut <mathieu.clabaut@gmail.com>"
parents:
2664
diff
changeset
|
1007 else: |
ec05ce9cbf47
mq: uniform verbose display of patche[s].
"Mathieu Clabaut <mathieu.clabaut@gmail.com>"
parents:
2664
diff
changeset
|
1008 p = str(self.series.index(pname)) + " " + p |
1808 | 1009 return p |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1010 |
1808 | 1011 def top(self, repo): |
1012 if len(self.applied): | |
1013 p = self.appliedname(-1) | |
1014 self.ui.write(p + '\n') | |
1015 else: | |
1016 self.ui.write("No patches applied\n") | |
1017 | |
1018 def next(self, repo): | |
1019 end = self.series_end() | |
1020 if end == len(self.series): | |
1021 self.ui.write("All patches applied\n") | |
1022 else: | |
2677
ec05ce9cbf47
mq: uniform verbose display of patche[s].
"Mathieu Clabaut <mathieu.clabaut@gmail.com>"
parents:
2664
diff
changeset
|
1023 p = self.series[end] |
ec05ce9cbf47
mq: uniform verbose display of patche[s].
"Mathieu Clabaut <mathieu.clabaut@gmail.com>"
parents:
2664
diff
changeset
|
1024 if self.ui.verbose: |
ec05ce9cbf47
mq: uniform verbose display of patche[s].
"Mathieu Clabaut <mathieu.clabaut@gmail.com>"
parents:
2664
diff
changeset
|
1025 self.ui.write("%d " % self.series.index(p)) |
ec05ce9cbf47
mq: uniform verbose display of patche[s].
"Mathieu Clabaut <mathieu.clabaut@gmail.com>"
parents:
2664
diff
changeset
|
1026 self.ui.write(p + '\n') |
1808 | 1027 |
1028 def prev(self, repo): | |
1029 if len(self.applied) > 1: | |
1030 p = self.appliedname(-2) | |
1031 self.ui.write(p + '\n') | |
1032 elif len(self.applied) == 1: | |
1033 self.ui.write("Only one patch applied\n") | |
1034 else: | |
1035 self.ui.write("No patches applied\n") | |
1036 | |
1037 def qimport(self, repo, files, patch=None, existing=None, force=None): | |
1038 if len(files) > 1 and patch: | |
1039 self.ui.warn("-n option not valid when importing multiple files\n") | |
1040 sys.exit(1) | |
1041 i = 0 | |
2488
2785aeb51be4
mq: add qimported patches if patch dir is a repo
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2301
diff
changeset
|
1042 added = [] |
1808 | 1043 for filename in files: |
1044 if existing: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1045 if not patch: |
1808 | 1046 patch = filename |
1047 if not os.path.isfile(os.path.join(self.path, patch)): | |
1048 self.ui.warn("patch %s does not exist\n" % patch) | |
1049 sys.exit(1) | |
1050 else: | |
1051 try: | |
1052 text = file(filename).read() | |
1053 except IOError: | |
1054 self.ui.warn("Unable to read %s\n" % patch) | |
1055 sys.exit(1) | |
1056 if not patch: | |
1057 patch = os.path.split(filename)[1] | |
1058 if not force and os.path.isfile(os.path.join(self.path, patch)): | |
1059 self.ui.warn("patch %s already exists\n" % patch) | |
1060 sys.exit(1) | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
1061 patchf = self.opener(patch, "w") |
1808 | 1062 patchf.write(text) |
1063 if patch in self.series: | |
1064 self.ui.warn("patch %s is already in the series file\n" % patch) | |
1065 sys.exit(1) | |
1066 index = self.series_end() + i | |
1067 self.full_series[index:index] = [patch] | |
1068 self.read_series(self.full_series) | |
1069 self.ui.warn("adding %s to series file\n" % patch) | |
1070 i += 1 | |
2488
2785aeb51be4
mq: add qimported patches if patch dir is a repo
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2301
diff
changeset
|
1071 added.append(patch) |
1808 | 1072 patch = None |
1073 self.series_dirty = 1 | |
2488
2785aeb51be4
mq: add qimported patches if patch dir is a repo
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2301
diff
changeset
|
1074 qrepo = self.qrepo() |
2785aeb51be4
mq: add qimported patches if patch dir is a repo
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2301
diff
changeset
|
1075 if qrepo: |
2785aeb51be4
mq: add qimported patches if patch dir is a repo
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2301
diff
changeset
|
1076 qrepo.add(added) |
1808 | 1077 |
1078 def delete(ui, repo, patch, **opts): | |
1079 """remove a patch from the series file""" | |
1080 q = repomap[repo] | |
1081 q.delete(repo, patch) | |
1082 q.save_dirty() | |
1083 return 0 | |
1084 | |
1085 def applied(ui, repo, patch=None, **opts): | |
1086 """print the patches already applied""" | |
1087 repomap[repo].qapplied(repo, patch) | |
1088 return 0 | |
1089 | |
1090 def unapplied(ui, repo, patch=None, **opts): | |
1091 """print the patches not yet applied""" | |
1092 repomap[repo].unapplied(repo, patch) | |
1093 return 0 | |
1094 | |
1095 def qimport(ui, repo, *filename, **opts): | |
1096 """import a patch""" | |
1097 q = repomap[repo] | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1098 q.qimport(repo, filename, patch=opts['name'], |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1099 existing=opts['existing'], force=opts['force']) |
1808 | 1100 q.save_dirty() |
1101 return 0 | |
1102 | |
1103 def init(ui, repo, **opts): | |
1104 """init a new queue repository""" | |
1105 q = repomap[repo] | |
1106 r = q.init(repo, create=opts['create_repo']) | |
1107 q.save_dirty() | |
1108 if r: | |
1109 fp = r.wopener('.hgignore', 'w') | |
1110 print >> fp, 'syntax: glob' | |
1111 print >> fp, 'status' | |
1112 fp.close() | |
1113 r.wopener('series', 'w').close() | |
1114 r.add(['.hgignore', 'series']) | |
1115 return 0 | |
1116 | |
1117 def commit(ui, repo, *pats, **opts): | |
2526
37785f986260
mq: Added help for qcommit, consistently talk about queue repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2488
diff
changeset
|
1118 """commit changes in the queue repository""" |
1808 | 1119 q = repomap[repo] |
1120 r = q.qrepo() | |
1121 if not r: raise util.Abort('no queue repository') | |
1122 commands.commit(r.ui, r, *pats, **opts) | |
1123 | |
1124 def series(ui, repo, **opts): | |
1125 """print the entire series file""" | |
1126 repomap[repo].qseries(repo, missing=opts['missing']) | |
1127 return 0 | |
1128 | |
1129 def top(ui, repo, **opts): | |
1130 """print the name of the current patch""" | |
1131 repomap[repo].top(repo) | |
1132 return 0 | |
1133 | |
1134 def next(ui, repo, **opts): | |
1135 """print the name of the next patch""" | |
1136 repomap[repo].next(repo) | |
1137 return 0 | |
1138 | |
1139 def prev(ui, repo, **opts): | |
1140 """print the name of the previous patch""" | |
1141 repomap[repo].prev(repo) | |
1142 return 0 | |
1143 | |
1144 def new(ui, repo, patch, **opts): | |
1145 """create a new patch""" | |
1146 q = repomap[repo] | |
1147 q.new(repo, patch, msg=opts['message'], force=opts['force']) | |
1148 q.save_dirty() | |
1149 return 0 | |
1150 | |
1151 def refresh(ui, repo, **opts): | |
1152 """update the current patch""" | |
1153 q = repomap[repo] | |
1154 q.refresh(repo, short=opts['short']) | |
1155 q.save_dirty() | |
1156 return 0 | |
1157 | |
1158 def diff(ui, repo, *files, **opts): | |
1159 """diff of the current patch""" | |
2097
4d2c2597876f
Fix hg qdiff <file>
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2086
diff
changeset
|
1160 # deep in the dirstate code, the walkhelper method wants a list, not a tuple |
4d2c2597876f
Fix hg qdiff <file>
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2086
diff
changeset
|
1161 repomap[repo].diff(repo, list(files)) |
1808 | 1162 return 0 |
1163 | |
1164 def lastsavename(path): | |
1165 (dir, base) = os.path.split(path) | |
1166 names = os.listdir(dir) | |
1167 namere = re.compile("%s.([0-9]+)" % base) | |
1168 max = None | |
1169 maxname = None | |
1170 for f in names: | |
1171 m = namere.match(f) | |
1172 if m: | |
1173 index = int(m.group(1)) | |
1174 if max == None or index > max: | |
1175 max = index | |
1176 maxname = f | |
1177 if maxname: | |
1178 return (os.path.join(dir, maxname), max) | |
1179 return (None, None) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1180 |
1808 | 1181 def savename(path): |
1182 (last, index) = lastsavename(path) | |
1183 if last is None: | |
1184 index = 0 | |
1185 newpath = path + ".%d" % (index + 1) | |
1186 return newpath | |
1187 | |
1188 def push(ui, repo, patch=None, **opts): | |
1189 """push the next patch onto the stack""" | |
1190 q = repomap[repo] | |
1191 mergeq = None | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1192 |
1808 | 1193 if opts['all']: |
1194 patch = q.series[-1] | |
1195 if opts['merge']: | |
1196 if opts['name']: | |
1197 newpath = opts['name'] | |
1198 else: | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1199 newpath, i = lastsavename(q.path) |
1808 | 1200 if not newpath: |
1201 ui.warn("no saved queues found, please use -n\n") | |
1202 return 1 | |
1203 mergeq = queue(ui, repo.join(""), newpath) | |
1204 ui.warn("merging with queue at: %s\n" % mergeq.path) | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1205 ret = q.push(repo, patch, force=opts['force'], list=opts['list'], |
1808 | 1206 mergeq=mergeq) |
1207 q.save_dirty() | |
1208 return ret | |
1209 | |
1210 def pop(ui, repo, patch=None, **opts): | |
1211 """pop the current patch off the stack""" | |
1212 localupdate = True | |
1213 if opts['name']: | |
1214 q = queue(ui, repo.join(""), repo.join(opts['name'])) | |
1215 ui.warn('using patch queue: %s\n' % q.path) | |
1216 localupdate = False | |
1217 else: | |
1218 q = repomap[repo] | |
1219 if opts['all'] and len(q.applied) > 0: | |
1220 patch = q.applied[0].split(':')[1] | |
1221 q.pop(repo, patch, force=opts['force'], update=localupdate) | |
1222 q.save_dirty() | |
1223 return 0 | |
1224 | |
1225 def restore(ui, repo, rev, **opts): | |
1226 """restore the queue state saved by a rev""" | |
1227 rev = repo.lookup(rev) | |
1228 q = repomap[repo] | |
1229 q.restore(repo, rev, delete=opts['delete'], | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1230 qupdate=opts['update']) |
1808 | 1231 q.save_dirty() |
1232 return 0 | |
1233 | |
1234 def save(ui, repo, **opts): | |
1235 """save current queue state""" | |
1236 q = repomap[repo] | |
1237 ret = q.save(repo, msg=opts['message']) | |
1238 if ret: | |
1239 return ret | |
1240 q.save_dirty() | |
1241 if opts['copy']: | |
1242 path = q.path | |
1243 if opts['name']: | |
1244 newpath = os.path.join(q.basepath, opts['name']) | |
1245 if os.path.exists(newpath): | |
1246 if not os.path.isdir(newpath): | |
1247 ui.warn("destination %s exists and is not a directory\n" % | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1248 newpath) |
1808 | 1249 sys.exit(1) |
1250 if not opts['force']: | |
1251 ui.warn("destination %s exists, use -f to force\n" % | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1252 newpath) |
1808 | 1253 sys.exit(1) |
1254 else: | |
1255 newpath = savename(path) | |
1256 ui.warn("copy %s to %s\n" % (path, newpath)) | |
1257 util.copyfiles(path, newpath) | |
1258 if opts['empty']: | |
1259 try: | |
1852
fdf9cbf56ec7
Fix mq's usage of opener, which don't allow absolute paths now.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1839
diff
changeset
|
1260 os.unlink(os.path.join(q.path, q.status_path)) |
1808 | 1261 except: |
1262 pass | |
1263 return 0 | |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1264 |
1808 | 1265 def strip(ui, repo, rev, **opts): |
1266 """strip a revision and all later revs on the same branch""" | |
1267 rev = repo.lookup(rev) | |
1268 backup = 'all' | |
1269 if opts['backup']: | |
1270 backup = 'strip' | |
1271 elif opts['nobackup']: | |
1272 backup = 'none' | |
1273 repomap[repo].strip(repo, rev, backup=backup) | |
1274 return 0 | |
1275 | |
1276 def version(ui, q=None): | |
1277 """print the version number""" | |
1278 ui.write("mq version %s\n" % versionstr) | |
1279 return 0 | |
1280 | |
1281 def reposetup(ui, repo): | |
1282 repomap[repo] = queue(ui, repo.join("")) | |
2682
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1283 oldtags = repo.tags |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1284 |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1285 def qtags(): |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1286 if repo.tagscache: |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1287 return repo.tagscache |
2663
96950d39171d
Mq: modify repo.lookup to resolve applied patches too.
Brendan Cully <brendan@kublai.com>
parents:
2554
diff
changeset
|
1288 |
2682
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1289 tagscache = oldtags() |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1290 |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1291 q = repomap[repo] |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1292 if len(q.applied) == 0: |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1293 return tagscache |
2664
9b8df8dceeed
Add qtip and qbase to mq qlookup.
Brendan Cully <brendan@kublai.com>
parents:
2663
diff
changeset
|
1294 |
2682
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1295 mqtags = [patch.split(':') for patch in q.applied] |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1296 mqtags.append((mqtags[-1][0], 'qtip')) |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1297 mqtags.append((mqtags[0][0], 'qbase')) |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1298 for patch in mqtags: |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1299 if patch[1] in tagscache: |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1300 repo.ui.warn('Tag %s overrides mq patch of the same name\n' % patch[1]) |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1301 else: |
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1302 tagscache[patch[1]] = revlog.bin(patch[0]) |
2664
9b8df8dceeed
Add qtip and qbase to mq qlookup.
Brendan Cully <brendan@kublai.com>
parents:
2663
diff
changeset
|
1303 |
2682
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1304 return tagscache |
2663
96950d39171d
Mq: modify repo.lookup to resolve applied patches too.
Brendan Cully <brendan@kublai.com>
parents:
2554
diff
changeset
|
1305 |
2682
4e2dc5c16e61
Add mq patch names to tagscache instead of overriding lookup.
Brendan Cully <brendan@kublai.com>
parents:
2677
diff
changeset
|
1306 repo.tags = qtags |
1808 | 1307 |
1308 cmdtable = { | |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1309 "qapplied": (applied, [], 'hg qapplied [PATCH]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1310 "qcommit|qci": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1311 (commit, |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1312 commands.table["^commit|ci"][1], |
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1313 'hg qcommit [OPTION]... [FILE]...'), |
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1314 "^qdiff": (diff, [], 'hg qdiff [FILE]...'), |
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1315 "qdelete": (delete, [], 'hg qdelete PATCH'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1316 "^qimport": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1317 (qimport, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1318 [('e', 'existing', None, 'import file in patch dir'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1319 ('n', 'name', '', 'patch file name'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1320 ('f', 'force', None, 'overwrite existing files')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1321 'hg qimport [-e] [-n NAME] [-f] FILE...'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1322 "^qinit": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1323 (init, |
2526
37785f986260
mq: Added help for qcommit, consistently talk about queue repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2488
diff
changeset
|
1324 [('c', 'create-repo', None, 'create queue repository')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1325 'hg qinit [-c]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1326 "qnew": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1327 (new, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1328 [('m', 'message', '', 'commit message'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1329 ('f', 'force', None, 'force')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1330 'hg qnew [-m TEXT] [-f] PATCH'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1331 "qnext": (next, [], 'hg qnext'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1332 "qprev": (prev, [], 'hg qprev'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1333 "^qpop": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1334 (pop, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1335 [('a', 'all', None, 'pop all patches'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1336 ('n', 'name', '', 'queue name to pop'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1337 ('f', 'force', None, 'forget any local changes')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1338 'hg qpop [-a] [-n NAME] [-f] [PATCH | INDEX]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1339 "^qpush": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1340 (push, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1341 [('f', 'force', None, 'apply if the patch has rejects'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1342 ('l', 'list', None, 'list patch name in commit text'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1343 ('a', 'all', None, 'apply all patches'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1344 ('m', 'merge', None, 'merge from another queue'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1345 ('n', 'name', '', 'merge queue name')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1346 'hg qpush [-f] [-l] [-a] [-m] [-n NAME] [PATCH | INDEX]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1347 "^qrefresh": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1348 (refresh, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1349 [('s', 'short', None, 'short refresh')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1350 'hg qrefresh [-s]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1351 "qrestore": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1352 (restore, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1353 [('d', 'delete', None, 'delete save entry'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1354 ('u', 'update', None, 'update queue working dir')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1355 'hg qrestore [-d] [-u] REV'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1356 "qsave": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1357 (save, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1358 [('m', 'message', '', 'commit message'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1359 ('c', 'copy', None, 'copy patch directory'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1360 ('n', 'name', '', 'copy directory name'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1361 ('e', 'empty', None, 'clear queue status file'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1362 ('f', 'force', None, 'force copy')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1363 'hg qsave [-m TEXT] [-c] [-n NAME] [-e] [-f]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1364 "qseries": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1365 (series, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1366 [('m', 'missing', None, 'print patches not in series')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1367 'hg qseries [-m]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1368 "^strip": |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1369 (strip, |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1370 [('f', 'force', None, 'force multi-head removal'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1371 ('b', 'backup', None, 'bundle unrelated changesets'), |
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1372 ('n', 'nobackup', None, 'no backups')], |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1373 'hg strip [-f] [-b] [-n] REV'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1374 "qtop": (top, [], 'hg qtop'), |
2185
5acd648770d0
Better help for mq: Corrected synopses, get qcommit options from commands.py.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2097
diff
changeset
|
1375 "qunapplied": (unapplied, [], 'hg qunapplied [PATCH]'), |
1810
7596611ab3d5
Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1808
diff
changeset
|
1376 "qversion": (version, [], 'hg qversion') |
1808 | 1377 } |
1378 |