##// END OF EJS Templates
tags: explicitly log which tags cache file is being written...
Gregory Szorc -
r24763:a698e088 default
parent child Browse files
Show More
@@ -1,533 +1,534
1 # tags.py - read tag info from local repository
1 # tags.py - read tag info from local repository
2 #
2 #
3 # Copyright 2009 Matt Mackall <mpm@selenic.com>
3 # Copyright 2009 Matt Mackall <mpm@selenic.com>
4 # Copyright 2009 Greg Ward <greg@gerg.ca>
4 # Copyright 2009 Greg Ward <greg@gerg.ca>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 # Currently this module only deals with reading and caching tags.
9 # Currently this module only deals with reading and caching tags.
10 # Eventually, it could take care of updating (adding/removing/moving)
10 # Eventually, it could take care of updating (adding/removing/moving)
11 # tags too.
11 # tags too.
12
12
13 from node import nullid, bin, hex, short
13 from node import nullid, bin, hex, short
14 from i18n import _
14 from i18n import _
15 import util
15 import util
16 import encoding
16 import encoding
17 import error
17 import error
18 from array import array
18 from array import array
19 import errno
19 import errno
20 import time
20 import time
21
21
22 # Tags computation can be expensive and caches exist to make it fast in
22 # Tags computation can be expensive and caches exist to make it fast in
23 # the common case.
23 # the common case.
24 #
24 #
25 # The "hgtagsfnodes1" cache file caches the .hgtags filenode values for
25 # The "hgtagsfnodes1" cache file caches the .hgtags filenode values for
26 # each revision in the repository. The file is effectively an array of
26 # each revision in the repository. The file is effectively an array of
27 # fixed length records. Read the docs for "hgtagsfnodescache" for technical
27 # fixed length records. Read the docs for "hgtagsfnodescache" for technical
28 # details.
28 # details.
29 #
29 #
30 # The .hgtags filenode cache grows in proportion to the length of the
30 # The .hgtags filenode cache grows in proportion to the length of the
31 # changelog. The file is truncated when the # changelog is stripped.
31 # changelog. The file is truncated when the # changelog is stripped.
32 #
32 #
33 # The purpose of the filenode cache is to avoid the most expensive part
33 # The purpose of the filenode cache is to avoid the most expensive part
34 # of finding global tags, which is looking up the .hgtags filenode in the
34 # of finding global tags, which is looking up the .hgtags filenode in the
35 # manifest for each head. This can take dozens or over 100ms for
35 # manifest for each head. This can take dozens or over 100ms for
36 # repositories with very large manifests. Multiplied by dozens or even
36 # repositories with very large manifests. Multiplied by dozens or even
37 # hundreds of heads and there is a significant performance concern.
37 # hundreds of heads and there is a significant performance concern.
38 #
38 #
39 # There also exist a separate cache file for each repository filter.
39 # There also exist a separate cache file for each repository filter.
40 # These "tags-*" files store information about the history of tags.
40 # These "tags-*" files store information about the history of tags.
41 #
41 #
42 # The tags cache files consists of a cache validation line followed by
42 # The tags cache files consists of a cache validation line followed by
43 # a history of tags.
43 # a history of tags.
44 #
44 #
45 # The cache validation line has the format:
45 # The cache validation line has the format:
46 #
46 #
47 # <tiprev> <tipnode> [<filteredhash>]
47 # <tiprev> <tipnode> [<filteredhash>]
48 #
48 #
49 # <tiprev> is an integer revision and <tipnode> is a 40 character hex
49 # <tiprev> is an integer revision and <tipnode> is a 40 character hex
50 # node for that changeset. These redundantly identify the repository
50 # node for that changeset. These redundantly identify the repository
51 # tip from the time the cache was written. In addition, <filteredhash>,
51 # tip from the time the cache was written. In addition, <filteredhash>,
52 # if present, is a 40 character hex hash of the contents of the filtered
52 # if present, is a 40 character hex hash of the contents of the filtered
53 # revisions for this filter. If the set of filtered revs changes, the
53 # revisions for this filter. If the set of filtered revs changes, the
54 # hash will change and invalidate the cache.
54 # hash will change and invalidate the cache.
55 #
55 #
56 # The history part of the tags cache consists of lines of the form:
56 # The history part of the tags cache consists of lines of the form:
57 #
57 #
58 # <node> <tag>
58 # <node> <tag>
59 #
59 #
60 # (This format is identical to that of .hgtags files.)
60 # (This format is identical to that of .hgtags files.)
61 #
61 #
62 # <tag> is the tag name and <node> is the 40 character hex changeset
62 # <tag> is the tag name and <node> is the 40 character hex changeset
63 # the tag is associated with.
63 # the tag is associated with.
64 #
64 #
65 # Tags are written sorted by tag name.
65 # Tags are written sorted by tag name.
66 #
66 #
67 # Tags associated with multiple changesets have an entry for each changeset.
67 # Tags associated with multiple changesets have an entry for each changeset.
68 # The most recent changeset (in terms of revlog ordering for the head
68 # The most recent changeset (in terms of revlog ordering for the head
69 # setting it) for each tag is last.
69 # setting it) for each tag is last.
70
70
71 def findglobaltags(ui, repo, alltags, tagtypes):
71 def findglobaltags(ui, repo, alltags, tagtypes):
72 '''Find global tags in a repo.
72 '''Find global tags in a repo.
73
73
74 "alltags" maps tag name to (node, hist) 2-tuples.
74 "alltags" maps tag name to (node, hist) 2-tuples.
75
75
76 "tagtypes" maps tag name to tag type. Global tags always have the
76 "tagtypes" maps tag name to tag type. Global tags always have the
77 "global" tag type.
77 "global" tag type.
78
78
79 The "alltags" and "tagtypes" dicts are updated in place. Empty dicts
79 The "alltags" and "tagtypes" dicts are updated in place. Empty dicts
80 should be passed in.
80 should be passed in.
81
81
82 The tags cache is read and updated as a side-effect of calling.
82 The tags cache is read and updated as a side-effect of calling.
83 '''
83 '''
84 # This is so we can be lazy and assume alltags contains only global
84 # This is so we can be lazy and assume alltags contains only global
85 # tags when we pass it to _writetagcache().
85 # tags when we pass it to _writetagcache().
86 assert len(alltags) == len(tagtypes) == 0, \
86 assert len(alltags) == len(tagtypes) == 0, \
87 "findglobaltags() should be called first"
87 "findglobaltags() should be called first"
88
88
89 (heads, tagfnode, valid, cachetags, shouldwrite) = _readtagcache(ui, repo)
89 (heads, tagfnode, valid, cachetags, shouldwrite) = _readtagcache(ui, repo)
90 if cachetags is not None:
90 if cachetags is not None:
91 assert not shouldwrite
91 assert not shouldwrite
92 # XXX is this really 100% correct? are there oddball special
92 # XXX is this really 100% correct? are there oddball special
93 # cases where a global tag should outrank a local tag but won't,
93 # cases where a global tag should outrank a local tag but won't,
94 # because cachetags does not contain rank info?
94 # because cachetags does not contain rank info?
95 _updatetags(cachetags, 'global', alltags, tagtypes)
95 _updatetags(cachetags, 'global', alltags, tagtypes)
96 return
96 return
97
97
98 seen = set() # set of fnode
98 seen = set() # set of fnode
99 fctx = None
99 fctx = None
100 for head in reversed(heads): # oldest to newest
100 for head in reversed(heads): # oldest to newest
101 assert head in repo.changelog.nodemap, \
101 assert head in repo.changelog.nodemap, \
102 "tag cache returned bogus head %s" % short(head)
102 "tag cache returned bogus head %s" % short(head)
103
103
104 fnode = tagfnode.get(head)
104 fnode = tagfnode.get(head)
105 if fnode and fnode not in seen:
105 if fnode and fnode not in seen:
106 seen.add(fnode)
106 seen.add(fnode)
107 if not fctx:
107 if not fctx:
108 fctx = repo.filectx('.hgtags', fileid=fnode)
108 fctx = repo.filectx('.hgtags', fileid=fnode)
109 else:
109 else:
110 fctx = fctx.filectx(fnode)
110 fctx = fctx.filectx(fnode)
111
111
112 filetags = _readtags(ui, repo, fctx.data().splitlines(), fctx)
112 filetags = _readtags(ui, repo, fctx.data().splitlines(), fctx)
113 _updatetags(filetags, 'global', alltags, tagtypes)
113 _updatetags(filetags, 'global', alltags, tagtypes)
114
114
115 # and update the cache (if necessary)
115 # and update the cache (if necessary)
116 if shouldwrite:
116 if shouldwrite:
117 _writetagcache(ui, repo, valid, alltags)
117 _writetagcache(ui, repo, valid, alltags)
118
118
119 def readlocaltags(ui, repo, alltags, tagtypes):
119 def readlocaltags(ui, repo, alltags, tagtypes):
120 '''Read local tags in repo. Update alltags and tagtypes.'''
120 '''Read local tags in repo. Update alltags and tagtypes.'''
121 try:
121 try:
122 data = repo.vfs.read("localtags")
122 data = repo.vfs.read("localtags")
123 except IOError, inst:
123 except IOError, inst:
124 if inst.errno != errno.ENOENT:
124 if inst.errno != errno.ENOENT:
125 raise
125 raise
126 return
126 return
127
127
128 # localtags is in the local encoding; re-encode to UTF-8 on
128 # localtags is in the local encoding; re-encode to UTF-8 on
129 # input for consistency with the rest of this module.
129 # input for consistency with the rest of this module.
130 filetags = _readtags(
130 filetags = _readtags(
131 ui, repo, data.splitlines(), "localtags",
131 ui, repo, data.splitlines(), "localtags",
132 recode=encoding.fromlocal)
132 recode=encoding.fromlocal)
133
133
134 # remove tags pointing to invalid nodes
134 # remove tags pointing to invalid nodes
135 cl = repo.changelog
135 cl = repo.changelog
136 for t in filetags.keys():
136 for t in filetags.keys():
137 try:
137 try:
138 cl.rev(filetags[t][0])
138 cl.rev(filetags[t][0])
139 except (LookupError, ValueError):
139 except (LookupError, ValueError):
140 del filetags[t]
140 del filetags[t]
141
141
142 _updatetags(filetags, "local", alltags, tagtypes)
142 _updatetags(filetags, "local", alltags, tagtypes)
143
143
144 def _readtaghist(ui, repo, lines, fn, recode=None, calcnodelines=False):
144 def _readtaghist(ui, repo, lines, fn, recode=None, calcnodelines=False):
145 '''Read tag definitions from a file (or any source of lines).
145 '''Read tag definitions from a file (or any source of lines).
146
146
147 This function returns two sortdicts with similar information:
147 This function returns two sortdicts with similar information:
148
148
149 - the first dict, bintaghist, contains the tag information as expected by
149 - the first dict, bintaghist, contains the tag information as expected by
150 the _readtags function, i.e. a mapping from tag name to (node, hist):
150 the _readtags function, i.e. a mapping from tag name to (node, hist):
151 - node is the node id from the last line read for that name,
151 - node is the node id from the last line read for that name,
152 - hist is the list of node ids previously associated with it (in file
152 - hist is the list of node ids previously associated with it (in file
153 order). All node ids are binary, not hex.
153 order). All node ids are binary, not hex.
154
154
155 - the second dict, hextaglines, is a mapping from tag name to a list of
155 - the second dict, hextaglines, is a mapping from tag name to a list of
156 [hexnode, line number] pairs, ordered from the oldest to the newest node.
156 [hexnode, line number] pairs, ordered from the oldest to the newest node.
157
157
158 When calcnodelines is False the hextaglines dict is not calculated (an
158 When calcnodelines is False the hextaglines dict is not calculated (an
159 empty dict is returned). This is done to improve this function's
159 empty dict is returned). This is done to improve this function's
160 performance in cases where the line numbers are not needed.
160 performance in cases where the line numbers are not needed.
161 '''
161 '''
162
162
163 bintaghist = util.sortdict()
163 bintaghist = util.sortdict()
164 hextaglines = util.sortdict()
164 hextaglines = util.sortdict()
165 count = 0
165 count = 0
166
166
167 def warn(msg):
167 def warn(msg):
168 ui.warn(_("%s, line %s: %s\n") % (fn, count, msg))
168 ui.warn(_("%s, line %s: %s\n") % (fn, count, msg))
169
169
170 for nline, line in enumerate(lines):
170 for nline, line in enumerate(lines):
171 count += 1
171 count += 1
172 if not line:
172 if not line:
173 continue
173 continue
174 try:
174 try:
175 (nodehex, name) = line.split(" ", 1)
175 (nodehex, name) = line.split(" ", 1)
176 except ValueError:
176 except ValueError:
177 warn(_("cannot parse entry"))
177 warn(_("cannot parse entry"))
178 continue
178 continue
179 name = name.strip()
179 name = name.strip()
180 if recode:
180 if recode:
181 name = recode(name)
181 name = recode(name)
182 try:
182 try:
183 nodebin = bin(nodehex)
183 nodebin = bin(nodehex)
184 except TypeError:
184 except TypeError:
185 warn(_("node '%s' is not well formed") % nodehex)
185 warn(_("node '%s' is not well formed") % nodehex)
186 continue
186 continue
187
187
188 # update filetags
188 # update filetags
189 if calcnodelines:
189 if calcnodelines:
190 # map tag name to a list of line numbers
190 # map tag name to a list of line numbers
191 if name not in hextaglines:
191 if name not in hextaglines:
192 hextaglines[name] = []
192 hextaglines[name] = []
193 hextaglines[name].append([nodehex, nline])
193 hextaglines[name].append([nodehex, nline])
194 continue
194 continue
195 # map tag name to (node, hist)
195 # map tag name to (node, hist)
196 if name not in bintaghist:
196 if name not in bintaghist:
197 bintaghist[name] = []
197 bintaghist[name] = []
198 bintaghist[name].append(nodebin)
198 bintaghist[name].append(nodebin)
199 return bintaghist, hextaglines
199 return bintaghist, hextaglines
200
200
201 def _readtags(ui, repo, lines, fn, recode=None, calcnodelines=False):
201 def _readtags(ui, repo, lines, fn, recode=None, calcnodelines=False):
202 '''Read tag definitions from a file (or any source of lines).
202 '''Read tag definitions from a file (or any source of lines).
203
203
204 Returns a mapping from tag name to (node, hist).
204 Returns a mapping from tag name to (node, hist).
205
205
206 "node" is the node id from the last line read for that name. "hist"
206 "node" is the node id from the last line read for that name. "hist"
207 is the list of node ids previously associated with it (in file order).
207 is the list of node ids previously associated with it (in file order).
208 All node ids are binary, not hex.
208 All node ids are binary, not hex.
209 '''
209 '''
210 filetags, nodelines = _readtaghist(ui, repo, lines, fn, recode=recode,
210 filetags, nodelines = _readtaghist(ui, repo, lines, fn, recode=recode,
211 calcnodelines=calcnodelines)
211 calcnodelines=calcnodelines)
212 for tag, taghist in filetags.items():
212 for tag, taghist in filetags.items():
213 filetags[tag] = (taghist[-1], taghist[:-1])
213 filetags[tag] = (taghist[-1], taghist[:-1])
214 return filetags
214 return filetags
215
215
216 def _updatetags(filetags, tagtype, alltags, tagtypes):
216 def _updatetags(filetags, tagtype, alltags, tagtypes):
217 '''Incorporate the tag info read from one file into the two
217 '''Incorporate the tag info read from one file into the two
218 dictionaries, alltags and tagtypes, that contain all tag
218 dictionaries, alltags and tagtypes, that contain all tag
219 info (global across all heads plus local).'''
219 info (global across all heads plus local).'''
220
220
221 for name, nodehist in filetags.iteritems():
221 for name, nodehist in filetags.iteritems():
222 if name not in alltags:
222 if name not in alltags:
223 alltags[name] = nodehist
223 alltags[name] = nodehist
224 tagtypes[name] = tagtype
224 tagtypes[name] = tagtype
225 continue
225 continue
226
226
227 # we prefer alltags[name] if:
227 # we prefer alltags[name] if:
228 # it supersedes us OR
228 # it supersedes us OR
229 # mutual supersedes and it has a higher rank
229 # mutual supersedes and it has a higher rank
230 # otherwise we win because we're tip-most
230 # otherwise we win because we're tip-most
231 anode, ahist = nodehist
231 anode, ahist = nodehist
232 bnode, bhist = alltags[name]
232 bnode, bhist = alltags[name]
233 if (bnode != anode and anode in bhist and
233 if (bnode != anode and anode in bhist and
234 (bnode not in ahist or len(bhist) > len(ahist))):
234 (bnode not in ahist or len(bhist) > len(ahist))):
235 anode = bnode
235 anode = bnode
236 else:
236 else:
237 tagtypes[name] = tagtype
237 tagtypes[name] = tagtype
238 ahist.extend([n for n in bhist if n not in ahist])
238 ahist.extend([n for n in bhist if n not in ahist])
239 alltags[name] = anode, ahist
239 alltags[name] = anode, ahist
240
240
241 def _filename(repo):
241 def _filename(repo):
242 """name of a tagcache file for a given repo or repoview"""
242 """name of a tagcache file for a given repo or repoview"""
243 filename = 'cache/tags2'
243 filename = 'cache/tags2'
244 if repo.filtername:
244 if repo.filtername:
245 filename = '%s-%s' % (filename, repo.filtername)
245 filename = '%s-%s' % (filename, repo.filtername)
246 return filename
246 return filename
247
247
248 def _readtagcache(ui, repo):
248 def _readtagcache(ui, repo):
249 '''Read the tag cache.
249 '''Read the tag cache.
250
250
251 Returns a tuple (heads, fnodes, validinfo, cachetags, shouldwrite).
251 Returns a tuple (heads, fnodes, validinfo, cachetags, shouldwrite).
252
252
253 If the cache is completely up-to-date, "cachetags" is a dict of the
253 If the cache is completely up-to-date, "cachetags" is a dict of the
254 form returned by _readtags() and "heads", "fnodes", and "validinfo" are
254 form returned by _readtags() and "heads", "fnodes", and "validinfo" are
255 None and "shouldwrite" is False.
255 None and "shouldwrite" is False.
256
256
257 If the cache is not up to date, "cachetags" is None. "heads" is a list
257 If the cache is not up to date, "cachetags" is None. "heads" is a list
258 of all heads currently in the repository, ordered from tip to oldest.
258 of all heads currently in the repository, ordered from tip to oldest.
259 "validinfo" is a tuple describing cache validation info. This is used
259 "validinfo" is a tuple describing cache validation info. This is used
260 when writing the tags cache. "fnodes" is a mapping from head to .hgtags
260 when writing the tags cache. "fnodes" is a mapping from head to .hgtags
261 filenode. "shouldwrite" is True.
261 filenode. "shouldwrite" is True.
262
262
263 If the cache is not up to date, the caller is responsible for reading tag
263 If the cache is not up to date, the caller is responsible for reading tag
264 info from each returned head. (See findglobaltags().)
264 info from each returned head. (See findglobaltags().)
265 '''
265 '''
266 import scmutil # avoid cycle
266 import scmutil # avoid cycle
267
267
268 try:
268 try:
269 cachefile = repo.vfs(_filename(repo), 'r')
269 cachefile = repo.vfs(_filename(repo), 'r')
270 # force reading the file for static-http
270 # force reading the file for static-http
271 cachelines = iter(cachefile)
271 cachelines = iter(cachefile)
272 except IOError:
272 except IOError:
273 cachefile = None
273 cachefile = None
274
274
275 cacherev = None
275 cacherev = None
276 cachenode = None
276 cachenode = None
277 cachehash = None
277 cachehash = None
278 if cachefile:
278 if cachefile:
279 try:
279 try:
280 validline = cachelines.next()
280 validline = cachelines.next()
281 validline = validline.split()
281 validline = validline.split()
282 cacherev = int(validline[0])
282 cacherev = int(validline[0])
283 cachenode = bin(validline[1])
283 cachenode = bin(validline[1])
284 if len(validline) > 2:
284 if len(validline) > 2:
285 cachehash = bin(validline[2])
285 cachehash = bin(validline[2])
286 except Exception:
286 except Exception:
287 # corruption of the cache, just recompute it.
287 # corruption of the cache, just recompute it.
288 pass
288 pass
289
289
290 tipnode = repo.changelog.tip()
290 tipnode = repo.changelog.tip()
291 tiprev = len(repo.changelog) - 1
291 tiprev = len(repo.changelog) - 1
292
292
293 # Case 1 (common): tip is the same, so nothing has changed.
293 # Case 1 (common): tip is the same, so nothing has changed.
294 # (Unchanged tip trivially means no changesets have been added.
294 # (Unchanged tip trivially means no changesets have been added.
295 # But, thanks to localrepository.destroyed(), it also means none
295 # But, thanks to localrepository.destroyed(), it also means none
296 # have been destroyed by strip or rollback.)
296 # have been destroyed by strip or rollback.)
297 if (cacherev == tiprev
297 if (cacherev == tiprev
298 and cachenode == tipnode
298 and cachenode == tipnode
299 and cachehash == scmutil.filteredhash(repo, tiprev)):
299 and cachehash == scmutil.filteredhash(repo, tiprev)):
300 tags = _readtags(ui, repo, cachelines, cachefile.name)
300 tags = _readtags(ui, repo, cachelines, cachefile.name)
301 cachefile.close()
301 cachefile.close()
302 return (None, None, None, tags, False)
302 return (None, None, None, tags, False)
303 if cachefile:
303 if cachefile:
304 cachefile.close() # ignore rest of file
304 cachefile.close() # ignore rest of file
305
305
306 valid = (tiprev, tipnode, scmutil.filteredhash(repo, tiprev))
306 valid = (tiprev, tipnode, scmutil.filteredhash(repo, tiprev))
307
307
308 repoheads = repo.heads()
308 repoheads = repo.heads()
309 # Case 2 (uncommon): empty repo; get out quickly and don't bother
309 # Case 2 (uncommon): empty repo; get out quickly and don't bother
310 # writing an empty cache.
310 # writing an empty cache.
311 if repoheads == [nullid]:
311 if repoheads == [nullid]:
312 return ([], {}, valid, {}, False)
312 return ([], {}, valid, {}, False)
313
313
314 # Case 3 (uncommon): cache file missing or empty.
314 # Case 3 (uncommon): cache file missing or empty.
315
315
316 # Case 4 (uncommon): tip rev decreased. This should only happen
316 # Case 4 (uncommon): tip rev decreased. This should only happen
317 # when we're called from localrepository.destroyed(). Refresh the
317 # when we're called from localrepository.destroyed(). Refresh the
318 # cache so future invocations will not see disappeared heads in the
318 # cache so future invocations will not see disappeared heads in the
319 # cache.
319 # cache.
320
320
321 # Case 5 (common): tip has changed, so we've added/replaced heads.
321 # Case 5 (common): tip has changed, so we've added/replaced heads.
322
322
323 # As it happens, the code to handle cases 3, 4, 5 is the same.
323 # As it happens, the code to handle cases 3, 4, 5 is the same.
324
324
325 # N.B. in case 4 (nodes destroyed), "new head" really means "newly
325 # N.B. in case 4 (nodes destroyed), "new head" really means "newly
326 # exposed".
326 # exposed".
327 if not len(repo.file('.hgtags')):
327 if not len(repo.file('.hgtags')):
328 # No tags have ever been committed, so we can avoid a
328 # No tags have ever been committed, so we can avoid a
329 # potentially expensive search.
329 # potentially expensive search.
330 return ([], {}, valid, None, True)
330 return ([], {}, valid, None, True)
331
331
332 starttime = time.time()
332 starttime = time.time()
333
333
334 # Now we have to lookup the .hgtags filenode for every new head.
334 # Now we have to lookup the .hgtags filenode for every new head.
335 # This is the most expensive part of finding tags, so performance
335 # This is the most expensive part of finding tags, so performance
336 # depends primarily on the size of newheads. Worst case: no cache
336 # depends primarily on the size of newheads. Worst case: no cache
337 # file, so newheads == repoheads.
337 # file, so newheads == repoheads.
338 fnodescache = hgtagsfnodescache(repo.unfiltered())
338 fnodescache = hgtagsfnodescache(repo.unfiltered())
339 cachefnode = {}
339 cachefnode = {}
340 for head in reversed(repoheads):
340 for head in reversed(repoheads):
341 fnode = fnodescache.getfnode(head)
341 fnode = fnodescache.getfnode(head)
342 if fnode != nullid:
342 if fnode != nullid:
343 cachefnode[head] = fnode
343 cachefnode[head] = fnode
344
344
345 fnodescache.write()
345 fnodescache.write()
346
346
347 duration = time.time() - starttime
347 duration = time.time() - starttime
348 ui.log('tagscache',
348 ui.log('tagscache',
349 '%d/%d cache hits/lookups in %0.4f '
349 '%d/%d cache hits/lookups in %0.4f '
350 'seconds\n',
350 'seconds\n',
351 fnodescache.hitcount, fnodescache.lookupcount, duration)
351 fnodescache.hitcount, fnodescache.lookupcount, duration)
352
352
353 # Caller has to iterate over all heads, but can use the filenodes in
353 # Caller has to iterate over all heads, but can use the filenodes in
354 # cachefnode to get to each .hgtags revision quickly.
354 # cachefnode to get to each .hgtags revision quickly.
355 return (repoheads, cachefnode, valid, None, True)
355 return (repoheads, cachefnode, valid, None, True)
356
356
357 def _writetagcache(ui, repo, valid, cachetags):
357 def _writetagcache(ui, repo, valid, cachetags):
358 filename = _filename(repo)
358 try:
359 try:
359 cachefile = repo.vfs(_filename(repo), 'w', atomictemp=True)
360 cachefile = repo.vfs(filename, 'w', atomictemp=True)
360 except (OSError, IOError):
361 except (OSError, IOError):
361 return
362 return
362
363
363 ui.log('tagscache', 'writing tags cache file with %d tags\n',
364 ui.log('tagscache', 'writing .hg/%s with %d tags\n',
364 len(cachetags))
365 filename, len(cachetags))
365
366
366 if valid[2]:
367 if valid[2]:
367 cachefile.write('%d %s %s\n' % (valid[0], hex(valid[1]), hex(valid[2])))
368 cachefile.write('%d %s %s\n' % (valid[0], hex(valid[1]), hex(valid[2])))
368 else:
369 else:
369 cachefile.write('%d %s\n' % (valid[0], hex(valid[1])))
370 cachefile.write('%d %s\n' % (valid[0], hex(valid[1])))
370
371
371 # Tag names in the cache are in UTF-8 -- which is the whole reason
372 # Tag names in the cache are in UTF-8 -- which is the whole reason
372 # we keep them in UTF-8 throughout this module. If we converted
373 # we keep them in UTF-8 throughout this module. If we converted
373 # them local encoding on input, we would lose info writing them to
374 # them local encoding on input, we would lose info writing them to
374 # the cache.
375 # the cache.
375 for (name, (node, hist)) in sorted(cachetags.iteritems()):
376 for (name, (node, hist)) in sorted(cachetags.iteritems()):
376 for n in hist:
377 for n in hist:
377 cachefile.write("%s %s\n" % (hex(n), name))
378 cachefile.write("%s %s\n" % (hex(n), name))
378 cachefile.write("%s %s\n" % (hex(node), name))
379 cachefile.write("%s %s\n" % (hex(node), name))
379
380
380 try:
381 try:
381 cachefile.close()
382 cachefile.close()
382 except (OSError, IOError):
383 except (OSError, IOError):
383 pass
384 pass
384
385
385 _fnodescachefile = 'cache/hgtagsfnodes1'
386 _fnodescachefile = 'cache/hgtagsfnodes1'
386 _fnodesrecsize = 4 + 20 # changeset fragment + filenode
387 _fnodesrecsize = 4 + 20 # changeset fragment + filenode
387 _fnodesmissingrec = '\xff' * 24
388 _fnodesmissingrec = '\xff' * 24
388
389
389 class hgtagsfnodescache(object):
390 class hgtagsfnodescache(object):
390 """Persistent cache mapping revisions to .hgtags filenodes.
391 """Persistent cache mapping revisions to .hgtags filenodes.
391
392
392 The cache is an array of records. Each item in the array corresponds to
393 The cache is an array of records. Each item in the array corresponds to
393 a changelog revision. Values in the array contain the first 4 bytes of
394 a changelog revision. Values in the array contain the first 4 bytes of
394 the node hash and the 20 bytes .hgtags filenode for that revision.
395 the node hash and the 20 bytes .hgtags filenode for that revision.
395
396
396 The first 4 bytes are present as a form of verification. Repository
397 The first 4 bytes are present as a form of verification. Repository
397 stripping and rewriting may change the node at a numeric revision in the
398 stripping and rewriting may change the node at a numeric revision in the
398 changelog. The changeset fragment serves as a verifier to detect
399 changelog. The changeset fragment serves as a verifier to detect
399 rewriting. This logic is shared with the rev branch cache (see
400 rewriting. This logic is shared with the rev branch cache (see
400 branchmap.py).
401 branchmap.py).
401
402
402 The instance holds in memory the full cache content but entries are
403 The instance holds in memory the full cache content but entries are
403 only parsed on read.
404 only parsed on read.
404
405
405 Instances behave like lists. ``c[i]`` works where i is a rev or
406 Instances behave like lists. ``c[i]`` works where i is a rev or
406 changeset node. Missing indexes are populated automatically on access.
407 changeset node. Missing indexes are populated automatically on access.
407 """
408 """
408 def __init__(self, repo):
409 def __init__(self, repo):
409 assert repo.filtername is None
410 assert repo.filtername is None
410
411
411 self._repo = repo
412 self._repo = repo
412
413
413 # Only for reporting purposes.
414 # Only for reporting purposes.
414 self.lookupcount = 0
415 self.lookupcount = 0
415 self.hitcount = 0
416 self.hitcount = 0
416
417
417 self._raw = array('c')
418 self._raw = array('c')
418
419
419 data = repo.vfs.tryread(_fnodescachefile)
420 data = repo.vfs.tryread(_fnodescachefile)
420 self._raw.fromstring(data)
421 self._raw.fromstring(data)
421
422
422 # The end state of self._raw is an array that is of the exact length
423 # The end state of self._raw is an array that is of the exact length
423 # required to hold a record for every revision in the repository.
424 # required to hold a record for every revision in the repository.
424 # We truncate or extend the array as necessary. self._dirtyoffset is
425 # We truncate or extend the array as necessary. self._dirtyoffset is
425 # defined to be the start offset at which we need to write the output
426 # defined to be the start offset at which we need to write the output
426 # file. This offset is also adjusted when new entries are calculated
427 # file. This offset is also adjusted when new entries are calculated
427 # for array members.
428 # for array members.
428 cllen = len(repo.changelog)
429 cllen = len(repo.changelog)
429 wantedlen = cllen * _fnodesrecsize
430 wantedlen = cllen * _fnodesrecsize
430 rawlen = len(self._raw)
431 rawlen = len(self._raw)
431
432
432 self._dirtyoffset = None
433 self._dirtyoffset = None
433
434
434 if rawlen < wantedlen:
435 if rawlen < wantedlen:
435 self._dirtyoffset = rawlen
436 self._dirtyoffset = rawlen
436 self._raw.extend('\xff' * (wantedlen - rawlen))
437 self._raw.extend('\xff' * (wantedlen - rawlen))
437 elif rawlen > wantedlen:
438 elif rawlen > wantedlen:
438 # There's no easy way to truncate array instances. This seems
439 # There's no easy way to truncate array instances. This seems
439 # slightly less evil than copying a potentially large array slice.
440 # slightly less evil than copying a potentially large array slice.
440 for i in range(rawlen - wantedlen):
441 for i in range(rawlen - wantedlen):
441 self._raw.pop()
442 self._raw.pop()
442 self._dirtyoffset = len(self._raw)
443 self._dirtyoffset = len(self._raw)
443
444
444 def getfnode(self, node):
445 def getfnode(self, node):
445 """Obtain the filenode of the .hgtags file at a specified revision.
446 """Obtain the filenode of the .hgtags file at a specified revision.
446
447
447 If the value is in the cache, the entry will be validated and returned.
448 If the value is in the cache, the entry will be validated and returned.
448 Otherwise, the filenode will be computed and returned.
449 Otherwise, the filenode will be computed and returned.
449
450
450 If an .hgtags does not exist at the specified revision, nullid is
451 If an .hgtags does not exist at the specified revision, nullid is
451 returned.
452 returned.
452 """
453 """
453 ctx = self._repo[node]
454 ctx = self._repo[node]
454 rev = ctx.rev()
455 rev = ctx.rev()
455
456
456 self.lookupcount += 1
457 self.lookupcount += 1
457
458
458 offset = rev * _fnodesrecsize
459 offset = rev * _fnodesrecsize
459 record = self._raw[offset:offset + _fnodesrecsize].tostring()
460 record = self._raw[offset:offset + _fnodesrecsize].tostring()
460 properprefix = node[0:4]
461 properprefix = node[0:4]
461
462
462 # Validate and return existing entry.
463 # Validate and return existing entry.
463 if record != _fnodesmissingrec:
464 if record != _fnodesmissingrec:
464 fileprefix = record[0:4]
465 fileprefix = record[0:4]
465
466
466 if fileprefix == properprefix:
467 if fileprefix == properprefix:
467 self.hitcount += 1
468 self.hitcount += 1
468 return record[4:]
469 return record[4:]
469
470
470 # Fall through.
471 # Fall through.
471
472
472 # If we get here, the entry is either missing or invalid. Populate it.
473 # If we get here, the entry is either missing or invalid. Populate it.
473 try:
474 try:
474 fnode = ctx.filenode('.hgtags')
475 fnode = ctx.filenode('.hgtags')
475 except error.LookupError:
476 except error.LookupError:
476 # No .hgtags file on this revision.
477 # No .hgtags file on this revision.
477 fnode = nullid
478 fnode = nullid
478
479
479 # Slices on array instances only accept other array.
480 # Slices on array instances only accept other array.
480 entry = array('c', properprefix + fnode)
481 entry = array('c', properprefix + fnode)
481 self._raw[offset:offset + _fnodesrecsize] = entry
482 self._raw[offset:offset + _fnodesrecsize] = entry
482 # self._dirtyoffset could be None.
483 # self._dirtyoffset could be None.
483 self._dirtyoffset = min(self._dirtyoffset, offset) or 0
484 self._dirtyoffset = min(self._dirtyoffset, offset) or 0
484
485
485 return fnode
486 return fnode
486
487
487 def write(self):
488 def write(self):
488 """Perform all necessary writes to cache file.
489 """Perform all necessary writes to cache file.
489
490
490 This may no-op if no writes are needed or if a write lock could
491 This may no-op if no writes are needed or if a write lock could
491 not be obtained.
492 not be obtained.
492 """
493 """
493 if self._dirtyoffset is None:
494 if self._dirtyoffset is None:
494 return
495 return
495
496
496 data = self._raw[self._dirtyoffset:]
497 data = self._raw[self._dirtyoffset:]
497 if not data:
498 if not data:
498 return
499 return
499
500
500 repo = self._repo
501 repo = self._repo
501
502
502 try:
503 try:
503 lock = repo.wlock(wait=False)
504 lock = repo.wlock(wait=False)
504 except error.LockHeld:
505 except error.LockHeld:
505 repo.ui.log('tagscache',
506 repo.ui.log('tagscache',
506 'not writing .hg/%s because lock held\n' %
507 'not writing .hg/%s because lock held\n' %
507 (_fnodescachefile))
508 (_fnodescachefile))
508 return
509 return
509
510
510 try:
511 try:
511 try:
512 try:
512 f = repo.vfs.open(_fnodescachefile, 'ab')
513 f = repo.vfs.open(_fnodescachefile, 'ab')
513 try:
514 try:
514 # if the file has been truncated
515 # if the file has been truncated
515 actualoffset = f.tell()
516 actualoffset = f.tell()
516 if actualoffset < self._dirtyoffset:
517 if actualoffset < self._dirtyoffset:
517 self._dirtyoffset = actualoffset
518 self._dirtyoffset = actualoffset
518 data = self._raw[self._dirtyoffset:]
519 data = self._raw[self._dirtyoffset:]
519 f.seek(self._dirtyoffset)
520 f.seek(self._dirtyoffset)
520 f.truncate()
521 f.truncate()
521 repo.ui.log('tagscache',
522 repo.ui.log('tagscache',
522 'writing %d bytes to %s\n' % (
523 'writing %d bytes to %s\n' % (
523 len(data), _fnodescachefile))
524 len(data), _fnodescachefile))
524 f.write(data)
525 f.write(data)
525 self._dirtyoffset = None
526 self._dirtyoffset = None
526 finally:
527 finally:
527 f.close()
528 f.close()
528 except (IOError, OSError), inst:
529 except (IOError, OSError), inst:
529 repo.ui.log('tagscache',
530 repo.ui.log('tagscache',
530 "couldn't write %s: %s\n" % (
531 "couldn't write %s: %s\n" % (
531 _fnodescachefile, inst))
532 _fnodescachefile, inst))
532 finally:
533 finally:
533 lock.release()
534 lock.release()
@@ -1,147 +1,147
1 setup
1 setup
2 $ cat >> $HGRCPATH <<EOF
2 $ cat >> $HGRCPATH <<EOF
3 > [extensions]
3 > [extensions]
4 > blackbox=
4 > blackbox=
5 > mock=$TESTDIR/mockblackbox.py
5 > mock=$TESTDIR/mockblackbox.py
6 > mq=
6 > mq=
7 > EOF
7 > EOF
8 $ hg init blackboxtest
8 $ hg init blackboxtest
9 $ cd blackboxtest
9 $ cd blackboxtest
10
10
11 command, exit codes, and duration
11 command, exit codes, and duration
12
12
13 $ echo a > a
13 $ echo a > a
14 $ hg add a
14 $ hg add a
15 $ hg blackbox
15 $ hg blackbox
16 1970/01/01 00:00:00 bob> add a
16 1970/01/01 00:00:00 bob> add a
17 1970/01/01 00:00:00 bob> add a exited 0 after * seconds (glob)
17 1970/01/01 00:00:00 bob> add a exited 0 after * seconds (glob)
18
18
19 incoming change tracking
19 incoming change tracking
20
20
21 create two heads to verify that we only see one change in the log later
21 create two heads to verify that we only see one change in the log later
22 $ hg commit -ma
22 $ hg commit -ma
23 $ hg up null
23 $ hg up null
24 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
24 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
25 $ echo b > b
25 $ echo b > b
26 $ hg commit -Amb
26 $ hg commit -Amb
27 adding b
27 adding b
28 created new head
28 created new head
29
29
30 clone, commit, pull
30 clone, commit, pull
31 $ hg clone . ../blackboxtest2
31 $ hg clone . ../blackboxtest2
32 updating to branch default
32 updating to branch default
33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 $ echo c > c
34 $ echo c > c
35 $ hg commit -Amc
35 $ hg commit -Amc
36 adding c
36 adding c
37 $ cd ../blackboxtest2
37 $ cd ../blackboxtest2
38 $ hg pull
38 $ hg pull
39 pulling from $TESTTMP/blackboxtest (glob)
39 pulling from $TESTTMP/blackboxtest (glob)
40 searching for changes
40 searching for changes
41 adding changesets
41 adding changesets
42 adding manifests
42 adding manifests
43 adding file changes
43 adding file changes
44 added 1 changesets with 1 changes to 1 files
44 added 1 changesets with 1 changes to 1 files
45 (run 'hg update' to get a working copy)
45 (run 'hg update' to get a working copy)
46 $ hg blackbox -l 5
46 $ hg blackbox -l 5
47 1970/01/01 00:00:00 bob> pull
47 1970/01/01 00:00:00 bob> pull
48 1970/01/01 00:00:00 bob> updated served branch cache in ?.???? seconds (glob)
48 1970/01/01 00:00:00 bob> updated served branch cache in ?.???? seconds (glob)
49 1970/01/01 00:00:00 bob> wrote served branch cache with 1 labels and 2 nodes
49 1970/01/01 00:00:00 bob> wrote served branch cache with 1 labels and 2 nodes
50 1970/01/01 00:00:00 bob> 1 incoming changes - new heads: d02f48003e62
50 1970/01/01 00:00:00 bob> 1 incoming changes - new heads: d02f48003e62
51 1970/01/01 00:00:00 bob> pull exited 0 after * seconds (glob)
51 1970/01/01 00:00:00 bob> pull exited 0 after * seconds (glob)
52
52
53 we must not cause a failure if we cannot write to the log
53 we must not cause a failure if we cannot write to the log
54
54
55 $ hg rollback
55 $ hg rollback
56 repository tip rolled back to revision 1 (undo pull)
56 repository tip rolled back to revision 1 (undo pull)
57
57
58 #if unix-permissions no-root
58 #if unix-permissions no-root
59 $ chmod 000 .hg/blackbox.log
59 $ chmod 000 .hg/blackbox.log
60 $ hg --debug incoming
60 $ hg --debug incoming
61 warning: cannot write to blackbox.log: Permission denied
61 warning: cannot write to blackbox.log: Permission denied
62 comparing with $TESTTMP/blackboxtest (glob)
62 comparing with $TESTTMP/blackboxtest (glob)
63 query 1; heads
63 query 1; heads
64 searching for changes
64 searching for changes
65 all local heads known remotely
65 all local heads known remotely
66 changeset: 2:d02f48003e62c24e2659d97d30f2a83abe5d5d51
66 changeset: 2:d02f48003e62c24e2659d97d30f2a83abe5d5d51
67 tag: tip
67 tag: tip
68 phase: draft
68 phase: draft
69 parent: 1:6563da9dcf87b1949716e38ff3e3dfaa3198eb06
69 parent: 1:6563da9dcf87b1949716e38ff3e3dfaa3198eb06
70 parent: -1:0000000000000000000000000000000000000000
70 parent: -1:0000000000000000000000000000000000000000
71 manifest: 2:ab9d46b053ebf45b7996f2922b9893ff4b63d892
71 manifest: 2:ab9d46b053ebf45b7996f2922b9893ff4b63d892
72 user: test
72 user: test
73 date: Thu Jan 01 00:00:00 1970 +0000
73 date: Thu Jan 01 00:00:00 1970 +0000
74 files+: c
74 files+: c
75 extra: branch=default
75 extra: branch=default
76 description:
76 description:
77 c
77 c
78
78
79
79
80 #endif
80 #endif
81 $ hg pull
81 $ hg pull
82 pulling from $TESTTMP/blackboxtest (glob)
82 pulling from $TESTTMP/blackboxtest (glob)
83 searching for changes
83 searching for changes
84 adding changesets
84 adding changesets
85 adding manifests
85 adding manifests
86 adding file changes
86 adding file changes
87 added 1 changesets with 1 changes to 1 files
87 added 1 changesets with 1 changes to 1 files
88 (run 'hg update' to get a working copy)
88 (run 'hg update' to get a working copy)
89
89
90 a failure reading from the log is fine
90 a failure reading from the log is fine
91 #if unix-permissions no-root
91 #if unix-permissions no-root
92 $ hg blackbox -l 3
92 $ hg blackbox -l 3
93 abort: Permission denied: $TESTTMP/blackboxtest2/.hg/blackbox.log
93 abort: Permission denied: $TESTTMP/blackboxtest2/.hg/blackbox.log
94 [255]
94 [255]
95
95
96 $ chmod 600 .hg/blackbox.log
96 $ chmod 600 .hg/blackbox.log
97 #endif
97 #endif
98
98
99 backup bundles get logged
99 backup bundles get logged
100
100
101 $ touch d
101 $ touch d
102 $ hg commit -Amd
102 $ hg commit -Amd
103 adding d
103 adding d
104 created new head
104 created new head
105 $ hg strip tip
105 $ hg strip tip
106 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
106 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
107 saved backup bundle to $TESTTMP/blackboxtest2/.hg/strip-backup/*-backup.hg (glob)
107 saved backup bundle to $TESTTMP/blackboxtest2/.hg/strip-backup/*-backup.hg (glob)
108 $ hg blackbox -l 5
108 $ hg blackbox -l 5
109 1970/01/01 00:00:00 bob> strip tip
109 1970/01/01 00:00:00 bob> strip tip
110 1970/01/01 00:00:00 bob> saved backup bundle to $TESTTMP/blackboxtest2/.hg/strip-backup/*-backup.hg (glob)
110 1970/01/01 00:00:00 bob> saved backup bundle to $TESTTMP/blackboxtest2/.hg/strip-backup/*-backup.hg (glob)
111 1970/01/01 00:00:00 bob> updated base branch cache in ?.???? seconds (glob)
111 1970/01/01 00:00:00 bob> updated base branch cache in ?.???? seconds (glob)
112 1970/01/01 00:00:00 bob> wrote base branch cache with 1 labels and 2 nodes
112 1970/01/01 00:00:00 bob> wrote base branch cache with 1 labels and 2 nodes
113 1970/01/01 00:00:00 bob> strip tip exited 0 after * seconds (glob)
113 1970/01/01 00:00:00 bob> strip tip exited 0 after * seconds (glob)
114
114
115 extension and python hooks - use the eol extension for a pythonhook
115 extension and python hooks - use the eol extension for a pythonhook
116
116
117 $ echo '[extensions]' >> .hg/hgrc
117 $ echo '[extensions]' >> .hg/hgrc
118 $ echo 'eol=' >> .hg/hgrc
118 $ echo 'eol=' >> .hg/hgrc
119 $ echo '[hooks]' >> .hg/hgrc
119 $ echo '[hooks]' >> .hg/hgrc
120 $ echo 'update = echo hooked' >> .hg/hgrc
120 $ echo 'update = echo hooked' >> .hg/hgrc
121 $ hg update
121 $ hg update
122 hooked
122 hooked
123 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
124 $ hg blackbox -l 5
124 $ hg blackbox -l 5
125 1970/01/01 00:00:00 bob> update
125 1970/01/01 00:00:00 bob> update
126 1970/01/01 00:00:00 bob> writing tags cache file with 0 tags
126 1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 0 tags
127 1970/01/01 00:00:00 bob> pythonhook-preupdate: hgext.eol.preupdate finished in * seconds (glob)
127 1970/01/01 00:00:00 bob> pythonhook-preupdate: hgext.eol.preupdate finished in * seconds (glob)
128 1970/01/01 00:00:00 bob> exthook-update: echo hooked finished in * seconds (glob)
128 1970/01/01 00:00:00 bob> exthook-update: echo hooked finished in * seconds (glob)
129 1970/01/01 00:00:00 bob> update exited 0 after * seconds (glob)
129 1970/01/01 00:00:00 bob> update exited 0 after * seconds (glob)
130
130
131 log rotation
131 log rotation
132
132
133 $ echo '[blackbox]' >> .hg/hgrc
133 $ echo '[blackbox]' >> .hg/hgrc
134 $ echo 'maxsize = 20 b' >> .hg/hgrc
134 $ echo 'maxsize = 20 b' >> .hg/hgrc
135 $ echo 'maxfiles = 3' >> .hg/hgrc
135 $ echo 'maxfiles = 3' >> .hg/hgrc
136 $ hg status
136 $ hg status
137 $ hg status
137 $ hg status
138 $ hg status
138 $ hg status
139 $ hg tip -q
139 $ hg tip -q
140 2:d02f48003e62
140 2:d02f48003e62
141 $ ls .hg/blackbox.log*
141 $ ls .hg/blackbox.log*
142 .hg/blackbox.log
142 .hg/blackbox.log
143 .hg/blackbox.log.1
143 .hg/blackbox.log.1
144 .hg/blackbox.log.2
144 .hg/blackbox.log.2
145
145
146 cleanup
146 cleanup
147 $ cd ..
147 $ cd ..
@@ -1,1608 +1,1608
1 $ checkundo()
1 $ checkundo()
2 > {
2 > {
3 > if [ -f .hg/store/undo ]; then
3 > if [ -f .hg/store/undo ]; then
4 > echo ".hg/store/undo still exists after $1"
4 > echo ".hg/store/undo still exists after $1"
5 > fi
5 > fi
6 > }
6 > }
7
7
8 $ cat <<EOF >> $HGRCPATH
8 $ cat <<EOF >> $HGRCPATH
9 > [extensions]
9 > [extensions]
10 > mq =
10 > mq =
11 > [mq]
11 > [mq]
12 > plain = true
12 > plain = true
13 > EOF
13 > EOF
14
14
15
15
16 help
16 help
17
17
18 $ hg help mq
18 $ hg help mq
19 mq extension - manage a stack of patches
19 mq extension - manage a stack of patches
20
20
21 This extension lets you work with a stack of patches in a Mercurial
21 This extension lets you work with a stack of patches in a Mercurial
22 repository. It manages two stacks of patches - all known patches, and applied
22 repository. It manages two stacks of patches - all known patches, and applied
23 patches (subset of known patches).
23 patches (subset of known patches).
24
24
25 Known patches are represented as patch files in the .hg/patches directory.
25 Known patches are represented as patch files in the .hg/patches directory.
26 Applied patches are both patch files and changesets.
26 Applied patches are both patch files and changesets.
27
27
28 Common tasks (use "hg help command" for more details):
28 Common tasks (use "hg help command" for more details):
29
29
30 create new patch qnew
30 create new patch qnew
31 import existing patch qimport
31 import existing patch qimport
32
32
33 print patch series qseries
33 print patch series qseries
34 print applied patches qapplied
34 print applied patches qapplied
35
35
36 add known patch to applied stack qpush
36 add known patch to applied stack qpush
37 remove patch from applied stack qpop
37 remove patch from applied stack qpop
38 refresh contents of top applied patch qrefresh
38 refresh contents of top applied patch qrefresh
39
39
40 By default, mq will automatically use git patches when required to avoid
40 By default, mq will automatically use git patches when required to avoid
41 losing file mode changes, copy records, binary files or empty files creations
41 losing file mode changes, copy records, binary files or empty files creations
42 or deletions. This behaviour can be configured with:
42 or deletions. This behaviour can be configured with:
43
43
44 [mq]
44 [mq]
45 git = auto/keep/yes/no
45 git = auto/keep/yes/no
46
46
47 If set to 'keep', mq will obey the [diff] section configuration while
47 If set to 'keep', mq will obey the [diff] section configuration while
48 preserving existing git patches upon qrefresh. If set to 'yes' or 'no', mq
48 preserving existing git patches upon qrefresh. If set to 'yes' or 'no', mq
49 will override the [diff] section and always generate git or regular patches,
49 will override the [diff] section and always generate git or regular patches,
50 possibly losing data in the second case.
50 possibly losing data in the second case.
51
51
52 It may be desirable for mq changesets to be kept in the secret phase (see "hg
52 It may be desirable for mq changesets to be kept in the secret phase (see "hg
53 help phases"), which can be enabled with the following setting:
53 help phases"), which can be enabled with the following setting:
54
54
55 [mq]
55 [mq]
56 secret = True
56 secret = True
57
57
58 You will by default be managing a patch queue named "patches". You can create
58 You will by default be managing a patch queue named "patches". You can create
59 other, independent patch queues with the "hg qqueue" command.
59 other, independent patch queues with the "hg qqueue" command.
60
60
61 If the working directory contains uncommitted files, qpush, qpop and qgoto
61 If the working directory contains uncommitted files, qpush, qpop and qgoto
62 abort immediately. If -f/--force is used, the changes are discarded. Setting:
62 abort immediately. If -f/--force is used, the changes are discarded. Setting:
63
63
64 [mq]
64 [mq]
65 keepchanges = True
65 keepchanges = True
66
66
67 make them behave as if --keep-changes were passed, and non-conflicting local
67 make them behave as if --keep-changes were passed, and non-conflicting local
68 changes will be tolerated and preserved. If incompatible options such as
68 changes will be tolerated and preserved. If incompatible options such as
69 -f/--force or --exact are passed, this setting is ignored.
69 -f/--force or --exact are passed, this setting is ignored.
70
70
71 This extension used to provide a strip command. This command now lives in the
71 This extension used to provide a strip command. This command now lives in the
72 strip extension.
72 strip extension.
73
73
74 list of commands:
74 list of commands:
75
75
76 qapplied print the patches already applied
76 qapplied print the patches already applied
77 qclone clone main and patch repository at same time
77 qclone clone main and patch repository at same time
78 qdelete remove patches from queue
78 qdelete remove patches from queue
79 qdiff diff of the current patch and subsequent modifications
79 qdiff diff of the current patch and subsequent modifications
80 qfinish move applied patches into repository history
80 qfinish move applied patches into repository history
81 qfold fold the named patches into the current patch
81 qfold fold the named patches into the current patch
82 qgoto push or pop patches until named patch is at top of stack
82 qgoto push or pop patches until named patch is at top of stack
83 qguard set or print guards for a patch
83 qguard set or print guards for a patch
84 qheader print the header of the topmost or specified patch
84 qheader print the header of the topmost or specified patch
85 qimport import a patch or existing changeset
85 qimport import a patch or existing changeset
86 qnew create a new patch
86 qnew create a new patch
87 qnext print the name of the next pushable patch
87 qnext print the name of the next pushable patch
88 qpop pop the current patch off the stack
88 qpop pop the current patch off the stack
89 qprev print the name of the preceding applied patch
89 qprev print the name of the preceding applied patch
90 qpush push the next patch onto the stack
90 qpush push the next patch onto the stack
91 qqueue manage multiple patch queues
91 qqueue manage multiple patch queues
92 qrefresh update the current patch
92 qrefresh update the current patch
93 qrename rename a patch
93 qrename rename a patch
94 qselect set or print guarded patches to push
94 qselect set or print guarded patches to push
95 qseries print the entire series file
95 qseries print the entire series file
96 qtop print the name of the current patch
96 qtop print the name of the current patch
97 qunapplied print the patches not yet applied
97 qunapplied print the patches not yet applied
98
98
99 (use "hg help -v mq" to show built-in aliases and global options)
99 (use "hg help -v mq" to show built-in aliases and global options)
100
100
101 $ hg init a
101 $ hg init a
102 $ cd a
102 $ cd a
103 $ echo a > a
103 $ echo a > a
104 $ hg ci -Ama
104 $ hg ci -Ama
105 adding a
105 adding a
106
106
107 $ hg clone . ../k
107 $ hg clone . ../k
108 updating to branch default
108 updating to branch default
109 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
110
110
111 $ mkdir b
111 $ mkdir b
112 $ echo z > b/z
112 $ echo z > b/z
113 $ hg ci -Ama
113 $ hg ci -Ama
114 adding b/z
114 adding b/z
115
115
116
116
117 qinit
117 qinit
118
118
119 $ hg qinit
119 $ hg qinit
120
120
121 $ cd ..
121 $ cd ..
122 $ hg init b
122 $ hg init b
123
123
124
124
125 -R qinit
125 -R qinit
126
126
127 $ hg -R b qinit
127 $ hg -R b qinit
128
128
129 $ hg init c
129 $ hg init c
130
130
131
131
132 qinit -c
132 qinit -c
133
133
134 $ hg --cwd c qinit -c
134 $ hg --cwd c qinit -c
135 $ hg -R c/.hg/patches st
135 $ hg -R c/.hg/patches st
136 A .hgignore
136 A .hgignore
137 A series
137 A series
138
138
139
139
140 qinit; qinit -c
140 qinit; qinit -c
141
141
142 $ hg init d
142 $ hg init d
143 $ cd d
143 $ cd d
144 $ hg qinit
144 $ hg qinit
145 $ hg qinit -c
145 $ hg qinit -c
146
146
147 qinit -c should create both files if they don't exist
147 qinit -c should create both files if they don't exist
148
148
149 $ cat .hg/patches/.hgignore
149 $ cat .hg/patches/.hgignore
150 ^\.hg
150 ^\.hg
151 ^\.mq
151 ^\.mq
152 syntax: glob
152 syntax: glob
153 status
153 status
154 guards
154 guards
155 $ cat .hg/patches/series
155 $ cat .hg/patches/series
156 $ hg qinit -c
156 $ hg qinit -c
157 abort: repository $TESTTMP/d/.hg/patches already exists! (glob)
157 abort: repository $TESTTMP/d/.hg/patches already exists! (glob)
158 [255]
158 [255]
159 $ cd ..
159 $ cd ..
160
160
161 $ echo '% qinit; <stuff>; qinit -c'
161 $ echo '% qinit; <stuff>; qinit -c'
162 % qinit; <stuff>; qinit -c
162 % qinit; <stuff>; qinit -c
163 $ hg init e
163 $ hg init e
164 $ cd e
164 $ cd e
165 $ hg qnew A
165 $ hg qnew A
166 $ checkundo qnew
166 $ checkundo qnew
167 $ echo foo > foo
167 $ echo foo > foo
168 $ hg phase -r qbase
168 $ hg phase -r qbase
169 0: draft
169 0: draft
170 $ hg add foo
170 $ hg add foo
171 $ hg qrefresh
171 $ hg qrefresh
172 $ hg phase -r qbase
172 $ hg phase -r qbase
173 0: draft
173 0: draft
174 $ hg qnew B
174 $ hg qnew B
175 $ echo >> foo
175 $ echo >> foo
176 $ hg qrefresh
176 $ hg qrefresh
177 $ echo status >> .hg/patches/.hgignore
177 $ echo status >> .hg/patches/.hgignore
178 $ echo bleh >> .hg/patches/.hgignore
178 $ echo bleh >> .hg/patches/.hgignore
179 $ hg qinit -c
179 $ hg qinit -c
180 adding .hg/patches/A (glob)
180 adding .hg/patches/A (glob)
181 adding .hg/patches/B (glob)
181 adding .hg/patches/B (glob)
182 $ hg -R .hg/patches status
182 $ hg -R .hg/patches status
183 A .hgignore
183 A .hgignore
184 A A
184 A A
185 A B
185 A B
186 A series
186 A series
187
187
188 qinit -c shouldn't touch these files if they already exist
188 qinit -c shouldn't touch these files if they already exist
189
189
190 $ cat .hg/patches/.hgignore
190 $ cat .hg/patches/.hgignore
191 status
191 status
192 bleh
192 bleh
193 $ cat .hg/patches/series
193 $ cat .hg/patches/series
194 A
194 A
195 B
195 B
196
196
197 add an untracked file
197 add an untracked file
198
198
199 $ echo >> .hg/patches/flaf
199 $ echo >> .hg/patches/flaf
200
200
201 status --mq with color (issue2096)
201 status --mq with color (issue2096)
202
202
203 $ hg status --mq --config extensions.color= --config color.mode=ansi --color=always
203 $ hg status --mq --config extensions.color= --config color.mode=ansi --color=always
204 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1m.hgignore\x1b[0m (esc)
204 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1m.hgignore\x1b[0m (esc)
205 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mA\x1b[0m (esc)
205 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mA\x1b[0m (esc)
206 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mB\x1b[0m (esc)
206 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mB\x1b[0m (esc)
207 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mseries\x1b[0m (esc)
207 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mseries\x1b[0m (esc)
208 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mflaf\x1b[0m (esc)
208 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mflaf\x1b[0m (esc)
209
209
210 try the --mq option on a command provided by an extension
210 try the --mq option on a command provided by an extension
211
211
212 $ hg purge --mq --verbose --config extensions.purge=
212 $ hg purge --mq --verbose --config extensions.purge=
213 removing file flaf
213 removing file flaf
214
214
215 $ cd ..
215 $ cd ..
216
216
217 #if no-outer-repo
217 #if no-outer-repo
218
218
219 init --mq without repo
219 init --mq without repo
220
220
221 $ mkdir f
221 $ mkdir f
222 $ cd f
222 $ cd f
223 $ hg init --mq
223 $ hg init --mq
224 abort: there is no Mercurial repository here (.hg not found)
224 abort: there is no Mercurial repository here (.hg not found)
225 [255]
225 [255]
226 $ cd ..
226 $ cd ..
227
227
228 #endif
228 #endif
229
229
230 init --mq with repo path
230 init --mq with repo path
231
231
232 $ hg init g
232 $ hg init g
233 $ hg init --mq g
233 $ hg init --mq g
234 $ test -d g/.hg/patches/.hg
234 $ test -d g/.hg/patches/.hg
235
235
236 init --mq with nonexistent directory
236 init --mq with nonexistent directory
237
237
238 $ hg init --mq nonexistentdir
238 $ hg init --mq nonexistentdir
239 abort: repository nonexistentdir not found!
239 abort: repository nonexistentdir not found!
240 [255]
240 [255]
241
241
242
242
243 init --mq with bundle (non "local")
243 init --mq with bundle (non "local")
244
244
245 $ hg -R a bundle --all a.bundle >/dev/null
245 $ hg -R a bundle --all a.bundle >/dev/null
246 $ hg init --mq a.bundle
246 $ hg init --mq a.bundle
247 abort: only a local queue repository may be initialized
247 abort: only a local queue repository may be initialized
248 [255]
248 [255]
249
249
250 $ cd a
250 $ cd a
251
251
252 $ hg qnew -m 'foo bar' test.patch
252 $ hg qnew -m 'foo bar' test.patch
253
253
254 $ echo '# comment' > .hg/patches/series.tmp
254 $ echo '# comment' > .hg/patches/series.tmp
255 $ echo >> .hg/patches/series.tmp # empty line
255 $ echo >> .hg/patches/series.tmp # empty line
256 $ cat .hg/patches/series >> .hg/patches/series.tmp
256 $ cat .hg/patches/series >> .hg/patches/series.tmp
257 $ mv .hg/patches/series.tmp .hg/patches/series
257 $ mv .hg/patches/series.tmp .hg/patches/series
258
258
259
259
260 qrefresh
260 qrefresh
261
261
262 $ echo a >> a
262 $ echo a >> a
263 $ hg qrefresh
263 $ hg qrefresh
264 $ cat .hg/patches/test.patch
264 $ cat .hg/patches/test.patch
265 foo bar
265 foo bar
266
266
267 diff -r [a-f0-9]* a (re)
267 diff -r [a-f0-9]* a (re)
268 --- a/a\t(?P<date>.*) (re)
268 --- a/a\t(?P<date>.*) (re)
269 \+\+\+ b/a\t(?P<date2>.*) (re)
269 \+\+\+ b/a\t(?P<date2>.*) (re)
270 @@ -1,1 +1,2 @@
270 @@ -1,1 +1,2 @@
271 a
271 a
272 +a
272 +a
273
273
274 empty qrefresh
274 empty qrefresh
275
275
276 $ hg qrefresh -X a
276 $ hg qrefresh -X a
277
277
278 revision:
278 revision:
279
279
280 $ hg diff -r -2 -r -1
280 $ hg diff -r -2 -r -1
281
281
282 patch:
282 patch:
283
283
284 $ cat .hg/patches/test.patch
284 $ cat .hg/patches/test.patch
285 foo bar
285 foo bar
286
286
287
287
288 working dir diff:
288 working dir diff:
289
289
290 $ hg diff --nodates -q
290 $ hg diff --nodates -q
291 --- a/a
291 --- a/a
292 +++ b/a
292 +++ b/a
293 @@ -1,1 +1,2 @@
293 @@ -1,1 +1,2 @@
294 a
294 a
295 +a
295 +a
296
296
297 restore things
297 restore things
298
298
299 $ hg qrefresh
299 $ hg qrefresh
300 $ checkundo qrefresh
300 $ checkundo qrefresh
301
301
302
302
303 qpop
303 qpop
304
304
305 $ hg qpop
305 $ hg qpop
306 popping test.patch
306 popping test.patch
307 patch queue now empty
307 patch queue now empty
308 $ checkundo qpop
308 $ checkundo qpop
309
309
310
310
311 qpush with dump of tag cache
311 qpush with dump of tag cache
312 Dump the tag cache to ensure that it has exactly one head after qpush.
312 Dump the tag cache to ensure that it has exactly one head after qpush.
313
313
314 $ rm -f .hg/cache/tags-visible
314 $ rm -f .hg/cache/tags2-visible
315 $ hg tags > /dev/null
315 $ hg tags > /dev/null
316
316
317 .hg/cache/tags-visible (pre qpush):
317 .hg/cache/tags2-visible (pre qpush):
318
318
319 $ cat .hg/cache/tags-visible
319 $ cat .hg/cache/tags2-visible
320 1 [\da-f]{40} (re)
320 1 [\da-f]{40} (re)
321 $ hg qpush
321 $ hg qpush
322 applying test.patch
322 applying test.patch
323 now at: test.patch
323 now at: test.patch
324 $ hg phase -r qbase
324 $ hg phase -r qbase
325 2: draft
325 2: draft
326 $ hg tags > /dev/null
326 $ hg tags > /dev/null
327
327
328 .hg/cache/tags-visible (post qpush):
328 .hg/cache/tags2-visible (post qpush):
329
329
330 $ cat .hg/cache/tags-visible
330 $ cat .hg/cache/tags2-visible
331 2 [\da-f]{40} (re)
331 2 [\da-f]{40} (re)
332 $ checkundo qpush
332 $ checkundo qpush
333 $ cd ..
333 $ cd ..
334
334
335
335
336 pop/push outside repo
336 pop/push outside repo
337 $ hg -R a qpop
337 $ hg -R a qpop
338 popping test.patch
338 popping test.patch
339 patch queue now empty
339 patch queue now empty
340 $ hg -R a qpush
340 $ hg -R a qpush
341 applying test.patch
341 applying test.patch
342 now at: test.patch
342 now at: test.patch
343
343
344 $ cd a
344 $ cd a
345 $ hg qnew test2.patch
345 $ hg qnew test2.patch
346
346
347 qrefresh in subdir
347 qrefresh in subdir
348
348
349 $ cd b
349 $ cd b
350 $ echo a > a
350 $ echo a > a
351 $ hg add a
351 $ hg add a
352 $ hg qrefresh
352 $ hg qrefresh
353
353
354 pop/push -a in subdir
354 pop/push -a in subdir
355
355
356 $ hg qpop -a
356 $ hg qpop -a
357 popping test2.patch
357 popping test2.patch
358 popping test.patch
358 popping test.patch
359 patch queue now empty
359 patch queue now empty
360 $ hg --traceback qpush -a
360 $ hg --traceback qpush -a
361 applying test.patch
361 applying test.patch
362 applying test2.patch
362 applying test2.patch
363 now at: test2.patch
363 now at: test2.patch
364
364
365
365
366 setting columns & formatted tests truncating (issue1912)
366 setting columns & formatted tests truncating (issue1912)
367
367
368 $ COLUMNS=4 hg qseries --config ui.formatted=true
368 $ COLUMNS=4 hg qseries --config ui.formatted=true
369 test.patch
369 test.patch
370 test2.patch
370 test2.patch
371 $ COLUMNS=20 hg qseries --config ui.formatted=true -vs
371 $ COLUMNS=20 hg qseries --config ui.formatted=true -vs
372 0 A test.patch: f...
372 0 A test.patch: f...
373 1 A test2.patch:
373 1 A test2.patch:
374 $ hg qpop
374 $ hg qpop
375 popping test2.patch
375 popping test2.patch
376 now at: test.patch
376 now at: test.patch
377 $ hg qseries -vs
377 $ hg qseries -vs
378 0 A test.patch: foo bar
378 0 A test.patch: foo bar
379 1 U test2.patch:
379 1 U test2.patch:
380 $ hg sum | grep mq
380 $ hg sum | grep mq
381 mq: 1 applied, 1 unapplied
381 mq: 1 applied, 1 unapplied
382 $ hg qpush
382 $ hg qpush
383 applying test2.patch
383 applying test2.patch
384 now at: test2.patch
384 now at: test2.patch
385 $ hg sum | grep mq
385 $ hg sum | grep mq
386 mq: 2 applied
386 mq: 2 applied
387 $ hg qapplied
387 $ hg qapplied
388 test.patch
388 test.patch
389 test2.patch
389 test2.patch
390 $ hg qtop
390 $ hg qtop
391 test2.patch
391 test2.patch
392
392
393
393
394 prev
394 prev
395
395
396 $ hg qapp -1
396 $ hg qapp -1
397 test.patch
397 test.patch
398
398
399 next
399 next
400
400
401 $ hg qunapp -1
401 $ hg qunapp -1
402 all patches applied
402 all patches applied
403 [1]
403 [1]
404
404
405 $ hg qpop
405 $ hg qpop
406 popping test2.patch
406 popping test2.patch
407 now at: test.patch
407 now at: test.patch
408
408
409 commit should fail
409 commit should fail
410
410
411 $ hg commit
411 $ hg commit
412 abort: cannot commit over an applied mq patch
412 abort: cannot commit over an applied mq patch
413 [255]
413 [255]
414
414
415 push should fail if draft
415 push should fail if draft
416
416
417 $ hg push ../../k
417 $ hg push ../../k
418 pushing to ../../k
418 pushing to ../../k
419 abort: source has mq patches applied
419 abort: source has mq patches applied
420 [255]
420 [255]
421
421
422
422
423 import should fail
423 import should fail
424
424
425 $ hg st .
425 $ hg st .
426 $ echo foo >> ../a
426 $ echo foo >> ../a
427 $ hg diff > ../../import.diff
427 $ hg diff > ../../import.diff
428 $ hg revert --no-backup ../a
428 $ hg revert --no-backup ../a
429 $ hg import ../../import.diff
429 $ hg import ../../import.diff
430 abort: cannot import over an applied patch
430 abort: cannot import over an applied patch
431 [255]
431 [255]
432 $ hg st
432 $ hg st
433
433
434 import --no-commit should succeed
434 import --no-commit should succeed
435
435
436 $ hg import --no-commit ../../import.diff
436 $ hg import --no-commit ../../import.diff
437 applying ../../import.diff
437 applying ../../import.diff
438 $ hg st
438 $ hg st
439 M a
439 M a
440 $ hg revert --no-backup ../a
440 $ hg revert --no-backup ../a
441
441
442
442
443 qunapplied
443 qunapplied
444
444
445 $ hg qunapplied
445 $ hg qunapplied
446 test2.patch
446 test2.patch
447
447
448
448
449 qpush/qpop with index
449 qpush/qpop with index
450
450
451 $ hg qnew test1b.patch
451 $ hg qnew test1b.patch
452 $ echo 1b > 1b
452 $ echo 1b > 1b
453 $ hg add 1b
453 $ hg add 1b
454 $ hg qrefresh
454 $ hg qrefresh
455 $ hg qpush 2
455 $ hg qpush 2
456 applying test2.patch
456 applying test2.patch
457 now at: test2.patch
457 now at: test2.patch
458 $ hg qpop 0
458 $ hg qpop 0
459 popping test2.patch
459 popping test2.patch
460 popping test1b.patch
460 popping test1b.patch
461 now at: test.patch
461 now at: test.patch
462 $ hg qpush test.patch+1
462 $ hg qpush test.patch+1
463 applying test1b.patch
463 applying test1b.patch
464 now at: test1b.patch
464 now at: test1b.patch
465 $ hg qpush test.patch+2
465 $ hg qpush test.patch+2
466 applying test2.patch
466 applying test2.patch
467 now at: test2.patch
467 now at: test2.patch
468 $ hg qpop test2.patch-1
468 $ hg qpop test2.patch-1
469 popping test2.patch
469 popping test2.patch
470 now at: test1b.patch
470 now at: test1b.patch
471 $ hg qpop test2.patch-2
471 $ hg qpop test2.patch-2
472 popping test1b.patch
472 popping test1b.patch
473 now at: test.patch
473 now at: test.patch
474 $ hg qpush test1b.patch+1
474 $ hg qpush test1b.patch+1
475 applying test1b.patch
475 applying test1b.patch
476 applying test2.patch
476 applying test2.patch
477 now at: test2.patch
477 now at: test2.patch
478
478
479
479
480 qpush --move
480 qpush --move
481
481
482 $ hg qpop -a
482 $ hg qpop -a
483 popping test2.patch
483 popping test2.patch
484 popping test1b.patch
484 popping test1b.patch
485 popping test.patch
485 popping test.patch
486 patch queue now empty
486 patch queue now empty
487 $ hg qguard test1b.patch -- -negguard
487 $ hg qguard test1b.patch -- -negguard
488 $ hg qguard test2.patch -- +posguard
488 $ hg qguard test2.patch -- +posguard
489 $ hg qpush --move test2.patch # can't move guarded patch
489 $ hg qpush --move test2.patch # can't move guarded patch
490 cannot push 'test2.patch' - guarded by '+posguard'
490 cannot push 'test2.patch' - guarded by '+posguard'
491 [1]
491 [1]
492 $ hg qselect posguard
492 $ hg qselect posguard
493 number of unguarded, unapplied patches has changed from 2 to 3
493 number of unguarded, unapplied patches has changed from 2 to 3
494 $ hg qpush --move test2.patch # move to front
494 $ hg qpush --move test2.patch # move to front
495 applying test2.patch
495 applying test2.patch
496 now at: test2.patch
496 now at: test2.patch
497 $ hg qpush --move test1b.patch # negative guard unselected
497 $ hg qpush --move test1b.patch # negative guard unselected
498 applying test1b.patch
498 applying test1b.patch
499 now at: test1b.patch
499 now at: test1b.patch
500 $ hg qpush --move test.patch # noop move
500 $ hg qpush --move test.patch # noop move
501 applying test.patch
501 applying test.patch
502 now at: test.patch
502 now at: test.patch
503 $ hg qseries -v
503 $ hg qseries -v
504 0 A test2.patch
504 0 A test2.patch
505 1 A test1b.patch
505 1 A test1b.patch
506 2 A test.patch
506 2 A test.patch
507 $ hg qpop -a
507 $ hg qpop -a
508 popping test.patch
508 popping test.patch
509 popping test1b.patch
509 popping test1b.patch
510 popping test2.patch
510 popping test2.patch
511 patch queue now empty
511 patch queue now empty
512
512
513 cleaning up
513 cleaning up
514
514
515 $ hg qselect --none
515 $ hg qselect --none
516 guards deactivated
516 guards deactivated
517 number of unguarded, unapplied patches has changed from 3 to 2
517 number of unguarded, unapplied patches has changed from 3 to 2
518 $ hg qguard --none test1b.patch
518 $ hg qguard --none test1b.patch
519 $ hg qguard --none test2.patch
519 $ hg qguard --none test2.patch
520 $ hg qpush --move test.patch
520 $ hg qpush --move test.patch
521 applying test.patch
521 applying test.patch
522 now at: test.patch
522 now at: test.patch
523 $ hg qpush --move test1b.patch
523 $ hg qpush --move test1b.patch
524 applying test1b.patch
524 applying test1b.patch
525 now at: test1b.patch
525 now at: test1b.patch
526 $ hg qpush --move bogus # nonexistent patch
526 $ hg qpush --move bogus # nonexistent patch
527 abort: patch bogus not in series
527 abort: patch bogus not in series
528 [255]
528 [255]
529 $ hg qpush --move # no patch
529 $ hg qpush --move # no patch
530 abort: please specify the patch to move
530 abort: please specify the patch to move
531 [255]
531 [255]
532 $ hg qpush --move test.patch # already applied
532 $ hg qpush --move test.patch # already applied
533 abort: cannot push to a previous patch: test.patch
533 abort: cannot push to a previous patch: test.patch
534 [255]
534 [255]
535 $ sed '2i\
535 $ sed '2i\
536 > # make qtip index different in series and fullseries
536 > # make qtip index different in series and fullseries
537 > ' `hg root`/.hg/patches/series > $TESTTMP/sedtmp
537 > ' `hg root`/.hg/patches/series > $TESTTMP/sedtmp
538 $ cp $TESTTMP/sedtmp `hg root`/.hg/patches/series
538 $ cp $TESTTMP/sedtmp `hg root`/.hg/patches/series
539 $ cat `hg root`/.hg/patches/series
539 $ cat `hg root`/.hg/patches/series
540 # comment
540 # comment
541 # make qtip index different in series and fullseries
541 # make qtip index different in series and fullseries
542
542
543 test.patch
543 test.patch
544 test1b.patch
544 test1b.patch
545 test2.patch
545 test2.patch
546 $ hg qpush --move test2.patch
546 $ hg qpush --move test2.patch
547 applying test2.patch
547 applying test2.patch
548 now at: test2.patch
548 now at: test2.patch
549
549
550
550
551 series after move
551 series after move
552
552
553 $ cat `hg root`/.hg/patches/series
553 $ cat `hg root`/.hg/patches/series
554 # comment
554 # comment
555 # make qtip index different in series and fullseries
555 # make qtip index different in series and fullseries
556
556
557 test.patch
557 test.patch
558 test1b.patch
558 test1b.patch
559 test2.patch
559 test2.patch
560
560
561
561
562 pop, qapplied, qunapplied
562 pop, qapplied, qunapplied
563
563
564 $ hg qseries -v
564 $ hg qseries -v
565 0 A test.patch
565 0 A test.patch
566 1 A test1b.patch
566 1 A test1b.patch
567 2 A test2.patch
567 2 A test2.patch
568
568
569 qapplied -1 test.patch
569 qapplied -1 test.patch
570
570
571 $ hg qapplied -1 test.patch
571 $ hg qapplied -1 test.patch
572 only one patch applied
572 only one patch applied
573 [1]
573 [1]
574
574
575 qapplied -1 test1b.patch
575 qapplied -1 test1b.patch
576
576
577 $ hg qapplied -1 test1b.patch
577 $ hg qapplied -1 test1b.patch
578 test.patch
578 test.patch
579
579
580 qapplied -1 test2.patch
580 qapplied -1 test2.patch
581
581
582 $ hg qapplied -1 test2.patch
582 $ hg qapplied -1 test2.patch
583 test1b.patch
583 test1b.patch
584
584
585 qapplied -1
585 qapplied -1
586
586
587 $ hg qapplied -1
587 $ hg qapplied -1
588 test1b.patch
588 test1b.patch
589
589
590 qapplied
590 qapplied
591
591
592 $ hg qapplied
592 $ hg qapplied
593 test.patch
593 test.patch
594 test1b.patch
594 test1b.patch
595 test2.patch
595 test2.patch
596
596
597 qapplied test1b.patch
597 qapplied test1b.patch
598
598
599 $ hg qapplied test1b.patch
599 $ hg qapplied test1b.patch
600 test.patch
600 test.patch
601 test1b.patch
601 test1b.patch
602
602
603 qunapplied -1
603 qunapplied -1
604
604
605 $ hg qunapplied -1
605 $ hg qunapplied -1
606 all patches applied
606 all patches applied
607 [1]
607 [1]
608
608
609 qunapplied
609 qunapplied
610
610
611 $ hg qunapplied
611 $ hg qunapplied
612
612
613 popping
613 popping
614
614
615 $ hg qpop
615 $ hg qpop
616 popping test2.patch
616 popping test2.patch
617 now at: test1b.patch
617 now at: test1b.patch
618
618
619 qunapplied -1
619 qunapplied -1
620
620
621 $ hg qunapplied -1
621 $ hg qunapplied -1
622 test2.patch
622 test2.patch
623
623
624 qunapplied
624 qunapplied
625
625
626 $ hg qunapplied
626 $ hg qunapplied
627 test2.patch
627 test2.patch
628
628
629 qunapplied test2.patch
629 qunapplied test2.patch
630
630
631 $ hg qunapplied test2.patch
631 $ hg qunapplied test2.patch
632
632
633 qunapplied -1 test2.patch
633 qunapplied -1 test2.patch
634
634
635 $ hg qunapplied -1 test2.patch
635 $ hg qunapplied -1 test2.patch
636 all patches applied
636 all patches applied
637 [1]
637 [1]
638
638
639 popping -a
639 popping -a
640
640
641 $ hg qpop -a
641 $ hg qpop -a
642 popping test1b.patch
642 popping test1b.patch
643 popping test.patch
643 popping test.patch
644 patch queue now empty
644 patch queue now empty
645
645
646 qapplied
646 qapplied
647
647
648 $ hg qapplied
648 $ hg qapplied
649
649
650 qapplied -1
650 qapplied -1
651
651
652 $ hg qapplied -1
652 $ hg qapplied -1
653 no patches applied
653 no patches applied
654 [1]
654 [1]
655 $ hg qpush
655 $ hg qpush
656 applying test.patch
656 applying test.patch
657 now at: test.patch
657 now at: test.patch
658
658
659
659
660 push should succeed
660 push should succeed
661
661
662 $ hg qpop -a
662 $ hg qpop -a
663 popping test.patch
663 popping test.patch
664 patch queue now empty
664 patch queue now empty
665 $ hg push ../../k
665 $ hg push ../../k
666 pushing to ../../k
666 pushing to ../../k
667 searching for changes
667 searching for changes
668 adding changesets
668 adding changesets
669 adding manifests
669 adding manifests
670 adding file changes
670 adding file changes
671 added 1 changesets with 1 changes to 1 files
671 added 1 changesets with 1 changes to 1 files
672
672
673
673
674 we want to start with some patches applied
674 we want to start with some patches applied
675
675
676 $ hg qpush -a
676 $ hg qpush -a
677 applying test.patch
677 applying test.patch
678 applying test1b.patch
678 applying test1b.patch
679 applying test2.patch
679 applying test2.patch
680 now at: test2.patch
680 now at: test2.patch
681
681
682 % pops all patches and succeeds
682 % pops all patches and succeeds
683
683
684 $ hg qpop -a
684 $ hg qpop -a
685 popping test2.patch
685 popping test2.patch
686 popping test1b.patch
686 popping test1b.patch
687 popping test.patch
687 popping test.patch
688 patch queue now empty
688 patch queue now empty
689
689
690 % does nothing and succeeds
690 % does nothing and succeeds
691
691
692 $ hg qpop -a
692 $ hg qpop -a
693 no patches applied
693 no patches applied
694
694
695 % fails - nothing else to pop
695 % fails - nothing else to pop
696
696
697 $ hg qpop
697 $ hg qpop
698 no patches applied
698 no patches applied
699 [1]
699 [1]
700
700
701 % pushes a patch and succeeds
701 % pushes a patch and succeeds
702
702
703 $ hg qpush
703 $ hg qpush
704 applying test.patch
704 applying test.patch
705 now at: test.patch
705 now at: test.patch
706
706
707 % pops a patch and succeeds
707 % pops a patch and succeeds
708
708
709 $ hg qpop
709 $ hg qpop
710 popping test.patch
710 popping test.patch
711 patch queue now empty
711 patch queue now empty
712
712
713 % pushes up to test1b.patch and succeeds
713 % pushes up to test1b.patch and succeeds
714
714
715 $ hg qpush test1b.patch
715 $ hg qpush test1b.patch
716 applying test.patch
716 applying test.patch
717 applying test1b.patch
717 applying test1b.patch
718 now at: test1b.patch
718 now at: test1b.patch
719
719
720 % does nothing and succeeds
720 % does nothing and succeeds
721
721
722 $ hg qpush test1b.patch
722 $ hg qpush test1b.patch
723 qpush: test1b.patch is already at the top
723 qpush: test1b.patch is already at the top
724
724
725 % does nothing and succeeds
725 % does nothing and succeeds
726
726
727 $ hg qpop test1b.patch
727 $ hg qpop test1b.patch
728 qpop: test1b.patch is already at the top
728 qpop: test1b.patch is already at the top
729
729
730 % fails - can't push to this patch
730 % fails - can't push to this patch
731
731
732 $ hg qpush test.patch
732 $ hg qpush test.patch
733 abort: cannot push to a previous patch: test.patch
733 abort: cannot push to a previous patch: test.patch
734 [255]
734 [255]
735
735
736 % fails - can't pop to this patch
736 % fails - can't pop to this patch
737
737
738 $ hg qpop test2.patch
738 $ hg qpop test2.patch
739 abort: patch test2.patch is not applied
739 abort: patch test2.patch is not applied
740 [255]
740 [255]
741
741
742 % pops up to test.patch and succeeds
742 % pops up to test.patch and succeeds
743
743
744 $ hg qpop test.patch
744 $ hg qpop test.patch
745 popping test1b.patch
745 popping test1b.patch
746 now at: test.patch
746 now at: test.patch
747
747
748 % pushes all patches and succeeds
748 % pushes all patches and succeeds
749
749
750 $ hg qpush -a
750 $ hg qpush -a
751 applying test1b.patch
751 applying test1b.patch
752 applying test2.patch
752 applying test2.patch
753 now at: test2.patch
753 now at: test2.patch
754
754
755 % does nothing and succeeds
755 % does nothing and succeeds
756
756
757 $ hg qpush -a
757 $ hg qpush -a
758 all patches are currently applied
758 all patches are currently applied
759
759
760 % fails - nothing else to push
760 % fails - nothing else to push
761
761
762 $ hg qpush
762 $ hg qpush
763 patch series already fully applied
763 patch series already fully applied
764 [1]
764 [1]
765
765
766 % does nothing and succeeds
766 % does nothing and succeeds
767
767
768 $ hg qpush test2.patch
768 $ hg qpush test2.patch
769 qpush: test2.patch is already at the top
769 qpush: test2.patch is already at the top
770
770
771 strip
771 strip
772
772
773 $ cd ../../b
773 $ cd ../../b
774 $ echo x>x
774 $ echo x>x
775 $ hg ci -Ama
775 $ hg ci -Ama
776 adding x
776 adding x
777 $ hg strip tip
777 $ hg strip tip
778 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
778 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
779 saved backup bundle to $TESTTMP/b/.hg/strip-backup/*-backup.hg (glob)
779 saved backup bundle to $TESTTMP/b/.hg/strip-backup/*-backup.hg (glob)
780 $ hg unbundle .hg/strip-backup/*
780 $ hg unbundle .hg/strip-backup/*
781 adding changesets
781 adding changesets
782 adding manifests
782 adding manifests
783 adding file changes
783 adding file changes
784 added 1 changesets with 1 changes to 1 files
784 added 1 changesets with 1 changes to 1 files
785 (run 'hg update' to get a working copy)
785 (run 'hg update' to get a working copy)
786
786
787
787
788 strip with local changes, should complain
788 strip with local changes, should complain
789
789
790 $ hg up
790 $ hg up
791 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
791 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
792 $ echo y>y
792 $ echo y>y
793 $ hg add y
793 $ hg add y
794 $ hg strip tip
794 $ hg strip tip
795 abort: local changes found
795 abort: local changes found
796 [255]
796 [255]
797
797
798 --force strip with local changes
798 --force strip with local changes
799
799
800 $ hg strip -f tip
800 $ hg strip -f tip
801 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
801 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
802 saved backup bundle to $TESTTMP/b/.hg/strip-backup/770eb8fce608-0ddcae0f-backup.hg (glob)
802 saved backup bundle to $TESTTMP/b/.hg/strip-backup/770eb8fce608-0ddcae0f-backup.hg (glob)
803 $ cd ..
803 $ cd ..
804
804
805
805
806 cd b; hg qrefresh
806 cd b; hg qrefresh
807
807
808 $ hg init refresh
808 $ hg init refresh
809 $ cd refresh
809 $ cd refresh
810 $ echo a > a
810 $ echo a > a
811 $ hg ci -Ama
811 $ hg ci -Ama
812 adding a
812 adding a
813 $ hg qnew -mfoo foo
813 $ hg qnew -mfoo foo
814 $ echo a >> a
814 $ echo a >> a
815 $ hg qrefresh
815 $ hg qrefresh
816 $ mkdir b
816 $ mkdir b
817 $ cd b
817 $ cd b
818 $ echo f > f
818 $ echo f > f
819 $ hg add f
819 $ hg add f
820 $ hg qrefresh
820 $ hg qrefresh
821 $ cat ../.hg/patches/foo
821 $ cat ../.hg/patches/foo
822 foo
822 foo
823
823
824 diff -r cb9a9f314b8b a
824 diff -r cb9a9f314b8b a
825 --- a/a\t(?P<date>.*) (re)
825 --- a/a\t(?P<date>.*) (re)
826 \+\+\+ b/a\t(?P<date>.*) (re)
826 \+\+\+ b/a\t(?P<date>.*) (re)
827 @@ -1,1 +1,2 @@
827 @@ -1,1 +1,2 @@
828 a
828 a
829 +a
829 +a
830 diff -r cb9a9f314b8b b/f
830 diff -r cb9a9f314b8b b/f
831 --- /dev/null\t(?P<date>.*) (re)
831 --- /dev/null\t(?P<date>.*) (re)
832 \+\+\+ b/b/f\t(?P<date>.*) (re)
832 \+\+\+ b/b/f\t(?P<date>.*) (re)
833 @@ -0,0 +1,1 @@
833 @@ -0,0 +1,1 @@
834 +f
834 +f
835
835
836 hg qrefresh .
836 hg qrefresh .
837
837
838 $ hg qrefresh .
838 $ hg qrefresh .
839 $ cat ../.hg/patches/foo
839 $ cat ../.hg/patches/foo
840 foo
840 foo
841
841
842 diff -r cb9a9f314b8b b/f
842 diff -r cb9a9f314b8b b/f
843 --- /dev/null\t(?P<date>.*) (re)
843 --- /dev/null\t(?P<date>.*) (re)
844 \+\+\+ b/b/f\t(?P<date>.*) (re)
844 \+\+\+ b/b/f\t(?P<date>.*) (re)
845 @@ -0,0 +1,1 @@
845 @@ -0,0 +1,1 @@
846 +f
846 +f
847 $ hg status
847 $ hg status
848 M a
848 M a
849
849
850
850
851 qpush failure
851 qpush failure
852
852
853 $ cd ..
853 $ cd ..
854 $ hg qrefresh
854 $ hg qrefresh
855 $ hg qnew -mbar bar
855 $ hg qnew -mbar bar
856 $ echo foo > foo
856 $ echo foo > foo
857 $ echo bar > bar
857 $ echo bar > bar
858 $ hg add foo bar
858 $ hg add foo bar
859 $ hg qrefresh
859 $ hg qrefresh
860 $ hg qpop -a
860 $ hg qpop -a
861 popping bar
861 popping bar
862 popping foo
862 popping foo
863 patch queue now empty
863 patch queue now empty
864 $ echo bar > foo
864 $ echo bar > foo
865 $ hg qpush -a
865 $ hg qpush -a
866 applying foo
866 applying foo
867 applying bar
867 applying bar
868 file foo already exists
868 file foo already exists
869 1 out of 1 hunks FAILED -- saving rejects to file foo.rej
869 1 out of 1 hunks FAILED -- saving rejects to file foo.rej
870 patch failed, unable to continue (try -v)
870 patch failed, unable to continue (try -v)
871 patch failed, rejects left in working directory
871 patch failed, rejects left in working directory
872 errors during apply, please fix and refresh bar
872 errors during apply, please fix and refresh bar
873 [2]
873 [2]
874 $ hg st
874 $ hg st
875 ? foo
875 ? foo
876 ? foo.rej
876 ? foo.rej
877
877
878
878
879 mq tags
879 mq tags
880
880
881 $ hg log --template '{rev} {tags}\n' -r qparent:qtip
881 $ hg log --template '{rev} {tags}\n' -r qparent:qtip
882 0 qparent
882 0 qparent
883 1 foo qbase
883 1 foo qbase
884 2 bar qtip tip
884 2 bar qtip tip
885
885
886 mq revset
886 mq revset
887
887
888 $ hg log -r 'mq()' --template '{rev}\n'
888 $ hg log -r 'mq()' --template '{rev}\n'
889 1
889 1
890 2
890 2
891 $ hg help revsets | grep -i mq
891 $ hg help revsets | grep -i mq
892 "mq()"
892 "mq()"
893 Changesets managed by MQ.
893 Changesets managed by MQ.
894
894
895 bad node in status
895 bad node in status
896
896
897 $ hg qpop
897 $ hg qpop
898 popping bar
898 popping bar
899 now at: foo
899 now at: foo
900 $ hg strip -qn tip
900 $ hg strip -qn tip
901 $ hg tip
901 $ hg tip
902 changeset: 0:cb9a9f314b8b
902 changeset: 0:cb9a9f314b8b
903 tag: tip
903 tag: tip
904 user: test
904 user: test
905 date: Thu Jan 01 00:00:00 1970 +0000
905 date: Thu Jan 01 00:00:00 1970 +0000
906 summary: a
906 summary: a
907
907
908 $ hg branches
908 $ hg branches
909 default 0:cb9a9f314b8b
909 default 0:cb9a9f314b8b
910 $ hg qpop
910 $ hg qpop
911 no patches applied
911 no patches applied
912 [1]
912 [1]
913
913
914 $ cd ..
914 $ cd ..
915
915
916
916
917 git patches
917 git patches
918
918
919 $ cat >>$HGRCPATH <<EOF
919 $ cat >>$HGRCPATH <<EOF
920 > [diff]
920 > [diff]
921 > git = True
921 > git = True
922 > EOF
922 > EOF
923 $ hg init git
923 $ hg init git
924 $ cd git
924 $ cd git
925 $ hg qinit
925 $ hg qinit
926
926
927 $ hg qnew -m'new file' new
927 $ hg qnew -m'new file' new
928 $ echo foo > new
928 $ echo foo > new
929 #if execbit
929 #if execbit
930 $ chmod +x new
930 $ chmod +x new
931 #endif
931 #endif
932 $ hg add new
932 $ hg add new
933 $ hg qrefresh
933 $ hg qrefresh
934 #if execbit
934 #if execbit
935 $ cat .hg/patches/new
935 $ cat .hg/patches/new
936 new file
936 new file
937
937
938 diff --git a/new b/new
938 diff --git a/new b/new
939 new file mode 100755
939 new file mode 100755
940 --- /dev/null
940 --- /dev/null
941 +++ b/new
941 +++ b/new
942 @@ -0,0 +1,1 @@
942 @@ -0,0 +1,1 @@
943 +foo
943 +foo
944 #else
944 #else
945 $ cat .hg/patches/new
945 $ cat .hg/patches/new
946 new file
946 new file
947
947
948 diff --git a/new b/new
948 diff --git a/new b/new
949 new file mode 100644
949 new file mode 100644
950 --- /dev/null
950 --- /dev/null
951 +++ b/new
951 +++ b/new
952 @@ -0,0 +1,1 @@
952 @@ -0,0 +1,1 @@
953 +foo
953 +foo
954 #endif
954 #endif
955
955
956 $ hg qnew -m'copy file' copy
956 $ hg qnew -m'copy file' copy
957 $ hg cp new copy
957 $ hg cp new copy
958 $ hg qrefresh
958 $ hg qrefresh
959 $ cat .hg/patches/copy
959 $ cat .hg/patches/copy
960 copy file
960 copy file
961
961
962 diff --git a/new b/copy
962 diff --git a/new b/copy
963 copy from new
963 copy from new
964 copy to copy
964 copy to copy
965
965
966 $ hg qpop
966 $ hg qpop
967 popping copy
967 popping copy
968 now at: new
968 now at: new
969 $ hg qpush
969 $ hg qpush
970 applying copy
970 applying copy
971 now at: copy
971 now at: copy
972 $ hg qdiff
972 $ hg qdiff
973 diff --git a/new b/copy
973 diff --git a/new b/copy
974 copy from new
974 copy from new
975 copy to copy
975 copy to copy
976 $ cat >>$HGRCPATH <<EOF
976 $ cat >>$HGRCPATH <<EOF
977 > [diff]
977 > [diff]
978 > git = False
978 > git = False
979 > EOF
979 > EOF
980 $ hg qdiff --git
980 $ hg qdiff --git
981 diff --git a/new b/copy
981 diff --git a/new b/copy
982 copy from new
982 copy from new
983 copy to copy
983 copy to copy
984 $ cd ..
984 $ cd ..
985
985
986 empty lines in status
986 empty lines in status
987
987
988 $ hg init emptystatus
988 $ hg init emptystatus
989 $ cd emptystatus
989 $ cd emptystatus
990 $ hg qinit
990 $ hg qinit
991 $ printf '\n\n' > .hg/patches/status
991 $ printf '\n\n' > .hg/patches/status
992 $ hg qser
992 $ hg qser
993 $ cd ..
993 $ cd ..
994
994
995 bad line in status (without ":")
995 bad line in status (without ":")
996
996
997 $ hg init badstatus
997 $ hg init badstatus
998 $ cd badstatus
998 $ cd badstatus
999 $ hg qinit
999 $ hg qinit
1000 $ printf 'babar has no colon in this line\n' > .hg/patches/status
1000 $ printf 'babar has no colon in this line\n' > .hg/patches/status
1001 $ hg qser
1001 $ hg qser
1002 malformated mq status line: ['babar has no colon in this line']
1002 malformated mq status line: ['babar has no colon in this line']
1003 $ cd ..
1003 $ cd ..
1004
1004
1005
1005
1006 test file addition in slow path
1006 test file addition in slow path
1007
1007
1008 $ hg init slow
1008 $ hg init slow
1009 $ cd slow
1009 $ cd slow
1010 $ hg qinit
1010 $ hg qinit
1011 $ echo foo > foo
1011 $ echo foo > foo
1012 $ hg add foo
1012 $ hg add foo
1013 $ hg ci -m 'add foo'
1013 $ hg ci -m 'add foo'
1014 $ hg qnew bar
1014 $ hg qnew bar
1015 $ echo bar > bar
1015 $ echo bar > bar
1016 $ hg add bar
1016 $ hg add bar
1017 $ hg mv foo baz
1017 $ hg mv foo baz
1018 $ hg qrefresh --git
1018 $ hg qrefresh --git
1019 $ hg up -C 0
1019 $ hg up -C 0
1020 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1020 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1021 $ echo >> foo
1021 $ echo >> foo
1022 $ hg ci -m 'change foo'
1022 $ hg ci -m 'change foo'
1023 created new head
1023 created new head
1024 $ hg up -C 1
1024 $ hg up -C 1
1025 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1025 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1026 $ hg qrefresh --git
1026 $ hg qrefresh --git
1027 $ cat .hg/patches/bar
1027 $ cat .hg/patches/bar
1028 diff --git a/bar b/bar
1028 diff --git a/bar b/bar
1029 new file mode 100644
1029 new file mode 100644
1030 --- /dev/null
1030 --- /dev/null
1031 +++ b/bar
1031 +++ b/bar
1032 @@ -0,0 +1,1 @@
1032 @@ -0,0 +1,1 @@
1033 +bar
1033 +bar
1034 diff --git a/foo b/baz
1034 diff --git a/foo b/baz
1035 rename from foo
1035 rename from foo
1036 rename to baz
1036 rename to baz
1037 $ hg log -v --template '{rev} {file_copies}\n' -r .
1037 $ hg log -v --template '{rev} {file_copies}\n' -r .
1038 2 baz (foo)
1038 2 baz (foo)
1039 $ hg qrefresh --git
1039 $ hg qrefresh --git
1040 $ cat .hg/patches/bar
1040 $ cat .hg/patches/bar
1041 diff --git a/bar b/bar
1041 diff --git a/bar b/bar
1042 new file mode 100644
1042 new file mode 100644
1043 --- /dev/null
1043 --- /dev/null
1044 +++ b/bar
1044 +++ b/bar
1045 @@ -0,0 +1,1 @@
1045 @@ -0,0 +1,1 @@
1046 +bar
1046 +bar
1047 diff --git a/foo b/baz
1047 diff --git a/foo b/baz
1048 rename from foo
1048 rename from foo
1049 rename to baz
1049 rename to baz
1050 $ hg log -v --template '{rev} {file_copies}\n' -r .
1050 $ hg log -v --template '{rev} {file_copies}\n' -r .
1051 2 baz (foo)
1051 2 baz (foo)
1052 $ hg qrefresh
1052 $ hg qrefresh
1053 $ grep 'diff --git' .hg/patches/bar
1053 $ grep 'diff --git' .hg/patches/bar
1054 diff --git a/bar b/bar
1054 diff --git a/bar b/bar
1055 diff --git a/foo b/baz
1055 diff --git a/foo b/baz
1056
1056
1057
1057
1058 test file move chains in the slow path
1058 test file move chains in the slow path
1059
1059
1060 $ hg up -C 1
1060 $ hg up -C 1
1061 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1061 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1062 $ echo >> foo
1062 $ echo >> foo
1063 $ hg ci -m 'change foo again'
1063 $ hg ci -m 'change foo again'
1064 $ hg up -C 2
1064 $ hg up -C 2
1065 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1065 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1066 $ hg mv bar quux
1066 $ hg mv bar quux
1067 $ hg mv baz bleh
1067 $ hg mv baz bleh
1068 $ hg qrefresh --git
1068 $ hg qrefresh --git
1069 $ cat .hg/patches/bar
1069 $ cat .hg/patches/bar
1070 diff --git a/foo b/bleh
1070 diff --git a/foo b/bleh
1071 rename from foo
1071 rename from foo
1072 rename to bleh
1072 rename to bleh
1073 diff --git a/quux b/quux
1073 diff --git a/quux b/quux
1074 new file mode 100644
1074 new file mode 100644
1075 --- /dev/null
1075 --- /dev/null
1076 +++ b/quux
1076 +++ b/quux
1077 @@ -0,0 +1,1 @@
1077 @@ -0,0 +1,1 @@
1078 +bar
1078 +bar
1079 $ hg log -v --template '{rev} {file_copies}\n' -r .
1079 $ hg log -v --template '{rev} {file_copies}\n' -r .
1080 3 bleh (foo)
1080 3 bleh (foo)
1081 $ hg mv quux fred
1081 $ hg mv quux fred
1082 $ hg mv bleh barney
1082 $ hg mv bleh barney
1083 $ hg qrefresh --git
1083 $ hg qrefresh --git
1084 $ cat .hg/patches/bar
1084 $ cat .hg/patches/bar
1085 diff --git a/foo b/barney
1085 diff --git a/foo b/barney
1086 rename from foo
1086 rename from foo
1087 rename to barney
1087 rename to barney
1088 diff --git a/fred b/fred
1088 diff --git a/fred b/fred
1089 new file mode 100644
1089 new file mode 100644
1090 --- /dev/null
1090 --- /dev/null
1091 +++ b/fred
1091 +++ b/fred
1092 @@ -0,0 +1,1 @@
1092 @@ -0,0 +1,1 @@
1093 +bar
1093 +bar
1094 $ hg log -v --template '{rev} {file_copies}\n' -r .
1094 $ hg log -v --template '{rev} {file_copies}\n' -r .
1095 3 barney (foo)
1095 3 barney (foo)
1096
1096
1097
1097
1098 refresh omitting an added file
1098 refresh omitting an added file
1099
1099
1100 $ hg qnew baz
1100 $ hg qnew baz
1101 $ echo newfile > newfile
1101 $ echo newfile > newfile
1102 $ hg add newfile
1102 $ hg add newfile
1103 $ hg qrefresh
1103 $ hg qrefresh
1104 $ hg st -A newfile
1104 $ hg st -A newfile
1105 C newfile
1105 C newfile
1106 $ hg qrefresh -X newfile
1106 $ hg qrefresh -X newfile
1107 $ hg st -A newfile
1107 $ hg st -A newfile
1108 A newfile
1108 A newfile
1109 $ hg revert newfile
1109 $ hg revert newfile
1110 $ rm newfile
1110 $ rm newfile
1111 $ hg qpop
1111 $ hg qpop
1112 popping baz
1112 popping baz
1113 now at: bar
1113 now at: bar
1114
1114
1115 test qdel/qrm
1115 test qdel/qrm
1116
1116
1117 $ hg qdel baz
1117 $ hg qdel baz
1118 $ echo p >> .hg/patches/series
1118 $ echo p >> .hg/patches/series
1119 $ hg qrm p
1119 $ hg qrm p
1120 $ hg qser
1120 $ hg qser
1121 bar
1121 bar
1122
1122
1123 create a git patch
1123 create a git patch
1124
1124
1125 $ echo a > alexander
1125 $ echo a > alexander
1126 $ hg add alexander
1126 $ hg add alexander
1127 $ hg qnew -f --git addalexander
1127 $ hg qnew -f --git addalexander
1128 $ grep diff .hg/patches/addalexander
1128 $ grep diff .hg/patches/addalexander
1129 diff --git a/alexander b/alexander
1129 diff --git a/alexander b/alexander
1130
1130
1131
1131
1132 create a git binary patch
1132 create a git binary patch
1133
1133
1134 $ cat > writebin.py <<EOF
1134 $ cat > writebin.py <<EOF
1135 > import sys
1135 > import sys
1136 > path = sys.argv[1]
1136 > path = sys.argv[1]
1137 > open(path, 'wb').write('BIN\x00ARY')
1137 > open(path, 'wb').write('BIN\x00ARY')
1138 > EOF
1138 > EOF
1139 $ python writebin.py bucephalus
1139 $ python writebin.py bucephalus
1140
1140
1141 $ python "$TESTDIR/md5sum.py" bucephalus
1141 $ python "$TESTDIR/md5sum.py" bucephalus
1142 8ba2a2f3e77b55d03051ff9c24ad65e7 bucephalus
1142 8ba2a2f3e77b55d03051ff9c24ad65e7 bucephalus
1143 $ hg add bucephalus
1143 $ hg add bucephalus
1144 $ hg qnew -f --git addbucephalus
1144 $ hg qnew -f --git addbucephalus
1145 $ grep diff .hg/patches/addbucephalus
1145 $ grep diff .hg/patches/addbucephalus
1146 diff --git a/bucephalus b/bucephalus
1146 diff --git a/bucephalus b/bucephalus
1147
1147
1148
1148
1149 check binary patches can be popped and pushed
1149 check binary patches can be popped and pushed
1150
1150
1151 $ hg qpop
1151 $ hg qpop
1152 popping addbucephalus
1152 popping addbucephalus
1153 now at: addalexander
1153 now at: addalexander
1154 $ test -f bucephalus && echo % bucephalus should not be there
1154 $ test -f bucephalus && echo % bucephalus should not be there
1155 [1]
1155 [1]
1156 $ hg qpush
1156 $ hg qpush
1157 applying addbucephalus
1157 applying addbucephalus
1158 now at: addbucephalus
1158 now at: addbucephalus
1159 $ test -f bucephalus
1159 $ test -f bucephalus
1160 $ python "$TESTDIR/md5sum.py" bucephalus
1160 $ python "$TESTDIR/md5sum.py" bucephalus
1161 8ba2a2f3e77b55d03051ff9c24ad65e7 bucephalus
1161 8ba2a2f3e77b55d03051ff9c24ad65e7 bucephalus
1162
1162
1163
1163
1164
1164
1165 strip again
1165 strip again
1166
1166
1167 $ cd ..
1167 $ cd ..
1168 $ hg init strip
1168 $ hg init strip
1169 $ cd strip
1169 $ cd strip
1170 $ touch foo
1170 $ touch foo
1171 $ hg add foo
1171 $ hg add foo
1172 $ hg ci -m 'add foo'
1172 $ hg ci -m 'add foo'
1173 $ echo >> foo
1173 $ echo >> foo
1174 $ hg ci -m 'change foo 1'
1174 $ hg ci -m 'change foo 1'
1175 $ hg up -C 0
1175 $ hg up -C 0
1176 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1176 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1177 $ echo 1 >> foo
1177 $ echo 1 >> foo
1178 $ hg ci -m 'change foo 2'
1178 $ hg ci -m 'change foo 2'
1179 created new head
1179 created new head
1180 $ HGMERGE=true hg merge
1180 $ HGMERGE=true hg merge
1181 merging foo
1181 merging foo
1182 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1182 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1183 (branch merge, don't forget to commit)
1183 (branch merge, don't forget to commit)
1184 $ hg ci -m merge
1184 $ hg ci -m merge
1185 $ hg log
1185 $ hg log
1186 changeset: 3:99615015637b
1186 changeset: 3:99615015637b
1187 tag: tip
1187 tag: tip
1188 parent: 2:20cbbe65cff7
1188 parent: 2:20cbbe65cff7
1189 parent: 1:d2871fc282d4
1189 parent: 1:d2871fc282d4
1190 user: test
1190 user: test
1191 date: Thu Jan 01 00:00:00 1970 +0000
1191 date: Thu Jan 01 00:00:00 1970 +0000
1192 summary: merge
1192 summary: merge
1193
1193
1194 changeset: 2:20cbbe65cff7
1194 changeset: 2:20cbbe65cff7
1195 parent: 0:53245c60e682
1195 parent: 0:53245c60e682
1196 user: test
1196 user: test
1197 date: Thu Jan 01 00:00:00 1970 +0000
1197 date: Thu Jan 01 00:00:00 1970 +0000
1198 summary: change foo 2
1198 summary: change foo 2
1199
1199
1200 changeset: 1:d2871fc282d4
1200 changeset: 1:d2871fc282d4
1201 user: test
1201 user: test
1202 date: Thu Jan 01 00:00:00 1970 +0000
1202 date: Thu Jan 01 00:00:00 1970 +0000
1203 summary: change foo 1
1203 summary: change foo 1
1204
1204
1205 changeset: 0:53245c60e682
1205 changeset: 0:53245c60e682
1206 user: test
1206 user: test
1207 date: Thu Jan 01 00:00:00 1970 +0000
1207 date: Thu Jan 01 00:00:00 1970 +0000
1208 summary: add foo
1208 summary: add foo
1209
1209
1210 $ hg strip 1
1210 $ hg strip 1
1211 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1211 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1212 saved backup bundle to $TESTTMP/strip/.hg/strip-backup/*-backup.hg (glob)
1212 saved backup bundle to $TESTTMP/strip/.hg/strip-backup/*-backup.hg (glob)
1213 $ checkundo strip
1213 $ checkundo strip
1214 $ hg log
1214 $ hg log
1215 changeset: 1:20cbbe65cff7
1215 changeset: 1:20cbbe65cff7
1216 tag: tip
1216 tag: tip
1217 user: test
1217 user: test
1218 date: Thu Jan 01 00:00:00 1970 +0000
1218 date: Thu Jan 01 00:00:00 1970 +0000
1219 summary: change foo 2
1219 summary: change foo 2
1220
1220
1221 changeset: 0:53245c60e682
1221 changeset: 0:53245c60e682
1222 user: test
1222 user: test
1223 date: Thu Jan 01 00:00:00 1970 +0000
1223 date: Thu Jan 01 00:00:00 1970 +0000
1224 summary: add foo
1224 summary: add foo
1225
1225
1226 $ cd ..
1226 $ cd ..
1227
1227
1228
1228
1229 qclone
1229 qclone
1230
1230
1231 $ qlog()
1231 $ qlog()
1232 > {
1232 > {
1233 > echo 'main repo:'
1233 > echo 'main repo:'
1234 > hg log --template ' rev {rev}: {desc}\n'
1234 > hg log --template ' rev {rev}: {desc}\n'
1235 > echo 'patch repo:'
1235 > echo 'patch repo:'
1236 > hg -R .hg/patches log --template ' rev {rev}: {desc}\n'
1236 > hg -R .hg/patches log --template ' rev {rev}: {desc}\n'
1237 > }
1237 > }
1238 $ hg init qclonesource
1238 $ hg init qclonesource
1239 $ cd qclonesource
1239 $ cd qclonesource
1240 $ echo foo > foo
1240 $ echo foo > foo
1241 $ hg add foo
1241 $ hg add foo
1242 $ hg ci -m 'add foo'
1242 $ hg ci -m 'add foo'
1243 $ hg qinit
1243 $ hg qinit
1244 $ hg qnew patch1
1244 $ hg qnew patch1
1245 $ echo bar >> foo
1245 $ echo bar >> foo
1246 $ hg qrefresh -m 'change foo'
1246 $ hg qrefresh -m 'change foo'
1247 $ cd ..
1247 $ cd ..
1248
1248
1249
1249
1250 repo with unversioned patch dir
1250 repo with unversioned patch dir
1251
1251
1252 $ hg qclone qclonesource failure
1252 $ hg qclone qclonesource failure
1253 abort: versioned patch repository not found (see init --mq)
1253 abort: versioned patch repository not found (see init --mq)
1254 [255]
1254 [255]
1255
1255
1256 $ cd qclonesource
1256 $ cd qclonesource
1257 $ hg qinit -c
1257 $ hg qinit -c
1258 adding .hg/patches/patch1 (glob)
1258 adding .hg/patches/patch1 (glob)
1259 $ hg qci -m checkpoint
1259 $ hg qci -m checkpoint
1260 $ qlog
1260 $ qlog
1261 main repo:
1261 main repo:
1262 rev 1: change foo
1262 rev 1: change foo
1263 rev 0: add foo
1263 rev 0: add foo
1264 patch repo:
1264 patch repo:
1265 rev 0: checkpoint
1265 rev 0: checkpoint
1266 $ cd ..
1266 $ cd ..
1267
1267
1268
1268
1269 repo with patches applied
1269 repo with patches applied
1270
1270
1271 $ hg qclone qclonesource qclonedest
1271 $ hg qclone qclonesource qclonedest
1272 updating to branch default
1272 updating to branch default
1273 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1273 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1274 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1274 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1275 $ cd qclonedest
1275 $ cd qclonedest
1276 $ qlog
1276 $ qlog
1277 main repo:
1277 main repo:
1278 rev 0: add foo
1278 rev 0: add foo
1279 patch repo:
1279 patch repo:
1280 rev 0: checkpoint
1280 rev 0: checkpoint
1281 $ cd ..
1281 $ cd ..
1282
1282
1283
1283
1284 repo with patches unapplied
1284 repo with patches unapplied
1285
1285
1286 $ cd qclonesource
1286 $ cd qclonesource
1287 $ hg qpop -a
1287 $ hg qpop -a
1288 popping patch1
1288 popping patch1
1289 patch queue now empty
1289 patch queue now empty
1290 $ qlog
1290 $ qlog
1291 main repo:
1291 main repo:
1292 rev 0: add foo
1292 rev 0: add foo
1293 patch repo:
1293 patch repo:
1294 rev 0: checkpoint
1294 rev 0: checkpoint
1295 $ cd ..
1295 $ cd ..
1296 $ hg qclone qclonesource qclonedest2
1296 $ hg qclone qclonesource qclonedest2
1297 updating to branch default
1297 updating to branch default
1298 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1298 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1299 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1299 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1300 $ cd qclonedest2
1300 $ cd qclonedest2
1301 $ qlog
1301 $ qlog
1302 main repo:
1302 main repo:
1303 rev 0: add foo
1303 rev 0: add foo
1304 patch repo:
1304 patch repo:
1305 rev 0: checkpoint
1305 rev 0: checkpoint
1306 $ cd ..
1306 $ cd ..
1307
1307
1308
1308
1309 Issue1033: test applying on an empty file
1309 Issue1033: test applying on an empty file
1310
1310
1311 $ hg init empty
1311 $ hg init empty
1312 $ cd empty
1312 $ cd empty
1313 $ touch a
1313 $ touch a
1314 $ hg ci -Am addempty
1314 $ hg ci -Am addempty
1315 adding a
1315 adding a
1316 $ echo a > a
1316 $ echo a > a
1317 $ hg qnew -f -e changea
1317 $ hg qnew -f -e changea
1318 $ hg qpop
1318 $ hg qpop
1319 popping changea
1319 popping changea
1320 patch queue now empty
1320 patch queue now empty
1321 $ hg qpush
1321 $ hg qpush
1322 applying changea
1322 applying changea
1323 now at: changea
1323 now at: changea
1324 $ cd ..
1324 $ cd ..
1325
1325
1326 test qpush with --force, issue1087
1326 test qpush with --force, issue1087
1327
1327
1328 $ hg init forcepush
1328 $ hg init forcepush
1329 $ cd forcepush
1329 $ cd forcepush
1330 $ echo hello > hello.txt
1330 $ echo hello > hello.txt
1331 $ echo bye > bye.txt
1331 $ echo bye > bye.txt
1332 $ hg ci -Ama
1332 $ hg ci -Ama
1333 adding bye.txt
1333 adding bye.txt
1334 adding hello.txt
1334 adding hello.txt
1335 $ hg qnew -d '0 0' empty
1335 $ hg qnew -d '0 0' empty
1336 $ hg qpop
1336 $ hg qpop
1337 popping empty
1337 popping empty
1338 patch queue now empty
1338 patch queue now empty
1339 $ echo world >> hello.txt
1339 $ echo world >> hello.txt
1340
1340
1341
1341
1342 qpush should fail, local changes
1342 qpush should fail, local changes
1343
1343
1344 $ hg qpush
1344 $ hg qpush
1345 abort: local changes found
1345 abort: local changes found
1346 [255]
1346 [255]
1347
1347
1348
1348
1349 apply force, should not discard changes with empty patch
1349 apply force, should not discard changes with empty patch
1350
1350
1351 $ hg qpush -f
1351 $ hg qpush -f
1352 applying empty
1352 applying empty
1353 patch empty is empty
1353 patch empty is empty
1354 now at: empty
1354 now at: empty
1355 $ hg diff --config diff.nodates=True
1355 $ hg diff --config diff.nodates=True
1356 diff -r d58265112590 hello.txt
1356 diff -r d58265112590 hello.txt
1357 --- a/hello.txt
1357 --- a/hello.txt
1358 +++ b/hello.txt
1358 +++ b/hello.txt
1359 @@ -1,1 +1,2 @@
1359 @@ -1,1 +1,2 @@
1360 hello
1360 hello
1361 +world
1361 +world
1362 $ hg qdiff --config diff.nodates=True
1362 $ hg qdiff --config diff.nodates=True
1363 diff -r 9ecee4f634e3 hello.txt
1363 diff -r 9ecee4f634e3 hello.txt
1364 --- a/hello.txt
1364 --- a/hello.txt
1365 +++ b/hello.txt
1365 +++ b/hello.txt
1366 @@ -1,1 +1,2 @@
1366 @@ -1,1 +1,2 @@
1367 hello
1367 hello
1368 +world
1368 +world
1369 $ hg log -l1 -p
1369 $ hg log -l1 -p
1370 changeset: 1:d58265112590
1370 changeset: 1:d58265112590
1371 tag: empty
1371 tag: empty
1372 tag: qbase
1372 tag: qbase
1373 tag: qtip
1373 tag: qtip
1374 tag: tip
1374 tag: tip
1375 user: test
1375 user: test
1376 date: Thu Jan 01 00:00:00 1970 +0000
1376 date: Thu Jan 01 00:00:00 1970 +0000
1377 summary: imported patch empty
1377 summary: imported patch empty
1378
1378
1379
1379
1380 $ hg qref -d '0 0'
1380 $ hg qref -d '0 0'
1381 $ hg qpop
1381 $ hg qpop
1382 popping empty
1382 popping empty
1383 patch queue now empty
1383 patch queue now empty
1384 $ echo universe >> hello.txt
1384 $ echo universe >> hello.txt
1385 $ echo universe >> bye.txt
1385 $ echo universe >> bye.txt
1386
1386
1387
1387
1388 qpush should fail, local changes
1388 qpush should fail, local changes
1389
1389
1390 $ hg qpush
1390 $ hg qpush
1391 abort: local changes found
1391 abort: local changes found
1392 [255]
1392 [255]
1393
1393
1394
1394
1395 apply force, should discard changes in hello, but not bye
1395 apply force, should discard changes in hello, but not bye
1396
1396
1397 $ hg qpush -f --verbose
1397 $ hg qpush -f --verbose
1398 applying empty
1398 applying empty
1399 saving current version of hello.txt as hello.txt.orig
1399 saving current version of hello.txt as hello.txt.orig
1400 patching file hello.txt
1400 patching file hello.txt
1401 committing files:
1401 committing files:
1402 hello.txt
1402 hello.txt
1403 committing manifest
1403 committing manifest
1404 committing changelog
1404 committing changelog
1405 now at: empty
1405 now at: empty
1406 $ hg st
1406 $ hg st
1407 M bye.txt
1407 M bye.txt
1408 ? hello.txt.orig
1408 ? hello.txt.orig
1409 $ hg diff --config diff.nodates=True
1409 $ hg diff --config diff.nodates=True
1410 diff -r ba252371dbc1 bye.txt
1410 diff -r ba252371dbc1 bye.txt
1411 --- a/bye.txt
1411 --- a/bye.txt
1412 +++ b/bye.txt
1412 +++ b/bye.txt
1413 @@ -1,1 +1,2 @@
1413 @@ -1,1 +1,2 @@
1414 bye
1414 bye
1415 +universe
1415 +universe
1416 $ hg qdiff --config diff.nodates=True
1416 $ hg qdiff --config diff.nodates=True
1417 diff -r 9ecee4f634e3 bye.txt
1417 diff -r 9ecee4f634e3 bye.txt
1418 --- a/bye.txt
1418 --- a/bye.txt
1419 +++ b/bye.txt
1419 +++ b/bye.txt
1420 @@ -1,1 +1,2 @@
1420 @@ -1,1 +1,2 @@
1421 bye
1421 bye
1422 +universe
1422 +universe
1423 diff -r 9ecee4f634e3 hello.txt
1423 diff -r 9ecee4f634e3 hello.txt
1424 --- a/hello.txt
1424 --- a/hello.txt
1425 +++ b/hello.txt
1425 +++ b/hello.txt
1426 @@ -1,1 +1,3 @@
1426 @@ -1,1 +1,3 @@
1427 hello
1427 hello
1428 +world
1428 +world
1429 +universe
1429 +universe
1430
1430
1431
1431
1432 test popping revisions not in working dir ancestry
1432 test popping revisions not in working dir ancestry
1433
1433
1434 $ hg qseries -v
1434 $ hg qseries -v
1435 0 A empty
1435 0 A empty
1436 $ hg up qparent
1436 $ hg up qparent
1437 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1437 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1438 $ hg qpop
1438 $ hg qpop
1439 popping empty
1439 popping empty
1440 patch queue now empty
1440 patch queue now empty
1441
1441
1442 $ cd ..
1442 $ cd ..
1443 $ hg init deletion-order
1443 $ hg init deletion-order
1444 $ cd deletion-order
1444 $ cd deletion-order
1445
1445
1446 $ touch a
1446 $ touch a
1447 $ hg ci -Aqm0
1447 $ hg ci -Aqm0
1448
1448
1449 $ hg qnew rename-dir
1449 $ hg qnew rename-dir
1450 $ hg rm a
1450 $ hg rm a
1451 $ hg qrefresh
1451 $ hg qrefresh
1452
1452
1453 $ mkdir a b
1453 $ mkdir a b
1454 $ touch a/a b/b
1454 $ touch a/a b/b
1455 $ hg add -q a b
1455 $ hg add -q a b
1456 $ hg qrefresh
1456 $ hg qrefresh
1457
1457
1458
1458
1459 test popping must remove files added in subdirectories first
1459 test popping must remove files added in subdirectories first
1460
1460
1461 $ hg qpop
1461 $ hg qpop
1462 popping rename-dir
1462 popping rename-dir
1463 patch queue now empty
1463 patch queue now empty
1464 $ cd ..
1464 $ cd ..
1465
1465
1466
1466
1467 test case preservation through patch pushing especially on case
1467 test case preservation through patch pushing especially on case
1468 insensitive filesystem
1468 insensitive filesystem
1469
1469
1470 $ hg init casepreserve
1470 $ hg init casepreserve
1471 $ cd casepreserve
1471 $ cd casepreserve
1472
1472
1473 $ hg qnew add-file1
1473 $ hg qnew add-file1
1474 $ echo a > TeXtFiLe.TxT
1474 $ echo a > TeXtFiLe.TxT
1475 $ hg add TeXtFiLe.TxT
1475 $ hg add TeXtFiLe.TxT
1476 $ hg qrefresh
1476 $ hg qrefresh
1477
1477
1478 $ hg qnew add-file2
1478 $ hg qnew add-file2
1479 $ echo b > AnOtHeRFiLe.TxT
1479 $ echo b > AnOtHeRFiLe.TxT
1480 $ hg add AnOtHeRFiLe.TxT
1480 $ hg add AnOtHeRFiLe.TxT
1481 $ hg qrefresh
1481 $ hg qrefresh
1482
1482
1483 $ hg qnew modify-file
1483 $ hg qnew modify-file
1484 $ echo c >> AnOtHeRFiLe.TxT
1484 $ echo c >> AnOtHeRFiLe.TxT
1485 $ hg qrefresh
1485 $ hg qrefresh
1486
1486
1487 $ hg qapplied
1487 $ hg qapplied
1488 add-file1
1488 add-file1
1489 add-file2
1489 add-file2
1490 modify-file
1490 modify-file
1491 $ hg qpop -a
1491 $ hg qpop -a
1492 popping modify-file
1492 popping modify-file
1493 popping add-file2
1493 popping add-file2
1494 popping add-file1
1494 popping add-file1
1495 patch queue now empty
1495 patch queue now empty
1496
1496
1497 this qpush causes problems below, if case preservation on case
1497 this qpush causes problems below, if case preservation on case
1498 insensitive filesystem is not enough:
1498 insensitive filesystem is not enough:
1499 (1) unexpected "adding ..." messages are shown
1499 (1) unexpected "adding ..." messages are shown
1500 (2) patching fails in modification of (1) files
1500 (2) patching fails in modification of (1) files
1501
1501
1502 $ hg qpush -a
1502 $ hg qpush -a
1503 applying add-file1
1503 applying add-file1
1504 applying add-file2
1504 applying add-file2
1505 applying modify-file
1505 applying modify-file
1506 now at: modify-file
1506 now at: modify-file
1507
1507
1508 Proper phase default with mq:
1508 Proper phase default with mq:
1509
1509
1510 1. mq.secret=false
1510 1. mq.secret=false
1511
1511
1512 $ rm .hg/store/phaseroots
1512 $ rm .hg/store/phaseroots
1513 $ hg phase 'qparent::'
1513 $ hg phase 'qparent::'
1514 -1: public
1514 -1: public
1515 0: draft
1515 0: draft
1516 1: draft
1516 1: draft
1517 2: draft
1517 2: draft
1518 $ echo '[mq]' >> $HGRCPATH
1518 $ echo '[mq]' >> $HGRCPATH
1519 $ echo 'secret=true' >> $HGRCPATH
1519 $ echo 'secret=true' >> $HGRCPATH
1520 $ rm -f .hg/store/phaseroots
1520 $ rm -f .hg/store/phaseroots
1521 $ hg phase 'qparent::'
1521 $ hg phase 'qparent::'
1522 -1: public
1522 -1: public
1523 0: secret
1523 0: secret
1524 1: secret
1524 1: secret
1525 2: secret
1525 2: secret
1526
1526
1527 Test that qfinish change phase when mq.secret=true
1527 Test that qfinish change phase when mq.secret=true
1528
1528
1529 $ hg qfinish qbase
1529 $ hg qfinish qbase
1530 patch add-file1 finalized without changeset message
1530 patch add-file1 finalized without changeset message
1531 $ hg phase 'all()'
1531 $ hg phase 'all()'
1532 0: draft
1532 0: draft
1533 1: secret
1533 1: secret
1534 2: secret
1534 2: secret
1535
1535
1536 Test that qfinish respect phases.new-commit setting
1536 Test that qfinish respect phases.new-commit setting
1537
1537
1538 $ echo '[phases]' >> $HGRCPATH
1538 $ echo '[phases]' >> $HGRCPATH
1539 $ echo 'new-commit=secret' >> $HGRCPATH
1539 $ echo 'new-commit=secret' >> $HGRCPATH
1540 $ hg qfinish qbase
1540 $ hg qfinish qbase
1541 patch add-file2 finalized without changeset message
1541 patch add-file2 finalized without changeset message
1542 $ hg phase 'all()'
1542 $ hg phase 'all()'
1543 0: draft
1543 0: draft
1544 1: secret
1544 1: secret
1545 2: secret
1545 2: secret
1546
1546
1547 (restore env for next test)
1547 (restore env for next test)
1548
1548
1549 $ sed -e 's/new-commit=secret//' $HGRCPATH > $TESTTMP/sedtmp
1549 $ sed -e 's/new-commit=secret//' $HGRCPATH > $TESTTMP/sedtmp
1550 $ cp $TESTTMP/sedtmp $HGRCPATH
1550 $ cp $TESTTMP/sedtmp $HGRCPATH
1551 $ hg qimport -r 1 --name add-file2
1551 $ hg qimport -r 1 --name add-file2
1552
1552
1553 Test that qfinish preserve phase when mq.secret=false
1553 Test that qfinish preserve phase when mq.secret=false
1554
1554
1555 $ sed -e 's/secret=true/secret=false/' $HGRCPATH > $TESTTMP/sedtmp
1555 $ sed -e 's/secret=true/secret=false/' $HGRCPATH > $TESTTMP/sedtmp
1556 $ cp $TESTTMP/sedtmp $HGRCPATH
1556 $ cp $TESTTMP/sedtmp $HGRCPATH
1557 $ hg qfinish qbase
1557 $ hg qfinish qbase
1558 patch add-file2 finalized without changeset message
1558 patch add-file2 finalized without changeset message
1559 $ hg phase 'all()'
1559 $ hg phase 'all()'
1560 0: draft
1560 0: draft
1561 1: secret
1561 1: secret
1562 2: secret
1562 2: secret
1563
1563
1564 Test that secret mq patch does not break hgweb
1564 Test that secret mq patch does not break hgweb
1565
1565
1566 $ cat > hgweb.cgi <<HGWEB
1566 $ cat > hgweb.cgi <<HGWEB
1567 > from mercurial import demandimport; demandimport.enable()
1567 > from mercurial import demandimport; demandimport.enable()
1568 > from mercurial.hgweb import hgweb
1568 > from mercurial.hgweb import hgweb
1569 > from mercurial.hgweb import wsgicgi
1569 > from mercurial.hgweb import wsgicgi
1570 > import cgitb
1570 > import cgitb
1571 > cgitb.enable()
1571 > cgitb.enable()
1572 > app = hgweb('.', 'test')
1572 > app = hgweb('.', 'test')
1573 > wsgicgi.launch(app)
1573 > wsgicgi.launch(app)
1574 > HGWEB
1574 > HGWEB
1575 $ . "$TESTDIR/cgienv"
1575 $ . "$TESTDIR/cgienv"
1576 #if msys
1576 #if msys
1577 $ PATH_INFO=//tags; export PATH_INFO
1577 $ PATH_INFO=//tags; export PATH_INFO
1578 #else
1578 #else
1579 $ PATH_INFO=/tags; export PATH_INFO
1579 $ PATH_INFO=/tags; export PATH_INFO
1580 #endif
1580 #endif
1581 $ QUERY_STRING='style=raw'
1581 $ QUERY_STRING='style=raw'
1582 $ python hgweb.cgi | grep '^tip'
1582 $ python hgweb.cgi | grep '^tip'
1583 tip [0-9a-f]{40} (re)
1583 tip [0-9a-f]{40} (re)
1584
1584
1585 $ cd ..
1585 $ cd ..
1586
1586
1587 Test interaction with revset (issue4426)
1587 Test interaction with revset (issue4426)
1588
1588
1589 $ hg init issue4426
1589 $ hg init issue4426
1590 $ cd issue4426
1590 $ cd issue4426
1591
1591
1592 $ echo a > a
1592 $ echo a > a
1593 $ hg ci -Am a
1593 $ hg ci -Am a
1594 adding a
1594 adding a
1595 $ echo a >> a
1595 $ echo a >> a
1596 $ hg ci -m a
1596 $ hg ci -m a
1597 $ echo a >> a
1597 $ echo a >> a
1598 $ hg ci -m a
1598 $ hg ci -m a
1599 $ hg qimport -r 0::
1599 $ hg qimport -r 0::
1600
1600
1601 reimport things
1601 reimport things
1602
1602
1603 $ hg qimport -r 1::
1603 $ hg qimport -r 1::
1604 abort: revision 2 is already managed
1604 abort: revision 2 is already managed
1605 [255]
1605 [255]
1606
1606
1607
1607
1608 $ cd ..
1608 $ cd ..
@@ -1,113 +1,113
1 $ cat >> $HGRCPATH << EOF
1 $ cat >> $HGRCPATH << EOF
2 > [extensions]
2 > [extensions]
3 > blackbox=
3 > blackbox=
4 > rebase=
4 > rebase=
5 > mock=$TESTDIR/mockblackbox.py
5 > mock=$TESTDIR/mockblackbox.py
6 >
6 >
7 > [experimental]
7 > [experimental]
8 > evolution = createmarkers
8 > evolution = createmarkers
9 > EOF
9 > EOF
10
10
11 Create a repo with some tags
11 Create a repo with some tags
12
12
13 $ hg init repo
13 $ hg init repo
14 $ cd repo
14 $ cd repo
15 $ echo initial > foo
15 $ echo initial > foo
16 $ hg -q commit -A -m initial
16 $ hg -q commit -A -m initial
17 $ hg tag -m 'test tag' test1
17 $ hg tag -m 'test tag' test1
18 $ echo first > first
18 $ echo first > first
19 $ hg -q commit -A -m first
19 $ hg -q commit -A -m first
20 $ hg tag -m 'test2 tag' test2
20 $ hg tag -m 'test2 tag' test2
21 $ hg -q up -r 0
21 $ hg -q up -r 0
22 $ echo newhead > newhead
22 $ echo newhead > newhead
23 $ hg commit -A -m newhead
23 $ hg commit -A -m newhead
24 adding newhead
24 adding newhead
25 created new head
25 created new head
26 $ hg tag -m 'test head 2 tag' head2
26 $ hg tag -m 'test head 2 tag' head2
27
27
28 $ hg log -G -T '{rev}:{node|short} {tags} {desc}\n'
28 $ hg log -G -T '{rev}:{node|short} {tags} {desc}\n'
29 @ 5:2942a772f72a tip test head 2 tag
29 @ 5:2942a772f72a tip test head 2 tag
30 |
30 |
31 o 4:042eb6bfcc49 head2 newhead
31 o 4:042eb6bfcc49 head2 newhead
32 |
32 |
33 | o 3:c3cb30f2d2cd test2 tag
33 | o 3:c3cb30f2d2cd test2 tag
34 | |
34 | |
35 | o 2:d75775ffbc6b test2 first
35 | o 2:d75775ffbc6b test2 first
36 | |
36 | |
37 | o 1:5f97d42da03f test tag
37 | o 1:5f97d42da03f test tag
38 |/
38 |/
39 o 0:55482a6fb4b1 test1 initial
39 o 0:55482a6fb4b1 test1 initial
40
40
41
41
42 Trigger tags cache population by doing something that accesses tags info
42 Trigger tags cache population by doing something that accesses tags info
43
43
44 $ hg tags
44 $ hg tags
45 tip 5:2942a772f72a
45 tip 5:2942a772f72a
46 head2 4:042eb6bfcc49
46 head2 4:042eb6bfcc49
47 test2 2:d75775ffbc6b
47 test2 2:d75775ffbc6b
48 test1 0:55482a6fb4b1
48 test1 0:55482a6fb4b1
49
49
50 $ cat .hg/cache/tags2-visible
50 $ cat .hg/cache/tags2-visible
51 5 2942a772f72a444bef4bef13874d515f50fa27b6
51 5 2942a772f72a444bef4bef13874d515f50fa27b6
52 042eb6bfcc4909bad84a1cbf6eb1ddf0ab587d41 head2
52 042eb6bfcc4909bad84a1cbf6eb1ddf0ab587d41 head2
53 55482a6fb4b1881fa8f746fd52cf6f096bb21c89 test1
53 55482a6fb4b1881fa8f746fd52cf6f096bb21c89 test1
54 d75775ffbc6bca1794d300f5571272879bd280da test2
54 d75775ffbc6bca1794d300f5571272879bd280da test2
55
55
56 Hiding a non-tip changeset should change filtered hash and cause tags recompute
56 Hiding a non-tip changeset should change filtered hash and cause tags recompute
57
57
58 $ hg debugobsolete -d '0 0' c3cb30f2d2cd0aae008cc91a07876e3c5131fd22 -u dummyuser
58 $ hg debugobsolete -d '0 0' c3cb30f2d2cd0aae008cc91a07876e3c5131fd22 -u dummyuser
59
59
60 $ hg tags
60 $ hg tags
61 tip 5:2942a772f72a
61 tip 5:2942a772f72a
62 head2 4:042eb6bfcc49
62 head2 4:042eb6bfcc49
63 test1 0:55482a6fb4b1
63 test1 0:55482a6fb4b1
64
64
65 $ cat .hg/cache/tags2-visible
65 $ cat .hg/cache/tags2-visible
66 5 2942a772f72a444bef4bef13874d515f50fa27b6 f34fbc9a9769ba9eff5aff3d008a6b49f85c08b1
66 5 2942a772f72a444bef4bef13874d515f50fa27b6 f34fbc9a9769ba9eff5aff3d008a6b49f85c08b1
67 042eb6bfcc4909bad84a1cbf6eb1ddf0ab587d41 head2
67 042eb6bfcc4909bad84a1cbf6eb1ddf0ab587d41 head2
68 55482a6fb4b1881fa8f746fd52cf6f096bb21c89 test1
68 55482a6fb4b1881fa8f746fd52cf6f096bb21c89 test1
69
69
70 $ hg blackbox -l 4
70 $ hg blackbox -l 4
71 1970/01/01 00:00:00 bob> tags
71 1970/01/01 00:00:00 bob> tags
72 1970/01/01 00:00:00 bob> 2/2 cache hits/lookups in * seconds (glob)
72 1970/01/01 00:00:00 bob> 2/2 cache hits/lookups in * seconds (glob)
73 1970/01/01 00:00:00 bob> writing tags cache file with 2 tags
73 1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 2 tags
74 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
74 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
75
75
76 Hiding another changeset should cause the filtered hash to change
76 Hiding another changeset should cause the filtered hash to change
77
77
78 $ hg debugobsolete -d '0 0' d75775ffbc6bca1794d300f5571272879bd280da -u dummyuser
78 $ hg debugobsolete -d '0 0' d75775ffbc6bca1794d300f5571272879bd280da -u dummyuser
79 $ hg debugobsolete -d '0 0' 5f97d42da03fd56f3b228b03dfe48af5c0adf75b -u dummyuser
79 $ hg debugobsolete -d '0 0' 5f97d42da03fd56f3b228b03dfe48af5c0adf75b -u dummyuser
80
80
81 $ hg tags
81 $ hg tags
82 tip 5:2942a772f72a
82 tip 5:2942a772f72a
83 head2 4:042eb6bfcc49
83 head2 4:042eb6bfcc49
84
84
85 $ cat .hg/cache/tags2-visible
85 $ cat .hg/cache/tags2-visible
86 5 2942a772f72a444bef4bef13874d515f50fa27b6 2fce1eec33263d08a4d04293960fc73a555230e4
86 5 2942a772f72a444bef4bef13874d515f50fa27b6 2fce1eec33263d08a4d04293960fc73a555230e4
87 042eb6bfcc4909bad84a1cbf6eb1ddf0ab587d41 head2
87 042eb6bfcc4909bad84a1cbf6eb1ddf0ab587d41 head2
88
88
89 $ hg blackbox -l 4
89 $ hg blackbox -l 4
90 1970/01/01 00:00:00 bob> tags
90 1970/01/01 00:00:00 bob> tags
91 1970/01/01 00:00:00 bob> 1/1 cache hits/lookups in * seconds (glob)
91 1970/01/01 00:00:00 bob> 1/1 cache hits/lookups in * seconds (glob)
92 1970/01/01 00:00:00 bob> writing tags cache file with 1 tags
92 1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 1 tags
93 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
93 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
94
94
95 Resolving tags on an unfiltered repo writes a separate tags cache
95 Resolving tags on an unfiltered repo writes a separate tags cache
96
96
97 $ hg --hidden tags
97 $ hg --hidden tags
98 tip 5:2942a772f72a
98 tip 5:2942a772f72a
99 head2 4:042eb6bfcc49
99 head2 4:042eb6bfcc49
100 test2 2:d75775ffbc6b
100 test2 2:d75775ffbc6b
101 test1 0:55482a6fb4b1
101 test1 0:55482a6fb4b1
102
102
103 $ cat .hg/cache/tags2
103 $ cat .hg/cache/tags2
104 5 2942a772f72a444bef4bef13874d515f50fa27b6
104 5 2942a772f72a444bef4bef13874d515f50fa27b6
105 042eb6bfcc4909bad84a1cbf6eb1ddf0ab587d41 head2
105 042eb6bfcc4909bad84a1cbf6eb1ddf0ab587d41 head2
106 55482a6fb4b1881fa8f746fd52cf6f096bb21c89 test1
106 55482a6fb4b1881fa8f746fd52cf6f096bb21c89 test1
107 d75775ffbc6bca1794d300f5571272879bd280da test2
107 d75775ffbc6bca1794d300f5571272879bd280da test2
108
108
109 $ hg blackbox -l 4
109 $ hg blackbox -l 4
110 1970/01/01 00:00:00 bob> --hidden tags
110 1970/01/01 00:00:00 bob> --hidden tags
111 1970/01/01 00:00:00 bob> 2/2 cache hits/lookups in * seconds (glob)
111 1970/01/01 00:00:00 bob> 2/2 cache hits/lookups in * seconds (glob)
112 1970/01/01 00:00:00 bob> writing tags cache file with 3 tags
112 1970/01/01 00:00:00 bob> writing .hg/cache/tags2 with 3 tags
113 1970/01/01 00:00:00 bob> --hidden tags exited 0 after * seconds (glob)
113 1970/01/01 00:00:00 bob> --hidden tags exited 0 after * seconds (glob)
@@ -1,612 +1,612
1 setup
1 setup
2
2
3 $ cat >> $HGRCPATH << EOF
3 $ cat >> $HGRCPATH << EOF
4 > [extensions]
4 > [extensions]
5 > blackbox=
5 > blackbox=
6 > mock=$TESTDIR/mockblackbox.py
6 > mock=$TESTDIR/mockblackbox.py
7 > EOF
7 > EOF
8
8
9 Helper functions:
9 Helper functions:
10
10
11 $ cacheexists() {
11 $ cacheexists() {
12 > [ -f .hg/cache/tags2-visible ] && echo "tag cache exists" || echo "no tag cache"
12 > [ -f .hg/cache/tags2-visible ] && echo "tag cache exists" || echo "no tag cache"
13 > }
13 > }
14
14
15 $ fnodescacheexists() {
15 $ fnodescacheexists() {
16 > [ -f .hg/cache/hgtagsfnodes1 ] && echo "fnodes cache exists" || echo "no fnodes cache"
16 > [ -f .hg/cache/hgtagsfnodes1 ] && echo "fnodes cache exists" || echo "no fnodes cache"
17 > }
17 > }
18
18
19 $ dumptags() {
19 $ dumptags() {
20 > rev=$1
20 > rev=$1
21 > echo "rev $rev: .hgtags:"
21 > echo "rev $rev: .hgtags:"
22 > hg cat -r$rev .hgtags
22 > hg cat -r$rev .hgtags
23 > }
23 > }
24
24
25 # XXX need to test that the tag cache works when we strip an old head
25 # XXX need to test that the tag cache works when we strip an old head
26 # and add a new one rooted off non-tip: i.e. node and rev of tip are the
26 # and add a new one rooted off non-tip: i.e. node and rev of tip are the
27 # same, but stuff has changed behind tip.
27 # same, but stuff has changed behind tip.
28
28
29 Setup:
29 Setup:
30
30
31 $ hg init t
31 $ hg init t
32 $ cd t
32 $ cd t
33 $ cacheexists
33 $ cacheexists
34 no tag cache
34 no tag cache
35 $ fnodescacheexists
35 $ fnodescacheexists
36 no fnodes cache
36 no fnodes cache
37 $ hg id
37 $ hg id
38 000000000000 tip
38 000000000000 tip
39 $ cacheexists
39 $ cacheexists
40 no tag cache
40 no tag cache
41 $ fnodescacheexists
41 $ fnodescacheexists
42 no fnodes cache
42 no fnodes cache
43 $ echo a > a
43 $ echo a > a
44 $ hg add a
44 $ hg add a
45 $ hg commit -m "test"
45 $ hg commit -m "test"
46 $ hg co
46 $ hg co
47 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
47 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 $ hg identify
48 $ hg identify
49 acb14030fe0a tip
49 acb14030fe0a tip
50 $ cacheexists
50 $ cacheexists
51 tag cache exists
51 tag cache exists
52 No fnodes cache because .hgtags file doesn't exist
52 No fnodes cache because .hgtags file doesn't exist
53 (this is an implementation detail)
53 (this is an implementation detail)
54 $ fnodescacheexists
54 $ fnodescacheexists
55 no fnodes cache
55 no fnodes cache
56
56
57 Try corrupting the cache
57 Try corrupting the cache
58
58
59 $ printf 'a b' > .hg/cache/tags2-visible
59 $ printf 'a b' > .hg/cache/tags2-visible
60 $ hg identify
60 $ hg identify
61 acb14030fe0a tip
61 acb14030fe0a tip
62 $ cacheexists
62 $ cacheexists
63 tag cache exists
63 tag cache exists
64 $ fnodescacheexists
64 $ fnodescacheexists
65 no fnodes cache
65 no fnodes cache
66 $ hg identify
66 $ hg identify
67 acb14030fe0a tip
67 acb14030fe0a tip
68
68
69 Create local tag with long name:
69 Create local tag with long name:
70
70
71 $ T=`hg identify --debug --id`
71 $ T=`hg identify --debug --id`
72 $ hg tag -l "This is a local tag with a really long name!"
72 $ hg tag -l "This is a local tag with a really long name!"
73 $ hg tags
73 $ hg tags
74 tip 0:acb14030fe0a
74 tip 0:acb14030fe0a
75 This is a local tag with a really long name! 0:acb14030fe0a
75 This is a local tag with a really long name! 0:acb14030fe0a
76 $ rm .hg/localtags
76 $ rm .hg/localtags
77
77
78 Create a tag behind hg's back:
78 Create a tag behind hg's back:
79
79
80 $ echo "$T first" > .hgtags
80 $ echo "$T first" > .hgtags
81 $ cat .hgtags
81 $ cat .hgtags
82 acb14030fe0a21b60322c440ad2d20cf7685a376 first
82 acb14030fe0a21b60322c440ad2d20cf7685a376 first
83 $ hg add .hgtags
83 $ hg add .hgtags
84 $ hg commit -m "add tags"
84 $ hg commit -m "add tags"
85 $ hg tags
85 $ hg tags
86 tip 1:b9154636be93
86 tip 1:b9154636be93
87 first 0:acb14030fe0a
87 first 0:acb14030fe0a
88 $ hg identify
88 $ hg identify
89 b9154636be93 tip
89 b9154636be93 tip
90
90
91 We should have a fnodes cache now that we have a real tag
91 We should have a fnodes cache now that we have a real tag
92 The cache should have an empty entry for rev 0 and a valid entry for rev 1.
92 The cache should have an empty entry for rev 0 and a valid entry for rev 1.
93
93
94
94
95 $ fnodescacheexists
95 $ fnodescacheexists
96 fnodes cache exists
96 fnodes cache exists
97 $ f --size --hexdump .hg/cache/hgtagsfnodes1
97 $ f --size --hexdump .hg/cache/hgtagsfnodes1
98 .hg/cache/hgtagsfnodes1: size=48
98 .hg/cache/hgtagsfnodes1: size=48
99 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
99 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
100 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
100 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
101 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
101 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
102
102
103 Repeat with cold tag cache:
103 Repeat with cold tag cache:
104
104
105 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
105 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
106 $ hg identify
106 $ hg identify
107 b9154636be93 tip
107 b9154636be93 tip
108
108
109 $ fnodescacheexists
109 $ fnodescacheexists
110 fnodes cache exists
110 fnodes cache exists
111 $ f --size --hexdump .hg/cache/hgtagsfnodes1
111 $ f --size --hexdump .hg/cache/hgtagsfnodes1
112 .hg/cache/hgtagsfnodes1: size=48
112 .hg/cache/hgtagsfnodes1: size=48
113 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
113 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
114 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
114 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
115 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
115 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
116
116
117 And again, but now unable to write tag cache:
117 And again, but now unable to write tag cache:
118
118
119 #if unix-permissions
119 #if unix-permissions
120 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
120 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
121 $ chmod 555 .hg/cache
121 $ chmod 555 .hg/cache
122 $ hg identify
122 $ hg identify
123 b9154636be93 tip
123 b9154636be93 tip
124 $ chmod 755 .hg/cache
124 $ chmod 755 .hg/cache
125 #endif
125 #endif
126
126
127 Tag cache debug info written to blackbox log
127 Tag cache debug info written to blackbox log
128
128
129 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
129 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
130 $ hg identify
130 $ hg identify
131 b9154636be93 tip
131 b9154636be93 tip
132 $ hg blackbox -l 5
132 $ hg blackbox -l 5
133 1970/01/01 00:00:00 bob> identify
133 1970/01/01 00:00:00 bob> identify
134 1970/01/01 00:00:00 bob> writing 48 bytes to cache/hgtagsfnodes1
134 1970/01/01 00:00:00 bob> writing 48 bytes to cache/hgtagsfnodes1
135 1970/01/01 00:00:00 bob> 0/1 cache hits/lookups in * seconds (glob)
135 1970/01/01 00:00:00 bob> 0/1 cache hits/lookups in * seconds (glob)
136 1970/01/01 00:00:00 bob> writing tags cache file with 1 tags
136 1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 1 tags
137 1970/01/01 00:00:00 bob> identify exited 0 after ?.?? seconds (glob)
137 1970/01/01 00:00:00 bob> identify exited 0 after ?.?? seconds (glob)
138
138
139 Failure to acquire lock results in no write
139 Failure to acquire lock results in no write
140
140
141 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
141 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
142 $ echo 'foo:1' > .hg/wlock
142 $ echo 'foo:1' > .hg/wlock
143 $ hg identify
143 $ hg identify
144 b9154636be93 tip
144 b9154636be93 tip
145 $ hg blackbox -l 5
145 $ hg blackbox -l 5
146 1970/01/01 00:00:00 bob> identify
146 1970/01/01 00:00:00 bob> identify
147 1970/01/01 00:00:00 bob> not writing .hg/cache/hgtagsfnodes1 because lock held
147 1970/01/01 00:00:00 bob> not writing .hg/cache/hgtagsfnodes1 because lock held
148 1970/01/01 00:00:00 bob> 0/1 cache hits/lookups in * seconds (glob)
148 1970/01/01 00:00:00 bob> 0/1 cache hits/lookups in * seconds (glob)
149 1970/01/01 00:00:00 bob> writing tags cache file with 1 tags
149 1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 1 tags
150 1970/01/01 00:00:00 bob> identify exited 0 after * seconds (glob)
150 1970/01/01 00:00:00 bob> identify exited 0 after * seconds (glob)
151
151
152 $ fnodescacheexists
152 $ fnodescacheexists
153 no fnodes cache
153 no fnodes cache
154
154
155 $ rm .hg/wlock
155 $ rm .hg/wlock
156
156
157 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
157 $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
158 $ hg identify
158 $ hg identify
159 b9154636be93 tip
159 b9154636be93 tip
160
160
161 Create a branch:
161 Create a branch:
162
162
163 $ echo bb > a
163 $ echo bb > a
164 $ hg status
164 $ hg status
165 M a
165 M a
166 $ hg identify
166 $ hg identify
167 b9154636be93+ tip
167 b9154636be93+ tip
168 $ hg co first
168 $ hg co first
169 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
169 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
170 $ hg id
170 $ hg id
171 acb14030fe0a+ first
171 acb14030fe0a+ first
172 $ hg -v id
172 $ hg -v id
173 acb14030fe0a+ first
173 acb14030fe0a+ first
174 $ hg status
174 $ hg status
175 M a
175 M a
176 $ echo 1 > b
176 $ echo 1 > b
177 $ hg add b
177 $ hg add b
178 $ hg commit -m "branch"
178 $ hg commit -m "branch"
179 created new head
179 created new head
180
180
181 Creating a new commit shouldn't append the .hgtags fnodes cache until
181 Creating a new commit shouldn't append the .hgtags fnodes cache until
182 tags info is accessed
182 tags info is accessed
183
183
184 $ f --size --hexdump .hg/cache/hgtagsfnodes1
184 $ f --size --hexdump .hg/cache/hgtagsfnodes1
185 .hg/cache/hgtagsfnodes1: size=48
185 .hg/cache/hgtagsfnodes1: size=48
186 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
186 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
187 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
187 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
188 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
188 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
189
189
190 $ hg id
190 $ hg id
191 c8edf04160c7 tip
191 c8edf04160c7 tip
192
192
193 First 4 bytes of record 3 are changeset fragment
193 First 4 bytes of record 3 are changeset fragment
194
194
195 $ f --size --hexdump .hg/cache/hgtagsfnodes1
195 $ f --size --hexdump .hg/cache/hgtagsfnodes1
196 .hg/cache/hgtagsfnodes1: size=72
196 .hg/cache/hgtagsfnodes1: size=72
197 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
197 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
198 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
198 0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
199 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
199 0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
200 0030: c8 ed f0 41 00 00 00 00 00 00 00 00 00 00 00 00 |...A............|
200 0030: c8 ed f0 41 00 00 00 00 00 00 00 00 00 00 00 00 |...A............|
201 0040: 00 00 00 00 00 00 00 00 |........|
201 0040: 00 00 00 00 00 00 00 00 |........|
202
202
203 Merge the two heads:
203 Merge the two heads:
204
204
205 $ hg merge 1
205 $ hg merge 1
206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 (branch merge, don't forget to commit)
207 (branch merge, don't forget to commit)
208 $ hg id
208 $ hg id
209 c8edf04160c7+b9154636be93+ tip
209 c8edf04160c7+b9154636be93+ tip
210 $ hg status
210 $ hg status
211 M .hgtags
211 M .hgtags
212 $ hg commit -m "merge"
212 $ hg commit -m "merge"
213
213
214 Create a fake head, make sure tag not visible afterwards:
214 Create a fake head, make sure tag not visible afterwards:
215
215
216 $ cp .hgtags tags
216 $ cp .hgtags tags
217 $ hg tag last
217 $ hg tag last
218 $ hg rm .hgtags
218 $ hg rm .hgtags
219 $ hg commit -m "remove"
219 $ hg commit -m "remove"
220
220
221 $ mv tags .hgtags
221 $ mv tags .hgtags
222 $ hg add .hgtags
222 $ hg add .hgtags
223 $ hg commit -m "readd"
223 $ hg commit -m "readd"
224 $
224 $
225 $ hg tags
225 $ hg tags
226 tip 6:35ff301afafe
226 tip 6:35ff301afafe
227 first 0:acb14030fe0a
227 first 0:acb14030fe0a
228
228
229 Add invalid tags:
229 Add invalid tags:
230
230
231 $ echo "spam" >> .hgtags
231 $ echo "spam" >> .hgtags
232 $ echo >> .hgtags
232 $ echo >> .hgtags
233 $ echo "foo bar" >> .hgtags
233 $ echo "foo bar" >> .hgtags
234 $ echo "a5a5 invalid" >> .hg/localtags
234 $ echo "a5a5 invalid" >> .hg/localtags
235 $ cat .hgtags
235 $ cat .hgtags
236 acb14030fe0a21b60322c440ad2d20cf7685a376 first
236 acb14030fe0a21b60322c440ad2d20cf7685a376 first
237 spam
237 spam
238
238
239 foo bar
239 foo bar
240 $ hg commit -m "tags"
240 $ hg commit -m "tags"
241
241
242 Report tag parse error on other head:
242 Report tag parse error on other head:
243
243
244 $ hg up 3
244 $ hg up 3
245 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
245 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
246 $ echo 'x y' >> .hgtags
246 $ echo 'x y' >> .hgtags
247 $ hg commit -m "head"
247 $ hg commit -m "head"
248 created new head
248 created new head
249
249
250 $ hg tags
250 $ hg tags
251 .hgtags@75d9f02dfe28, line 2: cannot parse entry
251 .hgtags@75d9f02dfe28, line 2: cannot parse entry
252 .hgtags@75d9f02dfe28, line 4: node 'foo' is not well formed
252 .hgtags@75d9f02dfe28, line 4: node 'foo' is not well formed
253 .hgtags@c4be69a18c11, line 2: node 'x' is not well formed
253 .hgtags@c4be69a18c11, line 2: node 'x' is not well formed
254 tip 8:c4be69a18c11
254 tip 8:c4be69a18c11
255 first 0:acb14030fe0a
255 first 0:acb14030fe0a
256 $ hg tip
256 $ hg tip
257 changeset: 8:c4be69a18c11
257 changeset: 8:c4be69a18c11
258 tag: tip
258 tag: tip
259 parent: 3:ac5e980c4dc0
259 parent: 3:ac5e980c4dc0
260 user: test
260 user: test
261 date: Thu Jan 01 00:00:00 1970 +0000
261 date: Thu Jan 01 00:00:00 1970 +0000
262 summary: head
262 summary: head
263
263
264
264
265 Test tag precedence rules:
265 Test tag precedence rules:
266
266
267 $ cd ..
267 $ cd ..
268 $ hg init t2
268 $ hg init t2
269 $ cd t2
269 $ cd t2
270 $ echo foo > foo
270 $ echo foo > foo
271 $ hg add foo
271 $ hg add foo
272 $ hg ci -m 'add foo' # rev 0
272 $ hg ci -m 'add foo' # rev 0
273 $ hg tag bar # rev 1
273 $ hg tag bar # rev 1
274 $ echo >> foo
274 $ echo >> foo
275 $ hg ci -m 'change foo 1' # rev 2
275 $ hg ci -m 'change foo 1' # rev 2
276 $ hg up -C 1
276 $ hg up -C 1
277 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
278 $ hg tag -r 1 -f bar # rev 3
278 $ hg tag -r 1 -f bar # rev 3
279 $ hg up -C 1
279 $ hg up -C 1
280 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
280 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
281 $ echo >> foo
281 $ echo >> foo
282 $ hg ci -m 'change foo 2' # rev 4
282 $ hg ci -m 'change foo 2' # rev 4
283 created new head
283 created new head
284 $ hg tags
284 $ hg tags
285 tip 4:0c192d7d5e6b
285 tip 4:0c192d7d5e6b
286 bar 1:78391a272241
286 bar 1:78391a272241
287
287
288 Repeat in case of cache effects:
288 Repeat in case of cache effects:
289
289
290 $ hg tags
290 $ hg tags
291 tip 4:0c192d7d5e6b
291 tip 4:0c192d7d5e6b
292 bar 1:78391a272241
292 bar 1:78391a272241
293
293
294 Detailed dump of tag info:
294 Detailed dump of tag info:
295
295
296 $ hg heads -q # expect 4, 3, 2
296 $ hg heads -q # expect 4, 3, 2
297 4:0c192d7d5e6b
297 4:0c192d7d5e6b
298 3:6fa450212aeb
298 3:6fa450212aeb
299 2:7a94127795a3
299 2:7a94127795a3
300 $ dumptags 2
300 $ dumptags 2
301 rev 2: .hgtags:
301 rev 2: .hgtags:
302 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
302 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
303 $ dumptags 3
303 $ dumptags 3
304 rev 3: .hgtags:
304 rev 3: .hgtags:
305 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
305 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
306 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
306 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
307 78391a272241d70354aa14c874552cad6b51bb42 bar
307 78391a272241d70354aa14c874552cad6b51bb42 bar
308 $ dumptags 4
308 $ dumptags 4
309 rev 4: .hgtags:
309 rev 4: .hgtags:
310 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
310 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
311
311
312 Dump cache:
312 Dump cache:
313
313
314 $ cat .hg/cache/tags2-visible
314 $ cat .hg/cache/tags2-visible
315 4 0c192d7d5e6b78a714de54a2e9627952a877e25a
315 4 0c192d7d5e6b78a714de54a2e9627952a877e25a
316 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
316 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
317 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
317 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
318 78391a272241d70354aa14c874552cad6b51bb42 bar
318 78391a272241d70354aa14c874552cad6b51bb42 bar
319
319
320 $ f --size --hexdump .hg/cache/hgtagsfnodes1
320 $ f --size --hexdump .hg/cache/hgtagsfnodes1
321 .hg/cache/hgtagsfnodes1: size=120
321 .hg/cache/hgtagsfnodes1: size=120
322 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
322 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
323 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
323 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
324 0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
324 0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
325 0030: 7a 94 12 77 0c 04 f2 a8 af 31 de 17 fa b7 42 28 |z..w.....1....B(|
325 0030: 7a 94 12 77 0c 04 f2 a8 af 31 de 17 fa b7 42 28 |z..w.....1....B(|
326 0040: 78 ee 5a 2d ad bc 94 3d 6f a4 50 21 7d 3b 71 8c |x.Z-...=o.P!};q.|
326 0040: 78 ee 5a 2d ad bc 94 3d 6f a4 50 21 7d 3b 71 8c |x.Z-...=o.P!};q.|
327 0050: 96 4e f3 7b 89 e5 50 eb da fd 57 89 e7 6c e1 b0 |.N.{..P...W..l..|
327 0050: 96 4e f3 7b 89 e5 50 eb da fd 57 89 e7 6c e1 b0 |.N.{..P...W..l..|
328 0060: 0c 19 2d 7d 0c 04 f2 a8 af 31 de 17 fa b7 42 28 |..-}.....1....B(|
328 0060: 0c 19 2d 7d 0c 04 f2 a8 af 31 de 17 fa b7 42 28 |..-}.....1....B(|
329 0070: 78 ee 5a 2d ad bc 94 3d |x.Z-...=|
329 0070: 78 ee 5a 2d ad bc 94 3d |x.Z-...=|
330
330
331 Corrupt the .hgtags fnodes cache
331 Corrupt the .hgtags fnodes cache
332 Extra junk data at the end should get overwritten on next cache update
332 Extra junk data at the end should get overwritten on next cache update
333
333
334 $ echo extra >> .hg/cache/hgtagsfnodes1
334 $ echo extra >> .hg/cache/hgtagsfnodes1
335 $ echo dummy1 > foo
335 $ echo dummy1 > foo
336 $ hg commit -m throwaway1
336 $ hg commit -m throwaway1
337
337
338 $ hg tags
338 $ hg tags
339 tip 5:8dbfe60eff30
339 tip 5:8dbfe60eff30
340 bar 1:78391a272241
340 bar 1:78391a272241
341
341
342 $ hg blackbox -l 5
342 $ hg blackbox -l 5
343 1970/01/01 00:00:00 bob> tags
343 1970/01/01 00:00:00 bob> tags
344 1970/01/01 00:00:00 bob> writing 24 bytes to cache/hgtagsfnodes1
344 1970/01/01 00:00:00 bob> writing 24 bytes to cache/hgtagsfnodes1
345 1970/01/01 00:00:00 bob> 2/3 cache hits/lookups in * seconds (glob)
345 1970/01/01 00:00:00 bob> 2/3 cache hits/lookups in * seconds (glob)
346 1970/01/01 00:00:00 bob> writing tags cache file with 1 tags
346 1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 1 tags
347 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
347 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
348
348
349 #if unix-permissions no-root
349 #if unix-permissions no-root
350 Errors writing to .hgtags fnodes cache are silently ignored
350 Errors writing to .hgtags fnodes cache are silently ignored
351
351
352 $ echo dummy2 > foo
352 $ echo dummy2 > foo
353 $ hg commit -m throwaway2
353 $ hg commit -m throwaway2
354
354
355 $ chmod a-w .hg/cache/hgtagsfnodes1
355 $ chmod a-w .hg/cache/hgtagsfnodes1
356 $ rm -f .hg/cache/tags2-visible
356 $ rm -f .hg/cache/tags2-visible
357
357
358 $ hg tags
358 $ hg tags
359 tip 6:b968051b5cf3
359 tip 6:b968051b5cf3
360 bar 1:78391a272241
360 bar 1:78391a272241
361
361
362 $ hg blackbox -l 5
362 $ hg blackbox -l 5
363 1970/01/01 00:00:00 bob> tags
363 1970/01/01 00:00:00 bob> tags
364 1970/01/01 00:00:00 bob> couldn't write cache/hgtagsfnodes1: [Errno 13] Permission denied: '$TESTTMP/t2/.hg/cache/hgtagsfnodes1'
364 1970/01/01 00:00:00 bob> couldn't write cache/hgtagsfnodes1: [Errno 13] Permission denied: '$TESTTMP/t2/.hg/cache/hgtagsfnodes1'
365 1970/01/01 00:00:00 bob> 2/3 cache hits/lookups in * seconds (glob)
365 1970/01/01 00:00:00 bob> 2/3 cache hits/lookups in * seconds (glob)
366 1970/01/01 00:00:00 bob> writing tags cache file with 1 tags
366 1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 1 tags
367 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
367 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
368
368
369 $ chmod a+w .hg/cache/hgtagsfnodes1
369 $ chmod a+w .hg/cache/hgtagsfnodes1
370 #endif
370 #endif
371
371
372 $ rm -f .hg/cache/tags2-visible
372 $ rm -f .hg/cache/tags2-visible
373 $ hg tags
373 $ hg tags
374 tip 6:b968051b5cf3
374 tip 6:b968051b5cf3
375 bar 1:78391a272241
375 bar 1:78391a272241
376
376
377 $ hg blackbox -l 5
377 $ hg blackbox -l 5
378 1970/01/01 00:00:00 bob> tags
378 1970/01/01 00:00:00 bob> tags
379 1970/01/01 00:00:00 bob> writing 24 bytes to cache/hgtagsfnodes1
379 1970/01/01 00:00:00 bob> writing 24 bytes to cache/hgtagsfnodes1
380 1970/01/01 00:00:00 bob> 2/3 cache hits/lookups in * seconds (glob)
380 1970/01/01 00:00:00 bob> 2/3 cache hits/lookups in * seconds (glob)
381 1970/01/01 00:00:00 bob> writing tags cache file with 1 tags
381 1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 1 tags
382 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
382 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
383
383
384 $ f --size .hg/cache/hgtagsfnodes1
384 $ f --size .hg/cache/hgtagsfnodes1
385 .hg/cache/hgtagsfnodes1: size=168
385 .hg/cache/hgtagsfnodes1: size=168
386
386
387 Stripping doesn't truncate the tags cache until new data is available
387 Stripping doesn't truncate the tags cache until new data is available
388
388
389 $ hg -q --config extensions.strip= strip -r 5 --no-backup
389 $ hg -q --config extensions.strip= strip -r 5 --no-backup
390 $ hg tags
390 $ hg tags
391 tip 4:0c192d7d5e6b
391 tip 4:0c192d7d5e6b
392 bar 1:78391a272241
392 bar 1:78391a272241
393
393
394 $ hg blackbox -l 4
394 $ hg blackbox -l 4
395 1970/01/01 00:00:00 bob> tags
395 1970/01/01 00:00:00 bob> tags
396 1970/01/01 00:00:00 bob> 3/3 cache hits/lookups in * seconds (glob)
396 1970/01/01 00:00:00 bob> 3/3 cache hits/lookups in * seconds (glob)
397 1970/01/01 00:00:00 bob> writing tags cache file with 1 tags
397 1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 1 tags
398 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
398 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
399
399
400 $ f --size .hg/cache/hgtagsfnodes1
400 $ f --size .hg/cache/hgtagsfnodes1
401 .hg/cache/hgtagsfnodes1: size=168
401 .hg/cache/hgtagsfnodes1: size=168
402
402
403 $ echo dummy > foo
403 $ echo dummy > foo
404 $ hg commit -m throwaway3
404 $ hg commit -m throwaway3
405
405
406 $ hg tags
406 $ hg tags
407 tip 5:035f65efb448
407 tip 5:035f65efb448
408 bar 1:78391a272241
408 bar 1:78391a272241
409
409
410 $ hg blackbox -l 5
410 $ hg blackbox -l 5
411 1970/01/01 00:00:00 bob> tags
411 1970/01/01 00:00:00 bob> tags
412 1970/01/01 00:00:00 bob> writing 24 bytes to cache/hgtagsfnodes1
412 1970/01/01 00:00:00 bob> writing 24 bytes to cache/hgtagsfnodes1
413 1970/01/01 00:00:00 bob> 2/3 cache hits/lookups in * seconds (glob)
413 1970/01/01 00:00:00 bob> 2/3 cache hits/lookups in * seconds (glob)
414 1970/01/01 00:00:00 bob> writing tags cache file with 1 tags
414 1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 1 tags
415 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
415 1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
416 $ f --size .hg/cache/hgtagsfnodes1
416 $ f --size .hg/cache/hgtagsfnodes1
417 .hg/cache/hgtagsfnodes1: size=144
417 .hg/cache/hgtagsfnodes1: size=144
418
418
419 $ hg -q --config extensions.strip= strip -r 5 --no-backup
419 $ hg -q --config extensions.strip= strip -r 5 --no-backup
420
420
421 Test tag removal:
421 Test tag removal:
422
422
423 $ hg tag --remove bar # rev 5
423 $ hg tag --remove bar # rev 5
424 $ hg tip -vp
424 $ hg tip -vp
425 changeset: 5:5f6e8655b1c7
425 changeset: 5:5f6e8655b1c7
426 tag: tip
426 tag: tip
427 user: test
427 user: test
428 date: Thu Jan 01 00:00:00 1970 +0000
428 date: Thu Jan 01 00:00:00 1970 +0000
429 files: .hgtags
429 files: .hgtags
430 description:
430 description:
431 Removed tag bar
431 Removed tag bar
432
432
433
433
434 diff -r 0c192d7d5e6b -r 5f6e8655b1c7 .hgtags
434 diff -r 0c192d7d5e6b -r 5f6e8655b1c7 .hgtags
435 --- a/.hgtags Thu Jan 01 00:00:00 1970 +0000
435 --- a/.hgtags Thu Jan 01 00:00:00 1970 +0000
436 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
436 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
437 @@ -1,1 +1,3 @@
437 @@ -1,1 +1,3 @@
438 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
438 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
439 +78391a272241d70354aa14c874552cad6b51bb42 bar
439 +78391a272241d70354aa14c874552cad6b51bb42 bar
440 +0000000000000000000000000000000000000000 bar
440 +0000000000000000000000000000000000000000 bar
441
441
442 $ hg tags
442 $ hg tags
443 tip 5:5f6e8655b1c7
443 tip 5:5f6e8655b1c7
444 $ hg tags # again, try to expose cache bugs
444 $ hg tags # again, try to expose cache bugs
445 tip 5:5f6e8655b1c7
445 tip 5:5f6e8655b1c7
446
446
447 Remove nonexistent tag:
447 Remove nonexistent tag:
448
448
449 $ hg tag --remove foobar
449 $ hg tag --remove foobar
450 abort: tag 'foobar' does not exist
450 abort: tag 'foobar' does not exist
451 [255]
451 [255]
452 $ hg tip
452 $ hg tip
453 changeset: 5:5f6e8655b1c7
453 changeset: 5:5f6e8655b1c7
454 tag: tip
454 tag: tip
455 user: test
455 user: test
456 date: Thu Jan 01 00:00:00 1970 +0000
456 date: Thu Jan 01 00:00:00 1970 +0000
457 summary: Removed tag bar
457 summary: Removed tag bar
458
458
459
459
460 Undo a tag with rollback:
460 Undo a tag with rollback:
461
461
462 $ hg rollback # destroy rev 5 (restore bar)
462 $ hg rollback # destroy rev 5 (restore bar)
463 repository tip rolled back to revision 4 (undo commit)
463 repository tip rolled back to revision 4 (undo commit)
464 working directory now based on revision 4
464 working directory now based on revision 4
465 $ hg tags
465 $ hg tags
466 tip 4:0c192d7d5e6b
466 tip 4:0c192d7d5e6b
467 bar 1:78391a272241
467 bar 1:78391a272241
468 $ hg tags
468 $ hg tags
469 tip 4:0c192d7d5e6b
469 tip 4:0c192d7d5e6b
470 bar 1:78391a272241
470 bar 1:78391a272241
471
471
472 Test tag rank:
472 Test tag rank:
473
473
474 $ cd ..
474 $ cd ..
475 $ hg init t3
475 $ hg init t3
476 $ cd t3
476 $ cd t3
477 $ echo foo > foo
477 $ echo foo > foo
478 $ hg add foo
478 $ hg add foo
479 $ hg ci -m 'add foo' # rev 0
479 $ hg ci -m 'add foo' # rev 0
480 $ hg tag -f bar # rev 1 bar -> 0
480 $ hg tag -f bar # rev 1 bar -> 0
481 $ hg tag -f bar # rev 2 bar -> 1
481 $ hg tag -f bar # rev 2 bar -> 1
482 $ hg tag -fr 0 bar # rev 3 bar -> 0
482 $ hg tag -fr 0 bar # rev 3 bar -> 0
483 $ hg tag -fr 1 bar # rev 4 bar -> 1
483 $ hg tag -fr 1 bar # rev 4 bar -> 1
484 $ hg tag -fr 0 bar # rev 5 bar -> 0
484 $ hg tag -fr 0 bar # rev 5 bar -> 0
485 $ hg tags
485 $ hg tags
486 tip 5:85f05169d91d
486 tip 5:85f05169d91d
487 bar 0:bbd179dfa0a7
487 bar 0:bbd179dfa0a7
488 $ hg co 3
488 $ hg co 3
489 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
489 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
490 $ echo barbar > foo
490 $ echo barbar > foo
491 $ hg ci -m 'change foo' # rev 6
491 $ hg ci -m 'change foo' # rev 6
492 created new head
492 created new head
493 $ hg tags
493 $ hg tags
494 tip 6:735c3ca72986
494 tip 6:735c3ca72986
495 bar 0:bbd179dfa0a7
495 bar 0:bbd179dfa0a7
496
496
497 Don't allow moving tag without -f:
497 Don't allow moving tag without -f:
498
498
499 $ hg tag -r 3 bar
499 $ hg tag -r 3 bar
500 abort: tag 'bar' already exists (use -f to force)
500 abort: tag 'bar' already exists (use -f to force)
501 [255]
501 [255]
502 $ hg tags
502 $ hg tags
503 tip 6:735c3ca72986
503 tip 6:735c3ca72986
504 bar 0:bbd179dfa0a7
504 bar 0:bbd179dfa0a7
505
505
506 Strip 1: expose an old head:
506 Strip 1: expose an old head:
507
507
508 $ hg --config extensions.mq= strip 5
508 $ hg --config extensions.mq= strip 5
509 saved backup bundle to $TESTTMP/t3/.hg/strip-backup/*-backup.hg (glob)
509 saved backup bundle to $TESTTMP/t3/.hg/strip-backup/*-backup.hg (glob)
510 $ hg tags # partly stale cache
510 $ hg tags # partly stale cache
511 tip 5:735c3ca72986
511 tip 5:735c3ca72986
512 bar 1:78391a272241
512 bar 1:78391a272241
513 $ hg tags # up-to-date cache
513 $ hg tags # up-to-date cache
514 tip 5:735c3ca72986
514 tip 5:735c3ca72986
515 bar 1:78391a272241
515 bar 1:78391a272241
516
516
517 Strip 2: destroy whole branch, no old head exposed
517 Strip 2: destroy whole branch, no old head exposed
518
518
519 $ hg --config extensions.mq= strip 4
519 $ hg --config extensions.mq= strip 4
520 saved backup bundle to $TESTTMP/t3/.hg/strip-backup/*-backup.hg (glob)
520 saved backup bundle to $TESTTMP/t3/.hg/strip-backup/*-backup.hg (glob)
521 $ hg tags # partly stale
521 $ hg tags # partly stale
522 tip 4:735c3ca72986
522 tip 4:735c3ca72986
523 bar 0:bbd179dfa0a7
523 bar 0:bbd179dfa0a7
524 $ rm -f .hg/cache/tags2-visible
524 $ rm -f .hg/cache/tags2-visible
525 $ hg tags # cold cache
525 $ hg tags # cold cache
526 tip 4:735c3ca72986
526 tip 4:735c3ca72986
527 bar 0:bbd179dfa0a7
527 bar 0:bbd179dfa0a7
528
528
529 Test tag rank with 3 heads:
529 Test tag rank with 3 heads:
530
530
531 $ cd ..
531 $ cd ..
532 $ hg init t4
532 $ hg init t4
533 $ cd t4
533 $ cd t4
534 $ echo foo > foo
534 $ echo foo > foo
535 $ hg add
535 $ hg add
536 adding foo
536 adding foo
537 $ hg ci -m 'add foo' # rev 0
537 $ hg ci -m 'add foo' # rev 0
538 $ hg tag bar # rev 1 bar -> 0
538 $ hg tag bar # rev 1 bar -> 0
539 $ hg tag -f bar # rev 2 bar -> 1
539 $ hg tag -f bar # rev 2 bar -> 1
540 $ hg up -qC 0
540 $ hg up -qC 0
541 $ hg tag -fr 2 bar # rev 3 bar -> 2
541 $ hg tag -fr 2 bar # rev 3 bar -> 2
542 $ hg tags
542 $ hg tags
543 tip 3:197c21bbbf2c
543 tip 3:197c21bbbf2c
544 bar 2:6fa450212aeb
544 bar 2:6fa450212aeb
545 $ hg up -qC 0
545 $ hg up -qC 0
546 $ hg tag -m 'retag rev 0' -fr 0 bar # rev 4 bar -> 0, but bar stays at 2
546 $ hg tag -m 'retag rev 0' -fr 0 bar # rev 4 bar -> 0, but bar stays at 2
547
547
548 Bar should still point to rev 2:
548 Bar should still point to rev 2:
549
549
550 $ hg tags
550 $ hg tags
551 tip 4:3b4b14ed0202
551 tip 4:3b4b14ed0202
552 bar 2:6fa450212aeb
552 bar 2:6fa450212aeb
553
553
554 Test that removing global/local tags does not get confused when trying
554 Test that removing global/local tags does not get confused when trying
555 to remove a tag of type X which actually only exists as a type Y:
555 to remove a tag of type X which actually only exists as a type Y:
556
556
557 $ cd ..
557 $ cd ..
558 $ hg init t5
558 $ hg init t5
559 $ cd t5
559 $ cd t5
560 $ echo foo > foo
560 $ echo foo > foo
561 $ hg add
561 $ hg add
562 adding foo
562 adding foo
563 $ hg ci -m 'add foo' # rev 0
563 $ hg ci -m 'add foo' # rev 0
564
564
565 $ hg tag -r 0 -l localtag
565 $ hg tag -r 0 -l localtag
566 $ hg tag --remove localtag
566 $ hg tag --remove localtag
567 abort: tag 'localtag' is not a global tag
567 abort: tag 'localtag' is not a global tag
568 [255]
568 [255]
569 $
569 $
570 $ hg tag -r 0 globaltag
570 $ hg tag -r 0 globaltag
571 $ hg tag --remove -l globaltag
571 $ hg tag --remove -l globaltag
572 abort: tag 'globaltag' is not a local tag
572 abort: tag 'globaltag' is not a local tag
573 [255]
573 [255]
574 $ hg tags -v
574 $ hg tags -v
575 tip 1:a0b6fe111088
575 tip 1:a0b6fe111088
576 localtag 0:bbd179dfa0a7 local
576 localtag 0:bbd179dfa0a7 local
577 globaltag 0:bbd179dfa0a7
577 globaltag 0:bbd179dfa0a7
578
578
579 Test for issue3911
579 Test for issue3911
580
580
581 $ hg tag -r 0 -l localtag2
581 $ hg tag -r 0 -l localtag2
582 $ hg tag -l --remove localtag2
582 $ hg tag -l --remove localtag2
583 $ hg tags -v
583 $ hg tags -v
584 tip 1:a0b6fe111088
584 tip 1:a0b6fe111088
585 localtag 0:bbd179dfa0a7 local
585 localtag 0:bbd179dfa0a7 local
586 globaltag 0:bbd179dfa0a7
586 globaltag 0:bbd179dfa0a7
587
587
588 $ hg tag -r 1 -f localtag
588 $ hg tag -r 1 -f localtag
589 $ hg tags -v
589 $ hg tags -v
590 tip 2:5c70a037bb37
590 tip 2:5c70a037bb37
591 localtag 1:a0b6fe111088
591 localtag 1:a0b6fe111088
592 globaltag 0:bbd179dfa0a7
592 globaltag 0:bbd179dfa0a7
593
593
594 $ hg tags -v
594 $ hg tags -v
595 tip 2:5c70a037bb37
595 tip 2:5c70a037bb37
596 localtag 1:a0b6fe111088
596 localtag 1:a0b6fe111088
597 globaltag 0:bbd179dfa0a7
597 globaltag 0:bbd179dfa0a7
598
598
599 $ hg tag -r 1 localtag2
599 $ hg tag -r 1 localtag2
600 $ hg tags -v
600 $ hg tags -v
601 tip 3:bbfb8cd42be2
601 tip 3:bbfb8cd42be2
602 localtag2 1:a0b6fe111088
602 localtag2 1:a0b6fe111088
603 localtag 1:a0b6fe111088
603 localtag 1:a0b6fe111088
604 globaltag 0:bbd179dfa0a7
604 globaltag 0:bbd179dfa0a7
605
605
606 $ hg tags -v
606 $ hg tags -v
607 tip 3:bbfb8cd42be2
607 tip 3:bbfb8cd42be2
608 localtag2 1:a0b6fe111088
608 localtag2 1:a0b6fe111088
609 localtag 1:a0b6fe111088
609 localtag 1:a0b6fe111088
610 globaltag 0:bbd179dfa0a7
610 globaltag 0:bbd179dfa0a7
611
611
612 $ cd ..
612 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now