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