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