##// END OF EJS Templates
keyword: restore kwtemplater.restrict at the end of wrapped patch.diff...
FUJIWARA Katsunori -
r33063:7f569ce3 default
parent child Browse files
Show More
@@ -1,758 +1,763 b''
1 # keyword.py - $Keyword$ expansion for Mercurial
1 # keyword.py - $Keyword$ expansion for Mercurial
2 #
2 #
3 # Copyright 2007-2015 Christian Ebert <blacktrash@gmx.net>
3 # Copyright 2007-2015 Christian Ebert <blacktrash@gmx.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7 #
7 #
8 # $Id$
8 # $Id$
9 #
9 #
10 # Keyword expansion hack against the grain of a Distributed SCM
10 # Keyword expansion hack against the grain of a Distributed SCM
11 #
11 #
12 # There are many good reasons why this is not needed in a distributed
12 # There are many good reasons why this is not needed in a distributed
13 # SCM, still it may be useful in very small projects based on single
13 # SCM, still it may be useful in very small projects based on single
14 # files (like LaTeX packages), that are mostly addressed to an
14 # files (like LaTeX packages), that are mostly addressed to an
15 # audience not running a version control system.
15 # audience not running a version control system.
16 #
16 #
17 # For in-depth discussion refer to
17 # For in-depth discussion refer to
18 # <https://mercurial-scm.org/wiki/KeywordPlan>.
18 # <https://mercurial-scm.org/wiki/KeywordPlan>.
19 #
19 #
20 # Keyword expansion is based on Mercurial's changeset template mappings.
20 # Keyword expansion is based on Mercurial's changeset template mappings.
21 #
21 #
22 # Binary files are not touched.
22 # Binary files are not touched.
23 #
23 #
24 # Files to act upon/ignore are specified in the [keyword] section.
24 # Files to act upon/ignore are specified in the [keyword] section.
25 # Customized keyword template mappings in the [keywordmaps] section.
25 # Customized keyword template mappings in the [keywordmaps] section.
26 #
26 #
27 # Run 'hg help keyword' and 'hg kwdemo' to get info on configuration.
27 # Run 'hg help keyword' and 'hg kwdemo' to get info on configuration.
28
28
29 '''expand keywords in tracked files
29 '''expand keywords in tracked files
30
30
31 This extension expands RCS/CVS-like or self-customized $Keywords$ in
31 This extension expands RCS/CVS-like or self-customized $Keywords$ in
32 tracked text files selected by your configuration.
32 tracked text files selected by your configuration.
33
33
34 Keywords are only expanded in local repositories and not stored in the
34 Keywords are only expanded in local repositories and not stored in the
35 change history. The mechanism can be regarded as a convenience for the
35 change history. The mechanism can be regarded as a convenience for the
36 current user or for archive distribution.
36 current user or for archive distribution.
37
37
38 Keywords expand to the changeset data pertaining to the latest change
38 Keywords expand to the changeset data pertaining to the latest change
39 relative to the working directory parent of each file.
39 relative to the working directory parent of each file.
40
40
41 Configuration is done in the [keyword], [keywordset] and [keywordmaps]
41 Configuration is done in the [keyword], [keywordset] and [keywordmaps]
42 sections of hgrc files.
42 sections of hgrc files.
43
43
44 Example::
44 Example::
45
45
46 [keyword]
46 [keyword]
47 # expand keywords in every python file except those matching "x*"
47 # expand keywords in every python file except those matching "x*"
48 **.py =
48 **.py =
49 x* = ignore
49 x* = ignore
50
50
51 [keywordset]
51 [keywordset]
52 # prefer svn- over cvs-like default keywordmaps
52 # prefer svn- over cvs-like default keywordmaps
53 svn = True
53 svn = True
54
54
55 .. note::
55 .. note::
56
56
57 The more specific you are in your filename patterns the less you
57 The more specific you are in your filename patterns the less you
58 lose speed in huge repositories.
58 lose speed in huge repositories.
59
59
60 For [keywordmaps] template mapping and expansion demonstration and
60 For [keywordmaps] template mapping and expansion demonstration and
61 control run :hg:`kwdemo`. See :hg:`help templates` for a list of
61 control run :hg:`kwdemo`. See :hg:`help templates` for a list of
62 available templates and filters.
62 available templates and filters.
63
63
64 Three additional date template filters are provided:
64 Three additional date template filters are provided:
65
65
66 :``utcdate``: "2006/09/18 15:13:13"
66 :``utcdate``: "2006/09/18 15:13:13"
67 :``svnutcdate``: "2006-09-18 15:13:13Z"
67 :``svnutcdate``: "2006-09-18 15:13:13Z"
68 :``svnisodate``: "2006-09-18 08:13:13 -700 (Mon, 18 Sep 2006)"
68 :``svnisodate``: "2006-09-18 08:13:13 -700 (Mon, 18 Sep 2006)"
69
69
70 The default template mappings (view with :hg:`kwdemo -d`) can be
70 The default template mappings (view with :hg:`kwdemo -d`) can be
71 replaced with customized keywords and templates. Again, run
71 replaced with customized keywords and templates. Again, run
72 :hg:`kwdemo` to control the results of your configuration changes.
72 :hg:`kwdemo` to control the results of your configuration changes.
73
73
74 Before changing/disabling active keywords, you must run :hg:`kwshrink`
74 Before changing/disabling active keywords, you must run :hg:`kwshrink`
75 to avoid storing expanded keywords in the change history.
75 to avoid storing expanded keywords in the change history.
76
76
77 To force expansion after enabling it, or a configuration change, run
77 To force expansion after enabling it, or a configuration change, run
78 :hg:`kwexpand`.
78 :hg:`kwexpand`.
79
79
80 Expansions spanning more than one line and incremental expansions,
80 Expansions spanning more than one line and incremental expansions,
81 like CVS' $Log$, are not supported. A keyword template map "Log =
81 like CVS' $Log$, are not supported. A keyword template map "Log =
82 {desc}" expands to the first line of the changeset description.
82 {desc}" expands to the first line of the changeset description.
83 '''
83 '''
84
84
85
85
86 from __future__ import absolute_import
86 from __future__ import absolute_import
87
87
88 import os
88 import os
89 import re
89 import re
90 import tempfile
90 import tempfile
91
91
92 from mercurial.i18n import _
92 from mercurial.i18n import _
93 from mercurial.hgweb import webcommands
93 from mercurial.hgweb import webcommands
94
94
95 from mercurial import (
95 from mercurial import (
96 cmdutil,
96 cmdutil,
97 context,
97 context,
98 dispatch,
98 dispatch,
99 error,
99 error,
100 extensions,
100 extensions,
101 filelog,
101 filelog,
102 localrepo,
102 localrepo,
103 match,
103 match,
104 patch,
104 patch,
105 pathutil,
105 pathutil,
106 registrar,
106 registrar,
107 scmutil,
107 scmutil,
108 templatefilters,
108 templatefilters,
109 util,
109 util,
110 )
110 )
111
111
112 cmdtable = {}
112 cmdtable = {}
113 command = registrar.command(cmdtable)
113 command = registrar.command(cmdtable)
114 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
114 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
115 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
115 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
116 # be specifying the version(s) of Mercurial they are tested with, or
116 # be specifying the version(s) of Mercurial they are tested with, or
117 # leave the attribute unspecified.
117 # leave the attribute unspecified.
118 testedwith = 'ships-with-hg-core'
118 testedwith = 'ships-with-hg-core'
119
119
120 # hg commands that do not act on keywords
120 # hg commands that do not act on keywords
121 nokwcommands = ('add addremove annotate bundle export grep incoming init log'
121 nokwcommands = ('add addremove annotate bundle export grep incoming init log'
122 ' outgoing push tip verify convert email glog')
122 ' outgoing push tip verify convert email glog')
123
123
124 # hg commands that trigger expansion only when writing to working dir,
124 # hg commands that trigger expansion only when writing to working dir,
125 # not when reading filelog, and unexpand when reading from working dir
125 # not when reading filelog, and unexpand when reading from working dir
126 restricted = ('merge kwexpand kwshrink record qrecord resolve transplant'
126 restricted = ('merge kwexpand kwshrink record qrecord resolve transplant'
127 ' unshelve rebase graft backout histedit fetch')
127 ' unshelve rebase graft backout histedit fetch')
128
128
129 # names of extensions using dorecord
129 # names of extensions using dorecord
130 recordextensions = 'record'
130 recordextensions = 'record'
131
131
132 colortable = {
132 colortable = {
133 'kwfiles.enabled': 'green bold',
133 'kwfiles.enabled': 'green bold',
134 'kwfiles.deleted': 'cyan bold underline',
134 'kwfiles.deleted': 'cyan bold underline',
135 'kwfiles.enabledunknown': 'green',
135 'kwfiles.enabledunknown': 'green',
136 'kwfiles.ignored': 'bold',
136 'kwfiles.ignored': 'bold',
137 'kwfiles.ignoredunknown': 'none'
137 'kwfiles.ignoredunknown': 'none'
138 }
138 }
139
139
140 templatefilter = registrar.templatefilter()
140 templatefilter = registrar.templatefilter()
141
141
142 # date like in cvs' $Date
142 # date like in cvs' $Date
143 @templatefilter('utcdate')
143 @templatefilter('utcdate')
144 def utcdate(text):
144 def utcdate(text):
145 '''Date. Returns a UTC-date in this format: "2009/08/18 11:00:13".
145 '''Date. Returns a UTC-date in this format: "2009/08/18 11:00:13".
146 '''
146 '''
147 return util.datestr((util.parsedate(text)[0], 0), '%Y/%m/%d %H:%M:%S')
147 return util.datestr((util.parsedate(text)[0], 0), '%Y/%m/%d %H:%M:%S')
148 # date like in svn's $Date
148 # date like in svn's $Date
149 @templatefilter('svnisodate')
149 @templatefilter('svnisodate')
150 def svnisodate(text):
150 def svnisodate(text):
151 '''Date. Returns a date in this format: "2009-08-18 13:00:13
151 '''Date. Returns a date in this format: "2009-08-18 13:00:13
152 +0200 (Tue, 18 Aug 2009)".
152 +0200 (Tue, 18 Aug 2009)".
153 '''
153 '''
154 return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
154 return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
155 # date like in svn's $Id
155 # date like in svn's $Id
156 @templatefilter('svnutcdate')
156 @templatefilter('svnutcdate')
157 def svnutcdate(text):
157 def svnutcdate(text):
158 '''Date. Returns a UTC-date in this format: "2009-08-18
158 '''Date. Returns a UTC-date in this format: "2009-08-18
159 11:00:13Z".
159 11:00:13Z".
160 '''
160 '''
161 return util.datestr((util.parsedate(text)[0], 0), '%Y-%m-%d %H:%M:%SZ')
161 return util.datestr((util.parsedate(text)[0], 0), '%Y-%m-%d %H:%M:%SZ')
162
162
163 # make keyword tools accessible
163 # make keyword tools accessible
164 kwtools = {'templater': None, 'hgcmd': ''}
164 kwtools = {'templater': None, 'hgcmd': ''}
165
165
166 def _defaultkwmaps(ui):
166 def _defaultkwmaps(ui):
167 '''Returns default keywordmaps according to keywordset configuration.'''
167 '''Returns default keywordmaps according to keywordset configuration.'''
168 templates = {
168 templates = {
169 'Revision': '{node|short}',
169 'Revision': '{node|short}',
170 'Author': '{author|user}',
170 'Author': '{author|user}',
171 }
171 }
172 kwsets = ({
172 kwsets = ({
173 'Date': '{date|utcdate}',
173 'Date': '{date|utcdate}',
174 'RCSfile': '{file|basename},v',
174 'RCSfile': '{file|basename},v',
175 'RCSFile': '{file|basename},v', # kept for backwards compatibility
175 'RCSFile': '{file|basename},v', # kept for backwards compatibility
176 # with hg-keyword
176 # with hg-keyword
177 'Source': '{root}/{file},v',
177 'Source': '{root}/{file},v',
178 'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
178 'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
179 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
179 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
180 }, {
180 }, {
181 'Date': '{date|svnisodate}',
181 'Date': '{date|svnisodate}',
182 'Id': '{file|basename},v {node|short} {date|svnutcdate} {author|user}',
182 'Id': '{file|basename},v {node|short} {date|svnutcdate} {author|user}',
183 'LastChangedRevision': '{node|short}',
183 'LastChangedRevision': '{node|short}',
184 'LastChangedBy': '{author|user}',
184 'LastChangedBy': '{author|user}',
185 'LastChangedDate': '{date|svnisodate}',
185 'LastChangedDate': '{date|svnisodate}',
186 })
186 })
187 templates.update(kwsets[ui.configbool('keywordset', 'svn')])
187 templates.update(kwsets[ui.configbool('keywordset', 'svn')])
188 return templates
188 return templates
189
189
190 def _shrinktext(text, subfunc):
190 def _shrinktext(text, subfunc):
191 '''Helper for keyword expansion removal in text.
191 '''Helper for keyword expansion removal in text.
192 Depending on subfunc also returns number of substitutions.'''
192 Depending on subfunc also returns number of substitutions.'''
193 return subfunc(r'$\1$', text)
193 return subfunc(r'$\1$', text)
194
194
195 def _preselect(wstatus, changed):
195 def _preselect(wstatus, changed):
196 '''Retrieves modified and added files from a working directory state
196 '''Retrieves modified and added files from a working directory state
197 and returns the subset of each contained in given changed files
197 and returns the subset of each contained in given changed files
198 retrieved from a change context.'''
198 retrieved from a change context.'''
199 modified = [f for f in wstatus.modified if f in changed]
199 modified = [f for f in wstatus.modified if f in changed]
200 added = [f for f in wstatus.added if f in changed]
200 added = [f for f in wstatus.added if f in changed]
201 return modified, added
201 return modified, added
202
202
203
203
204 class kwtemplater(object):
204 class kwtemplater(object):
205 '''
205 '''
206 Sets up keyword templates, corresponding keyword regex, and
206 Sets up keyword templates, corresponding keyword regex, and
207 provides keyword substitution functions.
207 provides keyword substitution functions.
208 '''
208 '''
209
209
210 def __init__(self, ui, repo, inc, exc):
210 def __init__(self, ui, repo, inc, exc):
211 self.ui = ui
211 self.ui = ui
212 self.repo = repo
212 self.repo = repo
213 self.match = match.match(repo.root, '', [], inc, exc)
213 self.match = match.match(repo.root, '', [], inc, exc)
214 self.restrict = kwtools['hgcmd'] in restricted.split()
214 self.restrict = kwtools['hgcmd'] in restricted.split()
215 self.postcommit = False
215 self.postcommit = False
216
216
217 kwmaps = self.ui.configitems('keywordmaps')
217 kwmaps = self.ui.configitems('keywordmaps')
218 if kwmaps: # override default templates
218 if kwmaps: # override default templates
219 self.templates = dict(kwmaps)
219 self.templates = dict(kwmaps)
220 else:
220 else:
221 self.templates = _defaultkwmaps(self.ui)
221 self.templates = _defaultkwmaps(self.ui)
222
222
223 @util.propertycache
223 @util.propertycache
224 def escape(self):
224 def escape(self):
225 '''Returns bar-separated and escaped keywords.'''
225 '''Returns bar-separated and escaped keywords.'''
226 return '|'.join(map(re.escape, self.templates.keys()))
226 return '|'.join(map(re.escape, self.templates.keys()))
227
227
228 @util.propertycache
228 @util.propertycache
229 def rekw(self):
229 def rekw(self):
230 '''Returns regex for unexpanded keywords.'''
230 '''Returns regex for unexpanded keywords.'''
231 return re.compile(r'\$(%s)\$' % self.escape)
231 return re.compile(r'\$(%s)\$' % self.escape)
232
232
233 @util.propertycache
233 @util.propertycache
234 def rekwexp(self):
234 def rekwexp(self):
235 '''Returns regex for expanded keywords.'''
235 '''Returns regex for expanded keywords.'''
236 return re.compile(r'\$(%s): [^$\n\r]*? \$' % self.escape)
236 return re.compile(r'\$(%s): [^$\n\r]*? \$' % self.escape)
237
237
238 def substitute(self, data, path, ctx, subfunc):
238 def substitute(self, data, path, ctx, subfunc):
239 '''Replaces keywords in data with expanded template.'''
239 '''Replaces keywords in data with expanded template.'''
240 def kwsub(mobj):
240 def kwsub(mobj):
241 kw = mobj.group(1)
241 kw = mobj.group(1)
242 ct = cmdutil.makelogtemplater(self.ui, self.repo,
242 ct = cmdutil.makelogtemplater(self.ui, self.repo,
243 self.templates[kw])
243 self.templates[kw])
244 self.ui.pushbuffer()
244 self.ui.pushbuffer()
245 ct.show(ctx, root=self.repo.root, file=path)
245 ct.show(ctx, root=self.repo.root, file=path)
246 ekw = templatefilters.firstline(self.ui.popbuffer())
246 ekw = templatefilters.firstline(self.ui.popbuffer())
247 return '$%s: %s $' % (kw, ekw)
247 return '$%s: %s $' % (kw, ekw)
248 return subfunc(kwsub, data)
248 return subfunc(kwsub, data)
249
249
250 def linkctx(self, path, fileid):
250 def linkctx(self, path, fileid):
251 '''Similar to filelog.linkrev, but returns a changectx.'''
251 '''Similar to filelog.linkrev, but returns a changectx.'''
252 return self.repo.filectx(path, fileid=fileid).changectx()
252 return self.repo.filectx(path, fileid=fileid).changectx()
253
253
254 def expand(self, path, node, data):
254 def expand(self, path, node, data):
255 '''Returns data with keywords expanded.'''
255 '''Returns data with keywords expanded.'''
256 if not self.restrict and self.match(path) and not util.binary(data):
256 if not self.restrict and self.match(path) and not util.binary(data):
257 ctx = self.linkctx(path, node)
257 ctx = self.linkctx(path, node)
258 return self.substitute(data, path, ctx, self.rekw.sub)
258 return self.substitute(data, path, ctx, self.rekw.sub)
259 return data
259 return data
260
260
261 def iskwfile(self, cand, ctx):
261 def iskwfile(self, cand, ctx):
262 '''Returns subset of candidates which are configured for keyword
262 '''Returns subset of candidates which are configured for keyword
263 expansion but are not symbolic links.'''
263 expansion but are not symbolic links.'''
264 return [f for f in cand if self.match(f) and 'l' not in ctx.flags(f)]
264 return [f for f in cand if self.match(f) and 'l' not in ctx.flags(f)]
265
265
266 def overwrite(self, ctx, candidates, lookup, expand, rekw=False):
266 def overwrite(self, ctx, candidates, lookup, expand, rekw=False):
267 '''Overwrites selected files expanding/shrinking keywords.'''
267 '''Overwrites selected files expanding/shrinking keywords.'''
268 if self.restrict or lookup or self.postcommit: # exclude kw_copy
268 if self.restrict or lookup or self.postcommit: # exclude kw_copy
269 candidates = self.iskwfile(candidates, ctx)
269 candidates = self.iskwfile(candidates, ctx)
270 if not candidates:
270 if not candidates:
271 return
271 return
272 kwcmd = self.restrict and lookup # kwexpand/kwshrink
272 kwcmd = self.restrict and lookup # kwexpand/kwshrink
273 if self.restrict or expand and lookup:
273 if self.restrict or expand and lookup:
274 mf = ctx.manifest()
274 mf = ctx.manifest()
275 if self.restrict or rekw:
275 if self.restrict or rekw:
276 re_kw = self.rekw
276 re_kw = self.rekw
277 else:
277 else:
278 re_kw = self.rekwexp
278 re_kw = self.rekwexp
279 if expand:
279 if expand:
280 msg = _('overwriting %s expanding keywords\n')
280 msg = _('overwriting %s expanding keywords\n')
281 else:
281 else:
282 msg = _('overwriting %s shrinking keywords\n')
282 msg = _('overwriting %s shrinking keywords\n')
283 for f in candidates:
283 for f in candidates:
284 if self.restrict:
284 if self.restrict:
285 data = self.repo.file(f).read(mf[f])
285 data = self.repo.file(f).read(mf[f])
286 else:
286 else:
287 data = self.repo.wread(f)
287 data = self.repo.wread(f)
288 if util.binary(data):
288 if util.binary(data):
289 continue
289 continue
290 if expand:
290 if expand:
291 parents = ctx.parents()
291 parents = ctx.parents()
292 if lookup:
292 if lookup:
293 ctx = self.linkctx(f, mf[f])
293 ctx = self.linkctx(f, mf[f])
294 elif self.restrict and len(parents) > 1:
294 elif self.restrict and len(parents) > 1:
295 # merge commit
295 # merge commit
296 # in case of conflict f is in modified state during
296 # in case of conflict f is in modified state during
297 # merge, even if f does not differ from f in parent
297 # merge, even if f does not differ from f in parent
298 for p in parents:
298 for p in parents:
299 if f in p and not p[f].cmp(ctx[f]):
299 if f in p and not p[f].cmp(ctx[f]):
300 ctx = p[f].changectx()
300 ctx = p[f].changectx()
301 break
301 break
302 data, found = self.substitute(data, f, ctx, re_kw.subn)
302 data, found = self.substitute(data, f, ctx, re_kw.subn)
303 elif self.restrict:
303 elif self.restrict:
304 found = re_kw.search(data)
304 found = re_kw.search(data)
305 else:
305 else:
306 data, found = _shrinktext(data, re_kw.subn)
306 data, found = _shrinktext(data, re_kw.subn)
307 if found:
307 if found:
308 self.ui.note(msg % f)
308 self.ui.note(msg % f)
309 fp = self.repo.wvfs(f, "wb", atomictemp=True)
309 fp = self.repo.wvfs(f, "wb", atomictemp=True)
310 fp.write(data)
310 fp.write(data)
311 fp.close()
311 fp.close()
312 if kwcmd:
312 if kwcmd:
313 self.repo.dirstate.normal(f)
313 self.repo.dirstate.normal(f)
314 elif self.postcommit:
314 elif self.postcommit:
315 self.repo.dirstate.normallookup(f)
315 self.repo.dirstate.normallookup(f)
316
316
317 def shrink(self, fname, text):
317 def shrink(self, fname, text):
318 '''Returns text with all keyword substitutions removed.'''
318 '''Returns text with all keyword substitutions removed.'''
319 if self.match(fname) and not util.binary(text):
319 if self.match(fname) and not util.binary(text):
320 return _shrinktext(text, self.rekwexp.sub)
320 return _shrinktext(text, self.rekwexp.sub)
321 return text
321 return text
322
322
323 def shrinklines(self, fname, lines):
323 def shrinklines(self, fname, lines):
324 '''Returns lines with keyword substitutions removed.'''
324 '''Returns lines with keyword substitutions removed.'''
325 if self.match(fname):
325 if self.match(fname):
326 text = ''.join(lines)
326 text = ''.join(lines)
327 if not util.binary(text):
327 if not util.binary(text):
328 return _shrinktext(text, self.rekwexp.sub).splitlines(True)
328 return _shrinktext(text, self.rekwexp.sub).splitlines(True)
329 return lines
329 return lines
330
330
331 def wread(self, fname, data):
331 def wread(self, fname, data):
332 '''If in restricted mode returns data read from wdir with
332 '''If in restricted mode returns data read from wdir with
333 keyword substitutions removed.'''
333 keyword substitutions removed.'''
334 if self.restrict:
334 if self.restrict:
335 return self.shrink(fname, data)
335 return self.shrink(fname, data)
336 return data
336 return data
337
337
338 class kwfilelog(filelog.filelog):
338 class kwfilelog(filelog.filelog):
339 '''
339 '''
340 Subclass of filelog to hook into its read, add, cmp methods.
340 Subclass of filelog to hook into its read, add, cmp methods.
341 Keywords are "stored" unexpanded, and processed on reading.
341 Keywords are "stored" unexpanded, and processed on reading.
342 '''
342 '''
343 def __init__(self, opener, kwt, path):
343 def __init__(self, opener, kwt, path):
344 super(kwfilelog, self).__init__(opener, path)
344 super(kwfilelog, self).__init__(opener, path)
345 self.kwt = kwt
345 self.kwt = kwt
346 self.path = path
346 self.path = path
347
347
348 def read(self, node):
348 def read(self, node):
349 '''Expands keywords when reading filelog.'''
349 '''Expands keywords when reading filelog.'''
350 data = super(kwfilelog, self).read(node)
350 data = super(kwfilelog, self).read(node)
351 if self.renamed(node):
351 if self.renamed(node):
352 return data
352 return data
353 return self.kwt.expand(self.path, node, data)
353 return self.kwt.expand(self.path, node, data)
354
354
355 def add(self, text, meta, tr, link, p1=None, p2=None):
355 def add(self, text, meta, tr, link, p1=None, p2=None):
356 '''Removes keyword substitutions when adding to filelog.'''
356 '''Removes keyword substitutions when adding to filelog.'''
357 text = self.kwt.shrink(self.path, text)
357 text = self.kwt.shrink(self.path, text)
358 return super(kwfilelog, self).add(text, meta, tr, link, p1, p2)
358 return super(kwfilelog, self).add(text, meta, tr, link, p1, p2)
359
359
360 def cmp(self, node, text):
360 def cmp(self, node, text):
361 '''Removes keyword substitutions for comparison.'''
361 '''Removes keyword substitutions for comparison.'''
362 text = self.kwt.shrink(self.path, text)
362 text = self.kwt.shrink(self.path, text)
363 return super(kwfilelog, self).cmp(node, text)
363 return super(kwfilelog, self).cmp(node, text)
364
364
365 def _status(ui, repo, wctx, kwt, *pats, **opts):
365 def _status(ui, repo, wctx, kwt, *pats, **opts):
366 '''Bails out if [keyword] configuration is not active.
366 '''Bails out if [keyword] configuration is not active.
367 Returns status of working directory.'''
367 Returns status of working directory.'''
368 if kwt:
368 if kwt:
369 return repo.status(match=scmutil.match(wctx, pats, opts), clean=True,
369 return repo.status(match=scmutil.match(wctx, pats, opts), clean=True,
370 unknown=opts.get('unknown') or opts.get('all'))
370 unknown=opts.get('unknown') or opts.get('all'))
371 if ui.configitems('keyword'):
371 if ui.configitems('keyword'):
372 raise error.Abort(_('[keyword] patterns cannot match'))
372 raise error.Abort(_('[keyword] patterns cannot match'))
373 raise error.Abort(_('no [keyword] patterns configured'))
373 raise error.Abort(_('no [keyword] patterns configured'))
374
374
375 def _kwfwrite(ui, repo, expand, *pats, **opts):
375 def _kwfwrite(ui, repo, expand, *pats, **opts):
376 '''Selects files and passes them to kwtemplater.overwrite.'''
376 '''Selects files and passes them to kwtemplater.overwrite.'''
377 wctx = repo[None]
377 wctx = repo[None]
378 if len(wctx.parents()) > 1:
378 if len(wctx.parents()) > 1:
379 raise error.Abort(_('outstanding uncommitted merge'))
379 raise error.Abort(_('outstanding uncommitted merge'))
380 kwt = kwtools['templater']
380 kwt = kwtools['templater']
381 with repo.wlock():
381 with repo.wlock():
382 status = _status(ui, repo, wctx, kwt, *pats, **opts)
382 status = _status(ui, repo, wctx, kwt, *pats, **opts)
383 if status.modified or status.added or status.removed or status.deleted:
383 if status.modified or status.added or status.removed or status.deleted:
384 raise error.Abort(_('outstanding uncommitted changes'))
384 raise error.Abort(_('outstanding uncommitted changes'))
385 kwt.overwrite(wctx, status.clean, True, expand)
385 kwt.overwrite(wctx, status.clean, True, expand)
386
386
387 @command('kwdemo',
387 @command('kwdemo',
388 [('d', 'default', None, _('show default keyword template maps')),
388 [('d', 'default', None, _('show default keyword template maps')),
389 ('f', 'rcfile', '',
389 ('f', 'rcfile', '',
390 _('read maps from rcfile'), _('FILE'))],
390 _('read maps from rcfile'), _('FILE'))],
391 _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...'),
391 _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...'),
392 optionalrepo=True)
392 optionalrepo=True)
393 def demo(ui, repo, *args, **opts):
393 def demo(ui, repo, *args, **opts):
394 '''print [keywordmaps] configuration and an expansion example
394 '''print [keywordmaps] configuration and an expansion example
395
395
396 Show current, custom, or default keyword template maps and their
396 Show current, custom, or default keyword template maps and their
397 expansions.
397 expansions.
398
398
399 Extend the current configuration by specifying maps as arguments
399 Extend the current configuration by specifying maps as arguments
400 and using -f/--rcfile to source an external hgrc file.
400 and using -f/--rcfile to source an external hgrc file.
401
401
402 Use -d/--default to disable current configuration.
402 Use -d/--default to disable current configuration.
403
403
404 See :hg:`help templates` for information on templates and filters.
404 See :hg:`help templates` for information on templates and filters.
405 '''
405 '''
406 def demoitems(section, items):
406 def demoitems(section, items):
407 ui.write('[%s]\n' % section)
407 ui.write('[%s]\n' % section)
408 for k, v in sorted(items):
408 for k, v in sorted(items):
409 ui.write('%s = %s\n' % (k, v))
409 ui.write('%s = %s\n' % (k, v))
410
410
411 fn = 'demo.txt'
411 fn = 'demo.txt'
412 tmpdir = tempfile.mkdtemp('', 'kwdemo.')
412 tmpdir = tempfile.mkdtemp('', 'kwdemo.')
413 ui.note(_('creating temporary repository at %s\n') % tmpdir)
413 ui.note(_('creating temporary repository at %s\n') % tmpdir)
414 if repo is None:
414 if repo is None:
415 baseui = ui
415 baseui = ui
416 else:
416 else:
417 baseui = repo.baseui
417 baseui = repo.baseui
418 repo = localrepo.localrepository(baseui, tmpdir, True)
418 repo = localrepo.localrepository(baseui, tmpdir, True)
419 ui.setconfig('keyword', fn, '', 'keyword')
419 ui.setconfig('keyword', fn, '', 'keyword')
420 svn = ui.configbool('keywordset', 'svn')
420 svn = ui.configbool('keywordset', 'svn')
421 # explicitly set keywordset for demo output
421 # explicitly set keywordset for demo output
422 ui.setconfig('keywordset', 'svn', svn, 'keyword')
422 ui.setconfig('keywordset', 'svn', svn, 'keyword')
423
423
424 uikwmaps = ui.configitems('keywordmaps')
424 uikwmaps = ui.configitems('keywordmaps')
425 if args or opts.get('rcfile'):
425 if args or opts.get('rcfile'):
426 ui.status(_('\n\tconfiguration using custom keyword template maps\n'))
426 ui.status(_('\n\tconfiguration using custom keyword template maps\n'))
427 if uikwmaps:
427 if uikwmaps:
428 ui.status(_('\textending current template maps\n'))
428 ui.status(_('\textending current template maps\n'))
429 if opts.get('default') or not uikwmaps:
429 if opts.get('default') or not uikwmaps:
430 if svn:
430 if svn:
431 ui.status(_('\toverriding default svn keywordset\n'))
431 ui.status(_('\toverriding default svn keywordset\n'))
432 else:
432 else:
433 ui.status(_('\toverriding default cvs keywordset\n'))
433 ui.status(_('\toverriding default cvs keywordset\n'))
434 if opts.get('rcfile'):
434 if opts.get('rcfile'):
435 ui.readconfig(opts.get('rcfile'))
435 ui.readconfig(opts.get('rcfile'))
436 if args:
436 if args:
437 # simulate hgrc parsing
437 # simulate hgrc parsing
438 rcmaps = '[keywordmaps]\n%s\n' % '\n'.join(args)
438 rcmaps = '[keywordmaps]\n%s\n' % '\n'.join(args)
439 repo.vfs.write('hgrc', rcmaps)
439 repo.vfs.write('hgrc', rcmaps)
440 ui.readconfig(repo.vfs.join('hgrc'))
440 ui.readconfig(repo.vfs.join('hgrc'))
441 kwmaps = dict(ui.configitems('keywordmaps'))
441 kwmaps = dict(ui.configitems('keywordmaps'))
442 elif opts.get('default'):
442 elif opts.get('default'):
443 if svn:
443 if svn:
444 ui.status(_('\n\tconfiguration using default svn keywordset\n'))
444 ui.status(_('\n\tconfiguration using default svn keywordset\n'))
445 else:
445 else:
446 ui.status(_('\n\tconfiguration using default cvs keywordset\n'))
446 ui.status(_('\n\tconfiguration using default cvs keywordset\n'))
447 kwmaps = _defaultkwmaps(ui)
447 kwmaps = _defaultkwmaps(ui)
448 if uikwmaps:
448 if uikwmaps:
449 ui.status(_('\tdisabling current template maps\n'))
449 ui.status(_('\tdisabling current template maps\n'))
450 for k, v in kwmaps.iteritems():
450 for k, v in kwmaps.iteritems():
451 ui.setconfig('keywordmaps', k, v, 'keyword')
451 ui.setconfig('keywordmaps', k, v, 'keyword')
452 else:
452 else:
453 ui.status(_('\n\tconfiguration using current keyword template maps\n'))
453 ui.status(_('\n\tconfiguration using current keyword template maps\n'))
454 if uikwmaps:
454 if uikwmaps:
455 kwmaps = dict(uikwmaps)
455 kwmaps = dict(uikwmaps)
456 else:
456 else:
457 kwmaps = _defaultkwmaps(ui)
457 kwmaps = _defaultkwmaps(ui)
458
458
459 uisetup(ui)
459 uisetup(ui)
460 reposetup(ui, repo)
460 reposetup(ui, repo)
461 ui.write(('[extensions]\nkeyword =\n'))
461 ui.write(('[extensions]\nkeyword =\n'))
462 demoitems('keyword', ui.configitems('keyword'))
462 demoitems('keyword', ui.configitems('keyword'))
463 demoitems('keywordset', ui.configitems('keywordset'))
463 demoitems('keywordset', ui.configitems('keywordset'))
464 demoitems('keywordmaps', kwmaps.iteritems())
464 demoitems('keywordmaps', kwmaps.iteritems())
465 keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
465 keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
466 repo.wvfs.write(fn, keywords)
466 repo.wvfs.write(fn, keywords)
467 repo[None].add([fn])
467 repo[None].add([fn])
468 ui.note(_('\nkeywords written to %s:\n') % fn)
468 ui.note(_('\nkeywords written to %s:\n') % fn)
469 ui.note(keywords)
469 ui.note(keywords)
470 with repo.wlock():
470 with repo.wlock():
471 repo.dirstate.setbranch('demobranch')
471 repo.dirstate.setbranch('demobranch')
472 for name, cmd in ui.configitems('hooks'):
472 for name, cmd in ui.configitems('hooks'):
473 if name.split('.', 1)[0].find('commit') > -1:
473 if name.split('.', 1)[0].find('commit') > -1:
474 repo.ui.setconfig('hooks', name, '', 'keyword')
474 repo.ui.setconfig('hooks', name, '', 'keyword')
475 msg = _('hg keyword configuration and expansion example')
475 msg = _('hg keyword configuration and expansion example')
476 ui.note(("hg ci -m '%s'\n" % msg))
476 ui.note(("hg ci -m '%s'\n" % msg))
477 repo.commit(text=msg)
477 repo.commit(text=msg)
478 ui.status(_('\n\tkeywords expanded\n'))
478 ui.status(_('\n\tkeywords expanded\n'))
479 ui.write(repo.wread(fn))
479 ui.write(repo.wread(fn))
480 repo.wvfs.rmtree(repo.root)
480 repo.wvfs.rmtree(repo.root)
481
481
482 @command('kwexpand',
482 @command('kwexpand',
483 cmdutil.walkopts,
483 cmdutil.walkopts,
484 _('hg kwexpand [OPTION]... [FILE]...'),
484 _('hg kwexpand [OPTION]... [FILE]...'),
485 inferrepo=True)
485 inferrepo=True)
486 def expand(ui, repo, *pats, **opts):
486 def expand(ui, repo, *pats, **opts):
487 '''expand keywords in the working directory
487 '''expand keywords in the working directory
488
488
489 Run after (re)enabling keyword expansion.
489 Run after (re)enabling keyword expansion.
490
490
491 kwexpand refuses to run if given files contain local changes.
491 kwexpand refuses to run if given files contain local changes.
492 '''
492 '''
493 # 3rd argument sets expansion to True
493 # 3rd argument sets expansion to True
494 _kwfwrite(ui, repo, True, *pats, **opts)
494 _kwfwrite(ui, repo, True, *pats, **opts)
495
495
496 @command('kwfiles',
496 @command('kwfiles',
497 [('A', 'all', None, _('show keyword status flags of all files')),
497 [('A', 'all', None, _('show keyword status flags of all files')),
498 ('i', 'ignore', None, _('show files excluded from expansion')),
498 ('i', 'ignore', None, _('show files excluded from expansion')),
499 ('u', 'unknown', None, _('only show unknown (not tracked) files')),
499 ('u', 'unknown', None, _('only show unknown (not tracked) files')),
500 ] + cmdutil.walkopts,
500 ] + cmdutil.walkopts,
501 _('hg kwfiles [OPTION]... [FILE]...'),
501 _('hg kwfiles [OPTION]... [FILE]...'),
502 inferrepo=True)
502 inferrepo=True)
503 def files(ui, repo, *pats, **opts):
503 def files(ui, repo, *pats, **opts):
504 '''show files configured for keyword expansion
504 '''show files configured for keyword expansion
505
505
506 List which files in the working directory are matched by the
506 List which files in the working directory are matched by the
507 [keyword] configuration patterns.
507 [keyword] configuration patterns.
508
508
509 Useful to prevent inadvertent keyword expansion and to speed up
509 Useful to prevent inadvertent keyword expansion and to speed up
510 execution by including only files that are actual candidates for
510 execution by including only files that are actual candidates for
511 expansion.
511 expansion.
512
512
513 See :hg:`help keyword` on how to construct patterns both for
513 See :hg:`help keyword` on how to construct patterns both for
514 inclusion and exclusion of files.
514 inclusion and exclusion of files.
515
515
516 With -A/--all and -v/--verbose the codes used to show the status
516 With -A/--all and -v/--verbose the codes used to show the status
517 of files are::
517 of files are::
518
518
519 K = keyword expansion candidate
519 K = keyword expansion candidate
520 k = keyword expansion candidate (not tracked)
520 k = keyword expansion candidate (not tracked)
521 I = ignored
521 I = ignored
522 i = ignored (not tracked)
522 i = ignored (not tracked)
523 '''
523 '''
524 kwt = kwtools['templater']
524 kwt = kwtools['templater']
525 wctx = repo[None]
525 wctx = repo[None]
526 status = _status(ui, repo, wctx, kwt, *pats, **opts)
526 status = _status(ui, repo, wctx, kwt, *pats, **opts)
527 if pats:
527 if pats:
528 cwd = repo.getcwd()
528 cwd = repo.getcwd()
529 else:
529 else:
530 cwd = ''
530 cwd = ''
531 files = []
531 files = []
532 if not opts.get('unknown') or opts.get('all'):
532 if not opts.get('unknown') or opts.get('all'):
533 files = sorted(status.modified + status.added + status.clean)
533 files = sorted(status.modified + status.added + status.clean)
534 kwfiles = kwt.iskwfile(files, wctx)
534 kwfiles = kwt.iskwfile(files, wctx)
535 kwdeleted = kwt.iskwfile(status.deleted, wctx)
535 kwdeleted = kwt.iskwfile(status.deleted, wctx)
536 kwunknown = kwt.iskwfile(status.unknown, wctx)
536 kwunknown = kwt.iskwfile(status.unknown, wctx)
537 if not opts.get('ignore') or opts.get('all'):
537 if not opts.get('ignore') or opts.get('all'):
538 showfiles = kwfiles, kwdeleted, kwunknown
538 showfiles = kwfiles, kwdeleted, kwunknown
539 else:
539 else:
540 showfiles = [], [], []
540 showfiles = [], [], []
541 if opts.get('all') or opts.get('ignore'):
541 if opts.get('all') or opts.get('ignore'):
542 showfiles += ([f for f in files if f not in kwfiles],
542 showfiles += ([f for f in files if f not in kwfiles],
543 [f for f in status.unknown if f not in kwunknown])
543 [f for f in status.unknown if f not in kwunknown])
544 kwlabels = 'enabled deleted enabledunknown ignored ignoredunknown'.split()
544 kwlabels = 'enabled deleted enabledunknown ignored ignoredunknown'.split()
545 kwstates = zip(kwlabels, 'K!kIi', showfiles)
545 kwstates = zip(kwlabels, 'K!kIi', showfiles)
546 fm = ui.formatter('kwfiles', opts)
546 fm = ui.formatter('kwfiles', opts)
547 fmt = '%.0s%s\n'
547 fmt = '%.0s%s\n'
548 if opts.get('all') or ui.verbose:
548 if opts.get('all') or ui.verbose:
549 fmt = '%s %s\n'
549 fmt = '%s %s\n'
550 for kwstate, char, filenames in kwstates:
550 for kwstate, char, filenames in kwstates:
551 label = 'kwfiles.' + kwstate
551 label = 'kwfiles.' + kwstate
552 for f in filenames:
552 for f in filenames:
553 fm.startitem()
553 fm.startitem()
554 fm.write('kwstatus path', fmt, char,
554 fm.write('kwstatus path', fmt, char,
555 repo.pathto(f, cwd), label=label)
555 repo.pathto(f, cwd), label=label)
556 fm.end()
556 fm.end()
557
557
558 @command('kwshrink',
558 @command('kwshrink',
559 cmdutil.walkopts,
559 cmdutil.walkopts,
560 _('hg kwshrink [OPTION]... [FILE]...'),
560 _('hg kwshrink [OPTION]... [FILE]...'),
561 inferrepo=True)
561 inferrepo=True)
562 def shrink(ui, repo, *pats, **opts):
562 def shrink(ui, repo, *pats, **opts):
563 '''revert expanded keywords in the working directory
563 '''revert expanded keywords in the working directory
564
564
565 Must be run before changing/disabling active keywords.
565 Must be run before changing/disabling active keywords.
566
566
567 kwshrink refuses to run if given files contain local changes.
567 kwshrink refuses to run if given files contain local changes.
568 '''
568 '''
569 # 3rd argument sets expansion to False
569 # 3rd argument sets expansion to False
570 _kwfwrite(ui, repo, False, *pats, **opts)
570 _kwfwrite(ui, repo, False, *pats, **opts)
571
571
572
572
573 def uisetup(ui):
573 def uisetup(ui):
574 ''' Monkeypatches dispatch._parse to retrieve user command.'''
574 ''' Monkeypatches dispatch._parse to retrieve user command.'''
575
575
576 def kwdispatch_parse(orig, ui, args):
576 def kwdispatch_parse(orig, ui, args):
577 '''Monkeypatch dispatch._parse to obtain running hg command.'''
577 '''Monkeypatch dispatch._parse to obtain running hg command.'''
578 cmd, func, args, options, cmdoptions = orig(ui, args)
578 cmd, func, args, options, cmdoptions = orig(ui, args)
579 kwtools['hgcmd'] = cmd
579 kwtools['hgcmd'] = cmd
580 return cmd, func, args, options, cmdoptions
580 return cmd, func, args, options, cmdoptions
581
581
582 extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
582 extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
583
583
584 def reposetup(ui, repo):
584 def reposetup(ui, repo):
585 '''Sets up repo as kwrepo for keyword substitution.
585 '''Sets up repo as kwrepo for keyword substitution.
586 Overrides file method to return kwfilelog instead of filelog
586 Overrides file method to return kwfilelog instead of filelog
587 if file matches user configuration.
587 if file matches user configuration.
588 Wraps commit to overwrite configured files with updated
588 Wraps commit to overwrite configured files with updated
589 keyword substitutions.
589 keyword substitutions.
590 Monkeypatches patch and webcommands.'''
590 Monkeypatches patch and webcommands.'''
591
591
592 try:
592 try:
593 if (not repo.local() or kwtools['hgcmd'] in nokwcommands.split()
593 if (not repo.local() or kwtools['hgcmd'] in nokwcommands.split()
594 or '.hg' in util.splitpath(repo.root)
594 or '.hg' in util.splitpath(repo.root)
595 or repo._url.startswith('bundle:')):
595 or repo._url.startswith('bundle:')):
596 return
596 return
597 except AttributeError:
597 except AttributeError:
598 pass
598 pass
599
599
600 inc, exc = [], ['.hg*']
600 inc, exc = [], ['.hg*']
601 for pat, opt in ui.configitems('keyword'):
601 for pat, opt in ui.configitems('keyword'):
602 if opt != 'ignore':
602 if opt != 'ignore':
603 inc.append(pat)
603 inc.append(pat)
604 else:
604 else:
605 exc.append(pat)
605 exc.append(pat)
606 if not inc:
606 if not inc:
607 return
607 return
608
608
609 kwtools['templater'] = kwt = kwtemplater(ui, repo, inc, exc)
609 kwtools['templater'] = kwt = kwtemplater(ui, repo, inc, exc)
610
610
611 class kwrepo(repo.__class__):
611 class kwrepo(repo.__class__):
612 def file(self, f):
612 def file(self, f):
613 if f[0] == '/':
613 if f[0] == '/':
614 f = f[1:]
614 f = f[1:]
615 return kwfilelog(self.svfs, kwt, f)
615 return kwfilelog(self.svfs, kwt, f)
616
616
617 def wread(self, filename):
617 def wread(self, filename):
618 data = super(kwrepo, self).wread(filename)
618 data = super(kwrepo, self).wread(filename)
619 return kwt.wread(filename, data)
619 return kwt.wread(filename, data)
620
620
621 def commit(self, *args, **opts):
621 def commit(self, *args, **opts):
622 # use custom commitctx for user commands
622 # use custom commitctx for user commands
623 # other extensions can still wrap repo.commitctx directly
623 # other extensions can still wrap repo.commitctx directly
624 self.commitctx = self.kwcommitctx
624 self.commitctx = self.kwcommitctx
625 try:
625 try:
626 return super(kwrepo, self).commit(*args, **opts)
626 return super(kwrepo, self).commit(*args, **opts)
627 finally:
627 finally:
628 del self.commitctx
628 del self.commitctx
629
629
630 def kwcommitctx(self, ctx, error=False):
630 def kwcommitctx(self, ctx, error=False):
631 n = super(kwrepo, self).commitctx(ctx, error)
631 n = super(kwrepo, self).commitctx(ctx, error)
632 # no lock needed, only called from repo.commit() which already locks
632 # no lock needed, only called from repo.commit() which already locks
633 if not kwt.postcommit:
633 if not kwt.postcommit:
634 restrict = kwt.restrict
634 restrict = kwt.restrict
635 kwt.restrict = True
635 kwt.restrict = True
636 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
636 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
637 False, True)
637 False, True)
638 kwt.restrict = restrict
638 kwt.restrict = restrict
639 return n
639 return n
640
640
641 def rollback(self, dryrun=False, force=False):
641 def rollback(self, dryrun=False, force=False):
642 with self.wlock():
642 with self.wlock():
643 origrestrict = kwt.restrict
643 origrestrict = kwt.restrict
644 try:
644 try:
645 if not dryrun:
645 if not dryrun:
646 changed = self['.'].files()
646 changed = self['.'].files()
647 ret = super(kwrepo, self).rollback(dryrun, force)
647 ret = super(kwrepo, self).rollback(dryrun, force)
648 if not dryrun:
648 if not dryrun:
649 ctx = self['.']
649 ctx = self['.']
650 modified, added = _preselect(ctx.status(), changed)
650 modified, added = _preselect(ctx.status(), changed)
651 kwt.restrict = False
651 kwt.restrict = False
652 kwt.overwrite(ctx, modified, True, True)
652 kwt.overwrite(ctx, modified, True, True)
653 kwt.overwrite(ctx, added, True, False)
653 kwt.overwrite(ctx, added, True, False)
654 return ret
654 return ret
655 finally:
655 finally:
656 kwt.restrict = origrestrict
656 kwt.restrict = origrestrict
657
657
658 # monkeypatches
658 # monkeypatches
659 def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None):
659 def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None):
660 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
660 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
661 rejects or conflicts due to expanded keywords in working dir.'''
661 rejects or conflicts due to expanded keywords in working dir.'''
662 orig(self, ui, gp, backend, store, eolmode)
662 orig(self, ui, gp, backend, store, eolmode)
663 # shrink keywords read from working dir
663 # shrink keywords read from working dir
664 self.lines = kwt.shrinklines(self.fname, self.lines)
664 self.lines = kwt.shrinklines(self.fname, self.lines)
665
665
666 def kwdiff(orig, *args, **kwargs):
666 def kwdiff(orig, *args, **kwargs):
667 '''Monkeypatch patch.diff to avoid expansion.'''
667 '''Monkeypatch patch.diff to avoid expansion.'''
668 restrict = kwt.restrict
668 kwt.restrict = True
669 kwt.restrict = True
669 return orig(*args, **kwargs)
670 try:
671 for chunk in orig(*args, **kwargs):
672 yield chunk
673 finally:
674 kwt.restrict = restrict
670
675
671 def kwweb_skip(orig, web, req, tmpl):
676 def kwweb_skip(orig, web, req, tmpl):
672 '''Wraps webcommands.x turning off keyword expansion.'''
677 '''Wraps webcommands.x turning off keyword expansion.'''
673 kwt.match = util.never
678 kwt.match = util.never
674 return orig(web, req, tmpl)
679 return orig(web, req, tmpl)
675
680
676 def kw_amend(orig, ui, repo, commitfunc, old, extra, pats, opts):
681 def kw_amend(orig, ui, repo, commitfunc, old, extra, pats, opts):
677 '''Wraps cmdutil.amend expanding keywords after amend.'''
682 '''Wraps cmdutil.amend expanding keywords after amend.'''
678 with repo.wlock():
683 with repo.wlock():
679 kwt.postcommit = True
684 kwt.postcommit = True
680 newid = orig(ui, repo, commitfunc, old, extra, pats, opts)
685 newid = orig(ui, repo, commitfunc, old, extra, pats, opts)
681 if newid != old.node():
686 if newid != old.node():
682 ctx = repo[newid]
687 ctx = repo[newid]
683 kwt.restrict = True
688 kwt.restrict = True
684 kwt.overwrite(ctx, ctx.files(), False, True)
689 kwt.overwrite(ctx, ctx.files(), False, True)
685 kwt.restrict = False
690 kwt.restrict = False
686 return newid
691 return newid
687
692
688 def kw_copy(orig, ui, repo, pats, opts, rename=False):
693 def kw_copy(orig, ui, repo, pats, opts, rename=False):
689 '''Wraps cmdutil.copy so that copy/rename destinations do not
694 '''Wraps cmdutil.copy so that copy/rename destinations do not
690 contain expanded keywords.
695 contain expanded keywords.
691 Note that the source of a regular file destination may also be a
696 Note that the source of a regular file destination may also be a
692 symlink:
697 symlink:
693 hg cp sym x -> x is symlink
698 hg cp sym x -> x is symlink
694 cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords)
699 cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords)
695 For the latter we have to follow the symlink to find out whether its
700 For the latter we have to follow the symlink to find out whether its
696 target is configured for expansion and we therefore must unexpand the
701 target is configured for expansion and we therefore must unexpand the
697 keywords in the destination.'''
702 keywords in the destination.'''
698 with repo.wlock():
703 with repo.wlock():
699 orig(ui, repo, pats, opts, rename)
704 orig(ui, repo, pats, opts, rename)
700 if opts.get('dry_run'):
705 if opts.get('dry_run'):
701 return
706 return
702 wctx = repo[None]
707 wctx = repo[None]
703 cwd = repo.getcwd()
708 cwd = repo.getcwd()
704
709
705 def haskwsource(dest):
710 def haskwsource(dest):
706 '''Returns true if dest is a regular file and configured for
711 '''Returns true if dest is a regular file and configured for
707 expansion or a symlink which points to a file configured for
712 expansion or a symlink which points to a file configured for
708 expansion. '''
713 expansion. '''
709 source = repo.dirstate.copied(dest)
714 source = repo.dirstate.copied(dest)
710 if 'l' in wctx.flags(source):
715 if 'l' in wctx.flags(source):
711 source = pathutil.canonpath(repo.root, cwd,
716 source = pathutil.canonpath(repo.root, cwd,
712 os.path.realpath(source))
717 os.path.realpath(source))
713 return kwt.match(source)
718 return kwt.match(source)
714
719
715 candidates = [f for f in repo.dirstate.copies() if
720 candidates = [f for f in repo.dirstate.copies() if
716 'l' not in wctx.flags(f) and haskwsource(f)]
721 'l' not in wctx.flags(f) and haskwsource(f)]
717 kwt.overwrite(wctx, candidates, False, False)
722 kwt.overwrite(wctx, candidates, False, False)
718
723
719 def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
724 def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
720 '''Wraps record.dorecord expanding keywords after recording.'''
725 '''Wraps record.dorecord expanding keywords after recording.'''
721 with repo.wlock():
726 with repo.wlock():
722 # record returns 0 even when nothing has changed
727 # record returns 0 even when nothing has changed
723 # therefore compare nodes before and after
728 # therefore compare nodes before and after
724 kwt.postcommit = True
729 kwt.postcommit = True
725 ctx = repo['.']
730 ctx = repo['.']
726 wstatus = ctx.status()
731 wstatus = ctx.status()
727 ret = orig(ui, repo, commitfunc, *pats, **opts)
732 ret = orig(ui, repo, commitfunc, *pats, **opts)
728 recctx = repo['.']
733 recctx = repo['.']
729 if ctx != recctx:
734 if ctx != recctx:
730 modified, added = _preselect(wstatus, recctx.files())
735 modified, added = _preselect(wstatus, recctx.files())
731 kwt.restrict = False
736 kwt.restrict = False
732 kwt.overwrite(recctx, modified, False, True)
737 kwt.overwrite(recctx, modified, False, True)
733 kwt.overwrite(recctx, added, False, True, True)
738 kwt.overwrite(recctx, added, False, True, True)
734 kwt.restrict = True
739 kwt.restrict = True
735 return ret
740 return ret
736
741
737 def kwfilectx_cmp(orig, self, fctx):
742 def kwfilectx_cmp(orig, self, fctx):
738 if fctx._customcmp:
743 if fctx._customcmp:
739 return fctx.cmp(self)
744 return fctx.cmp(self)
740 # keyword affects data size, comparing wdir and filelog size does
745 # keyword affects data size, comparing wdir and filelog size does
741 # not make sense
746 # not make sense
742 if (fctx._filenode is None and
747 if (fctx._filenode is None and
743 (self._repo._encodefilterpats or
748 (self._repo._encodefilterpats or
744 kwt.match(fctx.path()) and 'l' not in fctx.flags() or
749 kwt.match(fctx.path()) and 'l' not in fctx.flags() or
745 self.size() - 4 == fctx.size()) or
750 self.size() - 4 == fctx.size()) or
746 self.size() == fctx.size()):
751 self.size() == fctx.size()):
747 return self._filelog.cmp(self._filenode, fctx.data())
752 return self._filelog.cmp(self._filenode, fctx.data())
748 return True
753 return True
749
754
750 extensions.wrapfunction(context.filectx, 'cmp', kwfilectx_cmp)
755 extensions.wrapfunction(context.filectx, 'cmp', kwfilectx_cmp)
751 extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
756 extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
752 extensions.wrapfunction(patch, 'diff', kwdiff)
757 extensions.wrapfunction(patch, 'diff', kwdiff)
753 extensions.wrapfunction(cmdutil, 'amend', kw_amend)
758 extensions.wrapfunction(cmdutil, 'amend', kw_amend)
754 extensions.wrapfunction(cmdutil, 'copy', kw_copy)
759 extensions.wrapfunction(cmdutil, 'copy', kw_copy)
755 extensions.wrapfunction(cmdutil, 'dorecord', kw_dorecord)
760 extensions.wrapfunction(cmdutil, 'dorecord', kw_dorecord)
756 for c in 'annotate changeset rev filediff diff'.split():
761 for c in 'annotate changeset rev filediff diff'.split():
757 extensions.wrapfunction(webcommands, c, kwweb_skip)
762 extensions.wrapfunction(webcommands, c, kwweb_skip)
758 repo.__class__ = kwrepo
763 repo.__class__ = kwrepo
@@ -1,1381 +1,1412 b''
1 Run kwdemo outside a repo
1 Run kwdemo outside a repo
2 $ hg -q --config extensions.keyword= --config keywordmaps.Foo="{author|user}" kwdemo
2 $ hg -q --config extensions.keyword= --config keywordmaps.Foo="{author|user}" kwdemo
3 [extensions]
3 [extensions]
4 keyword =
4 keyword =
5 [keyword]
5 [keyword]
6 demo.txt =
6 demo.txt =
7 [keywordset]
7 [keywordset]
8 svn = False
8 svn = False
9 [keywordmaps]
9 [keywordmaps]
10 Foo = {author|user}
10 Foo = {author|user}
11 $Foo: test $
11 $Foo: test $
12
12
13 $ cat <<EOF >> $HGRCPATH
13 $ cat <<EOF >> $HGRCPATH
14 > [extensions]
14 > [extensions]
15 > keyword =
15 > keyword =
16 > mq =
16 > mq =
17 > notify =
17 > notify =
18 > record =
18 > record =
19 > transplant =
19 > transplant =
20 > [ui]
20 > [ui]
21 > interactive = true
21 > interactive = true
22 > EOF
22 > EOF
23
23
24 hide outer repo
24 hide outer repo
25 $ hg init
25 $ hg init
26
26
27 Run kwdemo before [keyword] files are set up
27 Run kwdemo before [keyword] files are set up
28 as it would succeed without uisetup otherwise
28 as it would succeed without uisetup otherwise
29
29
30 $ hg --quiet kwdemo
30 $ hg --quiet kwdemo
31 [extensions]
31 [extensions]
32 keyword =
32 keyword =
33 [keyword]
33 [keyword]
34 demo.txt =
34 demo.txt =
35 [keywordset]
35 [keywordset]
36 svn = False
36 svn = False
37 [keywordmaps]
37 [keywordmaps]
38 Author = {author|user}
38 Author = {author|user}
39 Date = {date|utcdate}
39 Date = {date|utcdate}
40 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
40 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
41 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
41 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
42 RCSFile = {file|basename},v
42 RCSFile = {file|basename},v
43 RCSfile = {file|basename},v
43 RCSfile = {file|basename},v
44 Revision = {node|short}
44 Revision = {node|short}
45 Source = {root}/{file},v
45 Source = {root}/{file},v
46 $Author: test $
46 $Author: test $
47 $Date: ????/??/?? ??:??:?? $ (glob)
47 $Date: ????/??/?? ??:??:?? $ (glob)
48 $Header: */demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
48 $Header: */demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
49 $Id: demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
49 $Id: demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
50 $RCSFile: demo.txt,v $
50 $RCSFile: demo.txt,v $
51 $RCSfile: demo.txt,v $
51 $RCSfile: demo.txt,v $
52 $Revision: ???????????? $ (glob)
52 $Revision: ???????????? $ (glob)
53 $Source: */demo.txt,v $ (glob)
53 $Source: */demo.txt,v $ (glob)
54
54
55 $ hg --quiet kwdemo "Branch = {branches}"
55 $ hg --quiet kwdemo "Branch = {branches}"
56 [extensions]
56 [extensions]
57 keyword =
57 keyword =
58 [keyword]
58 [keyword]
59 demo.txt =
59 demo.txt =
60 [keywordset]
60 [keywordset]
61 svn = False
61 svn = False
62 [keywordmaps]
62 [keywordmaps]
63 Branch = {branches}
63 Branch = {branches}
64 $Branch: demobranch $
64 $Branch: demobranch $
65
65
66 (test template filter svnisodate and svnutcdate)
66 (test template filter svnisodate and svnutcdate)
67
67
68 $ hg --quiet kwdemo --config keywordset.svn=True
68 $ hg --quiet kwdemo --config keywordset.svn=True
69 [extensions]
69 [extensions]
70 keyword =
70 keyword =
71 [keyword]
71 [keyword]
72 demo.txt =
72 demo.txt =
73 [keywordset]
73 [keywordset]
74 svn = True
74 svn = True
75 [keywordmaps]
75 [keywordmaps]
76 Author = {author|user}
76 Author = {author|user}
77 Date = {date|svnisodate}
77 Date = {date|svnisodate}
78 Id = {file|basename},v {node|short} {date|svnutcdate} {author|user}
78 Id = {file|basename},v {node|short} {date|svnutcdate} {author|user}
79 LastChangedBy = {author|user}
79 LastChangedBy = {author|user}
80 LastChangedDate = {date|svnisodate}
80 LastChangedDate = {date|svnisodate}
81 LastChangedRevision = {node|short}
81 LastChangedRevision = {node|short}
82 Revision = {node|short}
82 Revision = {node|short}
83 $Author: test $
83 $Author: test $
84 $Date: ????-??-?? ??:??:?? ????? (???, ?? ??? ????) $ (glob)
84 $Date: ????-??-?? ??:??:?? ????? (???, ?? ??? ????) $ (glob)
85 $Id: demo.txt,v ???????????? ????-??-?? ??:??:??Z test $ (glob)
85 $Id: demo.txt,v ???????????? ????-??-?? ??:??:??Z test $ (glob)
86 $LastChangedBy: test $
86 $LastChangedBy: test $
87 $LastChangedDate: ????-??-?? ??:??:?? ????? (???, ?? ??? ????) $ (glob)
87 $LastChangedDate: ????-??-?? ??:??:?? ????? (???, ?? ??? ????) $ (glob)
88 $LastChangedRevision: ???????????? $ (glob)
88 $LastChangedRevision: ???????????? $ (glob)
89 $Revision: ???????????? $ (glob)
89 $Revision: ???????????? $ (glob)
90
90
91 $ cat <<EOF >> $HGRCPATH
91 $ cat <<EOF >> $HGRCPATH
92 > [keyword]
92 > [keyword]
93 > ** =
93 > ** =
94 > b = ignore
94 > b = ignore
95 > i = ignore
95 > i = ignore
96 > [hooks]
96 > [hooks]
97 > EOF
97 > EOF
98 $ cp $HGRCPATH $HGRCPATH.nohooks
98 $ cp $HGRCPATH $HGRCPATH.nohooks
99 > cat <<EOF >> $HGRCPATH
99 > cat <<EOF >> $HGRCPATH
100 > commit=
100 > commit=
101 > commit.test=cp a hooktest
101 > commit.test=cp a hooktest
102 > EOF
102 > EOF
103
103
104 $ hg init Test-bndl
104 $ hg init Test-bndl
105 $ cd Test-bndl
105 $ cd Test-bndl
106
106
107 kwshrink should exit silently in empty/invalid repo
107 kwshrink should exit silently in empty/invalid repo
108
108
109 $ hg kwshrink
109 $ hg kwshrink
110
110
111 Symlinks cannot be created on Windows.
111 Symlinks cannot be created on Windows.
112 A bundle to test this was made with:
112 A bundle to test this was made with:
113 hg init t
113 hg init t
114 cd t
114 cd t
115 echo a > a
115 echo a > a
116 ln -s a sym
116 ln -s a sym
117 hg add sym
117 hg add sym
118 hg ci -m addsym -u mercurial
118 hg ci -m addsym -u mercurial
119 hg bundle --base null ../test-keyword.hg
119 hg bundle --base null ../test-keyword.hg
120
120
121 $ hg pull -u "$TESTDIR"/bundles/test-keyword.hg
121 $ hg pull -u "$TESTDIR"/bundles/test-keyword.hg
122 pulling from *test-keyword.hg (glob)
122 pulling from *test-keyword.hg (glob)
123 requesting all changes
123 requesting all changes
124 adding changesets
124 adding changesets
125 adding manifests
125 adding manifests
126 adding file changes
126 adding file changes
127 added 1 changesets with 1 changes to 1 files
127 added 1 changesets with 1 changes to 1 files
128 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
128 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
129
129
130 $ echo 'expand $Id$' > a
130 $ echo 'expand $Id$' > a
131 $ echo 'do not process $Id:' >> a
131 $ echo 'do not process $Id:' >> a
132 $ echo 'xxx $' >> a
132 $ echo 'xxx $' >> a
133 $ echo 'ignore $Id$' > b
133 $ echo 'ignore $Id$' > b
134
134
135 Output files as they were created
135 Output files as they were created
136
136
137 $ cat a b
137 $ cat a b
138 expand $Id$
138 expand $Id$
139 do not process $Id:
139 do not process $Id:
140 xxx $
140 xxx $
141 ignore $Id$
141 ignore $Id$
142
142
143 no kwfiles
143 no kwfiles
144
144
145 $ hg kwfiles
145 $ hg kwfiles
146
146
147 untracked candidates
147 untracked candidates
148
148
149 $ hg -v kwfiles --unknown
149 $ hg -v kwfiles --unknown
150 k a
150 k a
151
151
152 Add files and check status
152 Add files and check status
153
153
154 $ hg addremove
154 $ hg addremove
155 adding a
155 adding a
156 adding b
156 adding b
157 $ hg status
157 $ hg status
158 A a
158 A a
159 A b
159 A b
160
160
161
161
162 Default keyword expansion including commit hook
162 Default keyword expansion including commit hook
163 Interrupted commit should not change state or run commit hook
163 Interrupted commit should not change state or run commit hook
164
164
165 $ hg --debug commit
165 $ hg --debug commit
166 abort: empty commit message
166 abort: empty commit message
167 [255]
167 [255]
168 $ hg status
168 $ hg status
169 A a
169 A a
170 A b
170 A b
171
171
172 Commit with several checks
172 Commit with several checks
173
173
174 $ hg --debug commit -mabsym -u 'User Name <user@example.com>'
174 $ hg --debug commit -mabsym -u 'User Name <user@example.com>'
175 committing files:
175 committing files:
176 a
176 a
177 b
177 b
178 committing manifest
178 committing manifest
179 committing changelog
179 committing changelog
180 overwriting a expanding keywords
180 overwriting a expanding keywords
181 updating the branch cache
181 updating the branch cache
182 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
182 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
183 running hook commit.test: cp a hooktest
183 running hook commit.test: cp a hooktest
184 $ hg status
184 $ hg status
185 ? hooktest
185 ? hooktest
186 $ hg debugrebuildstate
186 $ hg debugrebuildstate
187 $ hg --quiet identify
187 $ hg --quiet identify
188 ef63ca68695b
188 ef63ca68695b
189
189
190 cat files in working directory with keywords expanded
190 cat files in working directory with keywords expanded
191
191
192 $ cat a b
192 $ cat a b
193 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
193 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
194 do not process $Id:
194 do not process $Id:
195 xxx $
195 xxx $
196 ignore $Id$
196 ignore $Id$
197
197
198 hg cat files and symlink, no expansion
198 hg cat files and symlink, no expansion
199
199
200 $ hg cat sym a b && echo
200 $ hg cat sym a b && echo
201 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
201 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
202 do not process $Id:
202 do not process $Id:
203 xxx $
203 xxx $
204 ignore $Id$
204 ignore $Id$
205 a
205 a
206
206
207 $ diff a hooktest
207 $ diff a hooktest
208
208
209 $ cp $HGRCPATH.nohooks $HGRCPATH
209 $ cp $HGRCPATH.nohooks $HGRCPATH
210 $ rm hooktest
210 $ rm hooktest
211
211
212 hg status of kw-ignored binary file starting with '\1\n'
212 hg status of kw-ignored binary file starting with '\1\n'
213
213
214 >>> open("i", "wb").write("\1\nfoo")
214 >>> open("i", "wb").write("\1\nfoo")
215 $ hg -q commit -Am metasep i
215 $ hg -q commit -Am metasep i
216 $ hg status
216 $ hg status
217 >>> open("i", "wb").write("\1\nbar")
217 >>> open("i", "wb").write("\1\nbar")
218 $ hg status
218 $ hg status
219 M i
219 M i
220 $ hg -q commit -m "modify metasep" i
220 $ hg -q commit -m "modify metasep" i
221 $ hg status --rev 2:3
221 $ hg status --rev 2:3
222 M i
222 M i
223 $ touch empty
223 $ touch empty
224 $ hg -q commit -A -m "another file"
224 $ hg -q commit -A -m "another file"
225 $ hg status -A --rev 3:4 i
225 $ hg status -A --rev 3:4 i
226 C i
226 C i
227
227
228 $ hg -q strip --no-backup 2
228 $ hg -q strip --no-backup 2
229
229
230 Test hook execution
230 Test hook execution
231
231
232 bundle
232 bundle
233
233
234 $ hg bundle --base null ../kw.hg
234 $ hg bundle --base null ../kw.hg
235 2 changesets found
235 2 changesets found
236 $ cd ..
236 $ cd ..
237 $ hg init Test
237 $ hg init Test
238 $ cd Test
238 $ cd Test
239
239
240 Notify on pull to check whether keywords stay as is in email
240 Notify on pull to check whether keywords stay as is in email
241 ie. if patch.diff wrapper acts as it should
241 ie. if patch.diff wrapper acts as it should
242
242
243 $ cat <<EOF >> $HGRCPATH
243 $ cat <<EOF >> $HGRCPATH
244 > [hooks]
244 > [hooks]
245 > incoming.notify = python:hgext.notify.hook
245 > incoming.notify = python:hgext.notify.hook
246 > [notify]
246 > [notify]
247 > sources = pull
247 > sources = pull
248 > diffstat = False
248 > diffstat = False
249 > maxsubject = 15
249 > maxsubject = 15
250 > [reposubs]
250 > [reposubs]
251 > * = Test
251 > * = Test
252 > EOF
252 > EOF
253
253
254 Pull from bundle and trigger notify
254 Pull from bundle and trigger notify
255
255
256 $ hg pull -u ../kw.hg
256 $ hg pull -u ../kw.hg
257 pulling from ../kw.hg
257 pulling from ../kw.hg
258 requesting all changes
258 requesting all changes
259 adding changesets
259 adding changesets
260 adding manifests
260 adding manifests
261 adding file changes
261 adding file changes
262 added 2 changesets with 3 changes to 3 files
262 added 2 changesets with 3 changes to 3 files
263 Content-Type: text/plain; charset="us-ascii"
263 Content-Type: text/plain; charset="us-ascii"
264 MIME-Version: 1.0
264 MIME-Version: 1.0
265 Content-Transfer-Encoding: 7bit
265 Content-Transfer-Encoding: 7bit
266 Date: * (glob)
266 Date: * (glob)
267 Subject: changeset in...
267 Subject: changeset in...
268 From: mercurial
268 From: mercurial
269 X-Hg-Notification: changeset a2392c293916
269 X-Hg-Notification: changeset a2392c293916
270 Message-Id: <hg.a2392c293916*> (glob)
270 Message-Id: <hg.a2392c293916*> (glob)
271 To: Test
271 To: Test
272
272
273 changeset a2392c293916 in $TESTTMP/Test (glob)
273 changeset a2392c293916 in $TESTTMP/Test (glob)
274 details: $TESTTMP/Test?cmd=changeset;node=a2392c293916
274 details: $TESTTMP/Test?cmd=changeset;node=a2392c293916
275 description:
275 description:
276 addsym
276 addsym
277
277
278 diffs (6 lines):
278 diffs (6 lines):
279
279
280 diff -r 000000000000 -r a2392c293916 sym
280 diff -r 000000000000 -r a2392c293916 sym
281 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
281 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
282 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
282 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
283 @@ -0,0 +1,1 @@
283 @@ -0,0 +1,1 @@
284 +a
284 +a
285 \ No newline at end of file
285 \ No newline at end of file
286 Content-Type: text/plain; charset="us-ascii"
286 Content-Type: text/plain; charset="us-ascii"
287 MIME-Version: 1.0
287 MIME-Version: 1.0
288 Content-Transfer-Encoding: 7bit
288 Content-Transfer-Encoding: 7bit
289 Date:* (glob)
289 Date:* (glob)
290 Subject: changeset in...
290 Subject: changeset in...
291 From: User Name <user@example.com>
291 From: User Name <user@example.com>
292 X-Hg-Notification: changeset ef63ca68695b
292 X-Hg-Notification: changeset ef63ca68695b
293 Message-Id: <hg.ef63ca68695b*> (glob)
293 Message-Id: <hg.ef63ca68695b*> (glob)
294 To: Test
294 To: Test
295
295
296 changeset ef63ca68695b in $TESTTMP/Test (glob)
296 changeset ef63ca68695b in $TESTTMP/Test (glob)
297 details: $TESTTMP/Test?cmd=changeset;node=ef63ca68695b
297 details: $TESTTMP/Test?cmd=changeset;node=ef63ca68695b
298 description:
298 description:
299 absym
299 absym
300
300
301 diffs (12 lines):
301 diffs (12 lines):
302
302
303 diff -r a2392c293916 -r ef63ca68695b a
303 diff -r a2392c293916 -r ef63ca68695b a
304 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
304 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
305 +++ b/a Thu Jan 01 00:00:00 1970 +0000
305 +++ b/a Thu Jan 01 00:00:00 1970 +0000
306 @@ -0,0 +1,3 @@
306 @@ -0,0 +1,3 @@
307 +expand $Id$
307 +expand $Id$
308 +do not process $Id:
308 +do not process $Id:
309 +xxx $
309 +xxx $
310 diff -r a2392c293916 -r ef63ca68695b b
310 diff -r a2392c293916 -r ef63ca68695b b
311 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
311 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
312 +++ b/b Thu Jan 01 00:00:00 1970 +0000
312 +++ b/b Thu Jan 01 00:00:00 1970 +0000
313 @@ -0,0 +1,1 @@
313 @@ -0,0 +1,1 @@
314 +ignore $Id$
314 +ignore $Id$
315 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
315 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
316
316
317 $ cp $HGRCPATH.nohooks $HGRCPATH
317 $ cp $HGRCPATH.nohooks $HGRCPATH
318
318
319 Touch files and check with status
319 Touch files and check with status
320
320
321 $ touch a b
321 $ touch a b
322 $ hg status
322 $ hg status
323
323
324 Update and expand
324 Update and expand
325
325
326 $ rm sym a b
326 $ rm sym a b
327 $ hg update -C
327 $ hg update -C
328 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
328 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 $ cat a b
329 $ cat a b
330 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
330 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
331 do not process $Id:
331 do not process $Id:
332 xxx $
332 xxx $
333 ignore $Id$
333 ignore $Id$
334
334
335 Check whether expansion is filewise and file mode is preserved
335 Check whether expansion is filewise and file mode is preserved
336
336
337 $ echo '$Id$' > c
337 $ echo '$Id$' > c
338 $ echo 'tests for different changenodes' >> c
338 $ echo 'tests for different changenodes' >> c
339 #if unix-permissions
339 #if unix-permissions
340 $ chmod 600 c
340 $ chmod 600 c
341 $ ls -l c | cut -b 1-10
341 $ ls -l c | cut -b 1-10
342 -rw-------
342 -rw-------
343 #endif
343 #endif
344
344
345 commit file c
345 commit file c
346
346
347 $ hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
347 $ hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
348 adding c
348 adding c
349 #if unix-permissions
349 #if unix-permissions
350 $ ls -l c | cut -b 1-10
350 $ ls -l c | cut -b 1-10
351 -rw-------
351 -rw-------
352 #endif
352 #endif
353
353
354 force expansion
354 force expansion
355
355
356 $ hg -v kwexpand
356 $ hg -v kwexpand
357 overwriting a expanding keywords
357 overwriting a expanding keywords
358 overwriting c expanding keywords
358 overwriting c expanding keywords
359
359
360 compare changenodes in a and c
360 compare changenodes in a and c
361
361
362 $ cat a c
362 $ cat a c
363 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
363 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
364 do not process $Id:
364 do not process $Id:
365 xxx $
365 xxx $
366 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
366 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
367 tests for different changenodes
367 tests for different changenodes
368
368
369 record
369 record
370
370
371 $ echo '$Id$' > r
371 $ echo '$Id$' > r
372 $ hg add r
372 $ hg add r
373
373
374 record chunk
374 record chunk
375
375
376 >>> lines = open('a', 'rb').readlines()
376 >>> lines = open('a', 'rb').readlines()
377 >>> lines.insert(1, 'foo\n')
377 >>> lines.insert(1, 'foo\n')
378 >>> lines.append('bar\n')
378 >>> lines.append('bar\n')
379 >>> open('a', 'wb').writelines(lines)
379 >>> open('a', 'wb').writelines(lines)
380 $ hg record -d '10 1' -m rectest a<<EOF
380 $ hg record -d '10 1' -m rectest a<<EOF
381 > y
381 > y
382 > y
382 > y
383 > n
383 > n
384 > EOF
384 > EOF
385 diff --git a/a b/a
385 diff --git a/a b/a
386 2 hunks, 2 lines changed
386 2 hunks, 2 lines changed
387 examine changes to 'a'? [Ynesfdaq?] y
387 examine changes to 'a'? [Ynesfdaq?] y
388
388
389 @@ -1,3 +1,4 @@
389 @@ -1,3 +1,4 @@
390 expand $Id$
390 expand $Id$
391 +foo
391 +foo
392 do not process $Id:
392 do not process $Id:
393 xxx $
393 xxx $
394 record change 1/2 to 'a'? [Ynesfdaq?] y
394 record change 1/2 to 'a'? [Ynesfdaq?] y
395
395
396 @@ -2,2 +3,3 @@
396 @@ -2,2 +3,3 @@
397 do not process $Id:
397 do not process $Id:
398 xxx $
398 xxx $
399 +bar
399 +bar
400 record change 2/2 to 'a'? [Ynesfdaq?] n
400 record change 2/2 to 'a'? [Ynesfdaq?] n
401
401
402
402
403 $ hg identify
403 $ hg identify
404 5f5eb23505c3+ tip
404 5f5eb23505c3+ tip
405 $ hg status
405 $ hg status
406 M a
406 M a
407 A r
407 A r
408
408
409 Cat modified file a
409 Cat modified file a
410
410
411 $ cat a
411 $ cat a
412 expand $Id: a,v 5f5eb23505c3 1970/01/01 00:00:10 test $
412 expand $Id: a,v 5f5eb23505c3 1970/01/01 00:00:10 test $
413 foo
413 foo
414 do not process $Id:
414 do not process $Id:
415 xxx $
415 xxx $
416 bar
416 bar
417
417
418 Diff remaining chunk
418 Diff remaining chunk
419
419
420 $ hg diff a
420 $ hg diff a
421 diff -r 5f5eb23505c3 a
421 diff -r 5f5eb23505c3 a
422 --- a/a Thu Jan 01 00:00:09 1970 -0000
422 --- a/a Thu Jan 01 00:00:09 1970 -0000
423 +++ b/a * (glob)
423 +++ b/a * (glob)
424 @@ -2,3 +2,4 @@
424 @@ -2,3 +2,4 @@
425 foo
425 foo
426 do not process $Id:
426 do not process $Id:
427 xxx $
427 xxx $
428 +bar
428 +bar
429
429
430 $ hg rollback
430 $ hg rollback
431 repository tip rolled back to revision 2 (undo commit)
431 repository tip rolled back to revision 2 (undo commit)
432 working directory now based on revision 2
432 working directory now based on revision 2
433
433
434 Record all chunks in file a
434 Record all chunks in file a
435
435
436 $ echo foo > msg
436 $ echo foo > msg
437
437
438 - do not use "hg record -m" here!
438 - do not use "hg record -m" here!
439
439
440 $ hg record -l msg -d '11 1' a<<EOF
440 $ hg record -l msg -d '11 1' a<<EOF
441 > y
441 > y
442 > y
442 > y
443 > y
443 > y
444 > EOF
444 > EOF
445 diff --git a/a b/a
445 diff --git a/a b/a
446 2 hunks, 2 lines changed
446 2 hunks, 2 lines changed
447 examine changes to 'a'? [Ynesfdaq?] y
447 examine changes to 'a'? [Ynesfdaq?] y
448
448
449 @@ -1,3 +1,4 @@
449 @@ -1,3 +1,4 @@
450 expand $Id$
450 expand $Id$
451 +foo
451 +foo
452 do not process $Id:
452 do not process $Id:
453 xxx $
453 xxx $
454 record change 1/2 to 'a'? [Ynesfdaq?] y
454 record change 1/2 to 'a'? [Ynesfdaq?] y
455
455
456 @@ -2,2 +3,3 @@
456 @@ -2,2 +3,3 @@
457 do not process $Id:
457 do not process $Id:
458 xxx $
458 xxx $
459 +bar
459 +bar
460 record change 2/2 to 'a'? [Ynesfdaq?] y
460 record change 2/2 to 'a'? [Ynesfdaq?] y
461
461
462
462
463 File a should be clean
463 File a should be clean
464
464
465 $ hg status -A a
465 $ hg status -A a
466 C a
466 C a
467
467
468 rollback and revert expansion
468 rollback and revert expansion
469
469
470 $ cat a
470 $ cat a
471 expand $Id: a,v 78e0a02d76aa 1970/01/01 00:00:11 test $
471 expand $Id: a,v 78e0a02d76aa 1970/01/01 00:00:11 test $
472 foo
472 foo
473 do not process $Id:
473 do not process $Id:
474 xxx $
474 xxx $
475 bar
475 bar
476 $ hg --verbose rollback
476 $ hg --verbose rollback
477 repository tip rolled back to revision 2 (undo commit)
477 repository tip rolled back to revision 2 (undo commit)
478 working directory now based on revision 2
478 working directory now based on revision 2
479 overwriting a expanding keywords
479 overwriting a expanding keywords
480 $ hg status a
480 $ hg status a
481 M a
481 M a
482 $ cat a
482 $ cat a
483 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
483 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
484 foo
484 foo
485 do not process $Id:
485 do not process $Id:
486 xxx $
486 xxx $
487 bar
487 bar
488 $ echo '$Id$' > y
488 $ echo '$Id$' > y
489 $ echo '$Id$' > z
489 $ echo '$Id$' > z
490 $ hg add y
490 $ hg add y
491 $ hg commit -Am "rollback only" z
491 $ hg commit -Am "rollback only" z
492 $ cat z
492 $ cat z
493 $Id: z,v 45a5d3adce53 1970/01/01 00:00:00 test $
493 $Id: z,v 45a5d3adce53 1970/01/01 00:00:00 test $
494 $ hg --verbose rollback
494 $ hg --verbose rollback
495 repository tip rolled back to revision 2 (undo commit)
495 repository tip rolled back to revision 2 (undo commit)
496 working directory now based on revision 2
496 working directory now based on revision 2
497 overwriting z shrinking keywords
497 overwriting z shrinking keywords
498
498
499 Only z should be overwritten
499 Only z should be overwritten
500
500
501 $ hg status a y z
501 $ hg status a y z
502 M a
502 M a
503 A y
503 A y
504 A z
504 A z
505 $ cat z
505 $ cat z
506 $Id$
506 $Id$
507 $ hg forget y z
507 $ hg forget y z
508 $ rm y z
508 $ rm y z
509
509
510 record added file alone
510 record added file alone
511
511
512 $ hg -v record -l msg -d '12 2' r<<EOF
512 $ hg -v record -l msg -d '12 2' r<<EOF
513 > y
513 > y
514 > y
514 > y
515 > EOF
515 > EOF
516 diff --git a/r b/r
516 diff --git a/r b/r
517 new file mode 100644
517 new file mode 100644
518 examine changes to 'r'? [Ynesfdaq?] y
518 examine changes to 'r'? [Ynesfdaq?] y
519
519
520 @@ -0,0 +1,1 @@
520 @@ -0,0 +1,1 @@
521 +$Id$
521 +$Id$
522 record this change to 'r'? [Ynesfdaq?] y
522 record this change to 'r'? [Ynesfdaq?] y
523
523
524 resolving manifests
524 resolving manifests
525 patching file r
525 patching file r
526 committing files:
526 committing files:
527 r
527 r
528 committing manifest
528 committing manifest
529 committing changelog
529 committing changelog
530 committed changeset 3:82a2f715724d
530 committed changeset 3:82a2f715724d
531 overwriting r expanding keywords
531 overwriting r expanding keywords
532 $ hg status r
532 $ hg status r
533 $ hg --verbose rollback
533 $ hg --verbose rollback
534 repository tip rolled back to revision 2 (undo commit)
534 repository tip rolled back to revision 2 (undo commit)
535 working directory now based on revision 2
535 working directory now based on revision 2
536 overwriting r shrinking keywords
536 overwriting r shrinking keywords
537 $ hg forget r
537 $ hg forget r
538 $ rm msg r
538 $ rm msg r
539 $ hg update -C
539 $ hg update -C
540 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
540 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
541
541
542 record added keyword ignored file
542 record added keyword ignored file
543
543
544 $ echo '$Id$' > i
544 $ echo '$Id$' > i
545 $ hg add i
545 $ hg add i
546 $ hg --verbose record -d '13 1' -m recignored<<EOF
546 $ hg --verbose record -d '13 1' -m recignored<<EOF
547 > y
547 > y
548 > y
548 > y
549 > EOF
549 > EOF
550 diff --git a/i b/i
550 diff --git a/i b/i
551 new file mode 100644
551 new file mode 100644
552 examine changes to 'i'? [Ynesfdaq?] y
552 examine changes to 'i'? [Ynesfdaq?] y
553
553
554 @@ -0,0 +1,1 @@
554 @@ -0,0 +1,1 @@
555 +$Id$
555 +$Id$
556 record this change to 'i'? [Ynesfdaq?] y
556 record this change to 'i'? [Ynesfdaq?] y
557
557
558 resolving manifests
558 resolving manifests
559 patching file i
559 patching file i
560 committing files:
560 committing files:
561 i
561 i
562 committing manifest
562 committing manifest
563 committing changelog
563 committing changelog
564 committed changeset 3:9f40ceb5a072
564 committed changeset 3:9f40ceb5a072
565 $ cat i
565 $ cat i
566 $Id$
566 $Id$
567 $ hg -q rollback
567 $ hg -q rollback
568 $ hg forget i
568 $ hg forget i
569 $ rm i
569 $ rm i
570
570
571 amend
571 amend
572
572
573 $ echo amend >> a
573 $ echo amend >> a
574 $ echo amend >> b
574 $ echo amend >> b
575 $ hg -q commit -d '14 1' -m 'prepare amend'
575 $ hg -q commit -d '14 1' -m 'prepare amend'
576
576
577 $ hg --debug commit --amend -d '15 1' -m 'amend without changes' | grep keywords
577 $ hg --debug commit --amend -d '15 1' -m 'amend without changes' | grep keywords
578 overwriting a expanding keywords
578 overwriting a expanding keywords
579 $ hg -q id
579 $ hg -q id
580 67d8c481a6be
580 67d8c481a6be
581 $ head -1 a
581 $ head -1 a
582 expand $Id: a,v 67d8c481a6be 1970/01/01 00:00:15 test $
582 expand $Id: a,v 67d8c481a6be 1970/01/01 00:00:15 test $
583
583
584 $ hg -q strip --no-backup tip
584 $ hg -q strip --no-backup tip
585
585
586 Test patch queue repo
586 Test patch queue repo
587
587
588 $ hg init --mq
588 $ hg init --mq
589 $ hg qimport -r tip -n mqtest.diff
589 $ hg qimport -r tip -n mqtest.diff
590 $ hg commit --mq -m mqtest
590 $ hg commit --mq -m mqtest
591
591
592 Keywords should not be expanded in patch
592 Keywords should not be expanded in patch
593
593
594 $ cat .hg/patches/mqtest.diff
594 $ cat .hg/patches/mqtest.diff
595 # HG changeset patch
595 # HG changeset patch
596 # User User Name <user@example.com>
596 # User User Name <user@example.com>
597 # Date 1 0
597 # Date 1 0
598 # Thu Jan 01 00:00:01 1970 +0000
598 # Thu Jan 01 00:00:01 1970 +0000
599 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
599 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
600 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
600 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
601 cndiff
601 cndiff
602
602
603 diff -r ef63ca68695b -r 40a904bbbe4c c
603 diff -r ef63ca68695b -r 40a904bbbe4c c
604 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
604 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
605 +++ b/c Thu Jan 01 00:00:01 1970 +0000
605 +++ b/c Thu Jan 01 00:00:01 1970 +0000
606 @@ -0,0 +1,2 @@
606 @@ -0,0 +1,2 @@
607 +$Id$
607 +$Id$
608 +tests for different changenodes
608 +tests for different changenodes
609
609
610 $ hg qpop
610 $ hg qpop
611 popping mqtest.diff
611 popping mqtest.diff
612 patch queue now empty
612 patch queue now empty
613
613
614 qgoto, implying qpush, should expand
614 qgoto, implying qpush, should expand
615
615
616 $ hg qgoto mqtest.diff
616 $ hg qgoto mqtest.diff
617 applying mqtest.diff
617 applying mqtest.diff
618 now at: mqtest.diff
618 now at: mqtest.diff
619 $ cat c
619 $ cat c
620 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
620 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
621 tests for different changenodes
621 tests for different changenodes
622 $ hg cat c
622 $ hg cat c
623 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
623 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
624 tests for different changenodes
624 tests for different changenodes
625
625
626 Keywords should not be expanded in filelog
626 Keywords should not be expanded in filelog
627
627
628 $ hg --config 'extensions.keyword=!' cat c
628 $ hg --config 'extensions.keyword=!' cat c
629 $Id$
629 $Id$
630 tests for different changenodes
630 tests for different changenodes
631
631
632 qpop and move on
632 qpop and move on
633
633
634 $ hg qpop
634 $ hg qpop
635 popping mqtest.diff
635 popping mqtest.diff
636 patch queue now empty
636 patch queue now empty
637
637
638 Copy and show added kwfiles
638 Copy and show added kwfiles
639
639
640 $ hg cp a c
640 $ hg cp a c
641 $ hg kwfiles
641 $ hg kwfiles
642 a
642 a
643 c
643 c
644
644
645 Commit and show expansion in original and copy
645 Commit and show expansion in original and copy
646
646
647 $ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
647 $ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
648 committing files:
648 committing files:
649 c
649 c
650 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
650 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
651 committing manifest
651 committing manifest
652 committing changelog
652 committing changelog
653 overwriting c expanding keywords
653 overwriting c expanding keywords
654 updating the branch cache
654 updating the branch cache
655 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
655 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
656 $ cat a c
656 $ cat a c
657 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
657 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
658 do not process $Id:
658 do not process $Id:
659 xxx $
659 xxx $
660 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
660 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
661 do not process $Id:
661 do not process $Id:
662 xxx $
662 xxx $
663
663
664 Touch copied c and check its status
664 Touch copied c and check its status
665
665
666 $ touch c
666 $ touch c
667 $ hg status
667 $ hg status
668
668
669 Copy kwfile to keyword ignored file unexpanding keywords
669 Copy kwfile to keyword ignored file unexpanding keywords
670
670
671 $ hg --verbose copy a i
671 $ hg --verbose copy a i
672 copying a to i
672 copying a to i
673 overwriting i shrinking keywords
673 overwriting i shrinking keywords
674 $ head -n 1 i
674 $ head -n 1 i
675 expand $Id$
675 expand $Id$
676 $ hg forget i
676 $ hg forget i
677 $ rm i
677 $ rm i
678
678
679 Copy ignored file to ignored file: no overwriting
679 Copy ignored file to ignored file: no overwriting
680
680
681 $ hg --verbose copy b i
681 $ hg --verbose copy b i
682 copying b to i
682 copying b to i
683 $ hg forget i
683 $ hg forget i
684 $ rm i
684 $ rm i
685
685
686 cp symlink file; hg cp -A symlink file (part1)
686 cp symlink file; hg cp -A symlink file (part1)
687 - copied symlink points to kwfile: overwrite
687 - copied symlink points to kwfile: overwrite
688
688
689 #if symlink
689 #if symlink
690 $ cp sym i
690 $ cp sym i
691 $ ls -l i
691 $ ls -l i
692 -rw-r--r--* (glob)
692 -rw-r--r--* (glob)
693 $ head -1 i
693 $ head -1 i
694 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
694 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
695 $ hg copy --after --verbose sym i
695 $ hg copy --after --verbose sym i
696 copying sym to i
696 copying sym to i
697 overwriting i shrinking keywords
697 overwriting i shrinking keywords
698 $ head -1 i
698 $ head -1 i
699 expand $Id$
699 expand $Id$
700 $ hg forget i
700 $ hg forget i
701 $ rm i
701 $ rm i
702 #endif
702 #endif
703
703
704 Test different options of hg kwfiles
704 Test different options of hg kwfiles
705
705
706 $ hg kwfiles
706 $ hg kwfiles
707 a
707 a
708 c
708 c
709 $ hg -v kwfiles --ignore
709 $ hg -v kwfiles --ignore
710 I b
710 I b
711 I sym
711 I sym
712 $ hg kwfiles --all
712 $ hg kwfiles --all
713 K a
713 K a
714 K c
714 K c
715 I b
715 I b
716 I sym
716 I sym
717
717
718 Diff specific revision
718 Diff specific revision
719
719
720 $ hg diff --rev 1
720 $ hg diff --rev 1
721 diff -r ef63ca68695b c
721 diff -r ef63ca68695b c
722 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
722 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
723 +++ b/c * (glob)
723 +++ b/c * (glob)
724 @@ -0,0 +1,3 @@
724 @@ -0,0 +1,3 @@
725 +expand $Id$
725 +expand $Id$
726 +do not process $Id:
726 +do not process $Id:
727 +xxx $
727 +xxx $
728
728
729 Status after rollback:
729 Status after rollback:
730
730
731 $ hg rollback
731 $ hg rollback
732 repository tip rolled back to revision 1 (undo commit)
732 repository tip rolled back to revision 1 (undo commit)
733 working directory now based on revision 1
733 working directory now based on revision 1
734 $ hg status
734 $ hg status
735 A c
735 A c
736 $ hg update --clean
736 $ hg update --clean
737 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
737 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
738
738
739 #if symlink
739 #if symlink
740
740
741 cp symlink file; hg cp -A symlink file (part2)
741 cp symlink file; hg cp -A symlink file (part2)
742 - copied symlink points to kw ignored file: do not overwrite
742 - copied symlink points to kw ignored file: do not overwrite
743
743
744 $ cat a > i
744 $ cat a > i
745 $ ln -s i symignored
745 $ ln -s i symignored
746 $ hg commit -Am 'fake expansion in ignored and symlink' i symignored
746 $ hg commit -Am 'fake expansion in ignored and symlink' i symignored
747 $ cp symignored x
747 $ cp symignored x
748 $ hg copy --after --verbose symignored x
748 $ hg copy --after --verbose symignored x
749 copying symignored to x
749 copying symignored to x
750 $ head -n 1 x
750 $ head -n 1 x
751 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
751 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
752 $ hg forget x
752 $ hg forget x
753 $ rm x
753 $ rm x
754
754
755 $ hg rollback
755 $ hg rollback
756 repository tip rolled back to revision 1 (undo commit)
756 repository tip rolled back to revision 1 (undo commit)
757 working directory now based on revision 1
757 working directory now based on revision 1
758 $ hg update --clean
758 $ hg update --clean
759 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
759 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
760 $ rm i symignored
760 $ rm i symignored
761
761
762 #endif
762 #endif
763
763
764 Custom keywordmaps as argument to kwdemo
764 Custom keywordmaps as argument to kwdemo
765
765
766 $ hg --quiet kwdemo "Xinfo = {author}: {desc}"
766 $ hg --quiet kwdemo "Xinfo = {author}: {desc}"
767 [extensions]
767 [extensions]
768 keyword =
768 keyword =
769 [keyword]
769 [keyword]
770 ** =
770 ** =
771 b = ignore
771 b = ignore
772 demo.txt =
772 demo.txt =
773 i = ignore
773 i = ignore
774 [keywordset]
774 [keywordset]
775 svn = False
775 svn = False
776 [keywordmaps]
776 [keywordmaps]
777 Xinfo = {author}: {desc}
777 Xinfo = {author}: {desc}
778 $Xinfo: test: hg keyword configuration and expansion example $
778 $Xinfo: test: hg keyword configuration and expansion example $
779
779
780 Configure custom keywordmaps
780 Configure custom keywordmaps
781
781
782 $ cat <<EOF >>$HGRCPATH
782 $ cat <<EOF >>$HGRCPATH
783 > [keywordmaps]
783 > [keywordmaps]
784 > Id = {file} {node|short} {date|rfc822date} {author|user}
784 > Id = {file} {node|short} {date|rfc822date} {author|user}
785 > Xinfo = {author}: {desc}
785 > Xinfo = {author}: {desc}
786 > EOF
786 > EOF
787
787
788 Cat and hg cat files before custom expansion
788 Cat and hg cat files before custom expansion
789
789
790 $ cat a b
790 $ cat a b
791 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
791 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
792 do not process $Id:
792 do not process $Id:
793 xxx $
793 xxx $
794 ignore $Id$
794 ignore $Id$
795 $ hg cat sym a b && echo
795 $ hg cat sym a b && echo
796 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
796 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
797 do not process $Id:
797 do not process $Id:
798 xxx $
798 xxx $
799 ignore $Id$
799 ignore $Id$
800 a
800 a
801
801
802 Write custom keyword and prepare multi-line commit message
802 Write custom keyword and prepare multi-line commit message
803
803
804 $ echo '$Xinfo$' >> a
804 $ echo '$Xinfo$' >> a
805 $ cat <<EOF >> log
805 $ cat <<EOF >> log
806 > firstline
806 > firstline
807 > secondline
807 > secondline
808 > EOF
808 > EOF
809
809
810 Interrupted commit should not change state
810 Interrupted commit should not change state
811
811
812 $ hg commit
812 $ hg commit
813 abort: empty commit message
813 abort: empty commit message
814 [255]
814 [255]
815 $ hg status
815 $ hg status
816 M a
816 M a
817 ? c
817 ? c
818 ? log
818 ? log
819
819
820 Commit with multi-line message and custom expansion
820 Commit with multi-line message and custom expansion
821
821
822 $ hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
822 $ hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
823 committing files:
823 committing files:
824 a
824 a
825 committing manifest
825 committing manifest
826 committing changelog
826 committing changelog
827 overwriting a expanding keywords
827 overwriting a expanding keywords
828 updating the branch cache
828 updating the branch cache
829 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
829 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
830 $ rm log
830 $ rm log
831
831
832 Stat, verify and show custom expansion (firstline)
832 Stat, verify and show custom expansion (firstline)
833
833
834 $ hg status
834 $ hg status
835 ? c
835 ? c
836 $ hg verify
836 $ hg verify
837 checking changesets
837 checking changesets
838 checking manifests
838 checking manifests
839 crosschecking files in changesets and manifests
839 crosschecking files in changesets and manifests
840 checking files
840 checking files
841 3 files, 3 changesets, 4 total revisions
841 3 files, 3 changesets, 4 total revisions
842 $ cat a b
842 $ cat a b
843 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
843 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
844 do not process $Id:
844 do not process $Id:
845 xxx $
845 xxx $
846 $Xinfo: User Name <user@example.com>: firstline $
846 $Xinfo: User Name <user@example.com>: firstline $
847 ignore $Id$
847 ignore $Id$
848 $ hg cat sym a b && echo
848 $ hg cat sym a b && echo
849 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
849 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
850 do not process $Id:
850 do not process $Id:
851 xxx $
851 xxx $
852 $Xinfo: User Name <user@example.com>: firstline $
852 $Xinfo: User Name <user@example.com>: firstline $
853 ignore $Id$
853 ignore $Id$
854 a
854 a
855
855
856 annotate
856 annotate
857
857
858 $ hg annotate a
858 $ hg annotate a
859 1: expand $Id$
859 1: expand $Id$
860 1: do not process $Id:
860 1: do not process $Id:
861 1: xxx $
861 1: xxx $
862 2: $Xinfo$
862 2: $Xinfo$
863
863
864 remove with status checks
864 remove with status checks
865
865
866 $ hg debugrebuildstate
866 $ hg debugrebuildstate
867 $ hg remove a
867 $ hg remove a
868 $ hg --debug commit -m rma
868 $ hg --debug commit -m rma
869 committing files:
869 committing files:
870 committing manifest
870 committing manifest
871 committing changelog
871 committing changelog
872 updating the branch cache
872 updating the branch cache
873 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
873 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
874 $ hg status
874 $ hg status
875 ? c
875 ? c
876
876
877 Rollback, revert, and check expansion
877 Rollback, revert, and check expansion
878
878
879 $ hg rollback
879 $ hg rollback
880 repository tip rolled back to revision 2 (undo commit)
880 repository tip rolled back to revision 2 (undo commit)
881 working directory now based on revision 2
881 working directory now based on revision 2
882 $ hg status
882 $ hg status
883 R a
883 R a
884 ? c
884 ? c
885 $ hg revert --no-backup --rev tip a
885 $ hg revert --no-backup --rev tip a
886 $ cat a
886 $ cat a
887 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
887 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
888 do not process $Id:
888 do not process $Id:
889 xxx $
889 xxx $
890 $Xinfo: User Name <user@example.com>: firstline $
890 $Xinfo: User Name <user@example.com>: firstline $
891
891
892 Clone to test global and local configurations
892 Clone to test global and local configurations
893
893
894 $ cd ..
894 $ cd ..
895
895
896 Expansion in destination with global configuration
896 Expansion in destination with global configuration
897
897
898 $ hg --quiet clone Test globalconf
898 $ hg --quiet clone Test globalconf
899 $ cat globalconf/a
899 $ cat globalconf/a
900 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
900 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
901 do not process $Id:
901 do not process $Id:
902 xxx $
902 xxx $
903 $Xinfo: User Name <user@example.com>: firstline $
903 $Xinfo: User Name <user@example.com>: firstline $
904
904
905 No expansion in destination with local configuration in origin only
905 No expansion in destination with local configuration in origin only
906
906
907 $ hg --quiet --config 'keyword.**=ignore' clone Test localconf
907 $ hg --quiet --config 'keyword.**=ignore' clone Test localconf
908 $ cat localconf/a
908 $ cat localconf/a
909 expand $Id$
909 expand $Id$
910 do not process $Id:
910 do not process $Id:
911 xxx $
911 xxx $
912 $Xinfo$
912 $Xinfo$
913
913
914 Clone to test incoming
914 Clone to test incoming
915
915
916 $ hg clone -r1 Test Test-a
916 $ hg clone -r1 Test Test-a
917 adding changesets
917 adding changesets
918 adding manifests
918 adding manifests
919 adding file changes
919 adding file changes
920 added 2 changesets with 3 changes to 3 files
920 added 2 changesets with 3 changes to 3 files
921 updating to branch default
921 updating to branch default
922 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
922 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
923 $ cd Test-a
923 $ cd Test-a
924 $ cat <<EOF >> .hg/hgrc
924 $ cat <<EOF >> .hg/hgrc
925 > [paths]
925 > [paths]
926 > default = ../Test
926 > default = ../Test
927 > EOF
927 > EOF
928 $ hg incoming
928 $ hg incoming
929 comparing with $TESTTMP/Test (glob)
929 comparing with $TESTTMP/Test (glob)
930 searching for changes
930 searching for changes
931 changeset: 2:bb948857c743
931 changeset: 2:bb948857c743
932 tag: tip
932 tag: tip
933 user: User Name <user@example.com>
933 user: User Name <user@example.com>
934 date: Thu Jan 01 00:00:02 1970 +0000
934 date: Thu Jan 01 00:00:02 1970 +0000
935 summary: firstline
935 summary: firstline
936
936
937 Imported patch should not be rejected
937 Imported patch should not be rejected
938
938
939 >>> import re
939 >>> import re
940 >>> text = re.sub(r'(Id.*)', r'\1 rejecttest', open('a').read())
940 >>> text = re.sub(r'(Id.*)', r'\1 rejecttest', open('a').read())
941 >>> open('a', 'wb').write(text)
941 >>> open('a', 'wb').write(text)
942 $ hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
942 $ hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
943 committing files:
943 committing files:
944 a
944 a
945 committing manifest
945 committing manifest
946 committing changelog
946 committing changelog
947 overwriting a expanding keywords
947 overwriting a expanding keywords
948 updating the branch cache
948 updating the branch cache
949 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
949 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
950 $ hg export -o ../rejecttest.diff tip
950 $ hg export -o ../rejecttest.diff tip
951 $ cd ../Test
951 $ cd ../Test
952 $ hg import ../rejecttest.diff
952 $ hg import ../rejecttest.diff
953 applying ../rejecttest.diff
953 applying ../rejecttest.diff
954 $ cat a b
954 $ cat a b
955 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
955 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
956 do not process $Id: rejecttest
956 do not process $Id: rejecttest
957 xxx $
957 xxx $
958 $Xinfo: User Name <user@example.com>: rejects? $
958 $Xinfo: User Name <user@example.com>: rejects? $
959 ignore $Id$
959 ignore $Id$
960
960
961 $ hg rollback
961 $ hg rollback
962 repository tip rolled back to revision 2 (undo import)
962 repository tip rolled back to revision 2 (undo import)
963 working directory now based on revision 2
963 working directory now based on revision 2
964 $ hg update --clean
964 $ hg update --clean
965 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
965 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
966
966
967 kwexpand/kwshrink on selected files
967 kwexpand/kwshrink on selected files
968
968
969 $ mkdir x
969 $ mkdir x
970 $ hg copy a x/a
970 $ hg copy a x/a
971 $ hg --verbose kwshrink a
971 $ hg --verbose kwshrink a
972 overwriting a shrinking keywords
972 overwriting a shrinking keywords
973 - sleep required for dirstate.normal() check
973 - sleep required for dirstate.normal() check
974 $ sleep 1
974 $ sleep 1
975 $ hg status a
975 $ hg status a
976 $ hg --verbose kwexpand a
976 $ hg --verbose kwexpand a
977 overwriting a expanding keywords
977 overwriting a expanding keywords
978 $ hg status a
978 $ hg status a
979
979
980 kwexpand x/a should abort
980 kwexpand x/a should abort
981
981
982 $ hg --verbose kwexpand x/a
982 $ hg --verbose kwexpand x/a
983 abort: outstanding uncommitted changes
983 abort: outstanding uncommitted changes
984 [255]
984 [255]
985 $ cd x
985 $ cd x
986 $ hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
986 $ hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
987 committing files:
987 committing files:
988 x/a
988 x/a
989 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
989 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
990 committing manifest
990 committing manifest
991 committing changelog
991 committing changelog
992 overwriting x/a expanding keywords
992 overwriting x/a expanding keywords
993 updating the branch cache
993 updating the branch cache
994 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
994 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
995 $ cat a
995 $ cat a
996 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
996 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
997 do not process $Id:
997 do not process $Id:
998 xxx $
998 xxx $
999 $Xinfo: User Name <user@example.com>: xa $
999 $Xinfo: User Name <user@example.com>: xa $
1000
1000
1001 kwshrink a inside directory x
1001 kwshrink a inside directory x
1002
1002
1003 $ hg --verbose kwshrink a
1003 $ hg --verbose kwshrink a
1004 overwriting x/a shrinking keywords
1004 overwriting x/a shrinking keywords
1005 $ cat a
1005 $ cat a
1006 expand $Id$
1006 expand $Id$
1007 do not process $Id:
1007 do not process $Id:
1008 xxx $
1008 xxx $
1009 $Xinfo$
1009 $Xinfo$
1010 $ cd ..
1010 $ cd ..
1011
1011
1012 kwexpand nonexistent
1012 kwexpand nonexistent
1013
1013
1014 $ hg kwexpand nonexistent
1014 $ hg kwexpand nonexistent
1015 nonexistent:* (glob)
1015 nonexistent:* (glob)
1016
1016
1017
1017
1018 #if serve
1018 #if serve
1019 hg serve
1019 hg serve
1020 - expand with hgweb file
1020 - expand with hgweb file
1021 - no expansion with hgweb annotate/changeset/filediff
1021 - no expansion with hgweb annotate/changeset/filediff
1022 - check errors
1022 - check errors
1023
1023
1024 $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1024 $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1025 $ cat hg.pid >> $DAEMON_PIDS
1025 $ cat hg.pid >> $DAEMON_PIDS
1026 $ get-with-headers.py localhost:$HGPORT 'file/tip/a/?style=raw'
1026 $ get-with-headers.py localhost:$HGPORT 'file/tip/a/?style=raw'
1027 200 Script output follows
1027 200 Script output follows
1028
1028
1029 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
1029 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
1030 do not process $Id:
1030 do not process $Id:
1031 xxx $
1031 xxx $
1032 $Xinfo: User Name <user@example.com>: firstline $
1032 $Xinfo: User Name <user@example.com>: firstline $
1033 $ get-with-headers.py localhost:$HGPORT 'annotate/tip/a/?style=raw'
1033 $ get-with-headers.py localhost:$HGPORT 'annotate/tip/a/?style=raw'
1034 200 Script output follows
1034 200 Script output follows
1035
1035
1036
1036
1037 user@1: expand $Id$
1037 user@1: expand $Id$
1038 user@1: do not process $Id:
1038 user@1: do not process $Id:
1039 user@1: xxx $
1039 user@1: xxx $
1040 user@2: $Xinfo$
1040 user@2: $Xinfo$
1041
1041
1042
1042
1043
1043
1044
1044
1045 $ get-with-headers.py localhost:$HGPORT 'rev/tip/?style=raw'
1045 $ get-with-headers.py localhost:$HGPORT 'rev/tip/?style=raw'
1046 200 Script output follows
1046 200 Script output follows
1047
1047
1048
1048
1049 # HG changeset patch
1049 # HG changeset patch
1050 # User User Name <user@example.com>
1050 # User User Name <user@example.com>
1051 # Date 3 0
1051 # Date 3 0
1052 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
1052 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
1053 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
1053 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
1054 xa
1054 xa
1055
1055
1056 diff -r bb948857c743 -r b4560182a3f9 x/a
1056 diff -r bb948857c743 -r b4560182a3f9 x/a
1057 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1057 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1058 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
1058 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
1059 @@ -0,0 +1,4 @@
1059 @@ -0,0 +1,4 @@
1060 +expand $Id$
1060 +expand $Id$
1061 +do not process $Id:
1061 +do not process $Id:
1062 +xxx $
1062 +xxx $
1063 +$Xinfo$
1063 +$Xinfo$
1064
1064
1065 $ get-with-headers.py localhost:$HGPORT 'diff/bb948857c743/a?style=raw'
1065 $ get-with-headers.py localhost:$HGPORT 'diff/bb948857c743/a?style=raw'
1066 200 Script output follows
1066 200 Script output follows
1067
1067
1068
1068
1069 diff -r ef63ca68695b -r bb948857c743 a
1069 diff -r ef63ca68695b -r bb948857c743 a
1070 --- a/a Thu Jan 01 00:00:00 1970 +0000
1070 --- a/a Thu Jan 01 00:00:00 1970 +0000
1071 +++ b/a Thu Jan 01 00:00:02 1970 +0000
1071 +++ b/a Thu Jan 01 00:00:02 1970 +0000
1072 @@ -1,3 +1,4 @@
1072 @@ -1,3 +1,4 @@
1073 expand $Id$
1073 expand $Id$
1074 do not process $Id:
1074 do not process $Id:
1075 xxx $
1075 xxx $
1076 +$Xinfo$
1076 +$Xinfo$
1077
1077
1078
1078
1079
1079
1080
1080
1081 $ cat errors.log
1081 $ cat errors.log
1082 #endif
1082 #endif
1083
1083
1084 Prepare merge and resolve tests
1084 Prepare merge and resolve tests
1085
1085
1086 $ echo '$Id$' > m
1086 $ echo '$Id$' > m
1087 $ hg add m
1087 $ hg add m
1088 $ hg commit -m 4kw
1088 $ hg commit -m 4kw
1089 $ echo foo >> m
1089 $ echo foo >> m
1090 $ hg commit -m 5foo
1090 $ hg commit -m 5foo
1091
1091
1092 simplemerge
1092 simplemerge
1093
1093
1094 $ hg update 4
1094 $ hg update 4
1095 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1095 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1096 $ echo foo >> m
1096 $ echo foo >> m
1097 $ hg commit -m 6foo
1097 $ hg commit -m 6foo
1098 created new head
1098 created new head
1099 $ hg merge
1099 $ hg merge
1100 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1100 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1101 (branch merge, don't forget to commit)
1101 (branch merge, don't forget to commit)
1102 $ hg commit -m simplemerge
1102 $ hg commit -m simplemerge
1103 $ cat m
1103 $ cat m
1104 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
1104 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
1105 foo
1105 foo
1106
1106
1107 conflict: keyword should stay outside conflict zone
1107 conflict: keyword should stay outside conflict zone
1108
1108
1109 $ hg update 4
1109 $ hg update 4
1110 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1110 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1111 $ echo bar >> m
1111 $ echo bar >> m
1112 $ hg commit -m 8bar
1112 $ hg commit -m 8bar
1113 created new head
1113 created new head
1114 $ hg merge
1114 $ hg merge
1115 merging m
1115 merging m
1116 warning: conflicts while merging m! (edit, then use 'hg resolve --mark')
1116 warning: conflicts while merging m! (edit, then use 'hg resolve --mark')
1117 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1117 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1118 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1118 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1119 [1]
1119 [1]
1120 $ cat m
1120 $ cat m
1121 $Id$
1121 $Id$
1122 <<<<<<< working copy: 88a80c8d172e - test: 8bar
1122 <<<<<<< working copy: 88a80c8d172e - test: 8bar
1123 bar
1123 bar
1124 =======
1124 =======
1125 foo
1125 foo
1126 >>>>>>> merge rev: 85d2d2d732a5 - test: simplemerge
1126 >>>>>>> merge rev: 85d2d2d732a5 - test: simplemerge
1127
1127
1128 resolve to local, m must contain hash of last change (local parent)
1128 resolve to local, m must contain hash of last change (local parent)
1129
1129
1130 $ hg resolve -t internal:local -a
1130 $ hg resolve -t internal:local -a
1131 (no more unresolved files)
1131 (no more unresolved files)
1132 $ hg commit -m localresolve
1132 $ hg commit -m localresolve
1133 $ cat m
1133 $ cat m
1134 $Id: m 88a80c8d172e Thu, 01 Jan 1970 00:00:00 +0000 test $
1134 $Id: m 88a80c8d172e Thu, 01 Jan 1970 00:00:00 +0000 test $
1135 bar
1135 bar
1136
1136
1137 Test restricted mode with transplant -b
1137 Test restricted mode with transplant -b
1138
1138
1139 $ hg update 6
1139 $ hg update 6
1140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1141 $ hg branch foo
1141 $ hg branch foo
1142 marked working directory as branch foo
1142 marked working directory as branch foo
1143 (branches are permanent and global, did you want a bookmark?)
1143 (branches are permanent and global, did you want a bookmark?)
1144 $ mv a a.bak
1144 $ mv a a.bak
1145 $ echo foobranch > a
1145 $ echo foobranch > a
1146 $ cat a.bak >> a
1146 $ cat a.bak >> a
1147 $ rm a.bak
1147 $ rm a.bak
1148 $ hg commit -m 9foobranch
1148 $ hg commit -m 9foobranch
1149 $ hg update default
1149 $ hg update default
1150 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1150 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1151 $ hg -y transplant -b foo tip
1151 $ hg -y transplant -b foo tip
1152 applying 4aa30d025d50
1152 applying 4aa30d025d50
1153 4aa30d025d50 transplanted to e00abbf63521
1153 4aa30d025d50 transplanted to e00abbf63521
1154
1154
1155 Expansion in changeset but not in file
1155 Expansion in changeset but not in file
1156
1156
1157 $ hg tip -p
1157 $ hg tip -p
1158 changeset: 11:e00abbf63521
1158 changeset: 11:e00abbf63521
1159 tag: tip
1159 tag: tip
1160 parent: 9:800511b3a22d
1160 parent: 9:800511b3a22d
1161 user: test
1161 user: test
1162 date: Thu Jan 01 00:00:00 1970 +0000
1162 date: Thu Jan 01 00:00:00 1970 +0000
1163 summary: 9foobranch
1163 summary: 9foobranch
1164
1164
1165 diff -r 800511b3a22d -r e00abbf63521 a
1165 diff -r 800511b3a22d -r e00abbf63521 a
1166 --- a/a Thu Jan 01 00:00:00 1970 +0000
1166 --- a/a Thu Jan 01 00:00:00 1970 +0000
1167 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1167 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1168 @@ -1,3 +1,4 @@
1168 @@ -1,3 +1,4 @@
1169 +foobranch
1169 +foobranch
1170 expand $Id$
1170 expand $Id$
1171 do not process $Id:
1171 do not process $Id:
1172 xxx $
1172 xxx $
1173
1173
1174 $ head -n 2 a
1174 $ head -n 2 a
1175 foobranch
1175 foobranch
1176 expand $Id: a e00abbf63521 Thu, 01 Jan 1970 00:00:00 +0000 test $
1176 expand $Id: a e00abbf63521 Thu, 01 Jan 1970 00:00:00 +0000 test $
1177
1177
1178 Turn off expansion
1178 Turn off expansion
1179
1179
1180 $ hg -q rollback
1180 $ hg -q rollback
1181 $ hg -q update -C
1181 $ hg -q update -C
1182
1182
1183 kwshrink with unknown file u
1183 kwshrink with unknown file u
1184
1184
1185 $ cp a u
1185 $ cp a u
1186 $ hg --verbose kwshrink
1186 $ hg --verbose kwshrink
1187 overwriting a shrinking keywords
1187 overwriting a shrinking keywords
1188 overwriting m shrinking keywords
1188 overwriting m shrinking keywords
1189 overwriting x/a shrinking keywords
1189 overwriting x/a shrinking keywords
1190
1190
1191 Keywords shrunk in working directory, but not yet disabled
1191 Keywords shrunk in working directory, but not yet disabled
1192 - cat shows unexpanded keywords
1192 - cat shows unexpanded keywords
1193 - hg cat shows expanded keywords
1193 - hg cat shows expanded keywords
1194
1194
1195 $ cat a b
1195 $ cat a b
1196 expand $Id$
1196 expand $Id$
1197 do not process $Id:
1197 do not process $Id:
1198 xxx $
1198 xxx $
1199 $Xinfo$
1199 $Xinfo$
1200 ignore $Id$
1200 ignore $Id$
1201 $ hg cat sym a b && echo
1201 $ hg cat sym a b && echo
1202 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
1202 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
1203 do not process $Id:
1203 do not process $Id:
1204 xxx $
1204 xxx $
1205 $Xinfo: User Name <user@example.com>: firstline $
1205 $Xinfo: User Name <user@example.com>: firstline $
1206 ignore $Id$
1206 ignore $Id$
1207 a
1207 a
1208
1208
1209 Now disable keyword expansion
1209 Now disable keyword expansion
1210
1210
1211 $ cp $HGRCPATH $HGRCPATH.backup
1211 $ cp $HGRCPATH $HGRCPATH.backup
1212 $ rm "$HGRCPATH"
1212 $ rm "$HGRCPATH"
1213 $ cat a b
1213 $ cat a b
1214 expand $Id$
1214 expand $Id$
1215 do not process $Id:
1215 do not process $Id:
1216 xxx $
1216 xxx $
1217 $Xinfo$
1217 $Xinfo$
1218 ignore $Id$
1218 ignore $Id$
1219 $ hg cat sym a b && echo
1219 $ hg cat sym a b && echo
1220 expand $Id$
1220 expand $Id$
1221 do not process $Id:
1221 do not process $Id:
1222 xxx $
1222 xxx $
1223 $Xinfo$
1223 $Xinfo$
1224 ignore $Id$
1224 ignore $Id$
1225 a
1225 a
1226
1226
1227 enable keyword expansion again
1227 enable keyword expansion again
1228
1228
1229 $ cat $HGRCPATH.backup >> $HGRCPATH
1229 $ cat $HGRCPATH.backup >> $HGRCPATH
1230
1230
1231 Test restricted mode with unshelve
1231 Test restricted mode with unshelve
1232
1232
1233 $ cat <<EOF >> $HGRCPATH
1233 $ cat <<EOF >> $HGRCPATH
1234 > [extensions]
1234 > [extensions]
1235 > shelve =
1235 > shelve =
1236 > EOF
1236 > EOF
1237
1237
1238 $ echo xxxx >> a
1238 $ echo xxxx >> a
1239 $ hg diff
1239 $ hg diff
1240 diff -r 800511b3a22d a
1240 diff -r 800511b3a22d a
1241 --- a/a Thu Jan 01 00:00:00 1970 +0000
1241 --- a/a Thu Jan 01 00:00:00 1970 +0000
1242 +++ b/a * (glob)
1242 +++ b/a * (glob)
1243 @@ -2,3 +2,4 @@
1243 @@ -2,3 +2,4 @@
1244 do not process $Id:
1244 do not process $Id:
1245 xxx $
1245 xxx $
1246 $Xinfo$
1246 $Xinfo$
1247 +xxxx
1247 +xxxx
1248 $ hg shelve -q --name tmp
1248 $ hg shelve -q --name tmp
1249 $ hg shelve --list --patch
1249 $ hg shelve --list --patch
1250 tmp (*)* changes to: localresolve (glob)
1250 tmp (*)* changes to: localresolve (glob)
1251
1251
1252 diff --git a/a b/a
1252 diff --git a/a b/a
1253 --- a/a
1253 --- a/a
1254 +++ b/a
1254 +++ b/a
1255 @@ -2,3 +2,4 @@
1255 @@ -2,3 +2,4 @@
1256 do not process $Id:
1256 do not process $Id:
1257 xxx $
1257 xxx $
1258 $Xinfo$
1258 $Xinfo$
1259 +xxxx
1259 +xxxx
1260
1260
1261 $ hg update -q -C 10
1261 $ hg update -q -C 10
1262 $ hg unshelve -q tmp
1262 $ hg unshelve -q tmp
1263 $ hg diff
1263 $ hg diff
1264 diff -r 4aa30d025d50 a
1264 diff -r 4aa30d025d50 a
1265 --- a/a Thu Jan 01 00:00:00 1970 +0000
1265 --- a/a Thu Jan 01 00:00:00 1970 +0000
1266 +++ b/a * (glob)
1266 +++ b/a * (glob)
1267 @@ -3,3 +3,4 @@
1267 @@ -3,3 +3,4 @@
1268 do not process $Id:
1268 do not process $Id:
1269 xxx $
1269 xxx $
1270 $Xinfo$
1270 $Xinfo$
1271 +xxxx
1271 +xxxx
1272
1272
1273 Test restricted mode with rebase
1273 Test restricted mode with rebase
1274
1274
1275 $ cat <<EOF >> $HGRCPATH
1275 $ cat <<EOF >> $HGRCPATH
1276 > [extensions]
1276 > [extensions]
1277 > rebase =
1277 > rebase =
1278 > EOF
1278 > EOF
1279
1279
1280 $ hg update -q -C 9
1280 $ hg update -q -C 9
1281
1281
1282 $ echo xxxx >> a
1282 $ echo xxxx >> a
1283 $ hg commit -m '#11'
1283 $ hg commit -m '#11'
1284 $ hg diff -c 11
1284 $ hg diff -c 11
1285 diff -r 800511b3a22d -r b07670694489 a
1285 diff -r 800511b3a22d -r b07670694489 a
1286 --- a/a Thu Jan 01 00:00:00 1970 +0000
1286 --- a/a Thu Jan 01 00:00:00 1970 +0000
1287 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1287 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1288 @@ -2,3 +2,4 @@
1288 @@ -2,3 +2,4 @@
1289 do not process $Id:
1289 do not process $Id:
1290 xxx $
1290 xxx $
1291 $Xinfo$
1291 $Xinfo$
1292 +xxxx
1292 +xxxx
1293
1293
1294 $ hg diff -c 10
1294 $ hg diff -c 10
1295 diff -r 27d48ee14f67 -r 4aa30d025d50 a
1295 diff -r 27d48ee14f67 -r 4aa30d025d50 a
1296 --- a/a Thu Jan 01 00:00:00 1970 +0000
1296 --- a/a Thu Jan 01 00:00:00 1970 +0000
1297 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1297 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1298 @@ -1,3 +1,4 @@
1298 @@ -1,3 +1,4 @@
1299 +foobranch
1299 +foobranch
1300 expand $Id$
1300 expand $Id$
1301 do not process $Id:
1301 do not process $Id:
1302 xxx $
1302 xxx $
1303
1303
1304 $ hg rebase -q -s 10 -d 11 --keep
1304 $ hg rebase -q -s 10 -d 11 --keep
1305 $ hg diff -r 9 -r 12 a
1305 $ hg diff -r 9 -r 12 a
1306 diff -r 800511b3a22d -r 1939b927726c a
1306 diff -r 800511b3a22d -r 1939b927726c a
1307 --- a/a Thu Jan 01 00:00:00 1970 +0000
1307 --- a/a Thu Jan 01 00:00:00 1970 +0000
1308 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1308 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1309 @@ -1,4 +1,6 @@
1309 @@ -1,4 +1,6 @@
1310 +foobranch
1310 +foobranch
1311 expand $Id$
1311 expand $Id$
1312 do not process $Id:
1312 do not process $Id:
1313 xxx $
1313 xxx $
1314 $Xinfo$
1314 $Xinfo$
1315 +xxxx
1315 +xxxx
1316
1316
1317 Test restricted mode with graft
1317 Test restricted mode with graft
1318
1318
1319 $ hg graft -q 10
1319 $ hg graft -q 10
1320 $ hg diff -r 9 -r 13 a
1320 $ hg diff -r 9 -r 13 a
1321 diff -r 800511b3a22d -r 01a68de1003a a
1321 diff -r 800511b3a22d -r 01a68de1003a a
1322 --- a/a Thu Jan 01 00:00:00 1970 +0000
1322 --- a/a Thu Jan 01 00:00:00 1970 +0000
1323 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1323 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1324 @@ -1,4 +1,6 @@
1324 @@ -1,4 +1,6 @@
1325 +foobranch
1325 +foobranch
1326 expand $Id$
1326 expand $Id$
1327 do not process $Id:
1327 do not process $Id:
1328 xxx $
1328 xxx $
1329 $Xinfo$
1329 $Xinfo$
1330 +xxxx
1330 +xxxx
1331
1331
1332 Test restricted mode with backout
1332 Test restricted mode with backout
1333
1333
1334 $ hg backout -q 11 --no-commit
1334 $ hg backout -q 11 --no-commit
1335 $ hg diff a
1335 $ hg diff a
1336 diff -r 01a68de1003a a
1336 diff -r 01a68de1003a a
1337 --- a/a Thu Jan 01 00:00:00 1970 +0000
1337 --- a/a Thu Jan 01 00:00:00 1970 +0000
1338 +++ b/a * (glob)
1338 +++ b/a * (glob)
1339 @@ -3,4 +3,3 @@
1339 @@ -3,4 +3,3 @@
1340 do not process $Id:
1340 do not process $Id:
1341 xxx $
1341 xxx $
1342 $Xinfo$
1342 $Xinfo$
1343 -xxxx
1343 -xxxx
1344
1344
1345 Test restricted mode with histedit
1345 Test restricted mode with histedit
1346
1346
1347 $ cat <<EOF >> $HGRCPATH
1347 $ cat <<EOF >> $HGRCPATH
1348 > [extensions]
1348 > [extensions]
1349 > histedit =
1349 > histedit =
1350 > EOF
1350 > EOF
1351
1351
1352 $ hg commit -m 'backout #11'
1352 $ hg commit -m 'backout #11'
1353 $ hg histedit -q --command - 13 <<EOF
1353 $ hg histedit -q --command - 13 <<EOF
1354 > pick 49f5f2d940c3 14 backout #11
1354 > pick 49f5f2d940c3 14 backout #11
1355 > pick 01a68de1003a 13 9foobranch
1355 > pick 01a68de1003a 13 9foobranch
1356 > EOF
1356 > EOF
1357
1357
1358 Test restricted mode with fetch (with merge)
1358 Test restricted mode with fetch (with merge)
1359
1359
1360 $ cat <<EOF >> $HGRCPATH
1360 $ cat <<EOF >> $HGRCPATH
1361 > [extensions]
1361 > [extensions]
1362 > fetch =
1362 > fetch =
1363 > EOF
1363 > EOF
1364
1364
1365 $ hg clone -q -r 9 . ../fetch-merge
1365 $ hg clone -q -r 9 . ../fetch-merge
1366 $ cd ../fetch-merge
1366 $ cd ../fetch-merge
1367 $ hg -R ../Test export 10 | hg import -q -
1367 $ hg -R ../Test export 10 | hg import -q -
1368 $ hg fetch -q -r 11
1368 $ hg fetch -q -r 11
1369 $ hg diff -r 9 a
1369 $ hg diff -r 9 a
1370 diff -r 800511b3a22d a
1370 diff -r 800511b3a22d a
1371 --- a/a Thu Jan 01 00:00:00 1970 +0000
1371 --- a/a Thu Jan 01 00:00:00 1970 +0000
1372 +++ b/a * (glob)
1372 +++ b/a * (glob)
1373 @@ -1,4 +1,6 @@
1373 @@ -1,4 +1,6 @@
1374 +foobranch
1374 +foobranch
1375 expand $Id$
1375 expand $Id$
1376 do not process $Id:
1376 do not process $Id:
1377 xxx $
1377 xxx $
1378 $Xinfo$
1378 $Xinfo$
1379 +xxxx
1379 +xxxx
1380
1380
1381 Test that patch.diff(), which is implied by "hg diff" or so, doesn't
1382 suppress expanding keywords at subsequent commands
1383
1384 #if windows
1385 $ PYTHONPATH="$TESTDIR/../contrib;$PYTHONPATH"
1386 #else
1387 $ PYTHONPATH="$TESTDIR/../contrib:$PYTHONPATH"
1388 #endif
1389 $ export PYTHONPATH
1390
1391 $ grep -v '^promptecho ' < $HGRCPATH >> $HGRCPATH.new
1392 $ mv $HGRCPATH.new $HGRCPATH
1393
1394 >>> from __future__ import print_function
1395 >>> from hgclient import readchannel, runcommand, check
1396 >>> @check
1397 ... def check(server):
1398 ... # hello block
1399 ... readchannel(server)
1400 ...
1401 ... runcommand(server, ['cat', 'm'])
1402 ... runcommand(server, ['diff', '-c', '.', 'm'])
1403 ... runcommand(server, ['cat', 'm'])
1404 *** runcommand cat m
1405 $Id: m 800511b3a22d Thu, 01 Jan 1970 00:00:00 +0000 test $
1406 bar
1407 *** runcommand diff -c . m
1408 *** runcommand cat m
1409 $Id: m 800511b3a22d Thu, 01 Jan 1970 00:00:00 +0000 test $
1410 bar
1411
1381 $ cd ..
1412 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now