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