##// END OF EJS Templates
subrepo: rewrite handling of subrepo state at commit (issue2403)...
Matt Mackall -
r16073:b254f827 default
parent child Browse files
Show More
@@ -1,2310 +1,2330 b''
1 # localrepo.py - read/write repository class for mercurial
1 # localrepo.py - read/write repository class for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
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 from node import bin, hex, nullid, nullrev, short
8 from node import bin, hex, nullid, nullrev, short
9 from i18n import _
9 from i18n import _
10 import repo, changegroup, subrepo, discovery, pushkey
10 import repo, changegroup, subrepo, discovery, pushkey
11 import changelog, dirstate, filelog, manifest, context, bookmarks, phases
11 import changelog, dirstate, filelog, manifest, context, bookmarks, phases
12 import lock, transaction, store, encoding
12 import lock, transaction, store, encoding
13 import scmutil, util, extensions, hook, error, revset
13 import scmutil, util, extensions, hook, error, revset
14 import match as matchmod
14 import match as matchmod
15 import merge as mergemod
15 import merge as mergemod
16 import tags as tagsmod
16 import tags as tagsmod
17 from lock import release
17 from lock import release
18 import weakref, errno, os, time, inspect
18 import weakref, errno, os, time, inspect
19 propertycache = util.propertycache
19 propertycache = util.propertycache
20 filecache = scmutil.filecache
20 filecache = scmutil.filecache
21
21
22 class localrepository(repo.repository):
22 class localrepository(repo.repository):
23 capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey',
23 capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey',
24 'known', 'getbundle'))
24 'known', 'getbundle'))
25 supportedformats = set(('revlogv1', 'generaldelta'))
25 supportedformats = set(('revlogv1', 'generaldelta'))
26 supported = supportedformats | set(('store', 'fncache', 'shared',
26 supported = supportedformats | set(('store', 'fncache', 'shared',
27 'dotencode'))
27 'dotencode'))
28
28
29 def __init__(self, baseui, path=None, create=False):
29 def __init__(self, baseui, path=None, create=False):
30 repo.repository.__init__(self)
30 repo.repository.__init__(self)
31 self.root = os.path.realpath(util.expandpath(path))
31 self.root = os.path.realpath(util.expandpath(path))
32 self.path = os.path.join(self.root, ".hg")
32 self.path = os.path.join(self.root, ".hg")
33 self.origroot = path
33 self.origroot = path
34 self.auditor = scmutil.pathauditor(self.root, self._checknested)
34 self.auditor = scmutil.pathauditor(self.root, self._checknested)
35 self.opener = scmutil.opener(self.path)
35 self.opener = scmutil.opener(self.path)
36 self.wopener = scmutil.opener(self.root)
36 self.wopener = scmutil.opener(self.root)
37 self.baseui = baseui
37 self.baseui = baseui
38 self.ui = baseui.copy()
38 self.ui = baseui.copy()
39 self._dirtyphases = False
39 self._dirtyphases = False
40 # A list of callback to shape the phase if no data were found.
40 # A list of callback to shape the phase if no data were found.
41 # Callback are in the form: func(repo, roots) --> processed root.
41 # Callback are in the form: func(repo, roots) --> processed root.
42 # This list it to be filled by extension during repo setup
42 # This list it to be filled by extension during repo setup
43 self._phasedefaults = []
43 self._phasedefaults = []
44
44
45 try:
45 try:
46 self.ui.readconfig(self.join("hgrc"), self.root)
46 self.ui.readconfig(self.join("hgrc"), self.root)
47 extensions.loadall(self.ui)
47 extensions.loadall(self.ui)
48 except IOError:
48 except IOError:
49 pass
49 pass
50
50
51 if not os.path.isdir(self.path):
51 if not os.path.isdir(self.path):
52 if create:
52 if create:
53 if not os.path.exists(path):
53 if not os.path.exists(path):
54 util.makedirs(path)
54 util.makedirs(path)
55 util.makedir(self.path, notindexed=True)
55 util.makedir(self.path, notindexed=True)
56 requirements = ["revlogv1"]
56 requirements = ["revlogv1"]
57 if self.ui.configbool('format', 'usestore', True):
57 if self.ui.configbool('format', 'usestore', True):
58 os.mkdir(os.path.join(self.path, "store"))
58 os.mkdir(os.path.join(self.path, "store"))
59 requirements.append("store")
59 requirements.append("store")
60 if self.ui.configbool('format', 'usefncache', True):
60 if self.ui.configbool('format', 'usefncache', True):
61 requirements.append("fncache")
61 requirements.append("fncache")
62 if self.ui.configbool('format', 'dotencode', True):
62 if self.ui.configbool('format', 'dotencode', True):
63 requirements.append('dotencode')
63 requirements.append('dotencode')
64 # create an invalid changelog
64 # create an invalid changelog
65 self.opener.append(
65 self.opener.append(
66 "00changelog.i",
66 "00changelog.i",
67 '\0\0\0\2' # represents revlogv2
67 '\0\0\0\2' # represents revlogv2
68 ' dummy changelog to prevent using the old repo layout'
68 ' dummy changelog to prevent using the old repo layout'
69 )
69 )
70 if self.ui.configbool('format', 'generaldelta', False):
70 if self.ui.configbool('format', 'generaldelta', False):
71 requirements.append("generaldelta")
71 requirements.append("generaldelta")
72 requirements = set(requirements)
72 requirements = set(requirements)
73 else:
73 else:
74 raise error.RepoError(_("repository %s not found") % path)
74 raise error.RepoError(_("repository %s not found") % path)
75 elif create:
75 elif create:
76 raise error.RepoError(_("repository %s already exists") % path)
76 raise error.RepoError(_("repository %s already exists") % path)
77 else:
77 else:
78 try:
78 try:
79 requirements = scmutil.readrequires(self.opener, self.supported)
79 requirements = scmutil.readrequires(self.opener, self.supported)
80 except IOError, inst:
80 except IOError, inst:
81 if inst.errno != errno.ENOENT:
81 if inst.errno != errno.ENOENT:
82 raise
82 raise
83 requirements = set()
83 requirements = set()
84
84
85 self.sharedpath = self.path
85 self.sharedpath = self.path
86 try:
86 try:
87 s = os.path.realpath(self.opener.read("sharedpath").rstrip('\n'))
87 s = os.path.realpath(self.opener.read("sharedpath").rstrip('\n'))
88 if not os.path.exists(s):
88 if not os.path.exists(s):
89 raise error.RepoError(
89 raise error.RepoError(
90 _('.hg/sharedpath points to nonexistent directory %s') % s)
90 _('.hg/sharedpath points to nonexistent directory %s') % s)
91 self.sharedpath = s
91 self.sharedpath = s
92 except IOError, inst:
92 except IOError, inst:
93 if inst.errno != errno.ENOENT:
93 if inst.errno != errno.ENOENT:
94 raise
94 raise
95
95
96 self.store = store.store(requirements, self.sharedpath, scmutil.opener)
96 self.store = store.store(requirements, self.sharedpath, scmutil.opener)
97 self.spath = self.store.path
97 self.spath = self.store.path
98 self.sopener = self.store.opener
98 self.sopener = self.store.opener
99 self.sjoin = self.store.join
99 self.sjoin = self.store.join
100 self.opener.createmode = self.store.createmode
100 self.opener.createmode = self.store.createmode
101 self._applyrequirements(requirements)
101 self._applyrequirements(requirements)
102 if create:
102 if create:
103 self._writerequirements()
103 self._writerequirements()
104
104
105
105
106 self._branchcache = None
106 self._branchcache = None
107 self._branchcachetip = None
107 self._branchcachetip = None
108 self.filterpats = {}
108 self.filterpats = {}
109 self._datafilters = {}
109 self._datafilters = {}
110 self._transref = self._lockref = self._wlockref = None
110 self._transref = self._lockref = self._wlockref = None
111
111
112 # A cache for various files under .hg/ that tracks file changes,
112 # A cache for various files under .hg/ that tracks file changes,
113 # (used by the filecache decorator)
113 # (used by the filecache decorator)
114 #
114 #
115 # Maps a property name to its util.filecacheentry
115 # Maps a property name to its util.filecacheentry
116 self._filecache = {}
116 self._filecache = {}
117
117
118 def _applyrequirements(self, requirements):
118 def _applyrequirements(self, requirements):
119 self.requirements = requirements
119 self.requirements = requirements
120 openerreqs = set(('revlogv1', 'generaldelta'))
120 openerreqs = set(('revlogv1', 'generaldelta'))
121 self.sopener.options = dict((r, 1) for r in requirements
121 self.sopener.options = dict((r, 1) for r in requirements
122 if r in openerreqs)
122 if r in openerreqs)
123
123
124 def _writerequirements(self):
124 def _writerequirements(self):
125 reqfile = self.opener("requires", "w")
125 reqfile = self.opener("requires", "w")
126 for r in self.requirements:
126 for r in self.requirements:
127 reqfile.write("%s\n" % r)
127 reqfile.write("%s\n" % r)
128 reqfile.close()
128 reqfile.close()
129
129
130 def _checknested(self, path):
130 def _checknested(self, path):
131 """Determine if path is a legal nested repository."""
131 """Determine if path is a legal nested repository."""
132 if not path.startswith(self.root):
132 if not path.startswith(self.root):
133 return False
133 return False
134 subpath = path[len(self.root) + 1:]
134 subpath = path[len(self.root) + 1:]
135 normsubpath = util.pconvert(subpath)
135 normsubpath = util.pconvert(subpath)
136
136
137 # XXX: Checking against the current working copy is wrong in
137 # XXX: Checking against the current working copy is wrong in
138 # the sense that it can reject things like
138 # the sense that it can reject things like
139 #
139 #
140 # $ hg cat -r 10 sub/x.txt
140 # $ hg cat -r 10 sub/x.txt
141 #
141 #
142 # if sub/ is no longer a subrepository in the working copy
142 # if sub/ is no longer a subrepository in the working copy
143 # parent revision.
143 # parent revision.
144 #
144 #
145 # However, it can of course also allow things that would have
145 # However, it can of course also allow things that would have
146 # been rejected before, such as the above cat command if sub/
146 # been rejected before, such as the above cat command if sub/
147 # is a subrepository now, but was a normal directory before.
147 # is a subrepository now, but was a normal directory before.
148 # The old path auditor would have rejected by mistake since it
148 # The old path auditor would have rejected by mistake since it
149 # panics when it sees sub/.hg/.
149 # panics when it sees sub/.hg/.
150 #
150 #
151 # All in all, checking against the working copy seems sensible
151 # All in all, checking against the working copy seems sensible
152 # since we want to prevent access to nested repositories on
152 # since we want to prevent access to nested repositories on
153 # the filesystem *now*.
153 # the filesystem *now*.
154 ctx = self[None]
154 ctx = self[None]
155 parts = util.splitpath(subpath)
155 parts = util.splitpath(subpath)
156 while parts:
156 while parts:
157 prefix = '/'.join(parts)
157 prefix = '/'.join(parts)
158 if prefix in ctx.substate:
158 if prefix in ctx.substate:
159 if prefix == normsubpath:
159 if prefix == normsubpath:
160 return True
160 return True
161 else:
161 else:
162 sub = ctx.sub(prefix)
162 sub = ctx.sub(prefix)
163 return sub.checknested(subpath[len(prefix) + 1:])
163 return sub.checknested(subpath[len(prefix) + 1:])
164 else:
164 else:
165 parts.pop()
165 parts.pop()
166 return False
166 return False
167
167
168 @filecache('bookmarks')
168 @filecache('bookmarks')
169 def _bookmarks(self):
169 def _bookmarks(self):
170 return bookmarks.read(self)
170 return bookmarks.read(self)
171
171
172 @filecache('bookmarks.current')
172 @filecache('bookmarks.current')
173 def _bookmarkcurrent(self):
173 def _bookmarkcurrent(self):
174 return bookmarks.readcurrent(self)
174 return bookmarks.readcurrent(self)
175
175
176 def _writebookmarks(self, marks):
176 def _writebookmarks(self, marks):
177 bookmarks.write(self)
177 bookmarks.write(self)
178
178
179 @filecache('phaseroots', True)
179 @filecache('phaseroots', True)
180 def _phaseroots(self):
180 def _phaseroots(self):
181 self._dirtyphases = False
181 self._dirtyphases = False
182 phaseroots = phases.readroots(self)
182 phaseroots = phases.readroots(self)
183 phases.filterunknown(self, phaseroots)
183 phases.filterunknown(self, phaseroots)
184 return phaseroots
184 return phaseroots
185
185
186 @propertycache
186 @propertycache
187 def _phaserev(self):
187 def _phaserev(self):
188 cache = [phases.public] * len(self)
188 cache = [phases.public] * len(self)
189 for phase in phases.trackedphases:
189 for phase in phases.trackedphases:
190 roots = map(self.changelog.rev, self._phaseroots[phase])
190 roots = map(self.changelog.rev, self._phaseroots[phase])
191 if roots:
191 if roots:
192 for rev in roots:
192 for rev in roots:
193 cache[rev] = phase
193 cache[rev] = phase
194 for rev in self.changelog.descendants(*roots):
194 for rev in self.changelog.descendants(*roots):
195 cache[rev] = phase
195 cache[rev] = phase
196 return cache
196 return cache
197
197
198 @filecache('00changelog.i', True)
198 @filecache('00changelog.i', True)
199 def changelog(self):
199 def changelog(self):
200 c = changelog.changelog(self.sopener)
200 c = changelog.changelog(self.sopener)
201 if 'HG_PENDING' in os.environ:
201 if 'HG_PENDING' in os.environ:
202 p = os.environ['HG_PENDING']
202 p = os.environ['HG_PENDING']
203 if p.startswith(self.root):
203 if p.startswith(self.root):
204 c.readpending('00changelog.i.a')
204 c.readpending('00changelog.i.a')
205 return c
205 return c
206
206
207 @filecache('00manifest.i', True)
207 @filecache('00manifest.i', True)
208 def manifest(self):
208 def manifest(self):
209 return manifest.manifest(self.sopener)
209 return manifest.manifest(self.sopener)
210
210
211 @filecache('dirstate')
211 @filecache('dirstate')
212 def dirstate(self):
212 def dirstate(self):
213 warned = [0]
213 warned = [0]
214 def validate(node):
214 def validate(node):
215 try:
215 try:
216 self.changelog.rev(node)
216 self.changelog.rev(node)
217 return node
217 return node
218 except error.LookupError:
218 except error.LookupError:
219 if not warned[0]:
219 if not warned[0]:
220 warned[0] = True
220 warned[0] = True
221 self.ui.warn(_("warning: ignoring unknown"
221 self.ui.warn(_("warning: ignoring unknown"
222 " working parent %s!\n") % short(node))
222 " working parent %s!\n") % short(node))
223 return nullid
223 return nullid
224
224
225 return dirstate.dirstate(self.opener, self.ui, self.root, validate)
225 return dirstate.dirstate(self.opener, self.ui, self.root, validate)
226
226
227 def __getitem__(self, changeid):
227 def __getitem__(self, changeid):
228 if changeid is None:
228 if changeid is None:
229 return context.workingctx(self)
229 return context.workingctx(self)
230 return context.changectx(self, changeid)
230 return context.changectx(self, changeid)
231
231
232 def __contains__(self, changeid):
232 def __contains__(self, changeid):
233 try:
233 try:
234 return bool(self.lookup(changeid))
234 return bool(self.lookup(changeid))
235 except error.RepoLookupError:
235 except error.RepoLookupError:
236 return False
236 return False
237
237
238 def __nonzero__(self):
238 def __nonzero__(self):
239 return True
239 return True
240
240
241 def __len__(self):
241 def __len__(self):
242 return len(self.changelog)
242 return len(self.changelog)
243
243
244 def __iter__(self):
244 def __iter__(self):
245 for i in xrange(len(self)):
245 for i in xrange(len(self)):
246 yield i
246 yield i
247
247
248 def revs(self, expr, *args):
248 def revs(self, expr, *args):
249 '''Return a list of revisions matching the given revset'''
249 '''Return a list of revisions matching the given revset'''
250 expr = revset.formatspec(expr, *args)
250 expr = revset.formatspec(expr, *args)
251 m = revset.match(None, expr)
251 m = revset.match(None, expr)
252 return [r for r in m(self, range(len(self)))]
252 return [r for r in m(self, range(len(self)))]
253
253
254 def set(self, expr, *args):
254 def set(self, expr, *args):
255 '''
255 '''
256 Yield a context for each matching revision, after doing arg
256 Yield a context for each matching revision, after doing arg
257 replacement via revset.formatspec
257 replacement via revset.formatspec
258 '''
258 '''
259 for r in self.revs(expr, *args):
259 for r in self.revs(expr, *args):
260 yield self[r]
260 yield self[r]
261
261
262 def url(self):
262 def url(self):
263 return 'file:' + self.root
263 return 'file:' + self.root
264
264
265 def hook(self, name, throw=False, **args):
265 def hook(self, name, throw=False, **args):
266 return hook.hook(self.ui, self, name, throw, **args)
266 return hook.hook(self.ui, self, name, throw, **args)
267
267
268 tag_disallowed = ':\r\n'
268 tag_disallowed = ':\r\n'
269
269
270 def _tag(self, names, node, message, local, user, date, extra={}):
270 def _tag(self, names, node, message, local, user, date, extra={}):
271 if isinstance(names, str):
271 if isinstance(names, str):
272 allchars = names
272 allchars = names
273 names = (names,)
273 names = (names,)
274 else:
274 else:
275 allchars = ''.join(names)
275 allchars = ''.join(names)
276 for c in self.tag_disallowed:
276 for c in self.tag_disallowed:
277 if c in allchars:
277 if c in allchars:
278 raise util.Abort(_('%r cannot be used in a tag name') % c)
278 raise util.Abort(_('%r cannot be used in a tag name') % c)
279
279
280 branches = self.branchmap()
280 branches = self.branchmap()
281 for name in names:
281 for name in names:
282 self.hook('pretag', throw=True, node=hex(node), tag=name,
282 self.hook('pretag', throw=True, node=hex(node), tag=name,
283 local=local)
283 local=local)
284 if name in branches:
284 if name in branches:
285 self.ui.warn(_("warning: tag %s conflicts with existing"
285 self.ui.warn(_("warning: tag %s conflicts with existing"
286 " branch name\n") % name)
286 " branch name\n") % name)
287
287
288 def writetags(fp, names, munge, prevtags):
288 def writetags(fp, names, munge, prevtags):
289 fp.seek(0, 2)
289 fp.seek(0, 2)
290 if prevtags and prevtags[-1] != '\n':
290 if prevtags and prevtags[-1] != '\n':
291 fp.write('\n')
291 fp.write('\n')
292 for name in names:
292 for name in names:
293 m = munge and munge(name) or name
293 m = munge and munge(name) or name
294 if self._tagscache.tagtypes and name in self._tagscache.tagtypes:
294 if self._tagscache.tagtypes and name in self._tagscache.tagtypes:
295 old = self.tags().get(name, nullid)
295 old = self.tags().get(name, nullid)
296 fp.write('%s %s\n' % (hex(old), m))
296 fp.write('%s %s\n' % (hex(old), m))
297 fp.write('%s %s\n' % (hex(node), m))
297 fp.write('%s %s\n' % (hex(node), m))
298 fp.close()
298 fp.close()
299
299
300 prevtags = ''
300 prevtags = ''
301 if local:
301 if local:
302 try:
302 try:
303 fp = self.opener('localtags', 'r+')
303 fp = self.opener('localtags', 'r+')
304 except IOError:
304 except IOError:
305 fp = self.opener('localtags', 'a')
305 fp = self.opener('localtags', 'a')
306 else:
306 else:
307 prevtags = fp.read()
307 prevtags = fp.read()
308
308
309 # local tags are stored in the current charset
309 # local tags are stored in the current charset
310 writetags(fp, names, None, prevtags)
310 writetags(fp, names, None, prevtags)
311 for name in names:
311 for name in names:
312 self.hook('tag', node=hex(node), tag=name, local=local)
312 self.hook('tag', node=hex(node), tag=name, local=local)
313 return
313 return
314
314
315 try:
315 try:
316 fp = self.wfile('.hgtags', 'rb+')
316 fp = self.wfile('.hgtags', 'rb+')
317 except IOError, e:
317 except IOError, e:
318 if e.errno != errno.ENOENT:
318 if e.errno != errno.ENOENT:
319 raise
319 raise
320 fp = self.wfile('.hgtags', 'ab')
320 fp = self.wfile('.hgtags', 'ab')
321 else:
321 else:
322 prevtags = fp.read()
322 prevtags = fp.read()
323
323
324 # committed tags are stored in UTF-8
324 # committed tags are stored in UTF-8
325 writetags(fp, names, encoding.fromlocal, prevtags)
325 writetags(fp, names, encoding.fromlocal, prevtags)
326
326
327 fp.close()
327 fp.close()
328
328
329 self.invalidatecaches()
329 self.invalidatecaches()
330
330
331 if '.hgtags' not in self.dirstate:
331 if '.hgtags' not in self.dirstate:
332 self[None].add(['.hgtags'])
332 self[None].add(['.hgtags'])
333
333
334 m = matchmod.exact(self.root, '', ['.hgtags'])
334 m = matchmod.exact(self.root, '', ['.hgtags'])
335 tagnode = self.commit(message, user, date, extra=extra, match=m)
335 tagnode = self.commit(message, user, date, extra=extra, match=m)
336
336
337 for name in names:
337 for name in names:
338 self.hook('tag', node=hex(node), tag=name, local=local)
338 self.hook('tag', node=hex(node), tag=name, local=local)
339
339
340 return tagnode
340 return tagnode
341
341
342 def tag(self, names, node, message, local, user, date):
342 def tag(self, names, node, message, local, user, date):
343 '''tag a revision with one or more symbolic names.
343 '''tag a revision with one or more symbolic names.
344
344
345 names is a list of strings or, when adding a single tag, names may be a
345 names is a list of strings or, when adding a single tag, names may be a
346 string.
346 string.
347
347
348 if local is True, the tags are stored in a per-repository file.
348 if local is True, the tags are stored in a per-repository file.
349 otherwise, they are stored in the .hgtags file, and a new
349 otherwise, they are stored in the .hgtags file, and a new
350 changeset is committed with the change.
350 changeset is committed with the change.
351
351
352 keyword arguments:
352 keyword arguments:
353
353
354 local: whether to store tags in non-version-controlled file
354 local: whether to store tags in non-version-controlled file
355 (default False)
355 (default False)
356
356
357 message: commit message to use if committing
357 message: commit message to use if committing
358
358
359 user: name of user to use if committing
359 user: name of user to use if committing
360
360
361 date: date tuple to use if committing'''
361 date: date tuple to use if committing'''
362
362
363 if not local:
363 if not local:
364 for x in self.status()[:5]:
364 for x in self.status()[:5]:
365 if '.hgtags' in x:
365 if '.hgtags' in x:
366 raise util.Abort(_('working copy of .hgtags is changed '
366 raise util.Abort(_('working copy of .hgtags is changed '
367 '(please commit .hgtags manually)'))
367 '(please commit .hgtags manually)'))
368
368
369 self.tags() # instantiate the cache
369 self.tags() # instantiate the cache
370 self._tag(names, node, message, local, user, date)
370 self._tag(names, node, message, local, user, date)
371
371
372 @propertycache
372 @propertycache
373 def _tagscache(self):
373 def _tagscache(self):
374 '''Returns a tagscache object that contains various tags related caches.'''
374 '''Returns a tagscache object that contains various tags related caches.'''
375
375
376 # This simplifies its cache management by having one decorated
376 # This simplifies its cache management by having one decorated
377 # function (this one) and the rest simply fetch things from it.
377 # function (this one) and the rest simply fetch things from it.
378 class tagscache(object):
378 class tagscache(object):
379 def __init__(self):
379 def __init__(self):
380 # These two define the set of tags for this repository. tags
380 # These two define the set of tags for this repository. tags
381 # maps tag name to node; tagtypes maps tag name to 'global' or
381 # maps tag name to node; tagtypes maps tag name to 'global' or
382 # 'local'. (Global tags are defined by .hgtags across all
382 # 'local'. (Global tags are defined by .hgtags across all
383 # heads, and local tags are defined in .hg/localtags.)
383 # heads, and local tags are defined in .hg/localtags.)
384 # They constitute the in-memory cache of tags.
384 # They constitute the in-memory cache of tags.
385 self.tags = self.tagtypes = None
385 self.tags = self.tagtypes = None
386
386
387 self.nodetagscache = self.tagslist = None
387 self.nodetagscache = self.tagslist = None
388
388
389 cache = tagscache()
389 cache = tagscache()
390 cache.tags, cache.tagtypes = self._findtags()
390 cache.tags, cache.tagtypes = self._findtags()
391
391
392 return cache
392 return cache
393
393
394 def tags(self):
394 def tags(self):
395 '''return a mapping of tag to node'''
395 '''return a mapping of tag to node'''
396 return self._tagscache.tags
396 return self._tagscache.tags
397
397
398 def _findtags(self):
398 def _findtags(self):
399 '''Do the hard work of finding tags. Return a pair of dicts
399 '''Do the hard work of finding tags. Return a pair of dicts
400 (tags, tagtypes) where tags maps tag name to node, and tagtypes
400 (tags, tagtypes) where tags maps tag name to node, and tagtypes
401 maps tag name to a string like \'global\' or \'local\'.
401 maps tag name to a string like \'global\' or \'local\'.
402 Subclasses or extensions are free to add their own tags, but
402 Subclasses or extensions are free to add their own tags, but
403 should be aware that the returned dicts will be retained for the
403 should be aware that the returned dicts will be retained for the
404 duration of the localrepo object.'''
404 duration of the localrepo object.'''
405
405
406 # XXX what tagtype should subclasses/extensions use? Currently
406 # XXX what tagtype should subclasses/extensions use? Currently
407 # mq and bookmarks add tags, but do not set the tagtype at all.
407 # mq and bookmarks add tags, but do not set the tagtype at all.
408 # Should each extension invent its own tag type? Should there
408 # Should each extension invent its own tag type? Should there
409 # be one tagtype for all such "virtual" tags? Or is the status
409 # be one tagtype for all such "virtual" tags? Or is the status
410 # quo fine?
410 # quo fine?
411
411
412 alltags = {} # map tag name to (node, hist)
412 alltags = {} # map tag name to (node, hist)
413 tagtypes = {}
413 tagtypes = {}
414
414
415 tagsmod.findglobaltags(self.ui, self, alltags, tagtypes)
415 tagsmod.findglobaltags(self.ui, self, alltags, tagtypes)
416 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
416 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
417
417
418 # Build the return dicts. Have to re-encode tag names because
418 # Build the return dicts. Have to re-encode tag names because
419 # the tags module always uses UTF-8 (in order not to lose info
419 # the tags module always uses UTF-8 (in order not to lose info
420 # writing to the cache), but the rest of Mercurial wants them in
420 # writing to the cache), but the rest of Mercurial wants them in
421 # local encoding.
421 # local encoding.
422 tags = {}
422 tags = {}
423 for (name, (node, hist)) in alltags.iteritems():
423 for (name, (node, hist)) in alltags.iteritems():
424 if node != nullid:
424 if node != nullid:
425 try:
425 try:
426 # ignore tags to unknown nodes
426 # ignore tags to unknown nodes
427 self.changelog.lookup(node)
427 self.changelog.lookup(node)
428 tags[encoding.tolocal(name)] = node
428 tags[encoding.tolocal(name)] = node
429 except error.LookupError:
429 except error.LookupError:
430 pass
430 pass
431 tags['tip'] = self.changelog.tip()
431 tags['tip'] = self.changelog.tip()
432 tagtypes = dict([(encoding.tolocal(name), value)
432 tagtypes = dict([(encoding.tolocal(name), value)
433 for (name, value) in tagtypes.iteritems()])
433 for (name, value) in tagtypes.iteritems()])
434 return (tags, tagtypes)
434 return (tags, tagtypes)
435
435
436 def tagtype(self, tagname):
436 def tagtype(self, tagname):
437 '''
437 '''
438 return the type of the given tag. result can be:
438 return the type of the given tag. result can be:
439
439
440 'local' : a local tag
440 'local' : a local tag
441 'global' : a global tag
441 'global' : a global tag
442 None : tag does not exist
442 None : tag does not exist
443 '''
443 '''
444
444
445 return self._tagscache.tagtypes.get(tagname)
445 return self._tagscache.tagtypes.get(tagname)
446
446
447 def tagslist(self):
447 def tagslist(self):
448 '''return a list of tags ordered by revision'''
448 '''return a list of tags ordered by revision'''
449 if not self._tagscache.tagslist:
449 if not self._tagscache.tagslist:
450 l = []
450 l = []
451 for t, n in self.tags().iteritems():
451 for t, n in self.tags().iteritems():
452 r = self.changelog.rev(n)
452 r = self.changelog.rev(n)
453 l.append((r, t, n))
453 l.append((r, t, n))
454 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
454 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
455
455
456 return self._tagscache.tagslist
456 return self._tagscache.tagslist
457
457
458 def nodetags(self, node):
458 def nodetags(self, node):
459 '''return the tags associated with a node'''
459 '''return the tags associated with a node'''
460 if not self._tagscache.nodetagscache:
460 if not self._tagscache.nodetagscache:
461 nodetagscache = {}
461 nodetagscache = {}
462 for t, n in self.tags().iteritems():
462 for t, n in self.tags().iteritems():
463 nodetagscache.setdefault(n, []).append(t)
463 nodetagscache.setdefault(n, []).append(t)
464 for tags in nodetagscache.itervalues():
464 for tags in nodetagscache.itervalues():
465 tags.sort()
465 tags.sort()
466 self._tagscache.nodetagscache = nodetagscache
466 self._tagscache.nodetagscache = nodetagscache
467 return self._tagscache.nodetagscache.get(node, [])
467 return self._tagscache.nodetagscache.get(node, [])
468
468
469 def nodebookmarks(self, node):
469 def nodebookmarks(self, node):
470 marks = []
470 marks = []
471 for bookmark, n in self._bookmarks.iteritems():
471 for bookmark, n in self._bookmarks.iteritems():
472 if n == node:
472 if n == node:
473 marks.append(bookmark)
473 marks.append(bookmark)
474 return sorted(marks)
474 return sorted(marks)
475
475
476 def _branchtags(self, partial, lrev):
476 def _branchtags(self, partial, lrev):
477 # TODO: rename this function?
477 # TODO: rename this function?
478 tiprev = len(self) - 1
478 tiprev = len(self) - 1
479 if lrev != tiprev:
479 if lrev != tiprev:
480 ctxgen = (self[r] for r in xrange(lrev + 1, tiprev + 1))
480 ctxgen = (self[r] for r in xrange(lrev + 1, tiprev + 1))
481 self._updatebranchcache(partial, ctxgen)
481 self._updatebranchcache(partial, ctxgen)
482 self._writebranchcache(partial, self.changelog.tip(), tiprev)
482 self._writebranchcache(partial, self.changelog.tip(), tiprev)
483
483
484 return partial
484 return partial
485
485
486 def updatebranchcache(self):
486 def updatebranchcache(self):
487 tip = self.changelog.tip()
487 tip = self.changelog.tip()
488 if self._branchcache is not None and self._branchcachetip == tip:
488 if self._branchcache is not None and self._branchcachetip == tip:
489 return
489 return
490
490
491 oldtip = self._branchcachetip
491 oldtip = self._branchcachetip
492 self._branchcachetip = tip
492 self._branchcachetip = tip
493 if oldtip is None or oldtip not in self.changelog.nodemap:
493 if oldtip is None or oldtip not in self.changelog.nodemap:
494 partial, last, lrev = self._readbranchcache()
494 partial, last, lrev = self._readbranchcache()
495 else:
495 else:
496 lrev = self.changelog.rev(oldtip)
496 lrev = self.changelog.rev(oldtip)
497 partial = self._branchcache
497 partial = self._branchcache
498
498
499 self._branchtags(partial, lrev)
499 self._branchtags(partial, lrev)
500 # this private cache holds all heads (not just tips)
500 # this private cache holds all heads (not just tips)
501 self._branchcache = partial
501 self._branchcache = partial
502
502
503 def branchmap(self):
503 def branchmap(self):
504 '''returns a dictionary {branch: [branchheads]}'''
504 '''returns a dictionary {branch: [branchheads]}'''
505 self.updatebranchcache()
505 self.updatebranchcache()
506 return self._branchcache
506 return self._branchcache
507
507
508 def branchtags(self):
508 def branchtags(self):
509 '''return a dict where branch names map to the tipmost head of
509 '''return a dict where branch names map to the tipmost head of
510 the branch, open heads come before closed'''
510 the branch, open heads come before closed'''
511 bt = {}
511 bt = {}
512 for bn, heads in self.branchmap().iteritems():
512 for bn, heads in self.branchmap().iteritems():
513 tip = heads[-1]
513 tip = heads[-1]
514 for h in reversed(heads):
514 for h in reversed(heads):
515 if 'close' not in self.changelog.read(h)[5]:
515 if 'close' not in self.changelog.read(h)[5]:
516 tip = h
516 tip = h
517 break
517 break
518 bt[bn] = tip
518 bt[bn] = tip
519 return bt
519 return bt
520
520
521 def _readbranchcache(self):
521 def _readbranchcache(self):
522 partial = {}
522 partial = {}
523 try:
523 try:
524 f = self.opener("cache/branchheads")
524 f = self.opener("cache/branchheads")
525 lines = f.read().split('\n')
525 lines = f.read().split('\n')
526 f.close()
526 f.close()
527 except (IOError, OSError):
527 except (IOError, OSError):
528 return {}, nullid, nullrev
528 return {}, nullid, nullrev
529
529
530 try:
530 try:
531 last, lrev = lines.pop(0).split(" ", 1)
531 last, lrev = lines.pop(0).split(" ", 1)
532 last, lrev = bin(last), int(lrev)
532 last, lrev = bin(last), int(lrev)
533 if lrev >= len(self) or self[lrev].node() != last:
533 if lrev >= len(self) or self[lrev].node() != last:
534 # invalidate the cache
534 # invalidate the cache
535 raise ValueError('invalidating branch cache (tip differs)')
535 raise ValueError('invalidating branch cache (tip differs)')
536 for l in lines:
536 for l in lines:
537 if not l:
537 if not l:
538 continue
538 continue
539 node, label = l.split(" ", 1)
539 node, label = l.split(" ", 1)
540 label = encoding.tolocal(label.strip())
540 label = encoding.tolocal(label.strip())
541 partial.setdefault(label, []).append(bin(node))
541 partial.setdefault(label, []).append(bin(node))
542 except KeyboardInterrupt:
542 except KeyboardInterrupt:
543 raise
543 raise
544 except Exception, inst:
544 except Exception, inst:
545 if self.ui.debugflag:
545 if self.ui.debugflag:
546 self.ui.warn(str(inst), '\n')
546 self.ui.warn(str(inst), '\n')
547 partial, last, lrev = {}, nullid, nullrev
547 partial, last, lrev = {}, nullid, nullrev
548 return partial, last, lrev
548 return partial, last, lrev
549
549
550 def _writebranchcache(self, branches, tip, tiprev):
550 def _writebranchcache(self, branches, tip, tiprev):
551 try:
551 try:
552 f = self.opener("cache/branchheads", "w", atomictemp=True)
552 f = self.opener("cache/branchheads", "w", atomictemp=True)
553 f.write("%s %s\n" % (hex(tip), tiprev))
553 f.write("%s %s\n" % (hex(tip), tiprev))
554 for label, nodes in branches.iteritems():
554 for label, nodes in branches.iteritems():
555 for node in nodes:
555 for node in nodes:
556 f.write("%s %s\n" % (hex(node), encoding.fromlocal(label)))
556 f.write("%s %s\n" % (hex(node), encoding.fromlocal(label)))
557 f.close()
557 f.close()
558 except (IOError, OSError):
558 except (IOError, OSError):
559 pass
559 pass
560
560
561 def _updatebranchcache(self, partial, ctxgen):
561 def _updatebranchcache(self, partial, ctxgen):
562 # collect new branch entries
562 # collect new branch entries
563 newbranches = {}
563 newbranches = {}
564 for c in ctxgen:
564 for c in ctxgen:
565 newbranches.setdefault(c.branch(), []).append(c.node())
565 newbranches.setdefault(c.branch(), []).append(c.node())
566 # if older branchheads are reachable from new ones, they aren't
566 # if older branchheads are reachable from new ones, they aren't
567 # really branchheads. Note checking parents is insufficient:
567 # really branchheads. Note checking parents is insufficient:
568 # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
568 # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
569 for branch, newnodes in newbranches.iteritems():
569 for branch, newnodes in newbranches.iteritems():
570 bheads = partial.setdefault(branch, [])
570 bheads = partial.setdefault(branch, [])
571 bheads.extend(newnodes)
571 bheads.extend(newnodes)
572 if len(bheads) <= 1:
572 if len(bheads) <= 1:
573 continue
573 continue
574 bheads = sorted(bheads, key=lambda x: self[x].rev())
574 bheads = sorted(bheads, key=lambda x: self[x].rev())
575 # starting from tip means fewer passes over reachable
575 # starting from tip means fewer passes over reachable
576 while newnodes:
576 while newnodes:
577 latest = newnodes.pop()
577 latest = newnodes.pop()
578 if latest not in bheads:
578 if latest not in bheads:
579 continue
579 continue
580 minbhrev = self[bheads[0]].node()
580 minbhrev = self[bheads[0]].node()
581 reachable = self.changelog.reachable(latest, minbhrev)
581 reachable = self.changelog.reachable(latest, minbhrev)
582 reachable.remove(latest)
582 reachable.remove(latest)
583 if reachable:
583 if reachable:
584 bheads = [b for b in bheads if b not in reachable]
584 bheads = [b for b in bheads if b not in reachable]
585 partial[branch] = bheads
585 partial[branch] = bheads
586
586
587 def lookup(self, key):
587 def lookup(self, key):
588 if isinstance(key, int):
588 if isinstance(key, int):
589 return self.changelog.node(key)
589 return self.changelog.node(key)
590 elif key == '.':
590 elif key == '.':
591 return self.dirstate.p1()
591 return self.dirstate.p1()
592 elif key == 'null':
592 elif key == 'null':
593 return nullid
593 return nullid
594 elif key == 'tip':
594 elif key == 'tip':
595 return self.changelog.tip()
595 return self.changelog.tip()
596 n = self.changelog._match(key)
596 n = self.changelog._match(key)
597 if n:
597 if n:
598 return n
598 return n
599 if key in self._bookmarks:
599 if key in self._bookmarks:
600 return self._bookmarks[key]
600 return self._bookmarks[key]
601 if key in self.tags():
601 if key in self.tags():
602 return self.tags()[key]
602 return self.tags()[key]
603 if key in self.branchtags():
603 if key in self.branchtags():
604 return self.branchtags()[key]
604 return self.branchtags()[key]
605 n = self.changelog._partialmatch(key)
605 n = self.changelog._partialmatch(key)
606 if n:
606 if n:
607 return n
607 return n
608
608
609 # can't find key, check if it might have come from damaged dirstate
609 # can't find key, check if it might have come from damaged dirstate
610 if key in self.dirstate.parents():
610 if key in self.dirstate.parents():
611 raise error.Abort(_("working directory has unknown parent '%s'!")
611 raise error.Abort(_("working directory has unknown parent '%s'!")
612 % short(key))
612 % short(key))
613 try:
613 try:
614 if len(key) == 20:
614 if len(key) == 20:
615 key = hex(key)
615 key = hex(key)
616 except TypeError:
616 except TypeError:
617 pass
617 pass
618 raise error.RepoLookupError(_("unknown revision '%s'") % key)
618 raise error.RepoLookupError(_("unknown revision '%s'") % key)
619
619
620 def lookupbranch(self, key, remote=None):
620 def lookupbranch(self, key, remote=None):
621 repo = remote or self
621 repo = remote or self
622 if key in repo.branchmap():
622 if key in repo.branchmap():
623 return key
623 return key
624
624
625 repo = (remote and remote.local()) and remote or self
625 repo = (remote and remote.local()) and remote or self
626 return repo[key].branch()
626 return repo[key].branch()
627
627
628 def known(self, nodes):
628 def known(self, nodes):
629 nm = self.changelog.nodemap
629 nm = self.changelog.nodemap
630 result = []
630 result = []
631 for n in nodes:
631 for n in nodes:
632 r = nm.get(n)
632 r = nm.get(n)
633 resp = not (r is None or self._phaserev[r] >= phases.secret)
633 resp = not (r is None or self._phaserev[r] >= phases.secret)
634 result.append(resp)
634 result.append(resp)
635 return result
635 return result
636
636
637 def local(self):
637 def local(self):
638 return self
638 return self
639
639
640 def join(self, f):
640 def join(self, f):
641 return os.path.join(self.path, f)
641 return os.path.join(self.path, f)
642
642
643 def wjoin(self, f):
643 def wjoin(self, f):
644 return os.path.join(self.root, f)
644 return os.path.join(self.root, f)
645
645
646 def file(self, f):
646 def file(self, f):
647 if f[0] == '/':
647 if f[0] == '/':
648 f = f[1:]
648 f = f[1:]
649 return filelog.filelog(self.sopener, f)
649 return filelog.filelog(self.sopener, f)
650
650
651 def changectx(self, changeid):
651 def changectx(self, changeid):
652 return self[changeid]
652 return self[changeid]
653
653
654 def parents(self, changeid=None):
654 def parents(self, changeid=None):
655 '''get list of changectxs for parents of changeid'''
655 '''get list of changectxs for parents of changeid'''
656 return self[changeid].parents()
656 return self[changeid].parents()
657
657
658 def filectx(self, path, changeid=None, fileid=None):
658 def filectx(self, path, changeid=None, fileid=None):
659 """changeid can be a changeset revision, node, or tag.
659 """changeid can be a changeset revision, node, or tag.
660 fileid can be a file revision or node."""
660 fileid can be a file revision or node."""
661 return context.filectx(self, path, changeid, fileid)
661 return context.filectx(self, path, changeid, fileid)
662
662
663 def getcwd(self):
663 def getcwd(self):
664 return self.dirstate.getcwd()
664 return self.dirstate.getcwd()
665
665
666 def pathto(self, f, cwd=None):
666 def pathto(self, f, cwd=None):
667 return self.dirstate.pathto(f, cwd)
667 return self.dirstate.pathto(f, cwd)
668
668
669 def wfile(self, f, mode='r'):
669 def wfile(self, f, mode='r'):
670 return self.wopener(f, mode)
670 return self.wopener(f, mode)
671
671
672 def _link(self, f):
672 def _link(self, f):
673 return os.path.islink(self.wjoin(f))
673 return os.path.islink(self.wjoin(f))
674
674
675 def _loadfilter(self, filter):
675 def _loadfilter(self, filter):
676 if filter not in self.filterpats:
676 if filter not in self.filterpats:
677 l = []
677 l = []
678 for pat, cmd in self.ui.configitems(filter):
678 for pat, cmd in self.ui.configitems(filter):
679 if cmd == '!':
679 if cmd == '!':
680 continue
680 continue
681 mf = matchmod.match(self.root, '', [pat])
681 mf = matchmod.match(self.root, '', [pat])
682 fn = None
682 fn = None
683 params = cmd
683 params = cmd
684 for name, filterfn in self._datafilters.iteritems():
684 for name, filterfn in self._datafilters.iteritems():
685 if cmd.startswith(name):
685 if cmd.startswith(name):
686 fn = filterfn
686 fn = filterfn
687 params = cmd[len(name):].lstrip()
687 params = cmd[len(name):].lstrip()
688 break
688 break
689 if not fn:
689 if not fn:
690 fn = lambda s, c, **kwargs: util.filter(s, c)
690 fn = lambda s, c, **kwargs: util.filter(s, c)
691 # Wrap old filters not supporting keyword arguments
691 # Wrap old filters not supporting keyword arguments
692 if not inspect.getargspec(fn)[2]:
692 if not inspect.getargspec(fn)[2]:
693 oldfn = fn
693 oldfn = fn
694 fn = lambda s, c, **kwargs: oldfn(s, c)
694 fn = lambda s, c, **kwargs: oldfn(s, c)
695 l.append((mf, fn, params))
695 l.append((mf, fn, params))
696 self.filterpats[filter] = l
696 self.filterpats[filter] = l
697 return self.filterpats[filter]
697 return self.filterpats[filter]
698
698
699 def _filter(self, filterpats, filename, data):
699 def _filter(self, filterpats, filename, data):
700 for mf, fn, cmd in filterpats:
700 for mf, fn, cmd in filterpats:
701 if mf(filename):
701 if mf(filename):
702 self.ui.debug("filtering %s through %s\n" % (filename, cmd))
702 self.ui.debug("filtering %s through %s\n" % (filename, cmd))
703 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
703 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
704 break
704 break
705
705
706 return data
706 return data
707
707
708 @propertycache
708 @propertycache
709 def _encodefilterpats(self):
709 def _encodefilterpats(self):
710 return self._loadfilter('encode')
710 return self._loadfilter('encode')
711
711
712 @propertycache
712 @propertycache
713 def _decodefilterpats(self):
713 def _decodefilterpats(self):
714 return self._loadfilter('decode')
714 return self._loadfilter('decode')
715
715
716 def adddatafilter(self, name, filter):
716 def adddatafilter(self, name, filter):
717 self._datafilters[name] = filter
717 self._datafilters[name] = filter
718
718
719 def wread(self, filename):
719 def wread(self, filename):
720 if self._link(filename):
720 if self._link(filename):
721 data = os.readlink(self.wjoin(filename))
721 data = os.readlink(self.wjoin(filename))
722 else:
722 else:
723 data = self.wopener.read(filename)
723 data = self.wopener.read(filename)
724 return self._filter(self._encodefilterpats, filename, data)
724 return self._filter(self._encodefilterpats, filename, data)
725
725
726 def wwrite(self, filename, data, flags):
726 def wwrite(self, filename, data, flags):
727 data = self._filter(self._decodefilterpats, filename, data)
727 data = self._filter(self._decodefilterpats, filename, data)
728 if 'l' in flags:
728 if 'l' in flags:
729 self.wopener.symlink(data, filename)
729 self.wopener.symlink(data, filename)
730 else:
730 else:
731 self.wopener.write(filename, data)
731 self.wopener.write(filename, data)
732 if 'x' in flags:
732 if 'x' in flags:
733 util.setflags(self.wjoin(filename), False, True)
733 util.setflags(self.wjoin(filename), False, True)
734
734
735 def wwritedata(self, filename, data):
735 def wwritedata(self, filename, data):
736 return self._filter(self._decodefilterpats, filename, data)
736 return self._filter(self._decodefilterpats, filename, data)
737
737
738 def transaction(self, desc):
738 def transaction(self, desc):
739 tr = self._transref and self._transref() or None
739 tr = self._transref and self._transref() or None
740 if tr and tr.running():
740 if tr and tr.running():
741 return tr.nest()
741 return tr.nest()
742
742
743 # abort here if the journal already exists
743 # abort here if the journal already exists
744 if os.path.exists(self.sjoin("journal")):
744 if os.path.exists(self.sjoin("journal")):
745 raise error.RepoError(
745 raise error.RepoError(
746 _("abandoned transaction found - run hg recover"))
746 _("abandoned transaction found - run hg recover"))
747
747
748 journalfiles = self._writejournal(desc)
748 journalfiles = self._writejournal(desc)
749 renames = [(x, undoname(x)) for x in journalfiles]
749 renames = [(x, undoname(x)) for x in journalfiles]
750
750
751 tr = transaction.transaction(self.ui.warn, self.sopener,
751 tr = transaction.transaction(self.ui.warn, self.sopener,
752 self.sjoin("journal"),
752 self.sjoin("journal"),
753 aftertrans(renames),
753 aftertrans(renames),
754 self.store.createmode)
754 self.store.createmode)
755 self._transref = weakref.ref(tr)
755 self._transref = weakref.ref(tr)
756 return tr
756 return tr
757
757
758 def _writejournal(self, desc):
758 def _writejournal(self, desc):
759 # save dirstate for rollback
759 # save dirstate for rollback
760 try:
760 try:
761 ds = self.opener.read("dirstate")
761 ds = self.opener.read("dirstate")
762 except IOError:
762 except IOError:
763 ds = ""
763 ds = ""
764 self.opener.write("journal.dirstate", ds)
764 self.opener.write("journal.dirstate", ds)
765 self.opener.write("journal.branch",
765 self.opener.write("journal.branch",
766 encoding.fromlocal(self.dirstate.branch()))
766 encoding.fromlocal(self.dirstate.branch()))
767 self.opener.write("journal.desc",
767 self.opener.write("journal.desc",
768 "%d\n%s\n" % (len(self), desc))
768 "%d\n%s\n" % (len(self), desc))
769
769
770 bkname = self.join('bookmarks')
770 bkname = self.join('bookmarks')
771 if os.path.exists(bkname):
771 if os.path.exists(bkname):
772 util.copyfile(bkname, self.join('journal.bookmarks'))
772 util.copyfile(bkname, self.join('journal.bookmarks'))
773 else:
773 else:
774 self.opener.write('journal.bookmarks', '')
774 self.opener.write('journal.bookmarks', '')
775 phasesname = self.sjoin('phaseroots')
775 phasesname = self.sjoin('phaseroots')
776 if os.path.exists(phasesname):
776 if os.path.exists(phasesname):
777 util.copyfile(phasesname, self.sjoin('journal.phaseroots'))
777 util.copyfile(phasesname, self.sjoin('journal.phaseroots'))
778 else:
778 else:
779 self.sopener.write('journal.phaseroots', '')
779 self.sopener.write('journal.phaseroots', '')
780
780
781 return (self.sjoin('journal'), self.join('journal.dirstate'),
781 return (self.sjoin('journal'), self.join('journal.dirstate'),
782 self.join('journal.branch'), self.join('journal.desc'),
782 self.join('journal.branch'), self.join('journal.desc'),
783 self.join('journal.bookmarks'),
783 self.join('journal.bookmarks'),
784 self.sjoin('journal.phaseroots'))
784 self.sjoin('journal.phaseroots'))
785
785
786 def recover(self):
786 def recover(self):
787 lock = self.lock()
787 lock = self.lock()
788 try:
788 try:
789 if os.path.exists(self.sjoin("journal")):
789 if os.path.exists(self.sjoin("journal")):
790 self.ui.status(_("rolling back interrupted transaction\n"))
790 self.ui.status(_("rolling back interrupted transaction\n"))
791 transaction.rollback(self.sopener, self.sjoin("journal"),
791 transaction.rollback(self.sopener, self.sjoin("journal"),
792 self.ui.warn)
792 self.ui.warn)
793 self.invalidate()
793 self.invalidate()
794 return True
794 return True
795 else:
795 else:
796 self.ui.warn(_("no interrupted transaction available\n"))
796 self.ui.warn(_("no interrupted transaction available\n"))
797 return False
797 return False
798 finally:
798 finally:
799 lock.release()
799 lock.release()
800
800
801 def rollback(self, dryrun=False, force=False):
801 def rollback(self, dryrun=False, force=False):
802 wlock = lock = None
802 wlock = lock = None
803 try:
803 try:
804 wlock = self.wlock()
804 wlock = self.wlock()
805 lock = self.lock()
805 lock = self.lock()
806 if os.path.exists(self.sjoin("undo")):
806 if os.path.exists(self.sjoin("undo")):
807 return self._rollback(dryrun, force)
807 return self._rollback(dryrun, force)
808 else:
808 else:
809 self.ui.warn(_("no rollback information available\n"))
809 self.ui.warn(_("no rollback information available\n"))
810 return 1
810 return 1
811 finally:
811 finally:
812 release(lock, wlock)
812 release(lock, wlock)
813
813
814 def _rollback(self, dryrun, force):
814 def _rollback(self, dryrun, force):
815 ui = self.ui
815 ui = self.ui
816 try:
816 try:
817 args = self.opener.read('undo.desc').splitlines()
817 args = self.opener.read('undo.desc').splitlines()
818 (oldlen, desc, detail) = (int(args[0]), args[1], None)
818 (oldlen, desc, detail) = (int(args[0]), args[1], None)
819 if len(args) >= 3:
819 if len(args) >= 3:
820 detail = args[2]
820 detail = args[2]
821 oldtip = oldlen - 1
821 oldtip = oldlen - 1
822
822
823 if detail and ui.verbose:
823 if detail and ui.verbose:
824 msg = (_('repository tip rolled back to revision %s'
824 msg = (_('repository tip rolled back to revision %s'
825 ' (undo %s: %s)\n')
825 ' (undo %s: %s)\n')
826 % (oldtip, desc, detail))
826 % (oldtip, desc, detail))
827 else:
827 else:
828 msg = (_('repository tip rolled back to revision %s'
828 msg = (_('repository tip rolled back to revision %s'
829 ' (undo %s)\n')
829 ' (undo %s)\n')
830 % (oldtip, desc))
830 % (oldtip, desc))
831 except IOError:
831 except IOError:
832 msg = _('rolling back unknown transaction\n')
832 msg = _('rolling back unknown transaction\n')
833 desc = None
833 desc = None
834
834
835 if not force and self['.'] != self['tip'] and desc == 'commit':
835 if not force and self['.'] != self['tip'] and desc == 'commit':
836 raise util.Abort(
836 raise util.Abort(
837 _('rollback of last commit while not checked out '
837 _('rollback of last commit while not checked out '
838 'may lose data'), hint=_('use -f to force'))
838 'may lose data'), hint=_('use -f to force'))
839
839
840 ui.status(msg)
840 ui.status(msg)
841 if dryrun:
841 if dryrun:
842 return 0
842 return 0
843
843
844 parents = self.dirstate.parents()
844 parents = self.dirstate.parents()
845 transaction.rollback(self.sopener, self.sjoin('undo'), ui.warn)
845 transaction.rollback(self.sopener, self.sjoin('undo'), ui.warn)
846 if os.path.exists(self.join('undo.bookmarks')):
846 if os.path.exists(self.join('undo.bookmarks')):
847 util.rename(self.join('undo.bookmarks'),
847 util.rename(self.join('undo.bookmarks'),
848 self.join('bookmarks'))
848 self.join('bookmarks'))
849 if os.path.exists(self.sjoin('undo.phaseroots')):
849 if os.path.exists(self.sjoin('undo.phaseroots')):
850 util.rename(self.sjoin('undo.phaseroots'),
850 util.rename(self.sjoin('undo.phaseroots'),
851 self.sjoin('phaseroots'))
851 self.sjoin('phaseroots'))
852 self.invalidate()
852 self.invalidate()
853
853
854 parentgone = (parents[0] not in self.changelog.nodemap or
854 parentgone = (parents[0] not in self.changelog.nodemap or
855 parents[1] not in self.changelog.nodemap)
855 parents[1] not in self.changelog.nodemap)
856 if parentgone:
856 if parentgone:
857 util.rename(self.join('undo.dirstate'), self.join('dirstate'))
857 util.rename(self.join('undo.dirstate'), self.join('dirstate'))
858 try:
858 try:
859 branch = self.opener.read('undo.branch')
859 branch = self.opener.read('undo.branch')
860 self.dirstate.setbranch(branch)
860 self.dirstate.setbranch(branch)
861 except IOError:
861 except IOError:
862 ui.warn(_('named branch could not be reset: '
862 ui.warn(_('named branch could not be reset: '
863 'current branch is still \'%s\'\n')
863 'current branch is still \'%s\'\n')
864 % self.dirstate.branch())
864 % self.dirstate.branch())
865
865
866 self.dirstate.invalidate()
866 self.dirstate.invalidate()
867 parents = tuple([p.rev() for p in self.parents()])
867 parents = tuple([p.rev() for p in self.parents()])
868 if len(parents) > 1:
868 if len(parents) > 1:
869 ui.status(_('working directory now based on '
869 ui.status(_('working directory now based on '
870 'revisions %d and %d\n') % parents)
870 'revisions %d and %d\n') % parents)
871 else:
871 else:
872 ui.status(_('working directory now based on '
872 ui.status(_('working directory now based on '
873 'revision %d\n') % parents)
873 'revision %d\n') % parents)
874 self.destroyed()
874 self.destroyed()
875 return 0
875 return 0
876
876
877 def invalidatecaches(self):
877 def invalidatecaches(self):
878 def delcache(name):
878 def delcache(name):
879 try:
879 try:
880 delattr(self, name)
880 delattr(self, name)
881 except AttributeError:
881 except AttributeError:
882 pass
882 pass
883
883
884 delcache('_tagscache')
884 delcache('_tagscache')
885 delcache('_phaserev')
885 delcache('_phaserev')
886
886
887 self._branchcache = None # in UTF-8
887 self._branchcache = None # in UTF-8
888 self._branchcachetip = None
888 self._branchcachetip = None
889
889
890 def invalidatedirstate(self):
890 def invalidatedirstate(self):
891 '''Invalidates the dirstate, causing the next call to dirstate
891 '''Invalidates the dirstate, causing the next call to dirstate
892 to check if it was modified since the last time it was read,
892 to check if it was modified since the last time it was read,
893 rereading it if it has.
893 rereading it if it has.
894
894
895 This is different to dirstate.invalidate() that it doesn't always
895 This is different to dirstate.invalidate() that it doesn't always
896 rereads the dirstate. Use dirstate.invalidate() if you want to
896 rereads the dirstate. Use dirstate.invalidate() if you want to
897 explicitly read the dirstate again (i.e. restoring it to a previous
897 explicitly read the dirstate again (i.e. restoring it to a previous
898 known good state).'''
898 known good state).'''
899 try:
899 try:
900 delattr(self, 'dirstate')
900 delattr(self, 'dirstate')
901 except AttributeError:
901 except AttributeError:
902 pass
902 pass
903
903
904 def invalidate(self):
904 def invalidate(self):
905 for k in self._filecache:
905 for k in self._filecache:
906 # dirstate is invalidated separately in invalidatedirstate()
906 # dirstate is invalidated separately in invalidatedirstate()
907 if k == 'dirstate':
907 if k == 'dirstate':
908 continue
908 continue
909
909
910 try:
910 try:
911 delattr(self, k)
911 delattr(self, k)
912 except AttributeError:
912 except AttributeError:
913 pass
913 pass
914 self.invalidatecaches()
914 self.invalidatecaches()
915
915
916 def _lock(self, lockname, wait, releasefn, acquirefn, desc):
916 def _lock(self, lockname, wait, releasefn, acquirefn, desc):
917 try:
917 try:
918 l = lock.lock(lockname, 0, releasefn, desc=desc)
918 l = lock.lock(lockname, 0, releasefn, desc=desc)
919 except error.LockHeld, inst:
919 except error.LockHeld, inst:
920 if not wait:
920 if not wait:
921 raise
921 raise
922 self.ui.warn(_("waiting for lock on %s held by %r\n") %
922 self.ui.warn(_("waiting for lock on %s held by %r\n") %
923 (desc, inst.locker))
923 (desc, inst.locker))
924 # default to 600 seconds timeout
924 # default to 600 seconds timeout
925 l = lock.lock(lockname, int(self.ui.config("ui", "timeout", "600")),
925 l = lock.lock(lockname, int(self.ui.config("ui", "timeout", "600")),
926 releasefn, desc=desc)
926 releasefn, desc=desc)
927 if acquirefn:
927 if acquirefn:
928 acquirefn()
928 acquirefn()
929 return l
929 return l
930
930
931 def _afterlock(self, callback):
931 def _afterlock(self, callback):
932 """add a callback to the current repository lock.
932 """add a callback to the current repository lock.
933
933
934 The callback will be executed on lock release."""
934 The callback will be executed on lock release."""
935 l = self._lockref and self._lockref()
935 l = self._lockref and self._lockref()
936 if l:
936 if l:
937 l.postrelease.append(callback)
937 l.postrelease.append(callback)
938
938
939 def lock(self, wait=True):
939 def lock(self, wait=True):
940 '''Lock the repository store (.hg/store) and return a weak reference
940 '''Lock the repository store (.hg/store) and return a weak reference
941 to the lock. Use this before modifying the store (e.g. committing or
941 to the lock. Use this before modifying the store (e.g. committing or
942 stripping). If you are opening a transaction, get a lock as well.)'''
942 stripping). If you are opening a transaction, get a lock as well.)'''
943 l = self._lockref and self._lockref()
943 l = self._lockref and self._lockref()
944 if l is not None and l.held:
944 if l is not None and l.held:
945 l.lock()
945 l.lock()
946 return l
946 return l
947
947
948 def unlock():
948 def unlock():
949 self.store.write()
949 self.store.write()
950 if self._dirtyphases:
950 if self._dirtyphases:
951 phases.writeroots(self)
951 phases.writeroots(self)
952 for k, ce in self._filecache.items():
952 for k, ce in self._filecache.items():
953 if k == 'dirstate':
953 if k == 'dirstate':
954 continue
954 continue
955 ce.refresh()
955 ce.refresh()
956
956
957 l = self._lock(self.sjoin("lock"), wait, unlock,
957 l = self._lock(self.sjoin("lock"), wait, unlock,
958 self.invalidate, _('repository %s') % self.origroot)
958 self.invalidate, _('repository %s') % self.origroot)
959 self._lockref = weakref.ref(l)
959 self._lockref = weakref.ref(l)
960 return l
960 return l
961
961
962 def wlock(self, wait=True):
962 def wlock(self, wait=True):
963 '''Lock the non-store parts of the repository (everything under
963 '''Lock the non-store parts of the repository (everything under
964 .hg except .hg/store) and return a weak reference to the lock.
964 .hg except .hg/store) and return a weak reference to the lock.
965 Use this before modifying files in .hg.'''
965 Use this before modifying files in .hg.'''
966 l = self._wlockref and self._wlockref()
966 l = self._wlockref and self._wlockref()
967 if l is not None and l.held:
967 if l is not None and l.held:
968 l.lock()
968 l.lock()
969 return l
969 return l
970
970
971 def unlock():
971 def unlock():
972 self.dirstate.write()
972 self.dirstate.write()
973 ce = self._filecache.get('dirstate')
973 ce = self._filecache.get('dirstate')
974 if ce:
974 if ce:
975 ce.refresh()
975 ce.refresh()
976
976
977 l = self._lock(self.join("wlock"), wait, unlock,
977 l = self._lock(self.join("wlock"), wait, unlock,
978 self.invalidatedirstate, _('working directory of %s') %
978 self.invalidatedirstate, _('working directory of %s') %
979 self.origroot)
979 self.origroot)
980 self._wlockref = weakref.ref(l)
980 self._wlockref = weakref.ref(l)
981 return l
981 return l
982
982
983 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist):
983 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist):
984 """
984 """
985 commit an individual file as part of a larger transaction
985 commit an individual file as part of a larger transaction
986 """
986 """
987
987
988 fname = fctx.path()
988 fname = fctx.path()
989 text = fctx.data()
989 text = fctx.data()
990 flog = self.file(fname)
990 flog = self.file(fname)
991 fparent1 = manifest1.get(fname, nullid)
991 fparent1 = manifest1.get(fname, nullid)
992 fparent2 = fparent2o = manifest2.get(fname, nullid)
992 fparent2 = fparent2o = manifest2.get(fname, nullid)
993
993
994 meta = {}
994 meta = {}
995 copy = fctx.renamed()
995 copy = fctx.renamed()
996 if copy and copy[0] != fname:
996 if copy and copy[0] != fname:
997 # Mark the new revision of this file as a copy of another
997 # Mark the new revision of this file as a copy of another
998 # file. This copy data will effectively act as a parent
998 # file. This copy data will effectively act as a parent
999 # of this new revision. If this is a merge, the first
999 # of this new revision. If this is a merge, the first
1000 # parent will be the nullid (meaning "look up the copy data")
1000 # parent will be the nullid (meaning "look up the copy data")
1001 # and the second one will be the other parent. For example:
1001 # and the second one will be the other parent. For example:
1002 #
1002 #
1003 # 0 --- 1 --- 3 rev1 changes file foo
1003 # 0 --- 1 --- 3 rev1 changes file foo
1004 # \ / rev2 renames foo to bar and changes it
1004 # \ / rev2 renames foo to bar and changes it
1005 # \- 2 -/ rev3 should have bar with all changes and
1005 # \- 2 -/ rev3 should have bar with all changes and
1006 # should record that bar descends from
1006 # should record that bar descends from
1007 # bar in rev2 and foo in rev1
1007 # bar in rev2 and foo in rev1
1008 #
1008 #
1009 # this allows this merge to succeed:
1009 # this allows this merge to succeed:
1010 #
1010 #
1011 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
1011 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
1012 # \ / merging rev3 and rev4 should use bar@rev2
1012 # \ / merging rev3 and rev4 should use bar@rev2
1013 # \- 2 --- 4 as the merge base
1013 # \- 2 --- 4 as the merge base
1014 #
1014 #
1015
1015
1016 cfname = copy[0]
1016 cfname = copy[0]
1017 crev = manifest1.get(cfname)
1017 crev = manifest1.get(cfname)
1018 newfparent = fparent2
1018 newfparent = fparent2
1019
1019
1020 if manifest2: # branch merge
1020 if manifest2: # branch merge
1021 if fparent2 == nullid or crev is None: # copied on remote side
1021 if fparent2 == nullid or crev is None: # copied on remote side
1022 if cfname in manifest2:
1022 if cfname in manifest2:
1023 crev = manifest2[cfname]
1023 crev = manifest2[cfname]
1024 newfparent = fparent1
1024 newfparent = fparent1
1025
1025
1026 # find source in nearest ancestor if we've lost track
1026 # find source in nearest ancestor if we've lost track
1027 if not crev:
1027 if not crev:
1028 self.ui.debug(" %s: searching for copy revision for %s\n" %
1028 self.ui.debug(" %s: searching for copy revision for %s\n" %
1029 (fname, cfname))
1029 (fname, cfname))
1030 for ancestor in self[None].ancestors():
1030 for ancestor in self[None].ancestors():
1031 if cfname in ancestor:
1031 if cfname in ancestor:
1032 crev = ancestor[cfname].filenode()
1032 crev = ancestor[cfname].filenode()
1033 break
1033 break
1034
1034
1035 if crev:
1035 if crev:
1036 self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(crev)))
1036 self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(crev)))
1037 meta["copy"] = cfname
1037 meta["copy"] = cfname
1038 meta["copyrev"] = hex(crev)
1038 meta["copyrev"] = hex(crev)
1039 fparent1, fparent2 = nullid, newfparent
1039 fparent1, fparent2 = nullid, newfparent
1040 else:
1040 else:
1041 self.ui.warn(_("warning: can't find ancestor for '%s' "
1041 self.ui.warn(_("warning: can't find ancestor for '%s' "
1042 "copied from '%s'!\n") % (fname, cfname))
1042 "copied from '%s'!\n") % (fname, cfname))
1043
1043
1044 elif fparent2 != nullid:
1044 elif fparent2 != nullid:
1045 # is one parent an ancestor of the other?
1045 # is one parent an ancestor of the other?
1046 fparentancestor = flog.ancestor(fparent1, fparent2)
1046 fparentancestor = flog.ancestor(fparent1, fparent2)
1047 if fparentancestor == fparent1:
1047 if fparentancestor == fparent1:
1048 fparent1, fparent2 = fparent2, nullid
1048 fparent1, fparent2 = fparent2, nullid
1049 elif fparentancestor == fparent2:
1049 elif fparentancestor == fparent2:
1050 fparent2 = nullid
1050 fparent2 = nullid
1051
1051
1052 # is the file changed?
1052 # is the file changed?
1053 if fparent2 != nullid or flog.cmp(fparent1, text) or meta:
1053 if fparent2 != nullid or flog.cmp(fparent1, text) or meta:
1054 changelist.append(fname)
1054 changelist.append(fname)
1055 return flog.add(text, meta, tr, linkrev, fparent1, fparent2)
1055 return flog.add(text, meta, tr, linkrev, fparent1, fparent2)
1056
1056
1057 # are just the flags changed during merge?
1057 # are just the flags changed during merge?
1058 if fparent1 != fparent2o and manifest1.flags(fname) != fctx.flags():
1058 if fparent1 != fparent2o and manifest1.flags(fname) != fctx.flags():
1059 changelist.append(fname)
1059 changelist.append(fname)
1060
1060
1061 return fparent1
1061 return fparent1
1062
1062
1063 def commit(self, text="", user=None, date=None, match=None, force=False,
1063 def commit(self, text="", user=None, date=None, match=None, force=False,
1064 editor=False, extra={}):
1064 editor=False, extra={}):
1065 """Add a new revision to current repository.
1065 """Add a new revision to current repository.
1066
1066
1067 Revision information is gathered from the working directory,
1067 Revision information is gathered from the working directory,
1068 match can be used to filter the committed files. If editor is
1068 match can be used to filter the committed files. If editor is
1069 supplied, it is called to get a commit message.
1069 supplied, it is called to get a commit message.
1070 """
1070 """
1071
1071
1072 def fail(f, msg):
1072 def fail(f, msg):
1073 raise util.Abort('%s: %s' % (f, msg))
1073 raise util.Abort('%s: %s' % (f, msg))
1074
1074
1075 if not match:
1075 if not match:
1076 match = matchmod.always(self.root, '')
1076 match = matchmod.always(self.root, '')
1077
1077
1078 if not force:
1078 if not force:
1079 vdirs = []
1079 vdirs = []
1080 match.dir = vdirs.append
1080 match.dir = vdirs.append
1081 match.bad = fail
1081 match.bad = fail
1082
1082
1083 wlock = self.wlock()
1083 wlock = self.wlock()
1084 try:
1084 try:
1085 wctx = self[None]
1085 wctx = self[None]
1086 merge = len(wctx.parents()) > 1
1086 merge = len(wctx.parents()) > 1
1087
1087
1088 if (not force and merge and match and
1088 if (not force and merge and match and
1089 (match.files() or match.anypats())):
1089 (match.files() or match.anypats())):
1090 raise util.Abort(_('cannot partially commit a merge '
1090 raise util.Abort(_('cannot partially commit a merge '
1091 '(do not specify files or patterns)'))
1091 '(do not specify files or patterns)'))
1092
1092
1093 changes = self.status(match=match, clean=force)
1093 changes = self.status(match=match, clean=force)
1094 if force:
1094 if force:
1095 changes[0].extend(changes[6]) # mq may commit unchanged files
1095 changes[0].extend(changes[6]) # mq may commit unchanged files
1096
1096
1097 # check subrepos
1097 # check subrepos
1098 subs = []
1098 subs = []
1099 removedsubs = set()
1099 commitsubs = set()
1100 newstate = wctx.substate.copy()
1101 # only manage subrepos and .hgsubstate if .hgsub is present
1100 if '.hgsub' in wctx:
1102 if '.hgsub' in wctx:
1101 # only manage subrepos and .hgsubstate if .hgsub is present
1103 # we'll decide whether to track this ourselves, thanks
1104 if '.hgsubstate' in changes[0]:
1105 changes[0].remove('.hgsubstate')
1106 if '.hgsubstate' in changes[2]:
1107 changes[2].remove('.hgsubstate')
1108
1109 # compare current state to last committed state
1110 # build new substate based on last committed state
1111 oldstate = wctx.p1().substate
1112 for s in sorted(newstate.keys()):
1113 if not match(s):
1114 # ignore working copy, use old state if present
1115 if s in oldstate:
1116 newstate[s] = oldstate[s]
1117 continue
1118 if not force:
1119 raise util.Abort(
1120 _("commit with new subrepo %s excluded") % s)
1121 if wctx.sub(s).dirty(True):
1122 if not self.ui.configbool('ui', 'commitsubrepos'):
1123 raise util.Abort(
1124 _("uncommitted changes in subrepo %s") % s,
1125 hint=_("use --subrepos for recursive commit"))
1126 subs.append(s)
1127 commitsubs.add(s)
1128 else:
1129 bs = wctx.sub(s).basestate()
1130 newstate[s] = (newstate[s][0], bs, newstate[s][2])
1131 if oldstate.get(s, (None, None, None))[1] != bs:
1132 subs.append(s)
1133
1134 # check for removed subrepos
1102 for p in wctx.parents():
1135 for p in wctx.parents():
1103 removedsubs.update(s for s in p.substate if match(s))
1136 r = [s for s in p.substate if s not in newstate]
1104 for s in wctx.substate:
1137 subs += [s for s in r if match(s)]
1105 removedsubs.discard(s)
1138 if subs:
1106 if match(s) and wctx.sub(s).dirty():
1107 subs.append(s)
1108 if (subs or removedsubs):
1109 if (not match('.hgsub') and
1139 if (not match('.hgsub') and
1110 '.hgsub' in (wctx.modified() + wctx.added())):
1140 '.hgsub' in (wctx.modified() + wctx.added())):
1111 raise util.Abort(
1141 raise util.Abort(
1112 _("can't commit subrepos without .hgsub"))
1142 _("can't commit subrepos without .hgsub"))
1113 if '.hgsubstate' not in changes[0]:
1114 changes[0].insert(0, '.hgsubstate')
1143 changes[0].insert(0, '.hgsubstate')
1115 if '.hgsubstate' in changes[2]:
1144
1116 changes[2].remove('.hgsubstate')
1117 elif '.hgsub' in changes[2]:
1145 elif '.hgsub' in changes[2]:
1118 # clean up .hgsubstate when .hgsub is removed
1146 # clean up .hgsubstate when .hgsub is removed
1119 if ('.hgsubstate' in wctx and
1147 if ('.hgsubstate' in wctx and
1120 '.hgsubstate' not in changes[0] + changes[1] + changes[2]):
1148 '.hgsubstate' not in changes[0] + changes[1] + changes[2]):
1121 changes[2].insert(0, '.hgsubstate')
1149 changes[2].insert(0, '.hgsubstate')
1122
1150
1123 if subs and not self.ui.configbool('ui', 'commitsubrepos', False):
1124 changedsubs = [s for s in subs if wctx.sub(s).dirty(True)]
1125 if changedsubs:
1126 raise util.Abort(_("uncommitted changes in subrepo %s")
1127 % changedsubs[0],
1128 hint=_("use --subrepos for recursive commit"))
1129
1130 # make sure all explicit patterns are matched
1151 # make sure all explicit patterns are matched
1131 if not force and match.files():
1152 if not force and match.files():
1132 matched = set(changes[0] + changes[1] + changes[2])
1153 matched = set(changes[0] + changes[1] + changes[2])
1133
1154
1134 for f in match.files():
1155 for f in match.files():
1135 if f == '.' or f in matched or f in wctx.substate:
1156 if f == '.' or f in matched or f in wctx.substate:
1136 continue
1157 continue
1137 if f in changes[3]: # missing
1158 if f in changes[3]: # missing
1138 fail(f, _('file not found!'))
1159 fail(f, _('file not found!'))
1139 if f in vdirs: # visited directory
1160 if f in vdirs: # visited directory
1140 d = f + '/'
1161 d = f + '/'
1141 for mf in matched:
1162 for mf in matched:
1142 if mf.startswith(d):
1163 if mf.startswith(d):
1143 break
1164 break
1144 else:
1165 else:
1145 fail(f, _("no match under directory!"))
1166 fail(f, _("no match under directory!"))
1146 elif f not in self.dirstate:
1167 elif f not in self.dirstate:
1147 fail(f, _("file not tracked!"))
1168 fail(f, _("file not tracked!"))
1148
1169
1149 if (not force and not extra.get("close") and not merge
1170 if (not force and not extra.get("close") and not merge
1150 and not (changes[0] or changes[1] or changes[2])
1171 and not (changes[0] or changes[1] or changes[2])
1151 and wctx.branch() == wctx.p1().branch()):
1172 and wctx.branch() == wctx.p1().branch()):
1152 return None
1173 return None
1153
1174
1154 ms = mergemod.mergestate(self)
1175 ms = mergemod.mergestate(self)
1155 for f in changes[0]:
1176 for f in changes[0]:
1156 if f in ms and ms[f] == 'u':
1177 if f in ms and ms[f] == 'u':
1157 raise util.Abort(_("unresolved merge conflicts "
1178 raise util.Abort(_("unresolved merge conflicts "
1158 "(see hg help resolve)"))
1179 "(see hg help resolve)"))
1159
1180
1160 cctx = context.workingctx(self, text, user, date, extra, changes)
1181 cctx = context.workingctx(self, text, user, date, extra, changes)
1161 if editor:
1182 if editor:
1162 cctx._text = editor(self, cctx, subs)
1183 cctx._text = editor(self, cctx, subs)
1163 edited = (text != cctx._text)
1184 edited = (text != cctx._text)
1164
1185
1165 # commit subs
1186 # commit subs and write new state
1166 if subs or removedsubs:
1187 if subs:
1167 state = wctx.substate.copy()
1188 for s in sorted(commitsubs):
1168 for s in sorted(subs):
1169 sub = wctx.sub(s)
1189 sub = wctx.sub(s)
1170 self.ui.status(_('committing subrepository %s\n') %
1190 self.ui.status(_('committing subrepository %s\n') %
1171 subrepo.subrelpath(sub))
1191 subrepo.subrelpath(sub))
1172 sr = sub.commit(cctx._text, user, date)
1192 sr = sub.commit(cctx._text, user, date)
1173 state[s] = (state[s][0], sr)
1193 newstate[s] = (newstate[s][0], sr)
1174 subrepo.writestate(self, state)
1194 subrepo.writestate(self, newstate)
1175
1195
1176 # Save commit message in case this transaction gets rolled back
1196 # Save commit message in case this transaction gets rolled back
1177 # (e.g. by a pretxncommit hook). Leave the content alone on
1197 # (e.g. by a pretxncommit hook). Leave the content alone on
1178 # the assumption that the user will use the same editor again.
1198 # the assumption that the user will use the same editor again.
1179 msgfn = self.savecommitmessage(cctx._text)
1199 msgfn = self.savecommitmessage(cctx._text)
1180
1200
1181 p1, p2 = self.dirstate.parents()
1201 p1, p2 = self.dirstate.parents()
1182 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
1202 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
1183 try:
1203 try:
1184 self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
1204 self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
1185 ret = self.commitctx(cctx, True)
1205 ret = self.commitctx(cctx, True)
1186 except:
1206 except:
1187 if edited:
1207 if edited:
1188 self.ui.write(
1208 self.ui.write(
1189 _('note: commit message saved in %s\n') % msgfn)
1209 _('note: commit message saved in %s\n') % msgfn)
1190 raise
1210 raise
1191
1211
1192 # update bookmarks, dirstate and mergestate
1212 # update bookmarks, dirstate and mergestate
1193 bookmarks.update(self, p1, ret)
1213 bookmarks.update(self, p1, ret)
1194 for f in changes[0] + changes[1]:
1214 for f in changes[0] + changes[1]:
1195 self.dirstate.normal(f)
1215 self.dirstate.normal(f)
1196 for f in changes[2]:
1216 for f in changes[2]:
1197 self.dirstate.drop(f)
1217 self.dirstate.drop(f)
1198 self.dirstate.setparents(ret)
1218 self.dirstate.setparents(ret)
1199 ms.reset()
1219 ms.reset()
1200 finally:
1220 finally:
1201 wlock.release()
1221 wlock.release()
1202
1222
1203 self.hook("commit", node=hex(ret), parent1=hookp1, parent2=hookp2)
1223 self.hook("commit", node=hex(ret), parent1=hookp1, parent2=hookp2)
1204 return ret
1224 return ret
1205
1225
1206 def commitctx(self, ctx, error=False):
1226 def commitctx(self, ctx, error=False):
1207 """Add a new revision to current repository.
1227 """Add a new revision to current repository.
1208 Revision information is passed via the context argument.
1228 Revision information is passed via the context argument.
1209 """
1229 """
1210
1230
1211 tr = lock = None
1231 tr = lock = None
1212 removed = list(ctx.removed())
1232 removed = list(ctx.removed())
1213 p1, p2 = ctx.p1(), ctx.p2()
1233 p1, p2 = ctx.p1(), ctx.p2()
1214 user = ctx.user()
1234 user = ctx.user()
1215
1235
1216 lock = self.lock()
1236 lock = self.lock()
1217 try:
1237 try:
1218 tr = self.transaction("commit")
1238 tr = self.transaction("commit")
1219 trp = weakref.proxy(tr)
1239 trp = weakref.proxy(tr)
1220
1240
1221 if ctx.files():
1241 if ctx.files():
1222 m1 = p1.manifest().copy()
1242 m1 = p1.manifest().copy()
1223 m2 = p2.manifest()
1243 m2 = p2.manifest()
1224
1244
1225 # check in files
1245 # check in files
1226 new = {}
1246 new = {}
1227 changed = []
1247 changed = []
1228 linkrev = len(self)
1248 linkrev = len(self)
1229 for f in sorted(ctx.modified() + ctx.added()):
1249 for f in sorted(ctx.modified() + ctx.added()):
1230 self.ui.note(f + "\n")
1250 self.ui.note(f + "\n")
1231 try:
1251 try:
1232 fctx = ctx[f]
1252 fctx = ctx[f]
1233 new[f] = self._filecommit(fctx, m1, m2, linkrev, trp,
1253 new[f] = self._filecommit(fctx, m1, m2, linkrev, trp,
1234 changed)
1254 changed)
1235 m1.set(f, fctx.flags())
1255 m1.set(f, fctx.flags())
1236 except OSError, inst:
1256 except OSError, inst:
1237 self.ui.warn(_("trouble committing %s!\n") % f)
1257 self.ui.warn(_("trouble committing %s!\n") % f)
1238 raise
1258 raise
1239 except IOError, inst:
1259 except IOError, inst:
1240 errcode = getattr(inst, 'errno', errno.ENOENT)
1260 errcode = getattr(inst, 'errno', errno.ENOENT)
1241 if error or errcode and errcode != errno.ENOENT:
1261 if error or errcode and errcode != errno.ENOENT:
1242 self.ui.warn(_("trouble committing %s!\n") % f)
1262 self.ui.warn(_("trouble committing %s!\n") % f)
1243 raise
1263 raise
1244 else:
1264 else:
1245 removed.append(f)
1265 removed.append(f)
1246
1266
1247 # update manifest
1267 # update manifest
1248 m1.update(new)
1268 m1.update(new)
1249 removed = [f for f in sorted(removed) if f in m1 or f in m2]
1269 removed = [f for f in sorted(removed) if f in m1 or f in m2]
1250 drop = [f for f in removed if f in m1]
1270 drop = [f for f in removed if f in m1]
1251 for f in drop:
1271 for f in drop:
1252 del m1[f]
1272 del m1[f]
1253 mn = self.manifest.add(m1, trp, linkrev, p1.manifestnode(),
1273 mn = self.manifest.add(m1, trp, linkrev, p1.manifestnode(),
1254 p2.manifestnode(), (new, drop))
1274 p2.manifestnode(), (new, drop))
1255 files = changed + removed
1275 files = changed + removed
1256 else:
1276 else:
1257 mn = p1.manifestnode()
1277 mn = p1.manifestnode()
1258 files = []
1278 files = []
1259
1279
1260 # update changelog
1280 # update changelog
1261 self.changelog.delayupdate()
1281 self.changelog.delayupdate()
1262 n = self.changelog.add(mn, files, ctx.description(),
1282 n = self.changelog.add(mn, files, ctx.description(),
1263 trp, p1.node(), p2.node(),
1283 trp, p1.node(), p2.node(),
1264 user, ctx.date(), ctx.extra().copy())
1284 user, ctx.date(), ctx.extra().copy())
1265 p = lambda: self.changelog.writepending() and self.root or ""
1285 p = lambda: self.changelog.writepending() and self.root or ""
1266 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
1286 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
1267 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
1287 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
1268 parent2=xp2, pending=p)
1288 parent2=xp2, pending=p)
1269 self.changelog.finalize(trp)
1289 self.changelog.finalize(trp)
1270 # set the new commit is proper phase
1290 # set the new commit is proper phase
1271 targetphase = phases.newcommitphase(self.ui)
1291 targetphase = phases.newcommitphase(self.ui)
1272 if targetphase:
1292 if targetphase:
1273 # retract boundary do not alter parent changeset.
1293 # retract boundary do not alter parent changeset.
1274 # if a parent have higher the resulting phase will
1294 # if a parent have higher the resulting phase will
1275 # be compliant anyway
1295 # be compliant anyway
1276 #
1296 #
1277 # if minimal phase was 0 we don't need to retract anything
1297 # if minimal phase was 0 we don't need to retract anything
1278 phases.retractboundary(self, targetphase, [n])
1298 phases.retractboundary(self, targetphase, [n])
1279 tr.close()
1299 tr.close()
1280 self.updatebranchcache()
1300 self.updatebranchcache()
1281 return n
1301 return n
1282 finally:
1302 finally:
1283 if tr:
1303 if tr:
1284 tr.release()
1304 tr.release()
1285 lock.release()
1305 lock.release()
1286
1306
1287 def destroyed(self):
1307 def destroyed(self):
1288 '''Inform the repository that nodes have been destroyed.
1308 '''Inform the repository that nodes have been destroyed.
1289 Intended for use by strip and rollback, so there's a common
1309 Intended for use by strip and rollback, so there's a common
1290 place for anything that has to be done after destroying history.'''
1310 place for anything that has to be done after destroying history.'''
1291 # XXX it might be nice if we could take the list of destroyed
1311 # XXX it might be nice if we could take the list of destroyed
1292 # nodes, but I don't see an easy way for rollback() to do that
1312 # nodes, but I don't see an easy way for rollback() to do that
1293
1313
1294 # Ensure the persistent tag cache is updated. Doing it now
1314 # Ensure the persistent tag cache is updated. Doing it now
1295 # means that the tag cache only has to worry about destroyed
1315 # means that the tag cache only has to worry about destroyed
1296 # heads immediately after a strip/rollback. That in turn
1316 # heads immediately after a strip/rollback. That in turn
1297 # guarantees that "cachetip == currenttip" (comparing both rev
1317 # guarantees that "cachetip == currenttip" (comparing both rev
1298 # and node) always means no nodes have been added or destroyed.
1318 # and node) always means no nodes have been added or destroyed.
1299
1319
1300 # XXX this is suboptimal when qrefresh'ing: we strip the current
1320 # XXX this is suboptimal when qrefresh'ing: we strip the current
1301 # head, refresh the tag cache, then immediately add a new head.
1321 # head, refresh the tag cache, then immediately add a new head.
1302 # But I think doing it this way is necessary for the "instant
1322 # But I think doing it this way is necessary for the "instant
1303 # tag cache retrieval" case to work.
1323 # tag cache retrieval" case to work.
1304 self.invalidatecaches()
1324 self.invalidatecaches()
1305
1325
1306 def walk(self, match, node=None):
1326 def walk(self, match, node=None):
1307 '''
1327 '''
1308 walk recursively through the directory tree or a given
1328 walk recursively through the directory tree or a given
1309 changeset, finding all files matched by the match
1329 changeset, finding all files matched by the match
1310 function
1330 function
1311 '''
1331 '''
1312 return self[node].walk(match)
1332 return self[node].walk(match)
1313
1333
1314 def status(self, node1='.', node2=None, match=None,
1334 def status(self, node1='.', node2=None, match=None,
1315 ignored=False, clean=False, unknown=False,
1335 ignored=False, clean=False, unknown=False,
1316 listsubrepos=False):
1336 listsubrepos=False):
1317 """return status of files between two nodes or node and working directory
1337 """return status of files between two nodes or node and working directory
1318
1338
1319 If node1 is None, use the first dirstate parent instead.
1339 If node1 is None, use the first dirstate parent instead.
1320 If node2 is None, compare node1 with working directory.
1340 If node2 is None, compare node1 with working directory.
1321 """
1341 """
1322
1342
1323 def mfmatches(ctx):
1343 def mfmatches(ctx):
1324 mf = ctx.manifest().copy()
1344 mf = ctx.manifest().copy()
1325 for fn in mf.keys():
1345 for fn in mf.keys():
1326 if not match(fn):
1346 if not match(fn):
1327 del mf[fn]
1347 del mf[fn]
1328 return mf
1348 return mf
1329
1349
1330 if isinstance(node1, context.changectx):
1350 if isinstance(node1, context.changectx):
1331 ctx1 = node1
1351 ctx1 = node1
1332 else:
1352 else:
1333 ctx1 = self[node1]
1353 ctx1 = self[node1]
1334 if isinstance(node2, context.changectx):
1354 if isinstance(node2, context.changectx):
1335 ctx2 = node2
1355 ctx2 = node2
1336 else:
1356 else:
1337 ctx2 = self[node2]
1357 ctx2 = self[node2]
1338
1358
1339 working = ctx2.rev() is None
1359 working = ctx2.rev() is None
1340 parentworking = working and ctx1 == self['.']
1360 parentworking = working and ctx1 == self['.']
1341 match = match or matchmod.always(self.root, self.getcwd())
1361 match = match or matchmod.always(self.root, self.getcwd())
1342 listignored, listclean, listunknown = ignored, clean, unknown
1362 listignored, listclean, listunknown = ignored, clean, unknown
1343
1363
1344 # load earliest manifest first for caching reasons
1364 # load earliest manifest first for caching reasons
1345 if not working and ctx2.rev() < ctx1.rev():
1365 if not working and ctx2.rev() < ctx1.rev():
1346 ctx2.manifest()
1366 ctx2.manifest()
1347
1367
1348 if not parentworking:
1368 if not parentworking:
1349 def bad(f, msg):
1369 def bad(f, msg):
1350 if f not in ctx1:
1370 if f not in ctx1:
1351 self.ui.warn('%s: %s\n' % (self.dirstate.pathto(f), msg))
1371 self.ui.warn('%s: %s\n' % (self.dirstate.pathto(f), msg))
1352 match.bad = bad
1372 match.bad = bad
1353
1373
1354 if working: # we need to scan the working dir
1374 if working: # we need to scan the working dir
1355 subrepos = []
1375 subrepos = []
1356 if '.hgsub' in self.dirstate:
1376 if '.hgsub' in self.dirstate:
1357 subrepos = ctx2.substate.keys()
1377 subrepos = ctx2.substate.keys()
1358 s = self.dirstate.status(match, subrepos, listignored,
1378 s = self.dirstate.status(match, subrepos, listignored,
1359 listclean, listunknown)
1379 listclean, listunknown)
1360 cmp, modified, added, removed, deleted, unknown, ignored, clean = s
1380 cmp, modified, added, removed, deleted, unknown, ignored, clean = s
1361
1381
1362 # check for any possibly clean files
1382 # check for any possibly clean files
1363 if parentworking and cmp:
1383 if parentworking and cmp:
1364 fixup = []
1384 fixup = []
1365 # do a full compare of any files that might have changed
1385 # do a full compare of any files that might have changed
1366 for f in sorted(cmp):
1386 for f in sorted(cmp):
1367 if (f not in ctx1 or ctx2.flags(f) != ctx1.flags(f)
1387 if (f not in ctx1 or ctx2.flags(f) != ctx1.flags(f)
1368 or ctx1[f].cmp(ctx2[f])):
1388 or ctx1[f].cmp(ctx2[f])):
1369 modified.append(f)
1389 modified.append(f)
1370 else:
1390 else:
1371 fixup.append(f)
1391 fixup.append(f)
1372
1392
1373 # update dirstate for files that are actually clean
1393 # update dirstate for files that are actually clean
1374 if fixup:
1394 if fixup:
1375 if listclean:
1395 if listclean:
1376 clean += fixup
1396 clean += fixup
1377
1397
1378 try:
1398 try:
1379 # updating the dirstate is optional
1399 # updating the dirstate is optional
1380 # so we don't wait on the lock
1400 # so we don't wait on the lock
1381 wlock = self.wlock(False)
1401 wlock = self.wlock(False)
1382 try:
1402 try:
1383 for f in fixup:
1403 for f in fixup:
1384 self.dirstate.normal(f)
1404 self.dirstate.normal(f)
1385 finally:
1405 finally:
1386 wlock.release()
1406 wlock.release()
1387 except error.LockError:
1407 except error.LockError:
1388 pass
1408 pass
1389
1409
1390 if not parentworking:
1410 if not parentworking:
1391 mf1 = mfmatches(ctx1)
1411 mf1 = mfmatches(ctx1)
1392 if working:
1412 if working:
1393 # we are comparing working dir against non-parent
1413 # we are comparing working dir against non-parent
1394 # generate a pseudo-manifest for the working dir
1414 # generate a pseudo-manifest for the working dir
1395 mf2 = mfmatches(self['.'])
1415 mf2 = mfmatches(self['.'])
1396 for f in cmp + modified + added:
1416 for f in cmp + modified + added:
1397 mf2[f] = None
1417 mf2[f] = None
1398 mf2.set(f, ctx2.flags(f))
1418 mf2.set(f, ctx2.flags(f))
1399 for f in removed:
1419 for f in removed:
1400 if f in mf2:
1420 if f in mf2:
1401 del mf2[f]
1421 del mf2[f]
1402 else:
1422 else:
1403 # we are comparing two revisions
1423 # we are comparing two revisions
1404 deleted, unknown, ignored = [], [], []
1424 deleted, unknown, ignored = [], [], []
1405 mf2 = mfmatches(ctx2)
1425 mf2 = mfmatches(ctx2)
1406
1426
1407 modified, added, clean = [], [], []
1427 modified, added, clean = [], [], []
1408 for fn in mf2:
1428 for fn in mf2:
1409 if fn in mf1:
1429 if fn in mf1:
1410 if (fn not in deleted and
1430 if (fn not in deleted and
1411 (mf1.flags(fn) != mf2.flags(fn) or
1431 (mf1.flags(fn) != mf2.flags(fn) or
1412 (mf1[fn] != mf2[fn] and
1432 (mf1[fn] != mf2[fn] and
1413 (mf2[fn] or ctx1[fn].cmp(ctx2[fn]))))):
1433 (mf2[fn] or ctx1[fn].cmp(ctx2[fn]))))):
1414 modified.append(fn)
1434 modified.append(fn)
1415 elif listclean:
1435 elif listclean:
1416 clean.append(fn)
1436 clean.append(fn)
1417 del mf1[fn]
1437 del mf1[fn]
1418 elif fn not in deleted:
1438 elif fn not in deleted:
1419 added.append(fn)
1439 added.append(fn)
1420 removed = mf1.keys()
1440 removed = mf1.keys()
1421
1441
1422 if working and modified and not self.dirstate._checklink:
1442 if working and modified and not self.dirstate._checklink:
1423 # Symlink placeholders may get non-symlink-like contents
1443 # Symlink placeholders may get non-symlink-like contents
1424 # via user error or dereferencing by NFS or Samba servers,
1444 # via user error or dereferencing by NFS or Samba servers,
1425 # so we filter out any placeholders that don't look like a
1445 # so we filter out any placeholders that don't look like a
1426 # symlink
1446 # symlink
1427 sane = []
1447 sane = []
1428 for f in modified:
1448 for f in modified:
1429 if ctx2.flags(f) == 'l':
1449 if ctx2.flags(f) == 'l':
1430 d = ctx2[f].data()
1450 d = ctx2[f].data()
1431 if len(d) >= 1024 or '\n' in d or util.binary(d):
1451 if len(d) >= 1024 or '\n' in d or util.binary(d):
1432 self.ui.debug('ignoring suspect symlink placeholder'
1452 self.ui.debug('ignoring suspect symlink placeholder'
1433 ' "%s"\n' % f)
1453 ' "%s"\n' % f)
1434 continue
1454 continue
1435 sane.append(f)
1455 sane.append(f)
1436 modified = sane
1456 modified = sane
1437
1457
1438 r = modified, added, removed, deleted, unknown, ignored, clean
1458 r = modified, added, removed, deleted, unknown, ignored, clean
1439
1459
1440 if listsubrepos:
1460 if listsubrepos:
1441 for subpath, sub in subrepo.itersubrepos(ctx1, ctx2):
1461 for subpath, sub in subrepo.itersubrepos(ctx1, ctx2):
1442 if working:
1462 if working:
1443 rev2 = None
1463 rev2 = None
1444 else:
1464 else:
1445 rev2 = ctx2.substate[subpath][1]
1465 rev2 = ctx2.substate[subpath][1]
1446 try:
1466 try:
1447 submatch = matchmod.narrowmatcher(subpath, match)
1467 submatch = matchmod.narrowmatcher(subpath, match)
1448 s = sub.status(rev2, match=submatch, ignored=listignored,
1468 s = sub.status(rev2, match=submatch, ignored=listignored,
1449 clean=listclean, unknown=listunknown,
1469 clean=listclean, unknown=listunknown,
1450 listsubrepos=True)
1470 listsubrepos=True)
1451 for rfiles, sfiles in zip(r, s):
1471 for rfiles, sfiles in zip(r, s):
1452 rfiles.extend("%s/%s" % (subpath, f) for f in sfiles)
1472 rfiles.extend("%s/%s" % (subpath, f) for f in sfiles)
1453 except error.LookupError:
1473 except error.LookupError:
1454 self.ui.status(_("skipping missing subrepository: %s\n")
1474 self.ui.status(_("skipping missing subrepository: %s\n")
1455 % subpath)
1475 % subpath)
1456
1476
1457 for l in r:
1477 for l in r:
1458 l.sort()
1478 l.sort()
1459 return r
1479 return r
1460
1480
1461 def heads(self, start=None):
1481 def heads(self, start=None):
1462 heads = self.changelog.heads(start)
1482 heads = self.changelog.heads(start)
1463 # sort the output in rev descending order
1483 # sort the output in rev descending order
1464 return sorted(heads, key=self.changelog.rev, reverse=True)
1484 return sorted(heads, key=self.changelog.rev, reverse=True)
1465
1485
1466 def branchheads(self, branch=None, start=None, closed=False):
1486 def branchheads(self, branch=None, start=None, closed=False):
1467 '''return a (possibly filtered) list of heads for the given branch
1487 '''return a (possibly filtered) list of heads for the given branch
1468
1488
1469 Heads are returned in topological order, from newest to oldest.
1489 Heads are returned in topological order, from newest to oldest.
1470 If branch is None, use the dirstate branch.
1490 If branch is None, use the dirstate branch.
1471 If start is not None, return only heads reachable from start.
1491 If start is not None, return only heads reachable from start.
1472 If closed is True, return heads that are marked as closed as well.
1492 If closed is True, return heads that are marked as closed as well.
1473 '''
1493 '''
1474 if branch is None:
1494 if branch is None:
1475 branch = self[None].branch()
1495 branch = self[None].branch()
1476 branches = self.branchmap()
1496 branches = self.branchmap()
1477 if branch not in branches:
1497 if branch not in branches:
1478 return []
1498 return []
1479 # the cache returns heads ordered lowest to highest
1499 # the cache returns heads ordered lowest to highest
1480 bheads = list(reversed(branches[branch]))
1500 bheads = list(reversed(branches[branch]))
1481 if start is not None:
1501 if start is not None:
1482 # filter out the heads that cannot be reached from startrev
1502 # filter out the heads that cannot be reached from startrev
1483 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
1503 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
1484 bheads = [h for h in bheads if h in fbheads]
1504 bheads = [h for h in bheads if h in fbheads]
1485 if not closed:
1505 if not closed:
1486 bheads = [h for h in bheads if
1506 bheads = [h for h in bheads if
1487 ('close' not in self.changelog.read(h)[5])]
1507 ('close' not in self.changelog.read(h)[5])]
1488 return bheads
1508 return bheads
1489
1509
1490 def branches(self, nodes):
1510 def branches(self, nodes):
1491 if not nodes:
1511 if not nodes:
1492 nodes = [self.changelog.tip()]
1512 nodes = [self.changelog.tip()]
1493 b = []
1513 b = []
1494 for n in nodes:
1514 for n in nodes:
1495 t = n
1515 t = n
1496 while True:
1516 while True:
1497 p = self.changelog.parents(n)
1517 p = self.changelog.parents(n)
1498 if p[1] != nullid or p[0] == nullid:
1518 if p[1] != nullid or p[0] == nullid:
1499 b.append((t, n, p[0], p[1]))
1519 b.append((t, n, p[0], p[1]))
1500 break
1520 break
1501 n = p[0]
1521 n = p[0]
1502 return b
1522 return b
1503
1523
1504 def between(self, pairs):
1524 def between(self, pairs):
1505 r = []
1525 r = []
1506
1526
1507 for top, bottom in pairs:
1527 for top, bottom in pairs:
1508 n, l, i = top, [], 0
1528 n, l, i = top, [], 0
1509 f = 1
1529 f = 1
1510
1530
1511 while n != bottom and n != nullid:
1531 while n != bottom and n != nullid:
1512 p = self.changelog.parents(n)[0]
1532 p = self.changelog.parents(n)[0]
1513 if i == f:
1533 if i == f:
1514 l.append(n)
1534 l.append(n)
1515 f = f * 2
1535 f = f * 2
1516 n = p
1536 n = p
1517 i += 1
1537 i += 1
1518
1538
1519 r.append(l)
1539 r.append(l)
1520
1540
1521 return r
1541 return r
1522
1542
1523 def pull(self, remote, heads=None, force=False):
1543 def pull(self, remote, heads=None, force=False):
1524 lock = self.lock()
1544 lock = self.lock()
1525 try:
1545 try:
1526 tmp = discovery.findcommonincoming(self, remote, heads=heads,
1546 tmp = discovery.findcommonincoming(self, remote, heads=heads,
1527 force=force)
1547 force=force)
1528 common, fetch, rheads = tmp
1548 common, fetch, rheads = tmp
1529 if not fetch:
1549 if not fetch:
1530 self.ui.status(_("no changes found\n"))
1550 self.ui.status(_("no changes found\n"))
1531 added = []
1551 added = []
1532 result = 0
1552 result = 0
1533 else:
1553 else:
1534 if heads is None and list(common) == [nullid]:
1554 if heads is None and list(common) == [nullid]:
1535 self.ui.status(_("requesting all changes\n"))
1555 self.ui.status(_("requesting all changes\n"))
1536 elif heads is None and remote.capable('changegroupsubset'):
1556 elif heads is None and remote.capable('changegroupsubset'):
1537 # issue1320, avoid a race if remote changed after discovery
1557 # issue1320, avoid a race if remote changed after discovery
1538 heads = rheads
1558 heads = rheads
1539
1559
1540 if remote.capable('getbundle'):
1560 if remote.capable('getbundle'):
1541 cg = remote.getbundle('pull', common=common,
1561 cg = remote.getbundle('pull', common=common,
1542 heads=heads or rheads)
1562 heads=heads or rheads)
1543 elif heads is None:
1563 elif heads is None:
1544 cg = remote.changegroup(fetch, 'pull')
1564 cg = remote.changegroup(fetch, 'pull')
1545 elif not remote.capable('changegroupsubset'):
1565 elif not remote.capable('changegroupsubset'):
1546 raise util.Abort(_("partial pull cannot be done because "
1566 raise util.Abort(_("partial pull cannot be done because "
1547 "other repository doesn't support "
1567 "other repository doesn't support "
1548 "changegroupsubset."))
1568 "changegroupsubset."))
1549 else:
1569 else:
1550 cg = remote.changegroupsubset(fetch, heads, 'pull')
1570 cg = remote.changegroupsubset(fetch, heads, 'pull')
1551 clstart = len(self.changelog)
1571 clstart = len(self.changelog)
1552 result = self.addchangegroup(cg, 'pull', remote.url())
1572 result = self.addchangegroup(cg, 'pull', remote.url())
1553 clend = len(self.changelog)
1573 clend = len(self.changelog)
1554 added = [self.changelog.node(r) for r in xrange(clstart, clend)]
1574 added = [self.changelog.node(r) for r in xrange(clstart, clend)]
1555
1575
1556 # compute target subset
1576 # compute target subset
1557 if heads is None:
1577 if heads is None:
1558 # We pulled every thing possible
1578 # We pulled every thing possible
1559 # sync on everything common
1579 # sync on everything common
1560 subset = common + added
1580 subset = common + added
1561 else:
1581 else:
1562 # We pulled a specific subset
1582 # We pulled a specific subset
1563 # sync on this subset
1583 # sync on this subset
1564 subset = heads
1584 subset = heads
1565
1585
1566 # Get remote phases data from remote
1586 # Get remote phases data from remote
1567 remotephases = remote.listkeys('phases')
1587 remotephases = remote.listkeys('phases')
1568 publishing = bool(remotephases.get('publishing', False))
1588 publishing = bool(remotephases.get('publishing', False))
1569 if remotephases and not publishing:
1589 if remotephases and not publishing:
1570 # remote is new and unpublishing
1590 # remote is new and unpublishing
1571 pheads, _dr = phases.analyzeremotephases(self, subset,
1591 pheads, _dr = phases.analyzeremotephases(self, subset,
1572 remotephases)
1592 remotephases)
1573 phases.advanceboundary(self, phases.public, pheads)
1593 phases.advanceboundary(self, phases.public, pheads)
1574 phases.advanceboundary(self, phases.draft, subset)
1594 phases.advanceboundary(self, phases.draft, subset)
1575 else:
1595 else:
1576 # Remote is old or publishing all common changesets
1596 # Remote is old or publishing all common changesets
1577 # should be seen as public
1597 # should be seen as public
1578 phases.advanceboundary(self, phases.public, subset)
1598 phases.advanceboundary(self, phases.public, subset)
1579 finally:
1599 finally:
1580 lock.release()
1600 lock.release()
1581
1601
1582 return result
1602 return result
1583
1603
1584 def checkpush(self, force, revs):
1604 def checkpush(self, force, revs):
1585 """Extensions can override this function if additional checks have
1605 """Extensions can override this function if additional checks have
1586 to be performed before pushing, or call it if they override push
1606 to be performed before pushing, or call it if they override push
1587 command.
1607 command.
1588 """
1608 """
1589 pass
1609 pass
1590
1610
1591 def push(self, remote, force=False, revs=None, newbranch=False):
1611 def push(self, remote, force=False, revs=None, newbranch=False):
1592 '''Push outgoing changesets (limited by revs) from the current
1612 '''Push outgoing changesets (limited by revs) from the current
1593 repository to remote. Return an integer:
1613 repository to remote. Return an integer:
1594 - None means nothing to push
1614 - None means nothing to push
1595 - 0 means HTTP error
1615 - 0 means HTTP error
1596 - 1 means we pushed and remote head count is unchanged *or*
1616 - 1 means we pushed and remote head count is unchanged *or*
1597 we have outgoing changesets but refused to push
1617 we have outgoing changesets but refused to push
1598 - other values as described by addchangegroup()
1618 - other values as described by addchangegroup()
1599 '''
1619 '''
1600 # there are two ways to push to remote repo:
1620 # there are two ways to push to remote repo:
1601 #
1621 #
1602 # addchangegroup assumes local user can lock remote
1622 # addchangegroup assumes local user can lock remote
1603 # repo (local filesystem, old ssh servers).
1623 # repo (local filesystem, old ssh servers).
1604 #
1624 #
1605 # unbundle assumes local user cannot lock remote repo (new ssh
1625 # unbundle assumes local user cannot lock remote repo (new ssh
1606 # servers, http servers).
1626 # servers, http servers).
1607
1627
1608 # get local lock as we might write phase data
1628 # get local lock as we might write phase data
1609 locallock = self.lock()
1629 locallock = self.lock()
1610 try:
1630 try:
1611 self.checkpush(force, revs)
1631 self.checkpush(force, revs)
1612 lock = None
1632 lock = None
1613 unbundle = remote.capable('unbundle')
1633 unbundle = remote.capable('unbundle')
1614 if not unbundle:
1634 if not unbundle:
1615 lock = remote.lock()
1635 lock = remote.lock()
1616 try:
1636 try:
1617 # discovery
1637 # discovery
1618 fci = discovery.findcommonincoming
1638 fci = discovery.findcommonincoming
1619 commoninc = fci(self, remote, force=force)
1639 commoninc = fci(self, remote, force=force)
1620 common, inc, remoteheads = commoninc
1640 common, inc, remoteheads = commoninc
1621 fco = discovery.findcommonoutgoing
1641 fco = discovery.findcommonoutgoing
1622 outgoing = fco(self, remote, onlyheads=revs,
1642 outgoing = fco(self, remote, onlyheads=revs,
1623 commoninc=commoninc, force=force)
1643 commoninc=commoninc, force=force)
1624
1644
1625
1645
1626 if not outgoing.missing:
1646 if not outgoing.missing:
1627 # nothing to push
1647 # nothing to push
1628 scmutil.nochangesfound(self.ui, outgoing.excluded)
1648 scmutil.nochangesfound(self.ui, outgoing.excluded)
1629 ret = None
1649 ret = None
1630 else:
1650 else:
1631 # something to push
1651 # something to push
1632 if not force:
1652 if not force:
1633 discovery.checkheads(self, remote, outgoing,
1653 discovery.checkheads(self, remote, outgoing,
1634 remoteheads, newbranch,
1654 remoteheads, newbranch,
1635 bool(inc))
1655 bool(inc))
1636
1656
1637 # create a changegroup from local
1657 # create a changegroup from local
1638 if revs is None and not outgoing.excluded:
1658 if revs is None and not outgoing.excluded:
1639 # push everything,
1659 # push everything,
1640 # use the fast path, no race possible on push
1660 # use the fast path, no race possible on push
1641 cg = self._changegroup(outgoing.missing, 'push')
1661 cg = self._changegroup(outgoing.missing, 'push')
1642 else:
1662 else:
1643 cg = self.getlocalbundle('push', outgoing)
1663 cg = self.getlocalbundle('push', outgoing)
1644
1664
1645 # apply changegroup to remote
1665 # apply changegroup to remote
1646 if unbundle:
1666 if unbundle:
1647 # local repo finds heads on server, finds out what
1667 # local repo finds heads on server, finds out what
1648 # revs it must push. once revs transferred, if server
1668 # revs it must push. once revs transferred, if server
1649 # finds it has different heads (someone else won
1669 # finds it has different heads (someone else won
1650 # commit/push race), server aborts.
1670 # commit/push race), server aborts.
1651 if force:
1671 if force:
1652 remoteheads = ['force']
1672 remoteheads = ['force']
1653 # ssh: return remote's addchangegroup()
1673 # ssh: return remote's addchangegroup()
1654 # http: return remote's addchangegroup() or 0 for error
1674 # http: return remote's addchangegroup() or 0 for error
1655 ret = remote.unbundle(cg, remoteheads, 'push')
1675 ret = remote.unbundle(cg, remoteheads, 'push')
1656 else:
1676 else:
1657 # we return an integer indicating remote head count change
1677 # we return an integer indicating remote head count change
1658 ret = remote.addchangegroup(cg, 'push', self.url())
1678 ret = remote.addchangegroup(cg, 'push', self.url())
1659
1679
1660 if ret:
1680 if ret:
1661 # push succeed, synchonize target of the push
1681 # push succeed, synchonize target of the push
1662 cheads = outgoing.missingheads
1682 cheads = outgoing.missingheads
1663 elif revs is None:
1683 elif revs is None:
1664 # All out push fails. synchronize all common
1684 # All out push fails. synchronize all common
1665 cheads = outgoing.commonheads
1685 cheads = outgoing.commonheads
1666 else:
1686 else:
1667 # I want cheads = heads(::missingheads and ::commonheads)
1687 # I want cheads = heads(::missingheads and ::commonheads)
1668 # (missingheads is revs with secret changeset filtered out)
1688 # (missingheads is revs with secret changeset filtered out)
1669 #
1689 #
1670 # This can be expressed as:
1690 # This can be expressed as:
1671 # cheads = ( (missingheads and ::commonheads)
1691 # cheads = ( (missingheads and ::commonheads)
1672 # + (commonheads and ::missingheads))"
1692 # + (commonheads and ::missingheads))"
1673 # )
1693 # )
1674 #
1694 #
1675 # while trying to push we already computed the following:
1695 # while trying to push we already computed the following:
1676 # common = (::commonheads)
1696 # common = (::commonheads)
1677 # missing = ((commonheads::missingheads) - commonheads)
1697 # missing = ((commonheads::missingheads) - commonheads)
1678 #
1698 #
1679 # We can pick:
1699 # We can pick:
1680 # * missingheads part of comon (::commonheads)
1700 # * missingheads part of comon (::commonheads)
1681 common = set(outgoing.common)
1701 common = set(outgoing.common)
1682 cheads = [node for node in revs if node in common]
1702 cheads = [node for node in revs if node in common]
1683 # and
1703 # and
1684 # * commonheads parents on missing
1704 # * commonheads parents on missing
1685 revset = self.set('%ln and parents(roots(%ln))',
1705 revset = self.set('%ln and parents(roots(%ln))',
1686 outgoing.commonheads,
1706 outgoing.commonheads,
1687 outgoing.missing)
1707 outgoing.missing)
1688 cheads.extend(c.node() for c in revset)
1708 cheads.extend(c.node() for c in revset)
1689 # even when we don't push, exchanging phase data is useful
1709 # even when we don't push, exchanging phase data is useful
1690 remotephases = remote.listkeys('phases')
1710 remotephases = remote.listkeys('phases')
1691 if not remotephases: # old server or public only repo
1711 if not remotephases: # old server or public only repo
1692 phases.advanceboundary(self, phases.public, cheads)
1712 phases.advanceboundary(self, phases.public, cheads)
1693 # don't push any phase data as there is nothing to push
1713 # don't push any phase data as there is nothing to push
1694 else:
1714 else:
1695 ana = phases.analyzeremotephases(self, cheads, remotephases)
1715 ana = phases.analyzeremotephases(self, cheads, remotephases)
1696 pheads, droots = ana
1716 pheads, droots = ana
1697 ### Apply remote phase on local
1717 ### Apply remote phase on local
1698 if remotephases.get('publishing', False):
1718 if remotephases.get('publishing', False):
1699 phases.advanceboundary(self, phases.public, cheads)
1719 phases.advanceboundary(self, phases.public, cheads)
1700 else: # publish = False
1720 else: # publish = False
1701 phases.advanceboundary(self, phases.public, pheads)
1721 phases.advanceboundary(self, phases.public, pheads)
1702 phases.advanceboundary(self, phases.draft, cheads)
1722 phases.advanceboundary(self, phases.draft, cheads)
1703 ### Apply local phase on remote
1723 ### Apply local phase on remote
1704
1724
1705 # Get the list of all revs draft on remote by public here.
1725 # Get the list of all revs draft on remote by public here.
1706 # XXX Beware that revset break if droots is not strictly
1726 # XXX Beware that revset break if droots is not strictly
1707 # XXX root we may want to ensure it is but it is costly
1727 # XXX root we may want to ensure it is but it is costly
1708 outdated = self.set('heads((%ln::%ln) and public())',
1728 outdated = self.set('heads((%ln::%ln) and public())',
1709 droots, cheads)
1729 droots, cheads)
1710 for newremotehead in outdated:
1730 for newremotehead in outdated:
1711 r = remote.pushkey('phases',
1731 r = remote.pushkey('phases',
1712 newremotehead.hex(),
1732 newremotehead.hex(),
1713 str(phases.draft),
1733 str(phases.draft),
1714 str(phases.public))
1734 str(phases.public))
1715 if not r:
1735 if not r:
1716 self.ui.warn(_('updating %s to public failed!\n')
1736 self.ui.warn(_('updating %s to public failed!\n')
1717 % newremotehead)
1737 % newremotehead)
1718 finally:
1738 finally:
1719 if lock is not None:
1739 if lock is not None:
1720 lock.release()
1740 lock.release()
1721 finally:
1741 finally:
1722 locallock.release()
1742 locallock.release()
1723
1743
1724 self.ui.debug("checking for updated bookmarks\n")
1744 self.ui.debug("checking for updated bookmarks\n")
1725 rb = remote.listkeys('bookmarks')
1745 rb = remote.listkeys('bookmarks')
1726 for k in rb.keys():
1746 for k in rb.keys():
1727 if k in self._bookmarks:
1747 if k in self._bookmarks:
1728 nr, nl = rb[k], hex(self._bookmarks[k])
1748 nr, nl = rb[k], hex(self._bookmarks[k])
1729 if nr in self:
1749 if nr in self:
1730 cr = self[nr]
1750 cr = self[nr]
1731 cl = self[nl]
1751 cl = self[nl]
1732 if cl in cr.descendants():
1752 if cl in cr.descendants():
1733 r = remote.pushkey('bookmarks', k, nr, nl)
1753 r = remote.pushkey('bookmarks', k, nr, nl)
1734 if r:
1754 if r:
1735 self.ui.status(_("updating bookmark %s\n") % k)
1755 self.ui.status(_("updating bookmark %s\n") % k)
1736 else:
1756 else:
1737 self.ui.warn(_('updating bookmark %s'
1757 self.ui.warn(_('updating bookmark %s'
1738 ' failed!\n') % k)
1758 ' failed!\n') % k)
1739
1759
1740 return ret
1760 return ret
1741
1761
1742 def changegroupinfo(self, nodes, source):
1762 def changegroupinfo(self, nodes, source):
1743 if self.ui.verbose or source == 'bundle':
1763 if self.ui.verbose or source == 'bundle':
1744 self.ui.status(_("%d changesets found\n") % len(nodes))
1764 self.ui.status(_("%d changesets found\n") % len(nodes))
1745 if self.ui.debugflag:
1765 if self.ui.debugflag:
1746 self.ui.debug("list of changesets:\n")
1766 self.ui.debug("list of changesets:\n")
1747 for node in nodes:
1767 for node in nodes:
1748 self.ui.debug("%s\n" % hex(node))
1768 self.ui.debug("%s\n" % hex(node))
1749
1769
1750 def changegroupsubset(self, bases, heads, source):
1770 def changegroupsubset(self, bases, heads, source):
1751 """Compute a changegroup consisting of all the nodes that are
1771 """Compute a changegroup consisting of all the nodes that are
1752 descendants of any of the bases and ancestors of any of the heads.
1772 descendants of any of the bases and ancestors of any of the heads.
1753 Return a chunkbuffer object whose read() method will return
1773 Return a chunkbuffer object whose read() method will return
1754 successive changegroup chunks.
1774 successive changegroup chunks.
1755
1775
1756 It is fairly complex as determining which filenodes and which
1776 It is fairly complex as determining which filenodes and which
1757 manifest nodes need to be included for the changeset to be complete
1777 manifest nodes need to be included for the changeset to be complete
1758 is non-trivial.
1778 is non-trivial.
1759
1779
1760 Another wrinkle is doing the reverse, figuring out which changeset in
1780 Another wrinkle is doing the reverse, figuring out which changeset in
1761 the changegroup a particular filenode or manifestnode belongs to.
1781 the changegroup a particular filenode or manifestnode belongs to.
1762 """
1782 """
1763 cl = self.changelog
1783 cl = self.changelog
1764 if not bases:
1784 if not bases:
1765 bases = [nullid]
1785 bases = [nullid]
1766 csets, bases, heads = cl.nodesbetween(bases, heads)
1786 csets, bases, heads = cl.nodesbetween(bases, heads)
1767 # We assume that all ancestors of bases are known
1787 # We assume that all ancestors of bases are known
1768 common = set(cl.ancestors(*[cl.rev(n) for n in bases]))
1788 common = set(cl.ancestors(*[cl.rev(n) for n in bases]))
1769 return self._changegroupsubset(common, csets, heads, source)
1789 return self._changegroupsubset(common, csets, heads, source)
1770
1790
1771 def getlocalbundle(self, source, outgoing):
1791 def getlocalbundle(self, source, outgoing):
1772 """Like getbundle, but taking a discovery.outgoing as an argument.
1792 """Like getbundle, but taking a discovery.outgoing as an argument.
1773
1793
1774 This is only implemented for local repos and reuses potentially
1794 This is only implemented for local repos and reuses potentially
1775 precomputed sets in outgoing."""
1795 precomputed sets in outgoing."""
1776 if not outgoing.missing:
1796 if not outgoing.missing:
1777 return None
1797 return None
1778 return self._changegroupsubset(outgoing.common,
1798 return self._changegroupsubset(outgoing.common,
1779 outgoing.missing,
1799 outgoing.missing,
1780 outgoing.missingheads,
1800 outgoing.missingheads,
1781 source)
1801 source)
1782
1802
1783 def getbundle(self, source, heads=None, common=None):
1803 def getbundle(self, source, heads=None, common=None):
1784 """Like changegroupsubset, but returns the set difference between the
1804 """Like changegroupsubset, but returns the set difference between the
1785 ancestors of heads and the ancestors common.
1805 ancestors of heads and the ancestors common.
1786
1806
1787 If heads is None, use the local heads. If common is None, use [nullid].
1807 If heads is None, use the local heads. If common is None, use [nullid].
1788
1808
1789 The nodes in common might not all be known locally due to the way the
1809 The nodes in common might not all be known locally due to the way the
1790 current discovery protocol works.
1810 current discovery protocol works.
1791 """
1811 """
1792 cl = self.changelog
1812 cl = self.changelog
1793 if common:
1813 if common:
1794 nm = cl.nodemap
1814 nm = cl.nodemap
1795 common = [n for n in common if n in nm]
1815 common = [n for n in common if n in nm]
1796 else:
1816 else:
1797 common = [nullid]
1817 common = [nullid]
1798 if not heads:
1818 if not heads:
1799 heads = cl.heads()
1819 heads = cl.heads()
1800 return self.getlocalbundle(source,
1820 return self.getlocalbundle(source,
1801 discovery.outgoing(cl, common, heads))
1821 discovery.outgoing(cl, common, heads))
1802
1822
1803 def _changegroupsubset(self, commonrevs, csets, heads, source):
1823 def _changegroupsubset(self, commonrevs, csets, heads, source):
1804
1824
1805 cl = self.changelog
1825 cl = self.changelog
1806 mf = self.manifest
1826 mf = self.manifest
1807 mfs = {} # needed manifests
1827 mfs = {} # needed manifests
1808 fnodes = {} # needed file nodes
1828 fnodes = {} # needed file nodes
1809 changedfiles = set()
1829 changedfiles = set()
1810 fstate = ['', {}]
1830 fstate = ['', {}]
1811 count = [0]
1831 count = [0]
1812
1832
1813 # can we go through the fast path ?
1833 # can we go through the fast path ?
1814 heads.sort()
1834 heads.sort()
1815 if heads == sorted(self.heads()):
1835 if heads == sorted(self.heads()):
1816 return self._changegroup(csets, source)
1836 return self._changegroup(csets, source)
1817
1837
1818 # slow path
1838 # slow path
1819 self.hook('preoutgoing', throw=True, source=source)
1839 self.hook('preoutgoing', throw=True, source=source)
1820 self.changegroupinfo(csets, source)
1840 self.changegroupinfo(csets, source)
1821
1841
1822 # filter any nodes that claim to be part of the known set
1842 # filter any nodes that claim to be part of the known set
1823 def prune(revlog, missing):
1843 def prune(revlog, missing):
1824 return [n for n in missing
1844 return [n for n in missing
1825 if revlog.linkrev(revlog.rev(n)) not in commonrevs]
1845 if revlog.linkrev(revlog.rev(n)) not in commonrevs]
1826
1846
1827 def lookup(revlog, x):
1847 def lookup(revlog, x):
1828 if revlog == cl:
1848 if revlog == cl:
1829 c = cl.read(x)
1849 c = cl.read(x)
1830 changedfiles.update(c[3])
1850 changedfiles.update(c[3])
1831 mfs.setdefault(c[0], x)
1851 mfs.setdefault(c[0], x)
1832 count[0] += 1
1852 count[0] += 1
1833 self.ui.progress(_('bundling'), count[0],
1853 self.ui.progress(_('bundling'), count[0],
1834 unit=_('changesets'), total=len(csets))
1854 unit=_('changesets'), total=len(csets))
1835 return x
1855 return x
1836 elif revlog == mf:
1856 elif revlog == mf:
1837 clnode = mfs[x]
1857 clnode = mfs[x]
1838 mdata = mf.readfast(x)
1858 mdata = mf.readfast(x)
1839 for f in changedfiles:
1859 for f in changedfiles:
1840 if f in mdata:
1860 if f in mdata:
1841 fnodes.setdefault(f, {}).setdefault(mdata[f], clnode)
1861 fnodes.setdefault(f, {}).setdefault(mdata[f], clnode)
1842 count[0] += 1
1862 count[0] += 1
1843 self.ui.progress(_('bundling'), count[0],
1863 self.ui.progress(_('bundling'), count[0],
1844 unit=_('manifests'), total=len(mfs))
1864 unit=_('manifests'), total=len(mfs))
1845 return mfs[x]
1865 return mfs[x]
1846 else:
1866 else:
1847 self.ui.progress(
1867 self.ui.progress(
1848 _('bundling'), count[0], item=fstate[0],
1868 _('bundling'), count[0], item=fstate[0],
1849 unit=_('files'), total=len(changedfiles))
1869 unit=_('files'), total=len(changedfiles))
1850 return fstate[1][x]
1870 return fstate[1][x]
1851
1871
1852 bundler = changegroup.bundle10(lookup)
1872 bundler = changegroup.bundle10(lookup)
1853 reorder = self.ui.config('bundle', 'reorder', 'auto')
1873 reorder = self.ui.config('bundle', 'reorder', 'auto')
1854 if reorder == 'auto':
1874 if reorder == 'auto':
1855 reorder = None
1875 reorder = None
1856 else:
1876 else:
1857 reorder = util.parsebool(reorder)
1877 reorder = util.parsebool(reorder)
1858
1878
1859 def gengroup():
1879 def gengroup():
1860 # Create a changenode group generator that will call our functions
1880 # Create a changenode group generator that will call our functions
1861 # back to lookup the owning changenode and collect information.
1881 # back to lookup the owning changenode and collect information.
1862 for chunk in cl.group(csets, bundler, reorder=reorder):
1882 for chunk in cl.group(csets, bundler, reorder=reorder):
1863 yield chunk
1883 yield chunk
1864 self.ui.progress(_('bundling'), None)
1884 self.ui.progress(_('bundling'), None)
1865
1885
1866 # Create a generator for the manifestnodes that calls our lookup
1886 # Create a generator for the manifestnodes that calls our lookup
1867 # and data collection functions back.
1887 # and data collection functions back.
1868 count[0] = 0
1888 count[0] = 0
1869 for chunk in mf.group(prune(mf, mfs), bundler, reorder=reorder):
1889 for chunk in mf.group(prune(mf, mfs), bundler, reorder=reorder):
1870 yield chunk
1890 yield chunk
1871 self.ui.progress(_('bundling'), None)
1891 self.ui.progress(_('bundling'), None)
1872
1892
1873 mfs.clear()
1893 mfs.clear()
1874
1894
1875 # Go through all our files in order sorted by name.
1895 # Go through all our files in order sorted by name.
1876 count[0] = 0
1896 count[0] = 0
1877 for fname in sorted(changedfiles):
1897 for fname in sorted(changedfiles):
1878 filerevlog = self.file(fname)
1898 filerevlog = self.file(fname)
1879 if not len(filerevlog):
1899 if not len(filerevlog):
1880 raise util.Abort(_("empty or missing revlog for %s") % fname)
1900 raise util.Abort(_("empty or missing revlog for %s") % fname)
1881 fstate[0] = fname
1901 fstate[0] = fname
1882 fstate[1] = fnodes.pop(fname, {})
1902 fstate[1] = fnodes.pop(fname, {})
1883
1903
1884 nodelist = prune(filerevlog, fstate[1])
1904 nodelist = prune(filerevlog, fstate[1])
1885 if nodelist:
1905 if nodelist:
1886 count[0] += 1
1906 count[0] += 1
1887 yield bundler.fileheader(fname)
1907 yield bundler.fileheader(fname)
1888 for chunk in filerevlog.group(nodelist, bundler, reorder):
1908 for chunk in filerevlog.group(nodelist, bundler, reorder):
1889 yield chunk
1909 yield chunk
1890
1910
1891 # Signal that no more groups are left.
1911 # Signal that no more groups are left.
1892 yield bundler.close()
1912 yield bundler.close()
1893 self.ui.progress(_('bundling'), None)
1913 self.ui.progress(_('bundling'), None)
1894
1914
1895 if csets:
1915 if csets:
1896 self.hook('outgoing', node=hex(csets[0]), source=source)
1916 self.hook('outgoing', node=hex(csets[0]), source=source)
1897
1917
1898 return changegroup.unbundle10(util.chunkbuffer(gengroup()), 'UN')
1918 return changegroup.unbundle10(util.chunkbuffer(gengroup()), 'UN')
1899
1919
1900 def changegroup(self, basenodes, source):
1920 def changegroup(self, basenodes, source):
1901 # to avoid a race we use changegroupsubset() (issue1320)
1921 # to avoid a race we use changegroupsubset() (issue1320)
1902 return self.changegroupsubset(basenodes, self.heads(), source)
1922 return self.changegroupsubset(basenodes, self.heads(), source)
1903
1923
1904 def _changegroup(self, nodes, source):
1924 def _changegroup(self, nodes, source):
1905 """Compute the changegroup of all nodes that we have that a recipient
1925 """Compute the changegroup of all nodes that we have that a recipient
1906 doesn't. Return a chunkbuffer object whose read() method will return
1926 doesn't. Return a chunkbuffer object whose read() method will return
1907 successive changegroup chunks.
1927 successive changegroup chunks.
1908
1928
1909 This is much easier than the previous function as we can assume that
1929 This is much easier than the previous function as we can assume that
1910 the recipient has any changenode we aren't sending them.
1930 the recipient has any changenode we aren't sending them.
1911
1931
1912 nodes is the set of nodes to send"""
1932 nodes is the set of nodes to send"""
1913
1933
1914 cl = self.changelog
1934 cl = self.changelog
1915 mf = self.manifest
1935 mf = self.manifest
1916 mfs = {}
1936 mfs = {}
1917 changedfiles = set()
1937 changedfiles = set()
1918 fstate = ['']
1938 fstate = ['']
1919 count = [0]
1939 count = [0]
1920
1940
1921 self.hook('preoutgoing', throw=True, source=source)
1941 self.hook('preoutgoing', throw=True, source=source)
1922 self.changegroupinfo(nodes, source)
1942 self.changegroupinfo(nodes, source)
1923
1943
1924 revset = set([cl.rev(n) for n in nodes])
1944 revset = set([cl.rev(n) for n in nodes])
1925
1945
1926 def gennodelst(log):
1946 def gennodelst(log):
1927 return [log.node(r) for r in log if log.linkrev(r) in revset]
1947 return [log.node(r) for r in log if log.linkrev(r) in revset]
1928
1948
1929 def lookup(revlog, x):
1949 def lookup(revlog, x):
1930 if revlog == cl:
1950 if revlog == cl:
1931 c = cl.read(x)
1951 c = cl.read(x)
1932 changedfiles.update(c[3])
1952 changedfiles.update(c[3])
1933 mfs.setdefault(c[0], x)
1953 mfs.setdefault(c[0], x)
1934 count[0] += 1
1954 count[0] += 1
1935 self.ui.progress(_('bundling'), count[0],
1955 self.ui.progress(_('bundling'), count[0],
1936 unit=_('changesets'), total=len(nodes))
1956 unit=_('changesets'), total=len(nodes))
1937 return x
1957 return x
1938 elif revlog == mf:
1958 elif revlog == mf:
1939 count[0] += 1
1959 count[0] += 1
1940 self.ui.progress(_('bundling'), count[0],
1960 self.ui.progress(_('bundling'), count[0],
1941 unit=_('manifests'), total=len(mfs))
1961 unit=_('manifests'), total=len(mfs))
1942 return cl.node(revlog.linkrev(revlog.rev(x)))
1962 return cl.node(revlog.linkrev(revlog.rev(x)))
1943 else:
1963 else:
1944 self.ui.progress(
1964 self.ui.progress(
1945 _('bundling'), count[0], item=fstate[0],
1965 _('bundling'), count[0], item=fstate[0],
1946 total=len(changedfiles), unit=_('files'))
1966 total=len(changedfiles), unit=_('files'))
1947 return cl.node(revlog.linkrev(revlog.rev(x)))
1967 return cl.node(revlog.linkrev(revlog.rev(x)))
1948
1968
1949 bundler = changegroup.bundle10(lookup)
1969 bundler = changegroup.bundle10(lookup)
1950 reorder = self.ui.config('bundle', 'reorder', 'auto')
1970 reorder = self.ui.config('bundle', 'reorder', 'auto')
1951 if reorder == 'auto':
1971 if reorder == 'auto':
1952 reorder = None
1972 reorder = None
1953 else:
1973 else:
1954 reorder = util.parsebool(reorder)
1974 reorder = util.parsebool(reorder)
1955
1975
1956 def gengroup():
1976 def gengroup():
1957 '''yield a sequence of changegroup chunks (strings)'''
1977 '''yield a sequence of changegroup chunks (strings)'''
1958 # construct a list of all changed files
1978 # construct a list of all changed files
1959
1979
1960 for chunk in cl.group(nodes, bundler, reorder=reorder):
1980 for chunk in cl.group(nodes, bundler, reorder=reorder):
1961 yield chunk
1981 yield chunk
1962 self.ui.progress(_('bundling'), None)
1982 self.ui.progress(_('bundling'), None)
1963
1983
1964 count[0] = 0
1984 count[0] = 0
1965 for chunk in mf.group(gennodelst(mf), bundler, reorder=reorder):
1985 for chunk in mf.group(gennodelst(mf), bundler, reorder=reorder):
1966 yield chunk
1986 yield chunk
1967 self.ui.progress(_('bundling'), None)
1987 self.ui.progress(_('bundling'), None)
1968
1988
1969 count[0] = 0
1989 count[0] = 0
1970 for fname in sorted(changedfiles):
1990 for fname in sorted(changedfiles):
1971 filerevlog = self.file(fname)
1991 filerevlog = self.file(fname)
1972 if not len(filerevlog):
1992 if not len(filerevlog):
1973 raise util.Abort(_("empty or missing revlog for %s") % fname)
1993 raise util.Abort(_("empty or missing revlog for %s") % fname)
1974 fstate[0] = fname
1994 fstate[0] = fname
1975 nodelist = gennodelst(filerevlog)
1995 nodelist = gennodelst(filerevlog)
1976 if nodelist:
1996 if nodelist:
1977 count[0] += 1
1997 count[0] += 1
1978 yield bundler.fileheader(fname)
1998 yield bundler.fileheader(fname)
1979 for chunk in filerevlog.group(nodelist, bundler, reorder):
1999 for chunk in filerevlog.group(nodelist, bundler, reorder):
1980 yield chunk
2000 yield chunk
1981 yield bundler.close()
2001 yield bundler.close()
1982 self.ui.progress(_('bundling'), None)
2002 self.ui.progress(_('bundling'), None)
1983
2003
1984 if nodes:
2004 if nodes:
1985 self.hook('outgoing', node=hex(nodes[0]), source=source)
2005 self.hook('outgoing', node=hex(nodes[0]), source=source)
1986
2006
1987 return changegroup.unbundle10(util.chunkbuffer(gengroup()), 'UN')
2007 return changegroup.unbundle10(util.chunkbuffer(gengroup()), 'UN')
1988
2008
1989 def addchangegroup(self, source, srctype, url, emptyok=False):
2009 def addchangegroup(self, source, srctype, url, emptyok=False):
1990 """Add the changegroup returned by source.read() to this repo.
2010 """Add the changegroup returned by source.read() to this repo.
1991 srctype is a string like 'push', 'pull', or 'unbundle'. url is
2011 srctype is a string like 'push', 'pull', or 'unbundle'. url is
1992 the URL of the repo where this changegroup is coming from.
2012 the URL of the repo where this changegroup is coming from.
1993
2013
1994 Return an integer summarizing the change to this repo:
2014 Return an integer summarizing the change to this repo:
1995 - nothing changed or no source: 0
2015 - nothing changed or no source: 0
1996 - more heads than before: 1+added heads (2..n)
2016 - more heads than before: 1+added heads (2..n)
1997 - fewer heads than before: -1-removed heads (-2..-n)
2017 - fewer heads than before: -1-removed heads (-2..-n)
1998 - number of heads stays the same: 1
2018 - number of heads stays the same: 1
1999 """
2019 """
2000 def csmap(x):
2020 def csmap(x):
2001 self.ui.debug("add changeset %s\n" % short(x))
2021 self.ui.debug("add changeset %s\n" % short(x))
2002 return len(cl)
2022 return len(cl)
2003
2023
2004 def revmap(x):
2024 def revmap(x):
2005 return cl.rev(x)
2025 return cl.rev(x)
2006
2026
2007 if not source:
2027 if not source:
2008 return 0
2028 return 0
2009
2029
2010 self.hook('prechangegroup', throw=True, source=srctype, url=url)
2030 self.hook('prechangegroup', throw=True, source=srctype, url=url)
2011
2031
2012 changesets = files = revisions = 0
2032 changesets = files = revisions = 0
2013 efiles = set()
2033 efiles = set()
2014
2034
2015 # write changelog data to temp files so concurrent readers will not see
2035 # write changelog data to temp files so concurrent readers will not see
2016 # inconsistent view
2036 # inconsistent view
2017 cl = self.changelog
2037 cl = self.changelog
2018 cl.delayupdate()
2038 cl.delayupdate()
2019 oldheads = cl.heads()
2039 oldheads = cl.heads()
2020
2040
2021 tr = self.transaction("\n".join([srctype, util.hidepassword(url)]))
2041 tr = self.transaction("\n".join([srctype, util.hidepassword(url)]))
2022 try:
2042 try:
2023 trp = weakref.proxy(tr)
2043 trp = weakref.proxy(tr)
2024 # pull off the changeset group
2044 # pull off the changeset group
2025 self.ui.status(_("adding changesets\n"))
2045 self.ui.status(_("adding changesets\n"))
2026 clstart = len(cl)
2046 clstart = len(cl)
2027 class prog(object):
2047 class prog(object):
2028 step = _('changesets')
2048 step = _('changesets')
2029 count = 1
2049 count = 1
2030 ui = self.ui
2050 ui = self.ui
2031 total = None
2051 total = None
2032 def __call__(self):
2052 def __call__(self):
2033 self.ui.progress(self.step, self.count, unit=_('chunks'),
2053 self.ui.progress(self.step, self.count, unit=_('chunks'),
2034 total=self.total)
2054 total=self.total)
2035 self.count += 1
2055 self.count += 1
2036 pr = prog()
2056 pr = prog()
2037 source.callback = pr
2057 source.callback = pr
2038
2058
2039 source.changelogheader()
2059 source.changelogheader()
2040 srccontent = cl.addgroup(source, csmap, trp)
2060 srccontent = cl.addgroup(source, csmap, trp)
2041 if not (srccontent or emptyok):
2061 if not (srccontent or emptyok):
2042 raise util.Abort(_("received changelog group is empty"))
2062 raise util.Abort(_("received changelog group is empty"))
2043 clend = len(cl)
2063 clend = len(cl)
2044 changesets = clend - clstart
2064 changesets = clend - clstart
2045 for c in xrange(clstart, clend):
2065 for c in xrange(clstart, clend):
2046 efiles.update(self[c].files())
2066 efiles.update(self[c].files())
2047 efiles = len(efiles)
2067 efiles = len(efiles)
2048 self.ui.progress(_('changesets'), None)
2068 self.ui.progress(_('changesets'), None)
2049
2069
2050 # pull off the manifest group
2070 # pull off the manifest group
2051 self.ui.status(_("adding manifests\n"))
2071 self.ui.status(_("adding manifests\n"))
2052 pr.step = _('manifests')
2072 pr.step = _('manifests')
2053 pr.count = 1
2073 pr.count = 1
2054 pr.total = changesets # manifests <= changesets
2074 pr.total = changesets # manifests <= changesets
2055 # no need to check for empty manifest group here:
2075 # no need to check for empty manifest group here:
2056 # if the result of the merge of 1 and 2 is the same in 3 and 4,
2076 # if the result of the merge of 1 and 2 is the same in 3 and 4,
2057 # no new manifest will be created and the manifest group will
2077 # no new manifest will be created and the manifest group will
2058 # be empty during the pull
2078 # be empty during the pull
2059 source.manifestheader()
2079 source.manifestheader()
2060 self.manifest.addgroup(source, revmap, trp)
2080 self.manifest.addgroup(source, revmap, trp)
2061 self.ui.progress(_('manifests'), None)
2081 self.ui.progress(_('manifests'), None)
2062
2082
2063 needfiles = {}
2083 needfiles = {}
2064 if self.ui.configbool('server', 'validate', default=False):
2084 if self.ui.configbool('server', 'validate', default=False):
2065 # validate incoming csets have their manifests
2085 # validate incoming csets have their manifests
2066 for cset in xrange(clstart, clend):
2086 for cset in xrange(clstart, clend):
2067 mfest = self.changelog.read(self.changelog.node(cset))[0]
2087 mfest = self.changelog.read(self.changelog.node(cset))[0]
2068 mfest = self.manifest.readdelta(mfest)
2088 mfest = self.manifest.readdelta(mfest)
2069 # store file nodes we must see
2089 # store file nodes we must see
2070 for f, n in mfest.iteritems():
2090 for f, n in mfest.iteritems():
2071 needfiles.setdefault(f, set()).add(n)
2091 needfiles.setdefault(f, set()).add(n)
2072
2092
2073 # process the files
2093 # process the files
2074 self.ui.status(_("adding file changes\n"))
2094 self.ui.status(_("adding file changes\n"))
2075 pr.step = _('files')
2095 pr.step = _('files')
2076 pr.count = 1
2096 pr.count = 1
2077 pr.total = efiles
2097 pr.total = efiles
2078 source.callback = None
2098 source.callback = None
2079
2099
2080 while True:
2100 while True:
2081 chunkdata = source.filelogheader()
2101 chunkdata = source.filelogheader()
2082 if not chunkdata:
2102 if not chunkdata:
2083 break
2103 break
2084 f = chunkdata["filename"]
2104 f = chunkdata["filename"]
2085 self.ui.debug("adding %s revisions\n" % f)
2105 self.ui.debug("adding %s revisions\n" % f)
2086 pr()
2106 pr()
2087 fl = self.file(f)
2107 fl = self.file(f)
2088 o = len(fl)
2108 o = len(fl)
2089 if not fl.addgroup(source, revmap, trp):
2109 if not fl.addgroup(source, revmap, trp):
2090 raise util.Abort(_("received file revlog group is empty"))
2110 raise util.Abort(_("received file revlog group is empty"))
2091 revisions += len(fl) - o
2111 revisions += len(fl) - o
2092 files += 1
2112 files += 1
2093 if f in needfiles:
2113 if f in needfiles:
2094 needs = needfiles[f]
2114 needs = needfiles[f]
2095 for new in xrange(o, len(fl)):
2115 for new in xrange(o, len(fl)):
2096 n = fl.node(new)
2116 n = fl.node(new)
2097 if n in needs:
2117 if n in needs:
2098 needs.remove(n)
2118 needs.remove(n)
2099 if not needs:
2119 if not needs:
2100 del needfiles[f]
2120 del needfiles[f]
2101 self.ui.progress(_('files'), None)
2121 self.ui.progress(_('files'), None)
2102
2122
2103 for f, needs in needfiles.iteritems():
2123 for f, needs in needfiles.iteritems():
2104 fl = self.file(f)
2124 fl = self.file(f)
2105 for n in needs:
2125 for n in needs:
2106 try:
2126 try:
2107 fl.rev(n)
2127 fl.rev(n)
2108 except error.LookupError:
2128 except error.LookupError:
2109 raise util.Abort(
2129 raise util.Abort(
2110 _('missing file data for %s:%s - run hg verify') %
2130 _('missing file data for %s:%s - run hg verify') %
2111 (f, hex(n)))
2131 (f, hex(n)))
2112
2132
2113 dh = 0
2133 dh = 0
2114 if oldheads:
2134 if oldheads:
2115 heads = cl.heads()
2135 heads = cl.heads()
2116 dh = len(heads) - len(oldheads)
2136 dh = len(heads) - len(oldheads)
2117 for h in heads:
2137 for h in heads:
2118 if h not in oldheads and 'close' in self[h].extra():
2138 if h not in oldheads and 'close' in self[h].extra():
2119 dh -= 1
2139 dh -= 1
2120 htext = ""
2140 htext = ""
2121 if dh:
2141 if dh:
2122 htext = _(" (%+d heads)") % dh
2142 htext = _(" (%+d heads)") % dh
2123
2143
2124 self.ui.status(_("added %d changesets"
2144 self.ui.status(_("added %d changesets"
2125 " with %d changes to %d files%s\n")
2145 " with %d changes to %d files%s\n")
2126 % (changesets, revisions, files, htext))
2146 % (changesets, revisions, files, htext))
2127
2147
2128 if changesets > 0:
2148 if changesets > 0:
2129 p = lambda: cl.writepending() and self.root or ""
2149 p = lambda: cl.writepending() and self.root or ""
2130 self.hook('pretxnchangegroup', throw=True,
2150 self.hook('pretxnchangegroup', throw=True,
2131 node=hex(cl.node(clstart)), source=srctype,
2151 node=hex(cl.node(clstart)), source=srctype,
2132 url=url, pending=p)
2152 url=url, pending=p)
2133
2153
2134 added = [cl.node(r) for r in xrange(clstart, clend)]
2154 added = [cl.node(r) for r in xrange(clstart, clend)]
2135 publishing = self.ui.configbool('phases', 'publish', True)
2155 publishing = self.ui.configbool('phases', 'publish', True)
2136 if srctype == 'push':
2156 if srctype == 'push':
2137 # Old server can not push the boundary themself.
2157 # Old server can not push the boundary themself.
2138 # New server won't push the boundary if changeset already
2158 # New server won't push the boundary if changeset already
2139 # existed locally as secrete
2159 # existed locally as secrete
2140 #
2160 #
2141 # We should not use added here but the list of all change in
2161 # We should not use added here but the list of all change in
2142 # the bundle
2162 # the bundle
2143 if publishing:
2163 if publishing:
2144 phases.advanceboundary(self, phases.public, srccontent)
2164 phases.advanceboundary(self, phases.public, srccontent)
2145 else:
2165 else:
2146 phases.advanceboundary(self, phases.draft, srccontent)
2166 phases.advanceboundary(self, phases.draft, srccontent)
2147 phases.retractboundary(self, phases.draft, added)
2167 phases.retractboundary(self, phases.draft, added)
2148 elif srctype != 'strip':
2168 elif srctype != 'strip':
2149 # publishing only alter behavior during push
2169 # publishing only alter behavior during push
2150 #
2170 #
2151 # strip should not touch boundary at all
2171 # strip should not touch boundary at all
2152 phases.retractboundary(self, phases.draft, added)
2172 phases.retractboundary(self, phases.draft, added)
2153
2173
2154 # make changelog see real files again
2174 # make changelog see real files again
2155 cl.finalize(trp)
2175 cl.finalize(trp)
2156
2176
2157 tr.close()
2177 tr.close()
2158
2178
2159 if changesets > 0:
2179 if changesets > 0:
2160 def runhooks():
2180 def runhooks():
2161 # forcefully update the on-disk branch cache
2181 # forcefully update the on-disk branch cache
2162 self.ui.debug("updating the branch cache\n")
2182 self.ui.debug("updating the branch cache\n")
2163 self.updatebranchcache()
2183 self.updatebranchcache()
2164 self.hook("changegroup", node=hex(cl.node(clstart)),
2184 self.hook("changegroup", node=hex(cl.node(clstart)),
2165 source=srctype, url=url)
2185 source=srctype, url=url)
2166
2186
2167 for n in added:
2187 for n in added:
2168 self.hook("incoming", node=hex(n), source=srctype,
2188 self.hook("incoming", node=hex(n), source=srctype,
2169 url=url)
2189 url=url)
2170 self._afterlock(runhooks)
2190 self._afterlock(runhooks)
2171
2191
2172 finally:
2192 finally:
2173 tr.release()
2193 tr.release()
2174 # never return 0 here:
2194 # never return 0 here:
2175 if dh < 0:
2195 if dh < 0:
2176 return dh - 1
2196 return dh - 1
2177 else:
2197 else:
2178 return dh + 1
2198 return dh + 1
2179
2199
2180 def stream_in(self, remote, requirements):
2200 def stream_in(self, remote, requirements):
2181 lock = self.lock()
2201 lock = self.lock()
2182 try:
2202 try:
2183 fp = remote.stream_out()
2203 fp = remote.stream_out()
2184 l = fp.readline()
2204 l = fp.readline()
2185 try:
2205 try:
2186 resp = int(l)
2206 resp = int(l)
2187 except ValueError:
2207 except ValueError:
2188 raise error.ResponseError(
2208 raise error.ResponseError(
2189 _('Unexpected response from remote server:'), l)
2209 _('Unexpected response from remote server:'), l)
2190 if resp == 1:
2210 if resp == 1:
2191 raise util.Abort(_('operation forbidden by server'))
2211 raise util.Abort(_('operation forbidden by server'))
2192 elif resp == 2:
2212 elif resp == 2:
2193 raise util.Abort(_('locking the remote repository failed'))
2213 raise util.Abort(_('locking the remote repository failed'))
2194 elif resp != 0:
2214 elif resp != 0:
2195 raise util.Abort(_('the server sent an unknown error code'))
2215 raise util.Abort(_('the server sent an unknown error code'))
2196 self.ui.status(_('streaming all changes\n'))
2216 self.ui.status(_('streaming all changes\n'))
2197 l = fp.readline()
2217 l = fp.readline()
2198 try:
2218 try:
2199 total_files, total_bytes = map(int, l.split(' ', 1))
2219 total_files, total_bytes = map(int, l.split(' ', 1))
2200 except (ValueError, TypeError):
2220 except (ValueError, TypeError):
2201 raise error.ResponseError(
2221 raise error.ResponseError(
2202 _('Unexpected response from remote server:'), l)
2222 _('Unexpected response from remote server:'), l)
2203 self.ui.status(_('%d files to transfer, %s of data\n') %
2223 self.ui.status(_('%d files to transfer, %s of data\n') %
2204 (total_files, util.bytecount(total_bytes)))
2224 (total_files, util.bytecount(total_bytes)))
2205 start = time.time()
2225 start = time.time()
2206 for i in xrange(total_files):
2226 for i in xrange(total_files):
2207 # XXX doesn't support '\n' or '\r' in filenames
2227 # XXX doesn't support '\n' or '\r' in filenames
2208 l = fp.readline()
2228 l = fp.readline()
2209 try:
2229 try:
2210 name, size = l.split('\0', 1)
2230 name, size = l.split('\0', 1)
2211 size = int(size)
2231 size = int(size)
2212 except (ValueError, TypeError):
2232 except (ValueError, TypeError):
2213 raise error.ResponseError(
2233 raise error.ResponseError(
2214 _('Unexpected response from remote server:'), l)
2234 _('Unexpected response from remote server:'), l)
2215 self.ui.debug('adding %s (%s)\n' % (name, util.bytecount(size)))
2235 self.ui.debug('adding %s (%s)\n' % (name, util.bytecount(size)))
2216 # for backwards compat, name was partially encoded
2236 # for backwards compat, name was partially encoded
2217 ofp = self.sopener(store.decodedir(name), 'w')
2237 ofp = self.sopener(store.decodedir(name), 'w')
2218 for chunk in util.filechunkiter(fp, limit=size):
2238 for chunk in util.filechunkiter(fp, limit=size):
2219 ofp.write(chunk)
2239 ofp.write(chunk)
2220 ofp.close()
2240 ofp.close()
2221 elapsed = time.time() - start
2241 elapsed = time.time() - start
2222 if elapsed <= 0:
2242 if elapsed <= 0:
2223 elapsed = 0.001
2243 elapsed = 0.001
2224 self.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') %
2244 self.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') %
2225 (util.bytecount(total_bytes), elapsed,
2245 (util.bytecount(total_bytes), elapsed,
2226 util.bytecount(total_bytes / elapsed)))
2246 util.bytecount(total_bytes / elapsed)))
2227
2247
2228 # new requirements = old non-format requirements + new format-related
2248 # new requirements = old non-format requirements + new format-related
2229 # requirements from the streamed-in repository
2249 # requirements from the streamed-in repository
2230 requirements.update(set(self.requirements) - self.supportedformats)
2250 requirements.update(set(self.requirements) - self.supportedformats)
2231 self._applyrequirements(requirements)
2251 self._applyrequirements(requirements)
2232 self._writerequirements()
2252 self._writerequirements()
2233
2253
2234 self.invalidate()
2254 self.invalidate()
2235 return len(self.heads()) + 1
2255 return len(self.heads()) + 1
2236 finally:
2256 finally:
2237 lock.release()
2257 lock.release()
2238
2258
2239 def clone(self, remote, heads=[], stream=False):
2259 def clone(self, remote, heads=[], stream=False):
2240 '''clone remote repository.
2260 '''clone remote repository.
2241
2261
2242 keyword arguments:
2262 keyword arguments:
2243 heads: list of revs to clone (forces use of pull)
2263 heads: list of revs to clone (forces use of pull)
2244 stream: use streaming clone if possible'''
2264 stream: use streaming clone if possible'''
2245
2265
2246 # now, all clients that can request uncompressed clones can
2266 # now, all clients that can request uncompressed clones can
2247 # read repo formats supported by all servers that can serve
2267 # read repo formats supported by all servers that can serve
2248 # them.
2268 # them.
2249
2269
2250 # if revlog format changes, client will have to check version
2270 # if revlog format changes, client will have to check version
2251 # and format flags on "stream" capability, and use
2271 # and format flags on "stream" capability, and use
2252 # uncompressed only if compatible.
2272 # uncompressed only if compatible.
2253
2273
2254 if stream and not heads:
2274 if stream and not heads:
2255 # 'stream' means remote revlog format is revlogv1 only
2275 # 'stream' means remote revlog format is revlogv1 only
2256 if remote.capable('stream'):
2276 if remote.capable('stream'):
2257 return self.stream_in(remote, set(('revlogv1',)))
2277 return self.stream_in(remote, set(('revlogv1',)))
2258 # otherwise, 'streamreqs' contains the remote revlog format
2278 # otherwise, 'streamreqs' contains the remote revlog format
2259 streamreqs = remote.capable('streamreqs')
2279 streamreqs = remote.capable('streamreqs')
2260 if streamreqs:
2280 if streamreqs:
2261 streamreqs = set(streamreqs.split(','))
2281 streamreqs = set(streamreqs.split(','))
2262 # if we support it, stream in and adjust our requirements
2282 # if we support it, stream in and adjust our requirements
2263 if not streamreqs - self.supportedformats:
2283 if not streamreqs - self.supportedformats:
2264 return self.stream_in(remote, streamreqs)
2284 return self.stream_in(remote, streamreqs)
2265 return self.pull(remote, heads)
2285 return self.pull(remote, heads)
2266
2286
2267 def pushkey(self, namespace, key, old, new):
2287 def pushkey(self, namespace, key, old, new):
2268 self.hook('prepushkey', throw=True, namespace=namespace, key=key,
2288 self.hook('prepushkey', throw=True, namespace=namespace, key=key,
2269 old=old, new=new)
2289 old=old, new=new)
2270 ret = pushkey.push(self, namespace, key, old, new)
2290 ret = pushkey.push(self, namespace, key, old, new)
2271 self.hook('pushkey', namespace=namespace, key=key, old=old, new=new,
2291 self.hook('pushkey', namespace=namespace, key=key, old=old, new=new,
2272 ret=ret)
2292 ret=ret)
2273 return ret
2293 return ret
2274
2294
2275 def listkeys(self, namespace):
2295 def listkeys(self, namespace):
2276 self.hook('prelistkeys', throw=True, namespace=namespace)
2296 self.hook('prelistkeys', throw=True, namespace=namespace)
2277 values = pushkey.list(self, namespace)
2297 values = pushkey.list(self, namespace)
2278 self.hook('listkeys', namespace=namespace, values=values)
2298 self.hook('listkeys', namespace=namespace, values=values)
2279 return values
2299 return values
2280
2300
2281 def debugwireargs(self, one, two, three=None, four=None, five=None):
2301 def debugwireargs(self, one, two, three=None, four=None, five=None):
2282 '''used to test argument passing over the wire'''
2302 '''used to test argument passing over the wire'''
2283 return "%s %s %s %s %s" % (one, two, three, four, five)
2303 return "%s %s %s %s %s" % (one, two, three, four, five)
2284
2304
2285 def savecommitmessage(self, text):
2305 def savecommitmessage(self, text):
2286 fp = self.opener('last-message.txt', 'wb')
2306 fp = self.opener('last-message.txt', 'wb')
2287 try:
2307 try:
2288 fp.write(text)
2308 fp.write(text)
2289 finally:
2309 finally:
2290 fp.close()
2310 fp.close()
2291 return self.pathto(fp.name[len(self.root)+1:])
2311 return self.pathto(fp.name[len(self.root)+1:])
2292
2312
2293 # used to avoid circular references so destructors work
2313 # used to avoid circular references so destructors work
2294 def aftertrans(files):
2314 def aftertrans(files):
2295 renamefiles = [tuple(t) for t in files]
2315 renamefiles = [tuple(t) for t in files]
2296 def a():
2316 def a():
2297 for src, dest in renamefiles:
2317 for src, dest in renamefiles:
2298 util.rename(src, dest)
2318 util.rename(src, dest)
2299 return a
2319 return a
2300
2320
2301 def undoname(fn):
2321 def undoname(fn):
2302 base, name = os.path.split(fn)
2322 base, name = os.path.split(fn)
2303 assert name.startswith('journal')
2323 assert name.startswith('journal')
2304 return os.path.join(base, name.replace('journal', 'undo', 1))
2324 return os.path.join(base, name.replace('journal', 'undo', 1))
2305
2325
2306 def instance(ui, path, create):
2326 def instance(ui, path, create):
2307 return localrepository(ui, util.urllocalpath(path), create)
2327 return localrepository(ui, util.urllocalpath(path), create)
2308
2328
2309 def islocal(path):
2329 def islocal(path):
2310 return True
2330 return True
@@ -1,660 +1,657 b''
1 $ check_code="$TESTDIR"/../contrib/check-code.py
1 $ check_code="$TESTDIR"/../contrib/check-code.py
2 $ cd "$TESTDIR"/..
2 $ cd "$TESTDIR"/..
3
3
4 $ "$check_code" `hg manifest` || echo 'FAILURE IS NOT AN OPTION!!!'
4 $ "$check_code" `hg manifest` || echo 'FAILURE IS NOT AN OPTION!!!'
5
5
6 $ "$check_code" --warnings --nolineno --per-file=0 `hg manifest`
6 $ "$check_code" --warnings --nolineno --per-file=0 `hg manifest`
7 contrib/check-code.py:0:
7 contrib/check-code.py:0:
8 > # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"),
8 > # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"),
9 warning: line over 80 characters
9 warning: line over 80 characters
10 contrib/perf.py:0:
10 contrib/perf.py:0:
11 > except:
11 > except:
12 warning: naked except clause
12 warning: naked except clause
13 contrib/perf.py:0:
13 contrib/perf.py:0:
14 > #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, False))))
14 > #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, False))))
15 warning: line over 80 characters
15 warning: line over 80 characters
16 contrib/perf.py:0:
16 contrib/perf.py:0:
17 > except:
17 > except:
18 warning: naked except clause
18 warning: naked except clause
19 contrib/setup3k.py:0:
19 contrib/setup3k.py:0:
20 > except:
20 > except:
21 warning: naked except clause
21 warning: naked except clause
22 contrib/setup3k.py:0:
22 contrib/setup3k.py:0:
23 > except:
23 > except:
24 warning: naked except clause
24 warning: naked except clause
25 contrib/setup3k.py:0:
25 contrib/setup3k.py:0:
26 > except:
26 > except:
27 warning: naked except clause
27 warning: naked except clause
28 warning: naked except clause
28 warning: naked except clause
29 warning: naked except clause
29 warning: naked except clause
30 contrib/shrink-revlog.py:0:
30 contrib/shrink-revlog.py:0:
31 > '(You can delete those files when you are satisfied that your\n'
31 > '(You can delete those files when you are satisfied that your\n'
32 warning: line over 80 characters
32 warning: line over 80 characters
33 contrib/shrink-revlog.py:0:
33 contrib/shrink-revlog.py:0:
34 > ('', 'sort', 'reversepostorder', 'name of sort algorithm to use'),
34 > ('', 'sort', 'reversepostorder', 'name of sort algorithm to use'),
35 warning: line over 80 characters
35 warning: line over 80 characters
36 contrib/shrink-revlog.py:0:
36 contrib/shrink-revlog.py:0:
37 > [('', 'revlog', '', _('index (.i) file of the revlog to shrink')),
37 > [('', 'revlog', '', _('index (.i) file of the revlog to shrink')),
38 warning: line over 80 characters
38 warning: line over 80 characters
39 contrib/shrink-revlog.py:0:
39 contrib/shrink-revlog.py:0:
40 > except:
40 > except:
41 warning: naked except clause
41 warning: naked except clause
42 doc/gendoc.py:0:
42 doc/gendoc.py:0:
43 > "together with Mercurial. Help for other extensions is available "
43 > "together with Mercurial. Help for other extensions is available "
44 warning: line over 80 characters
44 warning: line over 80 characters
45 hgext/bugzilla.py:0:
45 hgext/bugzilla.py:0:
46 > raise util.Abort(_('cannot find bugzilla user id for %s or %s') %
46 > raise util.Abort(_('cannot find bugzilla user id for %s or %s') %
47 warning: line over 80 characters
47 warning: line over 80 characters
48 hgext/bugzilla.py:0:
48 hgext/bugzilla.py:0:
49 > bzdir = self.ui.config('bugzilla', 'bzdir', '/var/www/html/bugzilla')
49 > bzdir = self.ui.config('bugzilla', 'bzdir', '/var/www/html/bugzilla')
50 warning: line over 80 characters
50 warning: line over 80 characters
51 hgext/convert/__init__.py:0:
51 hgext/convert/__init__.py:0:
52 > ('', 'ancestors', '', _('show current changeset in ancestor branches')),
52 > ('', 'ancestors', '', _('show current changeset in ancestor branches')),
53 warning: line over 80 characters
53 warning: line over 80 characters
54 hgext/convert/bzr.py:0:
54 hgext/convert/bzr.py:0:
55 > except:
55 > except:
56 warning: naked except clause
56 warning: naked except clause
57 hgext/convert/common.py:0:
57 hgext/convert/common.py:0:
58 > except:
58 > except:
59 warning: naked except clause
59 warning: naked except clause
60 hgext/convert/common.py:0:
60 hgext/convert/common.py:0:
61 > except:
61 > except:
62 warning: naked except clause
62 warning: naked except clause
63 warning: naked except clause
63 warning: naked except clause
64 hgext/convert/convcmd.py:0:
64 hgext/convert/convcmd.py:0:
65 > except:
65 > except:
66 warning: naked except clause
66 warning: naked except clause
67 hgext/convert/cvs.py:0:
67 hgext/convert/cvs.py:0:
68 > # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
68 > # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
69 warning: line over 80 characters
69 warning: line over 80 characters
70 hgext/convert/cvsps.py:0:
70 hgext/convert/cvsps.py:0:
71 > assert len(branches) == 1, 'unknown branch: %s' % e.mergepoint
71 > assert len(branches) == 1, 'unknown branch: %s' % e.mergepoint
72 warning: line over 80 characters
72 warning: line over 80 characters
73 hgext/convert/cvsps.py:0:
73 hgext/convert/cvsps.py:0:
74 > ui.write('Ancestors: %s\n' % (','.join(r)))
74 > ui.write('Ancestors: %s\n' % (','.join(r)))
75 warning: unwrapped ui message
75 warning: unwrapped ui message
76 hgext/convert/cvsps.py:0:
76 hgext/convert/cvsps.py:0:
77 > ui.write('Parent: %d\n' % cs.parents[0].id)
77 > ui.write('Parent: %d\n' % cs.parents[0].id)
78 warning: unwrapped ui message
78 warning: unwrapped ui message
79 hgext/convert/cvsps.py:0:
79 hgext/convert/cvsps.py:0:
80 > ui.write('Parents: %s\n' %
80 > ui.write('Parents: %s\n' %
81 warning: unwrapped ui message
81 warning: unwrapped ui message
82 hgext/convert/cvsps.py:0:
82 hgext/convert/cvsps.py:0:
83 > except:
83 > except:
84 warning: naked except clause
84 warning: naked except clause
85 hgext/convert/cvsps.py:0:
85 hgext/convert/cvsps.py:0:
86 > ui.write('Branchpoints: %s \n' % ', '.join(branchpoints))
86 > ui.write('Branchpoints: %s \n' % ', '.join(branchpoints))
87 warning: unwrapped ui message
87 warning: unwrapped ui message
88 hgext/convert/cvsps.py:0:
88 hgext/convert/cvsps.py:0:
89 > ui.write('Author: %s\n' % cs.author)
89 > ui.write('Author: %s\n' % cs.author)
90 warning: unwrapped ui message
90 warning: unwrapped ui message
91 hgext/convert/cvsps.py:0:
91 hgext/convert/cvsps.py:0:
92 > ui.write('Branch: %s\n' % (cs.branch or 'HEAD'))
92 > ui.write('Branch: %s\n' % (cs.branch or 'HEAD'))
93 warning: unwrapped ui message
93 warning: unwrapped ui message
94 hgext/convert/cvsps.py:0:
94 hgext/convert/cvsps.py:0:
95 > ui.write('Date: %s\n' % util.datestr(cs.date,
95 > ui.write('Date: %s\n' % util.datestr(cs.date,
96 warning: unwrapped ui message
96 warning: unwrapped ui message
97 hgext/convert/cvsps.py:0:
97 hgext/convert/cvsps.py:0:
98 > ui.write('Log:\n')
98 > ui.write('Log:\n')
99 warning: unwrapped ui message
99 warning: unwrapped ui message
100 hgext/convert/cvsps.py:0:
100 hgext/convert/cvsps.py:0:
101 > ui.write('Members: \n')
101 > ui.write('Members: \n')
102 warning: unwrapped ui message
102 warning: unwrapped ui message
103 hgext/convert/cvsps.py:0:
103 hgext/convert/cvsps.py:0:
104 > ui.write('PatchSet %d \n' % cs.id)
104 > ui.write('PatchSet %d \n' % cs.id)
105 warning: unwrapped ui message
105 warning: unwrapped ui message
106 hgext/convert/cvsps.py:0:
106 hgext/convert/cvsps.py:0:
107 > ui.write('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1],
107 > ui.write('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1],
108 warning: unwrapped ui message
108 warning: unwrapped ui message
109 hgext/convert/git.py:0:
109 hgext/convert/git.py:0:
110 > except:
110 > except:
111 warning: naked except clause
111 warning: naked except clause
112 hgext/convert/git.py:0:
112 hgext/convert/git.py:0:
113 > fh = self.gitopen('git diff-tree --name-only --root -r %s "%s^%s" --'
113 > fh = self.gitopen('git diff-tree --name-only --root -r %s "%s^%s" --'
114 warning: line over 80 characters
114 warning: line over 80 characters
115 hgext/convert/hg.py:0:
115 hgext/convert/hg.py:0:
116 > # detect missing revlogs and abort on errors or populate self.ignored
116 > # detect missing revlogs and abort on errors or populate self.ignored
117 warning: line over 80 characters
117 warning: line over 80 characters
118 hgext/convert/hg.py:0:
118 hgext/convert/hg.py:0:
119 > except:
119 > except:
120 warning: naked except clause
120 warning: naked except clause
121 warning: naked except clause
121 warning: naked except clause
122 hgext/convert/hg.py:0:
122 hgext/convert/hg.py:0:
123 > except:
123 > except:
124 warning: naked except clause
124 warning: naked except clause
125 hgext/convert/monotone.py:0:
125 hgext/convert/monotone.py:0:
126 > except:
126 > except:
127 warning: naked except clause
127 warning: naked except clause
128 hgext/convert/monotone.py:0:
128 hgext/convert/monotone.py:0:
129 > except:
129 > except:
130 warning: naked except clause
130 warning: naked except clause
131 hgext/convert/subversion.py:0:
131 hgext/convert/subversion.py:0:
132 > raise util.Abort(_('svn: branch has no revision %s') % to_revnum)
132 > raise util.Abort(_('svn: branch has no revision %s') % to_revnum)
133 warning: line over 80 characters
133 warning: line over 80 characters
134 hgext/convert/subversion.py:0:
134 hgext/convert/subversion.py:0:
135 > except:
135 > except:
136 warning: naked except clause
136 warning: naked except clause
137 hgext/convert/subversion.py:0:
137 hgext/convert/subversion.py:0:
138 > args = [self.baseurl, relpaths, start, end, limit, discover_changed_paths,
138 > args = [self.baseurl, relpaths, start, end, limit, discover_changed_paths,
139 warning: line over 80 characters
139 warning: line over 80 characters
140 hgext/convert/subversion.py:0:
140 hgext/convert/subversion.py:0:
141 > self.trunkname = self.ui.config('convert', 'svn.trunk', 'trunk').strip('/')
141 > self.trunkname = self.ui.config('convert', 'svn.trunk', 'trunk').strip('/')
142 warning: line over 80 characters
142 warning: line over 80 characters
143 hgext/convert/subversion.py:0:
143 hgext/convert/subversion.py:0:
144 > except:
144 > except:
145 warning: naked except clause
145 warning: naked except clause
146 hgext/convert/subversion.py:0:
146 hgext/convert/subversion.py:0:
147 > def get_log_child(fp, url, paths, start, end, limit=0, discover_changed_paths=True,
147 > def get_log_child(fp, url, paths, start, end, limit=0, discover_changed_paths=True,
148 warning: line over 80 characters
148 warning: line over 80 characters
149 hgext/eol.py:0:
149 hgext/eol.py:0:
150 > if ui.configbool('eol', 'fix-trailing-newline', False) and s and s[-1] != '\n':
150 > if ui.configbool('eol', 'fix-trailing-newline', False) and s and s[-1] != '\n':
151 warning: line over 80 characters
151 warning: line over 80 characters
152 warning: line over 80 characters
152 warning: line over 80 characters
153 hgext/gpg.py:0:
153 hgext/gpg.py:0:
154 > except:
154 > except:
155 warning: naked except clause
155 warning: naked except clause
156 hgext/hgcia.py:0:
156 hgext/hgcia.py:0:
157 > except:
157 > except:
158 warning: naked except clause
158 warning: naked except clause
159 hgext/hgk.py:0:
159 hgext/hgk.py:0:
160 > ui.write("%s%s\n" % (prefix, description.replace('\n', nlprefix).strip()))
160 > ui.write("%s%s\n" % (prefix, description.replace('\n', nlprefix).strip()))
161 warning: line over 80 characters
161 warning: line over 80 characters
162 hgext/hgk.py:0:
162 hgext/hgk.py:0:
163 > ui.write("parent %s\n" % p)
163 > ui.write("parent %s\n" % p)
164 warning: unwrapped ui message
164 warning: unwrapped ui message
165 hgext/hgk.py:0:
165 hgext/hgk.py:0:
166 > ui.write('k=%s\nv=%s\n' % (name, value))
166 > ui.write('k=%s\nv=%s\n' % (name, value))
167 warning: unwrapped ui message
167 warning: unwrapped ui message
168 hgext/hgk.py:0:
168 hgext/hgk.py:0:
169 > ui.write("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1]))
169 > ui.write("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1]))
170 warning: unwrapped ui message
170 warning: unwrapped ui message
171 hgext/hgk.py:0:
171 hgext/hgk.py:0:
172 > ui.write("branch %s\n\n" % ctx.branch())
172 > ui.write("branch %s\n\n" % ctx.branch())
173 warning: unwrapped ui message
173 warning: unwrapped ui message
174 hgext/hgk.py:0:
174 hgext/hgk.py:0:
175 > ui.write("committer %s %s %s\n" % (committer, int(date[0]), date[1]))
175 > ui.write("committer %s %s %s\n" % (committer, int(date[0]), date[1]))
176 warning: unwrapped ui message
176 warning: unwrapped ui message
177 hgext/hgk.py:0:
177 hgext/hgk.py:0:
178 > ui.write("revision %d\n" % ctx.rev())
178 > ui.write("revision %d\n" % ctx.rev())
179 warning: unwrapped ui message
179 warning: unwrapped ui message
180 hgext/hgk.py:0:
180 hgext/hgk.py:0:
181 > ui.write("tree %s\n" % short(ctx.changeset()[0])) # use ctx.node() instead ??
181 > ui.write("tree %s\n" % short(ctx.changeset()[0])) # use ctx.node() instead ??
182 warning: line over 80 characters
182 warning: line over 80 characters
183 warning: unwrapped ui message
183 warning: unwrapped ui message
184 hgext/highlight/__init__.py:0:
184 hgext/highlight/__init__.py:0:
185 > extensions.wrapfunction(webcommands, '_filerevision', filerevision_highlight)
185 > extensions.wrapfunction(webcommands, '_filerevision', filerevision_highlight)
186 warning: line over 80 characters
186 warning: line over 80 characters
187 hgext/highlight/__init__.py:0:
187 hgext/highlight/__init__.py:0:
188 > return ['/* pygments_style = %s */\n\n' % pg_style, fmter.get_style_defs('')]
188 > return ['/* pygments_style = %s */\n\n' % pg_style, fmter.get_style_defs('')]
189 warning: line over 80 characters
189 warning: line over 80 characters
190 hgext/inotify/__init__.py:0:
190 hgext/inotify/__init__.py:0:
191 > if self._inotifyon and not ignored and not subrepos and not self._dirty:
191 > if self._inotifyon and not ignored and not subrepos and not self._dirty:
192 warning: line over 80 characters
192 warning: line over 80 characters
193 hgext/inotify/server.py:0:
193 hgext/inotify/server.py:0:
194 > except:
194 > except:
195 warning: naked except clause
195 warning: naked except clause
196 hgext/inotify/server.py:0:
196 hgext/inotify/server.py:0:
197 > except:
197 > except:
198 warning: naked except clause
198 warning: naked except clause
199 hgext/keyword.py:0:
199 hgext/keyword.py:0:
200 > ui.note("hg ci -m '%s'\n" % msg)
200 > ui.note("hg ci -m '%s'\n" % msg)
201 warning: unwrapped ui message
201 warning: unwrapped ui message
202 hgext/largefiles/overrides.py:0:
202 hgext/largefiles/overrides.py:0:
203 > # When we call orig below it creates the standins but we don't add them
203 > # When we call orig below it creates the standins but we don't add them
204 warning: line over 80 characters
204 warning: line over 80 characters
205 hgext/largefiles/reposetup.py:0:
205 hgext/largefiles/reposetup.py:0:
206 > if os.path.exists(self.wjoin(lfutil.standin(lfile))):
206 > if os.path.exists(self.wjoin(lfutil.standin(lfile))):
207 warning: line over 80 characters
207 warning: line over 80 characters
208 hgext/mq.py:0:
208 hgext/mq.py:0:
209 > raise util.Abort(_("%s does not have a parent recorded" % root))
209 > raise util.Abort(_("%s does not have a parent recorded" % root))
210 warning: line over 80 characters
210 warning: line over 80 characters
211 hgext/mq.py:0:
211 hgext/mq.py:0:
212 > raise util.Abort(_("cannot push --exact with applied patches"))
212 > raise util.Abort(_("cannot push --exact with applied patches"))
213 warning: line over 80 characters
213 warning: line over 80 characters
214 hgext/mq.py:0:
214 hgext/mq.py:0:
215 > raise util.Abort(_("cannot use --exact and --move together"))
215 > raise util.Abort(_("cannot use --exact and --move together"))
216 warning: line over 80 characters
216 warning: line over 80 characters
217 hgext/mq.py:0:
217 hgext/mq.py:0:
218 > self.ui.warn(_('Tag %s overrides mq patch of the same name\n')
218 > self.ui.warn(_('Tag %s overrides mq patch of the same name\n')
219 warning: line over 80 characters
219 warning: line over 80 characters
220 hgext/mq.py:0:
220 hgext/mq.py:0:
221 > except:
221 > except:
222 warning: naked except clause
222 warning: naked except clause
223 warning: naked except clause
223 warning: naked except clause
224 hgext/mq.py:0:
224 hgext/mq.py:0:
225 > except:
225 > except:
226 warning: naked except clause
226 warning: naked except clause
227 warning: naked except clause
227 warning: naked except clause
228 warning: naked except clause
228 warning: naked except clause
229 warning: naked except clause
229 warning: naked except clause
230 hgext/mq.py:0:
230 hgext/mq.py:0:
231 > raise util.Abort(_('cannot mix -l/--list with options or arguments'))
231 > raise util.Abort(_('cannot mix -l/--list with options or arguments'))
232 warning: line over 80 characters
232 warning: line over 80 characters
233 hgext/mq.py:0:
233 hgext/mq.py:0:
234 > raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
234 > raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
235 warning: line over 80 characters
235 warning: line over 80 characters
236 hgext/mq.py:0:
236 hgext/mq.py:0:
237 > ('', 'move', None, _('reorder patch series and apply only the patch'))],
237 > ('', 'move', None, _('reorder patch series and apply only the patch'))],
238 warning: line over 80 characters
238 warning: line over 80 characters
239 hgext/mq.py:0:
239 hgext/mq.py:0:
240 > ('U', 'noupdate', None, _('do not update the new working directories')),
240 > ('U', 'noupdate', None, _('do not update the new working directories')),
241 warning: line over 80 characters
241 warning: line over 80 characters
242 hgext/mq.py:0:
242 hgext/mq.py:0:
243 > ('e', 'exact', None, _('apply the target patch to its recorded parent')),
243 > ('e', 'exact', None, _('apply the target patch to its recorded parent')),
244 warning: line over 80 characters
244 warning: line over 80 characters
245 hgext/mq.py:0:
245 hgext/mq.py:0:
246 > except:
246 > except:
247 warning: naked except clause
247 warning: naked except clause
248 hgext/mq.py:0:
248 hgext/mq.py:0:
249 > ui.write("mq: %s\n" % ', '.join(m))
249 > ui.write("mq: %s\n" % ', '.join(m))
250 warning: unwrapped ui message
250 warning: unwrapped ui message
251 hgext/mq.py:0:
251 hgext/mq.py:0:
252 > repo.mq.qseries(repo, missing=opts.get('missing'), summary=opts.get('summary'))
252 > repo.mq.qseries(repo, missing=opts.get('missing'), summary=opts.get('summary'))
253 warning: line over 80 characters
253 warning: line over 80 characters
254 hgext/notify.py:0:
254 hgext/notify.py:0:
255 > ui.note(_('notify: suppressing notification for merge %d:%s\n') %
255 > ui.note(_('notify: suppressing notification for merge %d:%s\n') %
256 warning: line over 80 characters
256 warning: line over 80 characters
257 hgext/patchbomb.py:0:
257 hgext/patchbomb.py:0:
258 > binnode, seqno=idx, total=total)
258 > binnode, seqno=idx, total=total)
259 warning: line over 80 characters
259 warning: line over 80 characters
260 hgext/patchbomb.py:0:
260 hgext/patchbomb.py:0:
261 > except:
261 > except:
262 warning: naked except clause
262 warning: naked except clause
263 hgext/patchbomb.py:0:
263 hgext/patchbomb.py:0:
264 > ui.write('Subject: %s\n' % subj)
264 > ui.write('Subject: %s\n' % subj)
265 warning: unwrapped ui message
265 warning: unwrapped ui message
266 hgext/patchbomb.py:0:
266 hgext/patchbomb.py:0:
267 > p = mail.mimetextpatch('\n'.join(patchlines), 'x-patch', opts.get('test'))
267 > p = mail.mimetextpatch('\n'.join(patchlines), 'x-patch', opts.get('test'))
268 warning: line over 80 characters
268 warning: line over 80 characters
269 hgext/patchbomb.py:0:
269 hgext/patchbomb.py:0:
270 > ui.write('From: %s\n' % sender)
270 > ui.write('From: %s\n' % sender)
271 warning: unwrapped ui message
271 warning: unwrapped ui message
272 hgext/record.py:0:
272 hgext/record.py:0:
273 > ignoreblanklines=opts.get('ignore_blank_lines'))
273 > ignoreblanklines=opts.get('ignore_blank_lines'))
274 warning: line over 80 characters
274 warning: line over 80 characters
275 hgext/record.py:0:
275 hgext/record.py:0:
276 > ignorewsamount=opts.get('ignore_space_change'),
276 > ignorewsamount=opts.get('ignore_space_change'),
277 warning: line over 80 characters
277 warning: line over 80 characters
278 hgext/zeroconf/__init__.py:0:
278 hgext/zeroconf/__init__.py:0:
279 > publish(name, desc, path, util.getport(u.config("web", "port", 8000)))
279 > publish(name, desc, path, util.getport(u.config("web", "port", 8000)))
280 warning: line over 80 characters
280 warning: line over 80 characters
281 hgext/zeroconf/__init__.py:0:
281 hgext/zeroconf/__init__.py:0:
282 > except:
282 > except:
283 warning: naked except clause
283 warning: naked except clause
284 warning: naked except clause
284 warning: naked except clause
285 mercurial/bundlerepo.py:0:
285 mercurial/bundlerepo.py:0:
286 > is a bundlerepo for the obtained bundle when the original "other" is remote.
286 > is a bundlerepo for the obtained bundle when the original "other" is remote.
287 warning: line over 80 characters
287 warning: line over 80 characters
288 mercurial/bundlerepo.py:0:
288 mercurial/bundlerepo.py:0:
289 > "local" is a local repo from which to obtain the actual incoming changesets; it
289 > "local" is a local repo from which to obtain the actual incoming changesets; it
290 warning: line over 80 characters
290 warning: line over 80 characters
291 mercurial/bundlerepo.py:0:
291 mercurial/bundlerepo.py:0:
292 > tmp = discovery.findcommonincoming(repo, other, heads=onlyheads, force=force)
292 > tmp = discovery.findcommonincoming(repo, other, heads=onlyheads, force=force)
293 warning: line over 80 characters
293 warning: line over 80 characters
294 mercurial/commands.py:0:
294 mercurial/commands.py:0:
295 > " size " + basehdr + " link p1 p2 nodeid\n")
295 > " size " + basehdr + " link p1 p2 nodeid\n")
296 warning: line over 80 characters
296 warning: line over 80 characters
297 mercurial/commands.py:0:
297 mercurial/commands.py:0:
298 > raise util.Abort('cannot use localheads with old style discovery')
298 > raise util.Abort('cannot use localheads with old style discovery')
299 warning: line over 80 characters
299 warning: line over 80 characters
300 mercurial/commands.py:0:
300 mercurial/commands.py:0:
301 > ui.note('branch %s\n' % data)
301 > ui.note('branch %s\n' % data)
302 warning: unwrapped ui message
302 warning: unwrapped ui message
303 mercurial/commands.py:0:
303 mercurial/commands.py:0:
304 > ui.note('node %s\n' % str(data))
304 > ui.note('node %s\n' % str(data))
305 warning: unwrapped ui message
305 warning: unwrapped ui message
306 mercurial/commands.py:0:
306 mercurial/commands.py:0:
307 > ui.note('tag %s\n' % name)
307 > ui.note('tag %s\n' % name)
308 warning: unwrapped ui message
308 warning: unwrapped ui message
309 mercurial/commands.py:0:
309 mercurial/commands.py:0:
310 > ui.write("unpruned common: %s\n" % " ".join([short(n)
310 > ui.write("unpruned common: %s\n" % " ".join([short(n)
311 warning: unwrapped ui message
311 warning: unwrapped ui message
312 mercurial/commands.py:0:
312 mercurial/commands.py:0:
313 > yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
313 > yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
314 warning: line over 80 characters
314 warning: line over 80 characters
315 mercurial/commands.py:0:
315 mercurial/commands.py:0:
316 > yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
316 > yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
317 warning: line over 80 characters
317 warning: line over 80 characters
318 mercurial/commands.py:0:
318 mercurial/commands.py:0:
319 > except:
319 > except:
320 warning: naked except clause
320 warning: naked except clause
321 mercurial/commands.py:0:
321 mercurial/commands.py:0:
322 > ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
322 > ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
323 warning: line over 80 characters
323 warning: line over 80 characters
324 mercurial/commands.py:0:
324 mercurial/commands.py:0:
325 > ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
325 > ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
326 warning: unwrapped ui message
326 warning: unwrapped ui message
327 mercurial/commands.py:0:
327 mercurial/commands.py:0:
328 > ui.write("local is subset\n")
328 > ui.write("local is subset\n")
329 warning: unwrapped ui message
329 warning: unwrapped ui message
330 mercurial/commands.py:0:
330 mercurial/commands.py:0:
331 > ui.write("remote is subset\n")
331 > ui.write("remote is subset\n")
332 warning: unwrapped ui message
332 warning: unwrapped ui message
333 mercurial/commands.py:0:
333 mercurial/commands.py:0:
334 > ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
334 > ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
335 warning: line over 80 characters
335 warning: line over 80 characters
336 mercurial/commands.py:0:
336 mercurial/commands.py:0:
337 > ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
337 > ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
338 warning: line over 80 characters
338 warning: line over 80 characters
339 mercurial/commands.py:0:
339 mercurial/commands.py:0:
340 > ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
340 > ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
341 warning: line over 80 characters
341 warning: line over 80 characters
342 mercurial/commands.py:0:
342 mercurial/commands.py:0:
343 > ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
343 > ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
344 warning: line over 80 characters
344 warning: line over 80 characters
345 warning: unwrapped ui message
345 warning: unwrapped ui message
346 mercurial/commands.py:0:
346 mercurial/commands.py:0:
347 > ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
347 > ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
348 warning: unwrapped ui message
348 warning: unwrapped ui message
349 mercurial/commands.py:0:
349 mercurial/commands.py:0:
350 > ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
350 > ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
351 warning: unwrapped ui message
351 warning: unwrapped ui message
352 mercurial/commands.py:0:
352 mercurial/commands.py:0:
353 > cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
353 > cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
354 warning: line over 80 characters
354 warning: line over 80 characters
355 mercurial/commands.py:0:
355 mercurial/commands.py:0:
356 > except:
356 > except:
357 warning: naked except clause
357 warning: naked except clause
358 mercurial/commands.py:0:
358 mercurial/commands.py:0:
359 > revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
359 > revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
360 warning: line over 80 characters
360 warning: line over 80 characters
361 mercurial/commands.py:0:
361 mercurial/commands.py:0:
362 > ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
362 > ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
363 warning: unwrapped ui message
363 warning: unwrapped ui message
364 mercurial/commands.py:0:
364 mercurial/commands.py:0:
365 > ui.write("match: %s\n" % m(d[0]))
365 > ui.write("match: %s\n" % m(d[0]))
366 warning: unwrapped ui message
366 warning: unwrapped ui message
367 mercurial/commands.py:0:
367 mercurial/commands.py:0:
368 > ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
368 > ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
369 warning: unwrapped ui message
369 warning: unwrapped ui message
370 mercurial/commands.py:0:
370 mercurial/commands.py:0:
371 > ui.write('path %s\n' % k)
371 > ui.write('path %s\n' % k)
372 warning: unwrapped ui message
372 warning: unwrapped ui message
373 mercurial/commands.py:0:
373 mercurial/commands.py:0:
374 > ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
374 > ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
375 warning: unwrapped ui message
375 warning: unwrapped ui message
376 mercurial/commands.py:0:
376 mercurial/commands.py:0:
377 > Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
377 > Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
378 warning: line over 80 characters
378 warning: line over 80 characters
379 mercurial/commands.py:0:
379 mercurial/commands.py:0:
380 > remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
380 > remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
381 warning: line over 80 characters
381 warning: line over 80 characters
382 mercurial/commands.py:0:
382 mercurial/commands.py:0:
383 > ui.write("digraph G {\n")
383 > ui.write("digraph G {\n")
384 warning: unwrapped ui message
384 warning: unwrapped ui message
385 mercurial/commands.py:0:
385 mercurial/commands.py:0:
386 > ui.write("internal: %s %s\n" % d)
386 > ui.write("internal: %s %s\n" % d)
387 warning: unwrapped ui message
387 warning: unwrapped ui message
388 mercurial/commands.py:0:
388 mercurial/commands.py:0:
389 > ui.write("standard: %s\n" % util.datestr(d))
389 > ui.write("standard: %s\n" % util.datestr(d))
390 warning: unwrapped ui message
390 warning: unwrapped ui message
391 mercurial/commands.py:0:
391 mercurial/commands.py:0:
392 > ui.write('avg chain length : ' + fmt % avgchainlen)
392 > ui.write('avg chain length : ' + fmt % avgchainlen)
393 warning: unwrapped ui message
393 warning: unwrapped ui message
394 mercurial/commands.py:0:
394 mercurial/commands.py:0:
395 > ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
395 > ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
396 warning: unwrapped ui message
396 warning: unwrapped ui message
397 mercurial/commands.py:0:
397 mercurial/commands.py:0:
398 > ui.write('compression ratio : ' + fmt % compratio)
398 > ui.write('compression ratio : ' + fmt % compratio)
399 warning: unwrapped ui message
399 warning: unwrapped ui message
400 mercurial/commands.py:0:
400 mercurial/commands.py:0:
401 > ui.write('delta size (min/max/avg) : %d / %d / %d\n'
401 > ui.write('delta size (min/max/avg) : %d / %d / %d\n'
402 warning: unwrapped ui message
402 warning: unwrapped ui message
403 mercurial/commands.py:0:
403 mercurial/commands.py:0:
404 > ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
404 > ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
405 warning: unwrapped ui message
405 warning: unwrapped ui message
406 mercurial/commands.py:0:
406 mercurial/commands.py:0:
407 > ui.write('flags : %s\n' % ', '.join(flags))
407 > ui.write('flags : %s\n' % ', '.join(flags))
408 warning: unwrapped ui message
408 warning: unwrapped ui message
409 mercurial/commands.py:0:
409 mercurial/commands.py:0:
410 > ui.write('format : %d\n' % format)
410 > ui.write('format : %d\n' % format)
411 warning: unwrapped ui message
411 warning: unwrapped ui message
412 mercurial/commands.py:0:
412 mercurial/commands.py:0:
413 > ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
413 > ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
414 warning: unwrapped ui message
414 warning: unwrapped ui message
415 mercurial/commands.py:0:
415 mercurial/commands.py:0:
416 > ui.write('revision size : ' + fmt2 % totalsize)
416 > ui.write('revision size : ' + fmt2 % totalsize)
417 warning: unwrapped ui message
417 warning: unwrapped ui message
418 mercurial/commands.py:0:
418 mercurial/commands.py:0:
419 > ui.write('revisions : ' + fmt2 % numrevs)
419 > ui.write('revisions : ' + fmt2 % numrevs)
420 warning: unwrapped ui message
420 warning: unwrapped ui message
421 warning: unwrapped ui message
421 warning: unwrapped ui message
422 mercurial/commands.py:0:
422 mercurial/commands.py:0:
423 > ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
423 > ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
424 warning: unwrapped ui message
424 warning: unwrapped ui message
425 mercurial/commandserver.py:0:
425 mercurial/commandserver.py:0:
426 > # the ui here is really the repo ui so take its baseui so we don't end up
426 > # the ui here is really the repo ui so take its baseui so we don't end up
427 warning: line over 80 characters
427 warning: line over 80 characters
428 mercurial/context.py:0:
428 mercurial/context.py:0:
429 > return self._manifestdelta[path], self._manifestdelta.flags(path)
429 > return self._manifestdelta[path], self._manifestdelta.flags(path)
430 warning: line over 80 characters
430 warning: line over 80 characters
431 mercurial/dagparser.py:0:
431 mercurial/dagparser.py:0:
432 > raise util.Abort(_("invalid character in dag description: %s...") % s)
432 > raise util.Abort(_("invalid character in dag description: %s...") % s)
433 warning: line over 80 characters
433 warning: line over 80 characters
434 mercurial/dagparser.py:0:
434 mercurial/dagparser.py:0:
435 > >>> dagtext([('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))])
435 > >>> dagtext([('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))])
436 warning: line over 80 characters
436 warning: line over 80 characters
437 mercurial/dirstate.py:0:
437 mercurial/dirstate.py:0:
438 > if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
438 > if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
439 warning: line over 80 characters
439 warning: line over 80 characters
440 mercurial/discovery.py:0:
440 mercurial/discovery.py:0:
441 > If onlyheads is given, only nodes ancestral to nodes in onlyheads (inclusive)
441 > If onlyheads is given, only nodes ancestral to nodes in onlyheads (inclusive)
442 warning: line over 80 characters
442 warning: line over 80 characters
443 mercurial/discovery.py:0:
443 mercurial/discovery.py:0:
444 > def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None):
444 > def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None):
445 warning: line over 80 characters
445 warning: line over 80 characters
446 mercurial/dispatch.py:0:
446 mercurial/dispatch.py:0:
447 > " (.hg not found)") % os.getcwd())
447 > " (.hg not found)") % os.getcwd())
448 warning: line over 80 characters
448 warning: line over 80 characters
449 mercurial/dispatch.py:0:
449 mercurial/dispatch.py:0:
450 > aliases, entry = cmdutil.findcmd(cmd, cmdtable, lui.config("ui", "strict"))
450 > aliases, entry = cmdutil.findcmd(cmd, cmdtable, lui.config("ui", "strict"))
451 warning: line over 80 characters
451 warning: line over 80 characters
452 mercurial/dispatch.py:0:
452 mercurial/dispatch.py:0:
453 > except:
453 > except:
454 warning: naked except clause
454 warning: naked except clause
455 mercurial/dispatch.py:0:
455 mercurial/dispatch.py:0:
456 > return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
456 > return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
457 warning: line over 80 characters
457 warning: line over 80 characters
458 mercurial/dispatch.py:0:
458 mercurial/dispatch.py:0:
459 > def __init__(self, args, ui=None, repo=None, fin=None, fout=None, ferr=None):
459 > def __init__(self, args, ui=None, repo=None, fin=None, fout=None, ferr=None):
460 warning: line over 80 characters
460 warning: line over 80 characters
461 mercurial/dispatch.py:0:
461 mercurial/dispatch.py:0:
462 > except:
462 > except:
463 warning: naked except clause
463 warning: naked except clause
464 mercurial/hg.py:0:
464 mercurial/hg.py:0:
465 > except:
465 > except:
466 warning: naked except clause
466 warning: naked except clause
467 mercurial/hgweb/hgweb_mod.py:0:
467 mercurial/hgweb/hgweb_mod.py:0:
468 > self.maxshortchanges = int(self.config("web", "maxshortchanges", 60))
468 > self.maxshortchanges = int(self.config("web", "maxshortchanges", 60))
469 warning: line over 80 characters
469 warning: line over 80 characters
470 mercurial/keepalive.py:0:
470 mercurial/keepalive.py:0:
471 > except:
471 > except:
472 warning: naked except clause
472 warning: naked except clause
473 mercurial/keepalive.py:0:
473 mercurial/keepalive.py:0:
474 > except:
474 > except:
475 warning: naked except clause
475 warning: naked except clause
476 mercurial/localrepo.py:0:
476 mercurial/localrepo.py:0:
477 > hint=_("use --subrepos for recursive commit"))
478 warning: line over 80 characters
479 mercurial/localrepo.py:0:
480 > # we return an integer indicating remote head count change
477 > # we return an integer indicating remote head count change
481 warning: line over 80 characters
478 warning: line over 80 characters
482 mercurial/localrepo.py:0:
479 mercurial/localrepo.py:0:
483 > raise util.Abort(_("empty or missing revlog for %s") % fname)
480 > raise util.Abort(_("empty or missing revlog for %s") % fname)
484 warning: line over 80 characters
481 warning: line over 80 characters
485 warning: line over 80 characters
482 warning: line over 80 characters
486 mercurial/localrepo.py:0:
483 mercurial/localrepo.py:0:
487 > if self._tagscache.tagtypes and name in self._tagscache.tagtypes:
484 > if self._tagscache.tagtypes and name in self._tagscache.tagtypes:
488 warning: line over 80 characters
485 warning: line over 80 characters
489 mercurial/localrepo.py:0:
486 mercurial/localrepo.py:0:
490 > self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
487 > self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
491 warning: line over 80 characters
488 warning: line over 80 characters
492 mercurial/localrepo.py:0:
489 mercurial/localrepo.py:0:
493 > # new requirements = old non-format requirements + new format-related
490 > # new requirements = old non-format requirements + new format-related
494 warning: line over 80 characters
491 warning: line over 80 characters
495 mercurial/localrepo.py:0:
492 mercurial/localrepo.py:0:
496 > except:
493 > except:
497 warning: naked except clause
494 warning: naked except clause
498 mercurial/localrepo.py:0:
495 mercurial/localrepo.py:0:
499 > """return status of files between two nodes or node and working directory
496 > """return status of files between two nodes or node and working directory
500 warning: line over 80 characters
497 warning: line over 80 characters
501 mercurial/localrepo.py:0:
498 mercurial/localrepo.py:0:
502 > '''Returns a tagscache object that contains various tags related caches.'''
499 > '''Returns a tagscache object that contains various tags related caches.'''
503 warning: line over 80 characters
500 warning: line over 80 characters
504 mercurial/manifest.py:0:
501 mercurial/manifest.py:0:
505 > return "".join(struct.pack(">lll", start, end, len(content)) + content
502 > return "".join(struct.pack(">lll", start, end, len(content)) + content
506 warning: line over 80 characters
503 warning: line over 80 characters
507 mercurial/merge.py:0:
504 mercurial/merge.py:0:
508 > subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
505 > subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
509 warning: line over 80 characters
506 warning: line over 80 characters
510 mercurial/patch.py:0:
507 mercurial/patch.py:0:
511 > modified, added, removed, copy, getfilectx, opts, losedata, prefix)
508 > modified, added, removed, copy, getfilectx, opts, losedata, prefix)
512 warning: line over 80 characters
509 warning: line over 80 characters
513 mercurial/patch.py:0:
510 mercurial/patch.py:0:
514 > diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a, self.b)
511 > diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a, self.b)
515 warning: line over 80 characters
512 warning: line over 80 characters
516 mercurial/patch.py:0:
513 mercurial/patch.py:0:
517 > output.append(_(' %d files changed, %d insertions(+), %d deletions(-)\n')
514 > output.append(_(' %d files changed, %d insertions(+), %d deletions(-)\n')
518 warning: line over 80 characters
515 warning: line over 80 characters
519 mercurial/patch.py:0:
516 mercurial/patch.py:0:
520 > except:
517 > except:
521 warning: naked except clause
518 warning: naked except clause
522 mercurial/pure/base85.py:0:
519 mercurial/pure/base85.py:0:
523 > raise OverflowError('Base85 overflow in hunk starting at byte %d' % i)
520 > raise OverflowError('Base85 overflow in hunk starting at byte %d' % i)
524 warning: line over 80 characters
521 warning: line over 80 characters
525 mercurial/pure/mpatch.py:0:
522 mercurial/pure/mpatch.py:0:
526 > frags.extend(reversed(new)) # what was left at the end
523 > frags.extend(reversed(new)) # what was left at the end
527 warning: line over 80 characters
524 warning: line over 80 characters
528 mercurial/repair.py:0:
525 mercurial/repair.py:0:
529 > except:
526 > except:
530 warning: naked except clause
527 warning: naked except clause
531 mercurial/repair.py:0:
528 mercurial/repair.py:0:
532 > except:
529 > except:
533 warning: naked except clause
530 warning: naked except clause
534 mercurial/revset.py:0:
531 mercurial/revset.py:0:
535 > elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
532 > elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
536 warning: line over 80 characters
533 warning: line over 80 characters
537 mercurial/revset.py:0:
534 mercurial/revset.py:0:
538 > Changesets that are the Nth ancestor (first parents only) of a changeset in set.
535 > Changesets that are the Nth ancestor (first parents only) of a changeset in set.
539 warning: line over 80 characters
536 warning: line over 80 characters
540 mercurial/scmutil.py:0:
537 mercurial/scmutil.py:0:
541 > raise util.Abort(_("path '%s' is inside nested repo %r") %
538 > raise util.Abort(_("path '%s' is inside nested repo %r") %
542 warning: line over 80 characters
539 warning: line over 80 characters
543 mercurial/scmutil.py:0:
540 mercurial/scmutil.py:0:
544 > "requires features '%s' (upgrade Mercurial)") % "', '".join(missings))
541 > "requires features '%s' (upgrade Mercurial)") % "', '".join(missings))
545 warning: line over 80 characters
542 warning: line over 80 characters
546 mercurial/scmutil.py:0:
543 mercurial/scmutil.py:0:
547 > elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target)
544 > elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target)
548 warning: line over 80 characters
545 warning: line over 80 characters
549 mercurial/setdiscovery.py:0:
546 mercurial/setdiscovery.py:0:
550 > # treat remote heads (and maybe own heads) as a first implicit sample response
547 > # treat remote heads (and maybe own heads) as a first implicit sample response
551 warning: line over 80 characters
548 warning: line over 80 characters
552 mercurial/setdiscovery.py:0:
549 mercurial/setdiscovery.py:0:
553 > undecided = dag.nodeset() # own nodes where I don't know if remote knows them
550 > undecided = dag.nodeset() # own nodes where I don't know if remote knows them
554 warning: line over 80 characters
551 warning: line over 80 characters
555 mercurial/similar.py:0:
552 mercurial/similar.py:0:
556 > repo.ui.progress(_('searching for similar files'), i, total=len(removed))
553 > repo.ui.progress(_('searching for similar files'), i, total=len(removed))
557 warning: line over 80 characters
554 warning: line over 80 characters
558 mercurial/simplemerge.py:0:
555 mercurial/simplemerge.py:0:
559 > for zmatch, zend, amatch, aend, bmatch, bend in self.find_sync_regions():
556 > for zmatch, zend, amatch, aend, bmatch, bend in self.find_sync_regions():
560 warning: line over 80 characters
557 warning: line over 80 characters
561 mercurial/sshrepo.py:0:
558 mercurial/sshrepo.py:0:
562 > self._abort(error.RepoError(_("no suitable response from remote hg")))
559 > self._abort(error.RepoError(_("no suitable response from remote hg")))
563 warning: line over 80 characters
560 warning: line over 80 characters
564 mercurial/sshrepo.py:0:
561 mercurial/sshrepo.py:0:
565 > except:
562 > except:
566 warning: naked except clause
563 warning: naked except clause
567 mercurial/subrepo.py:0:
564 mercurial/subrepo.py:0:
568 > other, self._repo = hg.clone(self._repo._subparent.ui, {}, other,
565 > other, self._repo = hg.clone(self._repo._subparent.ui, {}, other,
569 warning: line over 80 characters
566 warning: line over 80 characters
570 mercurial/subrepo.py:0:
567 mercurial/subrepo.py:0:
571 > msg = (_(' subrepository sources for %s differ (in checked out version)\n'
568 > msg = (_(' subrepository sources for %s differ (in checked out version)\n'
572 warning: line over 80 characters
569 warning: line over 80 characters
573 mercurial/transaction.py:0:
570 mercurial/transaction.py:0:
574 > except:
571 > except:
575 warning: naked except clause
572 warning: naked except clause
576 mercurial/ui.py:0:
573 mercurial/ui.py:0:
577 > traceback.print_exception(exc[0], exc[1], exc[2], file=self.ferr)
574 > traceback.print_exception(exc[0], exc[1], exc[2], file=self.ferr)
578 warning: line over 80 characters
575 warning: line over 80 characters
579 mercurial/url.py:0:
576 mercurial/url.py:0:
580 > conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
577 > conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
581 warning: line over 80 characters
578 warning: line over 80 characters
582 mercurial/util.py:0:
579 mercurial/util.py:0:
583 > except:
580 > except:
584 warning: naked except clause
581 warning: naked except clause
585 mercurial/util.py:0:
582 mercurial/util.py:0:
586 > except:
583 > except:
587 warning: naked except clause
584 warning: naked except clause
588 mercurial/verify.py:0:
585 mercurial/verify.py:0:
589 > except:
586 > except:
590 warning: naked except clause
587 warning: naked except clause
591 mercurial/verify.py:0:
588 mercurial/verify.py:0:
592 > except:
589 > except:
593 warning: naked except clause
590 warning: naked except clause
594 mercurial/wireproto.py:0:
591 mercurial/wireproto.py:0:
595 > # Assuming the future to be filled with the result from the batched request
592 > # Assuming the future to be filled with the result from the batched request
596 warning: line over 80 characters
593 warning: line over 80 characters
597 mercurial/wireproto.py:0:
594 mercurial/wireproto.py:0:
598 > '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)'''
595 > '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)'''
599 warning: line over 80 characters
596 warning: line over 80 characters
600 mercurial/wireproto.py:0:
597 mercurial/wireproto.py:0:
601 > All methods invoked on instances of this class are simply queued and return a
598 > All methods invoked on instances of this class are simply queued and return a
602 warning: line over 80 characters
599 warning: line over 80 characters
603 mercurial/wireproto.py:0:
600 mercurial/wireproto.py:0:
604 > The decorator returns a function which wraps this coroutine as a plain method,
601 > The decorator returns a function which wraps this coroutine as a plain method,
605 warning: line over 80 characters
602 warning: line over 80 characters
606 setup.py:0:
603 setup.py:0:
607 > raise SystemExit("Python headers are required to build Mercurial")
604 > raise SystemExit("Python headers are required to build Mercurial")
608 warning: line over 80 characters
605 warning: line over 80 characters
609 setup.py:0:
606 setup.py:0:
610 > except:
607 > except:
611 warning: naked except clause
608 warning: naked except clause
612 setup.py:0:
609 setup.py:0:
613 > # build_py), it will not find osutil & friends, thinking that those modules are
610 > # build_py), it will not find osutil & friends, thinking that those modules are
614 warning: line over 80 characters
611 warning: line over 80 characters
615 setup.py:0:
612 setup.py:0:
616 > except:
613 > except:
617 warning: naked except clause
614 warning: naked except clause
618 warning: naked except clause
615 warning: naked except clause
619 setup.py:0:
616 setup.py:0:
620 > isironpython = platform.python_implementation().lower().find("ironpython") != -1
617 > isironpython = platform.python_implementation().lower().find("ironpython") != -1
621 warning: line over 80 characters
618 warning: line over 80 characters
622 setup.py:0:
619 setup.py:0:
623 > except:
620 > except:
624 warning: naked except clause
621 warning: naked except clause
625 warning: naked except clause
622 warning: naked except clause
626 warning: naked except clause
623 warning: naked except clause
627 tests/autodiff.py:0:
624 tests/autodiff.py:0:
628 > ui.write('data lost for: %s\n' % fn)
625 > ui.write('data lost for: %s\n' % fn)
629 warning: unwrapped ui message
626 warning: unwrapped ui message
630 tests/run-tests.py:0:
627 tests/run-tests.py:0:
631 > except:
628 > except:
632 warning: naked except clause
629 warning: naked except clause
633 tests/test-commandserver.py:0:
630 tests/test-commandserver.py:0:
634 > 'hooks.pre-identify=python:test-commandserver.hook', 'id'],
631 > 'hooks.pre-identify=python:test-commandserver.hook', 'id'],
635 warning: line over 80 characters
632 warning: line over 80 characters
636 tests/test-commandserver.py:0:
633 tests/test-commandserver.py:0:
637 > # the cached repo local hgrc contains ui.foo=bar, so showconfig should show it
634 > # the cached repo local hgrc contains ui.foo=bar, so showconfig should show it
638 warning: line over 80 characters
635 warning: line over 80 characters
639 tests/test-commandserver.py:0:
636 tests/test-commandserver.py:0:
640 > print '%c, %r' % (ch, re.sub('encoding: [a-zA-Z0-9-]+', 'encoding: ***', data))
637 > print '%c, %r' % (ch, re.sub('encoding: [a-zA-Z0-9-]+', 'encoding: ***', data))
641 warning: line over 80 characters
638 warning: line over 80 characters
642 tests/test-filecache.py:0:
639 tests/test-filecache.py:0:
643 > except:
640 > except:
644 warning: naked except clause
641 warning: naked except clause
645 tests/test-filecache.py:0:
642 tests/test-filecache.py:0:
646 > if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'], 'cacheable']):
643 > if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'], 'cacheable']):
647 warning: line over 80 characters
644 warning: line over 80 characters
648 tests/test-ui-color.py:0:
645 tests/test-ui-color.py:0:
649 > testui.warn('warning\n')
646 > testui.warn('warning\n')
650 warning: unwrapped ui message
647 warning: unwrapped ui message
651 tests/test-ui-color.py:0:
648 tests/test-ui-color.py:0:
652 > testui.write('buffered\n')
649 > testui.write('buffered\n')
653 warning: unwrapped ui message
650 warning: unwrapped ui message
654 tests/test-walkrepo.py:0:
651 tests/test-walkrepo.py:0:
655 > print "Found %d repositories when I should have found 2" % (len(reposet),)
652 > print "Found %d repositories when I should have found 2" % (len(reposet),)
656 warning: line over 80 characters
653 warning: line over 80 characters
657 tests/test-walkrepo.py:0:
654 tests/test-walkrepo.py:0:
658 > print "Found %d repositories when I should have found 3" % (len(reposet),)
655 > print "Found %d repositories when I should have found 3" % (len(reposet),)
659 warning: line over 80 characters
656 warning: line over 80 characters
660 [1]
657 [1]
@@ -1,51 +1,50 b''
1 $ "$TESTDIR/hghave" svn13 || exit 80
1 $ "$TESTDIR/hghave" svn13 || exit 80
2
2
3 $ echo "[extensions]" >> $HGRCPATH
3 $ echo "[extensions]" >> $HGRCPATH
4 $ echo "mq=" >> $HGRCPATH
4 $ echo "mq=" >> $HGRCPATH
5 $ echo "[diff]" >> $HGRCPATH
5 $ echo "[diff]" >> $HGRCPATH
6 $ echo "nodates=1" >> $HGRCPATH
6 $ echo "nodates=1" >> $HGRCPATH
7
7
8 fn to create new repository, and cd into it
8 fn to create new repository, and cd into it
9 $ mkrepo() {
9 $ mkrepo() {
10 > hg init $1
10 > hg init $1
11 > cd $1
11 > cd $1
12 > hg qinit
12 > hg qinit
13 > }
13 > }
14
14
15
15
16 handle svn subrepos safely
16 handle svn subrepos safely
17
17
18 $ svnadmin create svn-repo-2499
18 $ svnadmin create svn-repo-2499
19 $ curpath=`pwd | tr '\\\\' /`
19 $ curpath=`pwd | tr '\\\\' /`
20 $ expr "$svnpath" : "\/" > /dev/null
20 $ expr "$svnpath" : "\/" > /dev/null
21 > if [ $? -ne 0 ]; then
21 > if [ $? -ne 0 ]; then
22 > curpath="/$curpath"
22 > curpath="/$curpath"
23 > fi
23 > fi
24 $ svnurl="file://$curpath/svn-repo-2499/project"
24 $ svnurl="file://$curpath/svn-repo-2499/project"
25 $ mkdir -p svn-project-2499/trunk
25 $ mkdir -p svn-project-2499/trunk
26 $ svn import -m 'init project' svn-project-2499 "$svnurl"
26 $ svn import -m 'init project' svn-project-2499 "$svnurl"
27 Adding svn-project-2499/trunk
27 Adding svn-project-2499/trunk
28
28
29 Committed revision 1.
29 Committed revision 1.
30
30
31 qnew on repo w/svn subrepo
31 qnew on repo w/svn subrepo
32 $ mkrepo repo-2499-svn-subrepo
32 $ mkrepo repo-2499-svn-subrepo
33 $ svn co "$svnurl"/trunk sub
33 $ svn co "$svnurl"/trunk sub
34 Checked out revision 1.
34 Checked out revision 1.
35 $ echo 'sub = [svn]sub' >> .hgsub
35 $ echo 'sub = [svn]sub' >> .hgsub
36 $ hg add .hgsub
36 $ hg add .hgsub
37 $ hg status -S -X '**/format'
37 $ hg status -S -X '**/format'
38 A .hgsub
38 A .hgsub
39 $ hg qnew -m0 0.diff
39 $ hg qnew -m0 0.diff
40 committing subrepository sub
41 $ cd sub
40 $ cd sub
42 $ echo a > a
41 $ echo a > a
43 $ svn add a
42 $ svn add a
44 A a
43 A a
45 $ svn st
44 $ svn st
46 A* a (glob)
45 A* a (glob)
47 $ cd ..
46 $ cd ..
48 $ hg status -S # doesn't show status for svn subrepos (yet)
47 $ hg status -S # doesn't show status for svn subrepos (yet)
49 $ hg qnew -m1 1.diff
48 $ hg qnew -m1 1.diff
50 abort: uncommitted changes in subrepository sub
49 abort: uncommitted changes in subrepository sub
51 [255]
50 [255]
@@ -1,363 +1,355 b''
1 $ echo "[ui]" >> $HGRCPATH
1 $ echo "[ui]" >> $HGRCPATH
2 $ echo "commitsubrepos = Yes" >> $HGRCPATH
2 $ echo "commitsubrepos = Yes" >> $HGRCPATH
3 $ echo "[extensions]" >> $HGRCPATH
3 $ echo "[extensions]" >> $HGRCPATH
4 $ echo "mq=" >> $HGRCPATH
4 $ echo "mq=" >> $HGRCPATH
5 $ echo "record=" >> $HGRCPATH
5 $ echo "record=" >> $HGRCPATH
6 $ echo "[diff]" >> $HGRCPATH
6 $ echo "[diff]" >> $HGRCPATH
7 $ echo "nodates=1" >> $HGRCPATH
7 $ echo "nodates=1" >> $HGRCPATH
8
8
9 $ stdin=`pwd`/stdin.tmp
9 $ stdin=`pwd`/stdin.tmp
10
10
11 fn to create new repository w/dirty subrepo, and cd into it
11 fn to create new repository w/dirty subrepo, and cd into it
12 $ mkrepo() {
12 $ mkrepo() {
13 > hg init $1
13 > hg init $1
14 > cd $1
14 > cd $1
15 > hg qinit
15 > hg qinit
16 > }
16 > }
17
17
18 fn to create dirty subrepo
18 fn to create dirty subrepo
19 $ mksubrepo() {
19 $ mksubrepo() {
20 > hg init $1
20 > hg init $1
21 > cd $1
21 > cd $1
22 > echo a > a
22 > echo a > a
23 > hg add
23 > hg add
24 > cd ..
24 > cd ..
25 > }
25 > }
26
26
27 $ testadd() {
27 $ testadd() {
28 > cat - > "$stdin"
28 > cat - > "$stdin"
29 > mksubrepo sub
29 > mksubrepo sub
30 > echo sub = sub >> .hgsub
30 > echo sub = sub >> .hgsub
31 > hg add .hgsub
31 > hg add .hgsub
32 > echo % abort when adding .hgsub w/dirty subrepo
32 > echo % abort when adding .hgsub w/dirty subrepo
33 > hg status -S
33 > hg status -S
34 > echo '%' $*
34 > echo '%' $*
35 > cat "$stdin" | hg $*
35 > cat "$stdin" | hg $*
36 > echo [$?]
36 > echo [$?]
37 > hg -R sub ci -m0sub
37 > hg -R sub ci -m0sub
38 > echo % update substate when adding .hgsub w/clean updated subrepo
38 > echo % update substate when adding .hgsub w/clean updated subrepo
39 > hg status -S
39 > hg status -S
40 > echo '%' $*
40 > echo '%' $*
41 > cat "$stdin" | hg $*
41 > cat "$stdin" | hg $*
42 > hg debugsub
42 > hg debugsub
43 > }
43 > }
44
44
45 $ testmod() {
45 $ testmod() {
46 > cat - > "$stdin"
46 > cat - > "$stdin"
47 > mksubrepo sub2
47 > mksubrepo sub2
48 > echo sub2 = sub2 >> .hgsub
48 > echo sub2 = sub2 >> .hgsub
49 > echo % abort when modifying .hgsub w/dirty subrepo
49 > echo % abort when modifying .hgsub w/dirty subrepo
50 > hg status -S
50 > hg status -S
51 > echo '%' $*
51 > echo '%' $*
52 > cat "$stdin" | hg $*
52 > cat "$stdin" | hg $*
53 > echo [$?]
53 > echo [$?]
54 > hg -R sub2 ci -m0sub2
54 > hg -R sub2 ci -m0sub2
55 > echo % update substate when modifying .hgsub w/clean updated subrepo
55 > echo % update substate when modifying .hgsub w/clean updated subrepo
56 > hg status -S
56 > hg status -S
57 > echo '%' $*
57 > echo '%' $*
58 > cat "$stdin" | hg $*
58 > cat "$stdin" | hg $*
59 > hg debugsub
59 > hg debugsub
60 > }
60 > }
61
61
62 $ testrm1() {
62 $ testrm1() {
63 > cat - > "$stdin"
63 > cat - > "$stdin"
64 > mksubrepo sub3
64 > mksubrepo sub3
65 > echo sub3 = sub3 >> .hgsub
65 > echo sub3 = sub3 >> .hgsub
66 > hg ci -Aqmsub3
66 > hg ci -Aqmsub3
67 > $EXTRA
67 > $EXTRA
68 > echo b >> sub3/a
68 > echo b >> sub3/a
69 > hg rm .hgsub
69 > hg rm .hgsub
70 > echo % update substate when removing .hgsub w/dirty subrepo
70 > echo % update substate when removing .hgsub w/dirty subrepo
71 > hg status -S
71 > hg status -S
72 > echo '%' $*
72 > echo '%' $*
73 > cat "$stdin" | hg $*
73 > cat "$stdin" | hg $*
74 > echo % debugsub should be empty
74 > echo % debugsub should be empty
75 > hg debugsub
75 > hg debugsub
76 > }
76 > }
77
77
78 $ testrm2() {
78 $ testrm2() {
79 > cat - > "$stdin"
79 > cat - > "$stdin"
80 > mksubrepo sub4
80 > mksubrepo sub4
81 > echo sub4 = sub4 >> .hgsub
81 > echo sub4 = sub4 >> .hgsub
82 > hg ci -Aqmsub4
82 > hg ci -Aqmsub4
83 > $EXTRA
83 > $EXTRA
84 > hg rm .hgsub
84 > hg rm .hgsub
85 > echo % update substate when removing .hgsub w/clean updated subrepo
85 > echo % update substate when removing .hgsub w/clean updated subrepo
86 > hg status -S
86 > hg status -S
87 > echo '%' $*
87 > echo '%' $*
88 > cat "$stdin" | hg $*
88 > cat "$stdin" | hg $*
89 > echo % debugsub should be empty
89 > echo % debugsub should be empty
90 > hg debugsub
90 > hg debugsub
91 > }
91 > }
92
92
93
93
94 handle subrepos safely on qnew
94 handle subrepos safely on qnew
95
95
96 $ mkrepo repo-2499-qnew
96 $ mkrepo repo-2499-qnew
97 $ testadd qnew -m0 0.diff
97 $ testadd qnew -m0 0.diff
98 adding a
98 adding a
99 % abort when adding .hgsub w/dirty subrepo
99 % abort when adding .hgsub w/dirty subrepo
100 A .hgsub
100 A .hgsub
101 A sub/a
101 A sub/a
102 % qnew -m0 0.diff
102 % qnew -m0 0.diff
103 abort: uncommitted changes in subrepository sub
103 abort: uncommitted changes in subrepository sub
104 [255]
104 [255]
105 % update substate when adding .hgsub w/clean updated subrepo
105 % update substate when adding .hgsub w/clean updated subrepo
106 A .hgsub
106 A .hgsub
107 % qnew -m0 0.diff
107 % qnew -m0 0.diff
108 committing subrepository sub
109 path sub
108 path sub
110 source sub
109 source sub
111 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
110 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
112
111
113 $ testmod qnew -m1 1.diff
112 $ testmod qnew -m1 1.diff
114 adding a
113 adding a
115 % abort when modifying .hgsub w/dirty subrepo
114 % abort when modifying .hgsub w/dirty subrepo
116 M .hgsub
115 M .hgsub
117 A sub2/a
116 A sub2/a
118 % qnew -m1 1.diff
117 % qnew -m1 1.diff
119 abort: uncommitted changes in subrepository sub2
118 abort: uncommitted changes in subrepository sub2
120 [255]
119 [255]
121 % update substate when modifying .hgsub w/clean updated subrepo
120 % update substate when modifying .hgsub w/clean updated subrepo
122 M .hgsub
121 M .hgsub
123 % qnew -m1 1.diff
122 % qnew -m1 1.diff
124 committing subrepository sub2
125 path sub
123 path sub
126 source sub
124 source sub
127 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
125 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
128 path sub2
126 path sub2
129 source sub2
127 source sub2
130 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
128 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
131
129
132 $ hg qpop -qa
130 $ hg qpop -qa
133 patch queue now empty
131 patch queue now empty
134 $ testrm1 qnew -m2 2.diff
132 $ testrm1 qnew -m2 2.diff
135 adding a
133 adding a
136 % update substate when removing .hgsub w/dirty subrepo
134 % update substate when removing .hgsub w/dirty subrepo
137 M sub3/a
135 M sub3/a
138 R .hgsub
136 R .hgsub
139 % qnew -m2 2.diff
137 % qnew -m2 2.diff
140 % debugsub should be empty
138 % debugsub should be empty
141
139
142 $ hg qpop -qa
140 $ hg qpop -qa
143 patch queue now empty
141 patch queue now empty
144 $ testrm2 qnew -m3 3.diff
142 $ testrm2 qnew -m3 3.diff
145 adding a
143 adding a
146 % update substate when removing .hgsub w/clean updated subrepo
144 % update substate when removing .hgsub w/clean updated subrepo
147 R .hgsub
145 R .hgsub
148 % qnew -m3 3.diff
146 % qnew -m3 3.diff
149 % debugsub should be empty
147 % debugsub should be empty
150
148
151 $ cd ..
149 $ cd ..
152
150
153
151
154 handle subrepos safely on qrefresh
152 handle subrepos safely on qrefresh
155
153
156 $ mkrepo repo-2499-qrefresh
154 $ mkrepo repo-2499-qrefresh
157 $ hg qnew -m0 0.diff
155 $ hg qnew -m0 0.diff
158 $ testadd qrefresh
156 $ testadd qrefresh
159 adding a
157 adding a
160 % abort when adding .hgsub w/dirty subrepo
158 % abort when adding .hgsub w/dirty subrepo
161 A .hgsub
159 A .hgsub
162 A sub/a
160 A sub/a
163 % qrefresh
161 % qrefresh
164 abort: uncommitted changes in subrepository sub
162 abort: uncommitted changes in subrepository sub
165 [255]
163 [255]
166 % update substate when adding .hgsub w/clean updated subrepo
164 % update substate when adding .hgsub w/clean updated subrepo
167 A .hgsub
165 A .hgsub
168 % qrefresh
166 % qrefresh
169 committing subrepository sub
170 path sub
167 path sub
171 source sub
168 source sub
172 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
169 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
173
170
174 $ hg qnew -m1 1.diff
171 $ hg qnew -m1 1.diff
175 $ testmod qrefresh
172 $ testmod qrefresh
176 adding a
173 adding a
177 % abort when modifying .hgsub w/dirty subrepo
174 % abort when modifying .hgsub w/dirty subrepo
178 M .hgsub
175 M .hgsub
179 A sub2/a
176 A sub2/a
180 % qrefresh
177 % qrefresh
181 abort: uncommitted changes in subrepository sub2
178 abort: uncommitted changes in subrepository sub2
182 [255]
179 [255]
183 % update substate when modifying .hgsub w/clean updated subrepo
180 % update substate when modifying .hgsub w/clean updated subrepo
184 M .hgsub
181 M .hgsub
185 % qrefresh
182 % qrefresh
186 committing subrepository sub2
187 path sub
183 path sub
188 source sub
184 source sub
189 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
185 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
190 path sub2
186 path sub2
191 source sub2
187 source sub2
192 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
188 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
193
189
194 $ hg qpop -qa
190 $ hg qpop -qa
195 patch queue now empty
191 patch queue now empty
196 $ EXTRA='hg qnew -m2 2.diff'
192 $ EXTRA='hg qnew -m2 2.diff'
197 $ testrm1 qrefresh
193 $ testrm1 qrefresh
198 adding a
194 adding a
199 % update substate when removing .hgsub w/dirty subrepo
195 % update substate when removing .hgsub w/dirty subrepo
200 M sub3/a
196 M sub3/a
201 R .hgsub
197 R .hgsub
202 % qrefresh
198 % qrefresh
203 % debugsub should be empty
199 % debugsub should be empty
204
200
205 $ hg qpop -qa
201 $ hg qpop -qa
206 patch queue now empty
202 patch queue now empty
207 $ EXTRA='hg qnew -m3 3.diff'
203 $ EXTRA='hg qnew -m3 3.diff'
208 $ testrm2 qrefresh
204 $ testrm2 qrefresh
209 adding a
205 adding a
210 % update substate when removing .hgsub w/clean updated subrepo
206 % update substate when removing .hgsub w/clean updated subrepo
211 R .hgsub
207 R .hgsub
212 % qrefresh
208 % qrefresh
213 % debugsub should be empty
209 % debugsub should be empty
214 $ EXTRA=
210 $ EXTRA=
215
211
216 $ cd ..
212 $ cd ..
217
213
218
214
219 handle subrepos safely on qpush/qpop
215 handle subrepos safely on qpush/qpop
220
216
221 $ mkrepo repo-2499-qpush
217 $ mkrepo repo-2499-qpush
222 $ mksubrepo sub
218 $ mksubrepo sub
223 adding a
219 adding a
224 $ hg -R sub ci -m0sub
220 $ hg -R sub ci -m0sub
225 $ echo sub = sub > .hgsub
221 $ echo sub = sub > .hgsub
226 $ hg add .hgsub
222 $ hg add .hgsub
227 $ hg qnew -m0 0.diff
223 $ hg qnew -m0 0.diff
228 committing subrepository sub
229 $ hg debugsub
224 $ hg debugsub
230 path sub
225 path sub
231 source sub
226 source sub
232 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
227 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
233
228
234 qpop
229 qpop
235 $ hg qpop
230 $ hg qpop
236 popping 0.diff
231 popping 0.diff
237 patch queue now empty
232 patch queue now empty
238 $ hg status -AS
233 $ hg status -AS
239 $ hg debugsub
234 $ hg debugsub
240
235
241 qpush
236 qpush
242 $ hg qpush
237 $ hg qpush
243 applying 0.diff
238 applying 0.diff
244 now at: 0.diff
239 now at: 0.diff
245 $ hg status -AS
240 $ hg status -AS
246 C .hgsub
241 C .hgsub
247 C .hgsubstate
242 C .hgsubstate
248 C sub/a
243 C sub/a
249 $ hg debugsub
244 $ hg debugsub
250 path sub
245 path sub
251 source sub
246 source sub
252 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
247 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
253
248
254 $ cd ..
249 $ cd ..
255
250
256
251
257 handle subrepos safely on qrecord
252 handle subrepos safely on qrecord
258
253
259 $ mkrepo repo-2499-qrecord
254 $ mkrepo repo-2499-qrecord
260 $ testadd qrecord --config ui.interactive=1 -m0 0.diff <<EOF
255 $ testadd qrecord --config ui.interactive=1 -m0 0.diff <<EOF
261 > y
256 > y
262 > y
257 > y
263 > EOF
258 > EOF
264 adding a
259 adding a
265 % abort when adding .hgsub w/dirty subrepo
260 % abort when adding .hgsub w/dirty subrepo
266 A .hgsub
261 A .hgsub
267 A sub/a
262 A sub/a
268 % qrecord --config ui.interactive=1 -m0 0.diff
263 % qrecord --config ui.interactive=1 -m0 0.diff
269 diff --git a/.hgsub b/.hgsub
264 diff --git a/.hgsub b/.hgsub
270 new file mode 100644
265 new file mode 100644
271 examine changes to '.hgsub'? [Ynsfdaq?]
266 examine changes to '.hgsub'? [Ynsfdaq?]
272 abort: uncommitted changes in subrepository sub
267 abort: uncommitted changes in subrepository sub
273 [255]
268 [255]
274 % update substate when adding .hgsub w/clean updated subrepo
269 % update substate when adding .hgsub w/clean updated subrepo
275 A .hgsub
270 A .hgsub
276 % qrecord --config ui.interactive=1 -m0 0.diff
271 % qrecord --config ui.interactive=1 -m0 0.diff
277 diff --git a/.hgsub b/.hgsub
272 diff --git a/.hgsub b/.hgsub
278 new file mode 100644
273 new file mode 100644
279 examine changes to '.hgsub'? [Ynsfdaq?]
274 examine changes to '.hgsub'? [Ynsfdaq?]
280 committing subrepository sub
281 path sub
275 path sub
282 source sub
276 source sub
283 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
277 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
284
278
285 $ testmod qrecord --config ui.interactive=1 -m1 1.diff <<EOF
279 $ testmod qrecord --config ui.interactive=1 -m1 1.diff <<EOF
286 > y
280 > y
287 > y
281 > y
288 > EOF
282 > EOF
289 adding a
283 adding a
290 % abort when modifying .hgsub w/dirty subrepo
284 % abort when modifying .hgsub w/dirty subrepo
291 M .hgsub
285 M .hgsub
292 A sub2/a
286 A sub2/a
293 % qrecord --config ui.interactive=1 -m1 1.diff
287 % qrecord --config ui.interactive=1 -m1 1.diff
294 diff --git a/.hgsub b/.hgsub
288 diff --git a/.hgsub b/.hgsub
295 1 hunks, 1 lines changed
289 1 hunks, 1 lines changed
296 examine changes to '.hgsub'? [Ynsfdaq?]
290 examine changes to '.hgsub'? [Ynsfdaq?]
297 @@ -1,1 +1,2 @@
291 @@ -1,1 +1,2 @@
298 sub = sub
292 sub = sub
299 +sub2 = sub2
293 +sub2 = sub2
300 record this change to '.hgsub'? [Ynsfdaq?]
294 record this change to '.hgsub'? [Ynsfdaq?]
301 abort: uncommitted changes in subrepository sub2
295 abort: uncommitted changes in subrepository sub2
302 [255]
296 [255]
303 % update substate when modifying .hgsub w/clean updated subrepo
297 % update substate when modifying .hgsub w/clean updated subrepo
304 M .hgsub
298 M .hgsub
305 % qrecord --config ui.interactive=1 -m1 1.diff
299 % qrecord --config ui.interactive=1 -m1 1.diff
306 diff --git a/.hgsub b/.hgsub
300 diff --git a/.hgsub b/.hgsub
307 1 hunks, 1 lines changed
301 1 hunks, 1 lines changed
308 examine changes to '.hgsub'? [Ynsfdaq?]
302 examine changes to '.hgsub'? [Ynsfdaq?]
309 @@ -1,1 +1,2 @@
303 @@ -1,1 +1,2 @@
310 sub = sub
304 sub = sub
311 +sub2 = sub2
305 +sub2 = sub2
312 record this change to '.hgsub'? [Ynsfdaq?]
306 record this change to '.hgsub'? [Ynsfdaq?]
313 committing subrepository sub2
314 path sub
307 path sub
315 source sub
308 source sub
316 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
309 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
317 path sub2
310 path sub2
318 source sub2
311 source sub2
319 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
312 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
320
313
321 $ hg qpop -qa
314 $ hg qpop -qa
322 patch queue now empty
315 patch queue now empty
323 $ testrm1 qrecord --config ui.interactive=1 -m2 2.diff <<EOF
316 $ testrm1 qrecord --config ui.interactive=1 -m2 2.diff <<EOF
324 > y
317 > y
325 > y
318 > y
326 > EOF
319 > EOF
327 adding a
320 adding a
328 % update substate when removing .hgsub w/dirty subrepo
321 % update substate when removing .hgsub w/dirty subrepo
329 M sub3/a
322 M sub3/a
330 R .hgsub
323 R .hgsub
331 % qrecord --config ui.interactive=1 -m2 2.diff
324 % qrecord --config ui.interactive=1 -m2 2.diff
332 diff --git a/.hgsub b/.hgsub
325 diff --git a/.hgsub b/.hgsub
333 deleted file mode 100644
326 deleted file mode 100644
334 examine changes to '.hgsub'? [Ynsfdaq?]
327 examine changes to '.hgsub'? [Ynsfdaq?]
335 % debugsub should be empty
328 % debugsub should be empty
336
329
337 $ hg qpop -qa
330 $ hg qpop -qa
338 patch queue now empty
331 patch queue now empty
339 $ testrm2 qrecord --config ui.interactive=1 -m3 3.diff <<EOF
332 $ testrm2 qrecord --config ui.interactive=1 -m3 3.diff <<EOF
340 > y
333 > y
341 > y
334 > y
342 > EOF
335 > EOF
343 adding a
336 adding a
344 % update substate when removing .hgsub w/clean updated subrepo
337 % update substate when removing .hgsub w/clean updated subrepo
345 R .hgsub
338 R .hgsub
346 % qrecord --config ui.interactive=1 -m3 3.diff
339 % qrecord --config ui.interactive=1 -m3 3.diff
347 diff --git a/.hgsub b/.hgsub
340 diff --git a/.hgsub b/.hgsub
348 deleted file mode 100644
341 deleted file mode 100644
349 examine changes to '.hgsub'? [Ynsfdaq?]
342 examine changes to '.hgsub'? [Ynsfdaq?]
350 % debugsub should be empty
343 % debugsub should be empty
351
344
352 $ cd ..
345 $ cd ..
353
346
354
347
355 correctly handle subrepos with patch queues
348 correctly handle subrepos with patch queues
356 $ mkrepo repo-subrepo-with-queue
349 $ mkrepo repo-subrepo-with-queue
357 $ mksubrepo sub
350 $ mksubrepo sub
358 adding a
351 adding a
359 $ hg -R sub qnew sub0.diff
352 $ hg -R sub qnew sub0.diff
360 $ echo sub = sub >> .hgsub
353 $ echo sub = sub >> .hgsub
361 $ hg add .hgsub
354 $ hg add .hgsub
362 $ hg qnew 0.diff
355 $ hg qnew 0.diff
363 committing subrepository sub
@@ -1,102 +1,100 b''
1 Preparing the subrepository 'sub2'
1 Preparing the subrepository 'sub2'
2
2
3 $ hg init sub2
3 $ hg init sub2
4 $ echo sub2 > sub2/sub2
4 $ echo sub2 > sub2/sub2
5 $ hg add -R sub2
5 $ hg add -R sub2
6 adding sub2/sub2 (glob)
6 adding sub2/sub2 (glob)
7 $ hg commit -R sub2 -m "sub2 import"
7 $ hg commit -R sub2 -m "sub2 import"
8
8
9 Preparing the 'sub1' repo which depends on the subrepo 'sub2'
9 Preparing the 'sub1' repo which depends on the subrepo 'sub2'
10
10
11 $ hg init sub1
11 $ hg init sub1
12 $ echo sub1 > sub1/sub1
12 $ echo sub1 > sub1/sub1
13 $ echo "sub2 = ../sub2" > sub1/.hgsub
13 $ echo "sub2 = ../sub2" > sub1/.hgsub
14 $ hg clone sub2 sub1/sub2
14 $ hg clone sub2 sub1/sub2
15 updating to branch default
15 updating to branch default
16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 $ hg add -R sub1
17 $ hg add -R sub1
18 adding sub1/.hgsub (glob)
18 adding sub1/.hgsub (glob)
19 adding sub1/sub1 (glob)
19 adding sub1/sub1 (glob)
20 $ hg commit -R sub1 -m "sub1 import"
20 $ hg commit -R sub1 -m "sub1 import"
21 committing subrepository sub2
22
21
23 Preparing the 'main' repo which depends on the subrepo 'sub1'
22 Preparing the 'main' repo which depends on the subrepo 'sub1'
24
23
25 $ hg init main
24 $ hg init main
26 $ echo main > main/main
25 $ echo main > main/main
27 $ echo "sub1 = ../sub1" > main/.hgsub
26 $ echo "sub1 = ../sub1" > main/.hgsub
28 $ hg clone sub1 main/sub1
27 $ hg clone sub1 main/sub1
29 updating to branch default
28 updating to branch default
30 cloning subrepo sub2 from $TESTTMP/sub2
29 cloning subrepo sub2 from $TESTTMP/sub2
31 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
30 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
32 $ hg add -R main
31 $ hg add -R main
33 adding main/.hgsub (glob)
32 adding main/.hgsub (glob)
34 adding main/main (glob)
33 adding main/main (glob)
35 $ hg commit -R main -m "main import"
34 $ hg commit -R main -m "main import"
36 committing subrepository sub1
37
35
38 Cleaning both repositories, just as a clone -U
36 Cleaning both repositories, just as a clone -U
39
37
40 $ hg up -C -R sub2 null
38 $ hg up -C -R sub2 null
41 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
39 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
42 $ hg up -C -R sub1 null
40 $ hg up -C -R sub1 null
43 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
41 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
44 $ hg up -C -R main null
42 $ hg up -C -R main null
45 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
43 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
46 $ rm -rf main/sub1
44 $ rm -rf main/sub1
47 $ rm -rf sub1/sub2
45 $ rm -rf sub1/sub2
48
46
49 Clone main
47 Clone main
50
48
51 $ hg clone main cloned
49 $ hg clone main cloned
52 updating to branch default
50 updating to branch default
53 cloning subrepo sub1 from $TESTTMP/sub1
51 cloning subrepo sub1 from $TESTTMP/sub1
54 cloning subrepo sub1/sub2 from $TESTTMP/sub2 (glob)
52 cloning subrepo sub1/sub2 from $TESTTMP/sub2 (glob)
55 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
53 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
56
54
57 Checking cloned repo ids
55 Checking cloned repo ids
58
56
59 $ printf "cloned " ; hg id -R cloned
57 $ printf "cloned " ; hg id -R cloned
60 cloned 7f491f53a367 tip
58 cloned 7f491f53a367 tip
61 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
59 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
62 cloned/sub1 fc3b4ce2696f tip
60 cloned/sub1 fc3b4ce2696f tip
63 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
61 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
64 cloned/sub1/sub2 c57a0840e3ba tip
62 cloned/sub1/sub2 c57a0840e3ba tip
65
63
66 debugsub output for main and sub1
64 debugsub output for main and sub1
67
65
68 $ hg debugsub -R cloned
66 $ hg debugsub -R cloned
69 path sub1
67 path sub1
70 source ../sub1
68 source ../sub1
71 revision fc3b4ce2696f7741438c79207583768f2ce6b0dd
69 revision fc3b4ce2696f7741438c79207583768f2ce6b0dd
72 $ hg debugsub -R cloned/sub1
70 $ hg debugsub -R cloned/sub1
73 path sub2
71 path sub2
74 source ../sub2
72 source ../sub2
75 revision c57a0840e3badd667ef3c3ef65471609acb2ba3c
73 revision c57a0840e3badd667ef3c3ef65471609acb2ba3c
76
74
77 Modifying deeply nested 'sub2'
75 Modifying deeply nested 'sub2'
78
76
79 $ echo modified > cloned/sub1/sub2/sub2
77 $ echo modified > cloned/sub1/sub2/sub2
80 $ hg commit --subrepos -m "deep nested modif should trigger a commit" -R cloned
78 $ hg commit --subrepos -m "deep nested modif should trigger a commit" -R cloned
81 committing subrepository sub1
79 committing subrepository sub1
82 committing subrepository sub1/sub2 (glob)
80 committing subrepository sub1/sub2 (glob)
83
81
84 Checking modified node ids
82 Checking modified node ids
85
83
86 $ printf "cloned " ; hg id -R cloned
84 $ printf "cloned " ; hg id -R cloned
87 cloned ffe6649062fe tip
85 cloned ffe6649062fe tip
88 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
86 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
89 cloned/sub1 2ecb03bf44a9 tip
87 cloned/sub1 2ecb03bf44a9 tip
90 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
88 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
91 cloned/sub1/sub2 53dd3430bcaf tip
89 cloned/sub1/sub2 53dd3430bcaf tip
92
90
93 debugsub output for main and sub1
91 debugsub output for main and sub1
94
92
95 $ hg debugsub -R cloned
93 $ hg debugsub -R cloned
96 path sub1
94 path sub1
97 source ../sub1
95 source ../sub1
98 revision 2ecb03bf44a94e749e8669481dd9069526ce7cb9
96 revision 2ecb03bf44a94e749e8669481dd9069526ce7cb9
99 $ hg debugsub -R cloned/sub1
97 $ hg debugsub -R cloned/sub1
100 path sub2
98 path sub2
101 source ../sub2
99 source ../sub2
102 revision 53dd3430bcaf5ab4a7c48262bcad6d441f510487
100 revision 53dd3430bcaf5ab4a7c48262bcad6d441f510487
@@ -1,510 +1,511 b''
1 $ "$TESTDIR/hghave" git || exit 80
1 $ "$TESTDIR/hghave" git || exit 80
2
2
3 make git commits repeatable
3 make git commits repeatable
4
4
5 $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
5 $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
6 $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
6 $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
7 $ GIT_AUTHOR_DATE='1234567891 +0000'; export GIT_AUTHOR_DATE
7 $ GIT_AUTHOR_DATE='1234567891 +0000'; export GIT_AUTHOR_DATE
8 $ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
8 $ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
9 $ GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
9 $ GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
10 $ GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
10 $ GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
11
11
12 root hg repo
12 root hg repo
13
13
14 $ hg init t
14 $ hg init t
15 $ cd t
15 $ cd t
16 $ echo a > a
16 $ echo a > a
17 $ hg add a
17 $ hg add a
18 $ hg commit -m a
18 $ hg commit -m a
19 $ cd ..
19 $ cd ..
20
20
21 new external git repo
21 new external git repo
22
22
23 $ mkdir gitroot
23 $ mkdir gitroot
24 $ cd gitroot
24 $ cd gitroot
25 $ git init -q
25 $ git init -q
26 $ echo g > g
26 $ echo g > g
27 $ git add g
27 $ git add g
28 $ git commit -q -m g
28 $ git commit -q -m g
29
29
30 add subrepo clone
30 add subrepo clone
31
31
32 $ cd ../t
32 $ cd ../t
33 $ echo 's = [git]../gitroot' > .hgsub
33 $ echo 's = [git]../gitroot' > .hgsub
34 $ git clone -q ../gitroot s
34 $ git clone -q ../gitroot s
35 $ hg add .hgsub
35 $ hg add .hgsub
36 $ hg commit -m 'new git subrepo'
36 $ hg commit -m 'new git subrepo'
37 committing subrepository s
38 $ hg debugsub
37 $ hg debugsub
39 path s
38 path s
40 source ../gitroot
39 source ../gitroot
41 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
40 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
42
41
43 record a new commit from upstream from a different branch
42 record a new commit from upstream from a different branch
44
43
45 $ cd ../gitroot
44 $ cd ../gitroot
46 $ git checkout -q -b testing
45 $ git checkout -q -b testing
47 $ echo gg >> g
46 $ echo gg >> g
48 $ git commit -q -a -m gg
47 $ git commit -q -a -m gg
49
48
50 $ cd ../t/s
49 $ cd ../t/s
51 $ git pull -q >/dev/null 2>/dev/null
50 $ git pull -q >/dev/null 2>/dev/null
52 $ git checkout -q -b testing origin/testing >/dev/null
51 $ git checkout -q -b testing origin/testing >/dev/null
53
52
54 $ cd ..
53 $ cd ..
55 $ hg status --subrepos
54 $ hg status --subrepos
56 M s/g
55 M s/g
57 $ hg commit -m 'update git subrepo'
56 $ hg commit -m 'update git subrepo'
58 committing subrepository s
59 $ hg debugsub
57 $ hg debugsub
60 path s
58 path s
61 source ../gitroot
59 source ../gitroot
62 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
60 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
63
61
64 make $GITROOT pushable, by replacing it with a clone with nothing checked out
62 make $GITROOT pushable, by replacing it with a clone with nothing checked out
65
63
66 $ cd ..
64 $ cd ..
67 $ git clone gitroot gitrootbare --bare -q
65 $ git clone gitroot gitrootbare --bare -q
68 $ rm -rf gitroot
66 $ rm -rf gitroot
69 $ mv gitrootbare gitroot
67 $ mv gitrootbare gitroot
70
68
71 clone root
69 clone root
72
70
73 $ cd t
71 $ cd t
74 $ hg clone . ../tc
72 $ hg clone . ../tc
75 updating to branch default
73 updating to branch default
76 cloning subrepo s from $TESTTMP/gitroot
74 cloning subrepo s from $TESTTMP/gitroot
77 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 $ cd ../tc
76 $ cd ../tc
79 $ hg debugsub
77 $ hg debugsub
80 path s
78 path s
81 source ../gitroot
79 source ../gitroot
82 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
80 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
83
81
84 update to previous substate
82 update to previous substate
85
83
86 $ hg update 1 -q
84 $ hg update 1 -q
87 $ cat s/g
85 $ cat s/g
88 g
86 g
89 $ hg debugsub
87 $ hg debugsub
90 path s
88 path s
91 source ../gitroot
89 source ../gitroot
92 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
90 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
93
91
94 clone root, make local change
92 clone root, make local change
95
93
96 $ cd ../t
94 $ cd ../t
97 $ hg clone . ../ta
95 $ hg clone . ../ta
98 updating to branch default
96 updating to branch default
99 cloning subrepo s from $TESTTMP/gitroot
97 cloning subrepo s from $TESTTMP/gitroot
100 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
101
99
102 $ cd ../ta
100 $ cd ../ta
103 $ echo ggg >> s/g
101 $ echo ggg >> s/g
104 $ hg status --subrepos
102 $ hg status --subrepos
105 M s/g
103 M s/g
106 $ hg commit --subrepos -m ggg
104 $ hg commit --subrepos -m ggg
107 committing subrepository s
105 committing subrepository s
108 $ hg debugsub
106 $ hg debugsub
109 path s
107 path s
110 source ../gitroot
108 source ../gitroot
111 revision 79695940086840c99328513acbe35f90fcd55e57
109 revision 79695940086840c99328513acbe35f90fcd55e57
112
110
113 clone root separately, make different local change
111 clone root separately, make different local change
114
112
115 $ cd ../t
113 $ cd ../t
116 $ hg clone . ../tb
114 $ hg clone . ../tb
117 updating to branch default
115 updating to branch default
118 cloning subrepo s from $TESTTMP/gitroot
116 cloning subrepo s from $TESTTMP/gitroot
119 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
120
118
121 $ cd ../tb/s
119 $ cd ../tb/s
122 $ echo f > f
120 $ echo f > f
123 $ git add f
121 $ git add f
124 $ cd ..
122 $ cd ..
125
123
126 $ hg status --subrepos
124 $ hg status --subrepos
127 A s/f
125 A s/f
128 $ hg commit --subrepos -m f
126 $ hg commit --subrepos -m f
129 committing subrepository s
127 committing subrepository s
130 $ hg debugsub
128 $ hg debugsub
131 path s
129 path s
132 source ../gitroot
130 source ../gitroot
133 revision aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
131 revision aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
134
132
135 user b push changes
133 user b push changes
136
134
137 $ hg push 2>/dev/null
135 $ hg push 2>/dev/null
138 pushing to $TESTTMP/t
136 pushing to $TESTTMP/t
139 pushing branch testing of subrepo s
137 pushing branch testing of subrepo s
140 searching for changes
138 searching for changes
141 adding changesets
139 adding changesets
142 adding manifests
140 adding manifests
143 adding file changes
141 adding file changes
144 added 1 changesets with 1 changes to 1 files
142 added 1 changesets with 1 changes to 1 files
145
143
146 user a pulls, merges, commits
144 user a pulls, merges, commits
147
145
148 $ cd ../ta
146 $ cd ../ta
149 $ hg pull
147 $ hg pull
150 pulling from $TESTTMP/t
148 pulling from $TESTTMP/t
151 searching for changes
149 searching for changes
152 adding changesets
150 adding changesets
153 adding manifests
151 adding manifests
154 adding file changes
152 adding file changes
155 added 1 changesets with 1 changes to 1 files (+1 heads)
153 added 1 changesets with 1 changes to 1 files (+1 heads)
156 (run 'hg heads' to see heads, 'hg merge' to merge)
154 (run 'hg heads' to see heads, 'hg merge' to merge)
157 $ hg merge 2>/dev/null
155 $ hg merge 2>/dev/null
158 pulling subrepo s from $TESTTMP/gitroot
156 pulling subrepo s from $TESTTMP/gitroot
159 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
157 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 (branch merge, don't forget to commit)
158 (branch merge, don't forget to commit)
161 $ cat s/f
159 $ cat s/f
162 f
160 f
163 $ cat s/g
161 $ cat s/g
164 g
162 g
165 gg
163 gg
166 ggg
164 ggg
167 $ hg commit --subrepos -m 'merge'
165 $ hg commit --subrepos -m 'merge'
168 committing subrepository s
166 committing subrepository s
169 $ hg status --subrepos --rev 1:5
167 $ hg status --subrepos --rev 1:5
170 M .hgsubstate
168 M .hgsubstate
171 M s/g
169 M s/g
172 A s/f
170 A s/f
173 $ hg debugsub
171 $ hg debugsub
174 path s
172 path s
175 source ../gitroot
173 source ../gitroot
176 revision f47b465e1bce645dbf37232a00574aa1546ca8d3
174 revision f47b465e1bce645dbf37232a00574aa1546ca8d3
177 $ hg push 2>/dev/null
175 $ hg push 2>/dev/null
178 pushing to $TESTTMP/t
176 pushing to $TESTTMP/t
179 pushing branch testing of subrepo s
177 pushing branch testing of subrepo s
180 searching for changes
178 searching for changes
181 adding changesets
179 adding changesets
182 adding manifests
180 adding manifests
183 adding file changes
181 adding file changes
184 added 2 changesets with 2 changes to 1 files
182 added 2 changesets with 2 changes to 1 files
185
183
186 make upstream git changes
184 make upstream git changes
187
185
188 $ cd ..
186 $ cd ..
189 $ git clone -q gitroot gitclone
187 $ git clone -q gitroot gitclone
190 $ cd gitclone
188 $ cd gitclone
191 $ echo ff >> f
189 $ echo ff >> f
192 $ git commit -q -a -m ff
190 $ git commit -q -a -m ff
193 $ echo fff >> f
191 $ echo fff >> f
194 $ git commit -q -a -m fff
192 $ git commit -q -a -m fff
195 $ git push origin testing 2>/dev/null
193 $ git push origin testing 2>/dev/null
196
194
197 make and push changes to hg without updating the subrepo
195 make and push changes to hg without updating the subrepo
198
196
199 $ cd ../t
197 $ cd ../t
200 $ hg clone . ../td
198 $ hg clone . ../td
201 updating to branch default
199 updating to branch default
202 cloning subrepo s from $TESTTMP/gitroot
200 cloning subrepo s from $TESTTMP/gitroot
203 checking out detached HEAD in subrepo s
201 checking out detached HEAD in subrepo s
204 check out a git branch if you intend to make changes
202 check out a git branch if you intend to make changes
205 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
203 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 $ cd ../td
204 $ cd ../td
207 $ echo aa >> a
205 $ echo aa >> a
208 $ hg commit -m aa
206 $ hg commit -m aa
209 $ hg push
207 $ hg push
210 pushing to $TESTTMP/t
208 pushing to $TESTTMP/t
211 searching for changes
209 searching for changes
212 adding changesets
210 adding changesets
213 adding manifests
211 adding manifests
214 adding file changes
212 adding file changes
215 added 1 changesets with 1 changes to 1 files
213 added 1 changesets with 1 changes to 1 files
216
214
217 sync to upstream git, distribute changes
215 sync to upstream git, distribute changes
218
216
219 $ cd ../ta
217 $ cd ../ta
220 $ hg pull -u -q
218 $ hg pull -u -q
221 $ cd s
219 $ cd s
222 $ git pull -q >/dev/null 2>/dev/null
220 $ git pull -q >/dev/null 2>/dev/null
223 $ cd ..
221 $ cd ..
224 $ hg commit -m 'git upstream sync'
222 $ hg commit -m 'git upstream sync'
225 committing subrepository s
226 $ hg debugsub
223 $ hg debugsub
227 path s
224 path s
228 source ../gitroot
225 source ../gitroot
229 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
226 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
230 $ hg push -q
227 $ hg push -q
231
228
232 $ cd ../tb
229 $ cd ../tb
233 $ hg pull -q
230 $ hg pull -q
234 $ hg update 2>/dev/null
231 $ hg update 2>/dev/null
235 pulling subrepo s from $TESTTMP/gitroot
232 pulling subrepo s from $TESTTMP/gitroot
236 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
233 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
237 $ hg debugsub
234 $ hg debugsub
238 path s
235 path s
239 source ../gitroot
236 source ../gitroot
240 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
237 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
241
238
242 update to a revision without the subrepo, keeping the local git repository
239 update to a revision without the subrepo, keeping the local git repository
243
240
244 $ cd ../t
241 $ cd ../t
245 $ hg up 0
242 $ hg up 0
246 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
243 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
247 $ ls -a s
244 $ ls -a s
248 .
245 .
249 ..
246 ..
250 .git
247 .git
251
248
252 $ hg up 2
249 $ hg up 2
253 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
250 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 $ ls -a s
251 $ ls -a s
255 .
252 .
256 ..
253 ..
257 .git
254 .git
258 g
255 g
259
256
260 archive subrepos
257 archive subrepos
261
258
262 $ cd ../tc
259 $ cd ../tc
263 $ hg pull -q
260 $ hg pull -q
264 $ hg archive --subrepos -r 5 ../archive 2>/dev/null
261 $ hg archive --subrepos -r 5 ../archive 2>/dev/null
265 pulling subrepo s from $TESTTMP/gitroot
262 pulling subrepo s from $TESTTMP/gitroot
266 $ cd ../archive
263 $ cd ../archive
267 $ cat s/f
264 $ cat s/f
268 f
265 f
269 $ cat s/g
266 $ cat s/g
270 g
267 g
271 gg
268 gg
272 ggg
269 ggg
273
270
274 create nested repo
271 create nested repo
275
272
276 $ cd ..
273 $ cd ..
277 $ hg init outer
274 $ hg init outer
278 $ cd outer
275 $ cd outer
279 $ echo b>b
276 $ echo b>b
280 $ hg add b
277 $ hg add b
281 $ hg commit -m b
278 $ hg commit -m b
282
279
283 $ hg clone ../t inner
280 $ hg clone ../t inner
284 updating to branch default
281 updating to branch default
285 cloning subrepo s from $TESTTMP/gitroot
282 cloning subrepo s from $TESTTMP/gitroot
286 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
283 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
287 $ echo inner = inner > .hgsub
284 $ echo inner = inner > .hgsub
288 $ hg add .hgsub
285 $ hg add .hgsub
289 $ hg commit -m 'nested sub'
286 $ hg commit -m 'nested sub'
290 committing subrepository inner
291
287
292 nested commit
288 nested commit
293
289
294 $ echo ffff >> inner/s/f
290 $ echo ffff >> inner/s/f
295 $ hg status --subrepos
291 $ hg status --subrepos
296 M inner/s/f
292 M inner/s/f
297 $ hg commit --subrepos -m nested
293 $ hg commit --subrepos -m nested
298 committing subrepository inner
294 committing subrepository inner
299 committing subrepository inner/s
295 committing subrepository inner/s
300
296
301 nested archive
297 nested archive
302
298
303 $ hg archive --subrepos ../narchive
299 $ hg archive --subrepos ../narchive
304 $ ls ../narchive/inner/s | grep -v pax_global_header
300 $ ls ../narchive/inner/s | grep -v pax_global_header
305 f
301 f
306 g
302 g
307
303
308 relative source expansion
304 relative source expansion
309
305
310 $ cd ..
306 $ cd ..
311 $ mkdir d
307 $ mkdir d
312 $ hg clone t d/t
308 $ hg clone t d/t
313 updating to branch default
309 updating to branch default
314 cloning subrepo s from $TESTTMP/gitroot
310 cloning subrepo s from $TESTTMP/gitroot
315 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
311 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
316
312
317 Don't crash if the subrepo is missing
313 Don't crash if the subrepo is missing
318
314
319 $ hg clone t missing -q
315 $ hg clone t missing -q
320 $ cd missing
316 $ cd missing
321 $ rm -rf s
317 $ rm -rf s
322 $ hg status -S
318 $ hg status -S
323 $ hg sum | grep commit
319 $ hg sum | grep commit
324 commit: 1 subrepos
320 commit: 1 subrepos
325 $ hg push -q
321 $ hg push -q
326 abort: subrepo s is missing
322 abort: subrepo s is missing
327 [255]
323 [255]
328 $ hg commit --subrepos -qm missing
324 $ hg commit --subrepos -qm missing
329 abort: subrepo s is missing
325 abort: subrepo s is missing
330 [255]
326 [255]
331 $ hg update -C
327 $ hg update -C
332 cloning subrepo s from $TESTTMP/gitroot
328 cloning subrepo s from $TESTTMP/gitroot
333 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
334 $ hg sum | grep commit
330 $ hg sum | grep commit
335 commit: (clean)
331 commit: (clean)
336
332
337 Don't crash if the .hgsubstate entry is missing
333 Don't crash if the .hgsubstate entry is missing
338
334
339 $ hg update 1 -q
335 $ hg update 1 -q
340 $ hg rm .hgsubstate
336 $ hg rm .hgsubstate
341 $ hg commit .hgsubstate -m 'no substate'
337 $ hg commit .hgsubstate -m 'no substate'
342 created new head
338 nothing changed
339 [1]
343 $ hg tag -l nosubstate
340 $ hg tag -l nosubstate
344 $ hg manifest
341 $ hg manifest
345 .hgsub
342 .hgsub
343 .hgsubstate
346 a
344 a
347
345
348 $ hg status -S
346 $ hg status -S
347 R .hgsubstate
349 $ hg sum | grep commit
348 $ hg sum | grep commit
350 commit: 1 subrepos
349 commit: 1 removed, 1 subrepos (new branch head)
351
350
352 $ hg commit -m 'restore substate'
351 $ hg commit -m 'restore substate'
353 committing subrepository s
352 nothing changed
353 [1]
354 $ hg manifest
354 $ hg manifest
355 .hgsub
355 .hgsub
356 .hgsubstate
356 .hgsubstate
357 a
357 a
358 $ hg sum | grep commit
358 $ hg sum | grep commit
359 commit: (clean)
359 commit: 1 removed, 1 subrepos (new branch head)
360
360
361 $ hg update -qC nosubstate
361 $ hg update -qC nosubstate
362 $ ls s
362 $ ls s
363 g
363
364
364 issue3109: false positives in git diff-index
365 issue3109: false positives in git diff-index
365
366
366 $ hg update -q
367 $ hg update -q
367 $ touch -t 200001010000 s/g
368 $ touch -t 200001010000 s/g
368 $ hg status --subrepos
369 $ hg status --subrepos
369 $ touch -t 200001010000 s/g
370 $ touch -t 200001010000 s/g
370 $ hg sum | grep commit
371 $ hg sum | grep commit
371 commit: (clean)
372 commit: (clean)
372
373
373 Check hg update --clean
374 Check hg update --clean
374 $ cd $TESTTMP/ta
375 $ cd $TESTTMP/ta
375 $ echo > s/g
376 $ echo > s/g
376 $ cd s
377 $ cd s
377 $ echo c1 > f1
378 $ echo c1 > f1
378 $ echo c1 > f2
379 $ echo c1 > f2
379 $ git add f1
380 $ git add f1
380 $ cd ..
381 $ cd ..
381 $ hg status -S
382 $ hg status -S
382 M s/g
383 M s/g
383 A s/f1
384 A s/f1
384 $ ls s
385 $ ls s
385 f
386 f
386 f1
387 f1
387 f2
388 f2
388 g
389 g
389 $ hg update --clean
390 $ hg update --clean
390 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
391 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
391 $ hg status -S
392 $ hg status -S
392 $ ls s
393 $ ls s
393 f
394 f
394 f1
395 f1
395 f2
396 f2
396 g
397 g
397
398
398 Sticky subrepositories, no changes
399 Sticky subrepositories, no changes
399 $ cd $TESTTMP/ta
400 $ cd $TESTTMP/ta
400 $ hg id -n
401 $ hg id -n
401 7
402 7
402 $ cd s
403 $ cd s
403 $ git rev-parse HEAD
404 $ git rev-parse HEAD
404 32a343883b74769118bb1d3b4b1fbf9156f4dddc
405 32a343883b74769118bb1d3b4b1fbf9156f4dddc
405 $ cd ..
406 $ cd ..
406 $ hg update 1 > /dev/null 2>&1
407 $ hg update 1 > /dev/null 2>&1
407 $ hg id -n
408 $ hg id -n
408 1
409 1
409 $ cd s
410 $ cd s
410 $ git rev-parse HEAD
411 $ git rev-parse HEAD
411 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
412 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
412 $ cd ..
413 $ cd ..
413
414
414 Sticky subrepositorys, file changes
415 Sticky subrepositorys, file changes
415 $ touch s/f1
416 $ touch s/f1
416 $ cd s
417 $ cd s
417 $ git add f1
418 $ git add f1
418 $ cd ..
419 $ cd ..
419 $ hg id -n
420 $ hg id -n
420 1
421 1
421 $ cd s
422 $ cd s
422 $ git rev-parse HEAD
423 $ git rev-parse HEAD
423 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
424 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
424 $ cd ..
425 $ cd ..
425 $ hg update 4
426 $ hg update 4
426 subrepository sources for s differ
427 subrepository sources for s differ
427 use (l)ocal source (da5f5b1) or (r)emote source (aa84837)?
428 use (l)ocal source (da5f5b1) or (r)emote source (aa84837)?
428 l
429 l
429 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
430 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
430 $ hg id -n
431 $ hg id -n
431 4+
432 4+
432 $ cd s
433 $ cd s
433 $ git rev-parse HEAD
434 $ git rev-parse HEAD
434 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
435 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
435 $ cd ..
436 $ cd ..
436 $ hg update --clean tip > /dev/null 2>&1
437 $ hg update --clean tip > /dev/null 2>&1
437
438
438 Sticky subrepository, revision updates
439 Sticky subrepository, revision updates
439 $ hg id -n
440 $ hg id -n
440 7
441 7
441 $ cd s
442 $ cd s
442 $ git rev-parse HEAD
443 $ git rev-parse HEAD
443 32a343883b74769118bb1d3b4b1fbf9156f4dddc
444 32a343883b74769118bb1d3b4b1fbf9156f4dddc
444 $ cd ..
445 $ cd ..
445 $ cd s
446 $ cd s
446 $ git checkout aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
447 $ git checkout aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
447 Previous HEAD position was 32a3438... fff
448 Previous HEAD position was 32a3438... fff
448 HEAD is now at aa84837... f
449 HEAD is now at aa84837... f
449 $ cd ..
450 $ cd ..
450 $ hg update 1
451 $ hg update 1
451 subrepository sources for s differ (in checked out version)
452 subrepository sources for s differ (in checked out version)
452 use (l)ocal source (32a3438) or (r)emote source (da5f5b1)?
453 use (l)ocal source (32a3438) or (r)emote source (da5f5b1)?
453 l
454 l
454 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
455 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
455 $ hg id -n
456 $ hg id -n
456 1+
457 1+
457 $ cd s
458 $ cd s
458 $ git rev-parse HEAD
459 $ git rev-parse HEAD
459 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
460 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
460 $ cd ..
461 $ cd ..
461
462
462 Sticky subrepository, file changes and revision updates
463 Sticky subrepository, file changes and revision updates
463 $ touch s/f1
464 $ touch s/f1
464 $ cd s
465 $ cd s
465 $ git add f1
466 $ git add f1
466 $ git rev-parse HEAD
467 $ git rev-parse HEAD
467 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
468 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
468 $ cd ..
469 $ cd ..
469 $ hg id -n
470 $ hg id -n
470 1+
471 1+
471 $ hg update 7
472 $ hg update 7
472 subrepository sources for s differ
473 subrepository sources for s differ
473 use (l)ocal source (32a3438) or (r)emote source (32a3438)?
474 use (l)ocal source (32a3438) or (r)emote source (32a3438)?
474 l
475 l
475 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
476 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
476 $ hg id -n
477 $ hg id -n
477 7
478 7
478 $ cd s
479 $ cd s
479 $ git rev-parse HEAD
480 $ git rev-parse HEAD
480 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
481 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
481 $ cd ..
482 $ cd ..
482
483
483 Sticky repository, update --clean
484 Sticky repository, update --clean
484 $ hg update --clean tip
485 $ hg update --clean tip
485 Previous HEAD position was aa84837... f
486 Previous HEAD position was aa84837... f
486 HEAD is now at 32a3438... fff
487 HEAD is now at 32a3438... fff
487 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
488 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
488 $ hg id -n
489 $ hg id -n
489 7
490 7
490 $ cd s
491 $ cd s
491 $ git rev-parse HEAD
492 $ git rev-parse HEAD
492 32a343883b74769118bb1d3b4b1fbf9156f4dddc
493 32a343883b74769118bb1d3b4b1fbf9156f4dddc
493 $ cd ..
494 $ cd ..
494
495
495 Test subrepo already at intended revision:
496 Test subrepo already at intended revision:
496 $ cd s
497 $ cd s
497 $ git checkout 32a343883b74769118bb1d3b4b1fbf9156f4dddc
498 $ git checkout 32a343883b74769118bb1d3b4b1fbf9156f4dddc
498 HEAD is now at 32a3438... fff
499 HEAD is now at 32a3438... fff
499 $ cd ..
500 $ cd ..
500 $ hg update 1
501 $ hg update 1
501 Previous HEAD position was 32a3438... fff
502 Previous HEAD position was 32a3438... fff
502 HEAD is now at da5f5b1... g
503 HEAD is now at da5f5b1... g
503 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
504 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
504 $ hg id -n
505 $ hg id -n
505 1
506 1
506 $ cd s
507 $ cd s
507 $ git rev-parse HEAD
508 $ git rev-parse HEAD
508 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
509 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
509 $ cd ..
510 $ cd ..
510
511
@@ -1,55 +1,53 b''
1 $ hg init repo
1 $ hg init repo
2 $ cd repo
2 $ cd repo
3 $ hg init subrepo
3 $ hg init subrepo
4 $ echo a > subrepo/a
4 $ echo a > subrepo/a
5 $ hg -R subrepo ci -Am adda
5 $ hg -R subrepo ci -Am adda
6 adding a
6 adding a
7 $ echo 'subrepo = subrepo' > .hgsub
7 $ echo 'subrepo = subrepo' > .hgsub
8 $ hg ci -Am addsubrepo
8 $ hg ci -Am addsubrepo
9 adding .hgsub
9 adding .hgsub
10 committing subrepository subrepo
11 $ echo b > subrepo/b
10 $ echo b > subrepo/b
12 $ hg -R subrepo ci -Am addb
11 $ hg -R subrepo ci -Am addb
13 adding b
12 adding b
14 $ hg ci -m updatedsub
13 $ hg ci -m updatedsub
15 committing subrepository subrepo
16
14
17 delete .hgsub and revert it
15 delete .hgsub and revert it
18
16
19 $ rm .hgsub
17 $ rm .hgsub
20 $ hg revert .hgsub
18 $ hg revert .hgsub
21 warning: subrepo spec file .hgsub not found
19 warning: subrepo spec file .hgsub not found
22 warning: subrepo spec file .hgsub not found
20 warning: subrepo spec file .hgsub not found
23
21
24 delete .hgsubstate and revert it
22 delete .hgsubstate and revert it
25
23
26 $ rm .hgsubstate
24 $ rm .hgsubstate
27 $ hg revert .hgsubstate
25 $ hg revert .hgsubstate
28
26
29 delete .hgsub and update
27 delete .hgsub and update
30
28
31 $ rm .hgsub
29 $ rm .hgsub
32 $ hg up 0
30 $ hg up 0
33 warning: subrepo spec file .hgsub not found
31 warning: subrepo spec file .hgsub not found
34 warning: subrepo spec file .hgsub not found
32 warning: subrepo spec file .hgsub not found
35 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
36 $ hg st
34 $ hg st
37 warning: subrepo spec file .hgsub not found
35 warning: subrepo spec file .hgsub not found
38 ! .hgsub
36 ! .hgsub
39 $ ls subrepo
37 $ ls subrepo
40 a
38 a
41
39
42 delete .hgsubstate and update
40 delete .hgsubstate and update
43
41
44 $ hg up -C
42 $ hg up -C
45 warning: subrepo spec file .hgsub not found
43 warning: subrepo spec file .hgsub not found
46 warning: subrepo spec file .hgsub not found
44 warning: subrepo spec file .hgsub not found
47 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 $ rm .hgsubstate
46 $ rm .hgsubstate
49 $ hg up 0
47 $ hg up 0
50 remote changed .hgsubstate which local deleted
48 remote changed .hgsubstate which local deleted
51 use (c)hanged version or leave (d)eleted? c
49 use (c)hanged version or leave (d)eleted? c
52 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
50 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
53 $ hg st
51 $ hg st
54 $ ls subrepo
52 $ ls subrepo
55 a
53 a
@@ -1,490 +1,488 b''
1 Create test repository:
1 Create test repository:
2
2
3 $ hg init repo
3 $ hg init repo
4 $ cd repo
4 $ cd repo
5 $ echo x1 > x.txt
5 $ echo x1 > x.txt
6
6
7 $ hg init foo
7 $ hg init foo
8 $ cd foo
8 $ cd foo
9 $ echo y1 > y.txt
9 $ echo y1 > y.txt
10
10
11 $ hg init bar
11 $ hg init bar
12 $ cd bar
12 $ cd bar
13 $ echo z1 > z.txt
13 $ echo z1 > z.txt
14
14
15 $ cd ..
15 $ cd ..
16 $ echo 'bar = bar' > .hgsub
16 $ echo 'bar = bar' > .hgsub
17
17
18 $ cd ..
18 $ cd ..
19 $ echo 'foo = foo' > .hgsub
19 $ echo 'foo = foo' > .hgsub
20
20
21 Add files --- .hgsub files must go first to trigger subrepos:
21 Add files --- .hgsub files must go first to trigger subrepos:
22
22
23 $ hg add -S .hgsub
23 $ hg add -S .hgsub
24 $ hg add -S foo/.hgsub
24 $ hg add -S foo/.hgsub
25 $ hg add -S foo/bar
25 $ hg add -S foo/bar
26 adding foo/bar/z.txt (glob)
26 adding foo/bar/z.txt (glob)
27 $ hg add -S
27 $ hg add -S
28 adding x.txt
28 adding x.txt
29 adding foo/y.txt (glob)
29 adding foo/y.txt (glob)
30
30
31 Test recursive status without committing anything:
31 Test recursive status without committing anything:
32
32
33 $ hg status -S
33 $ hg status -S
34 A .hgsub
34 A .hgsub
35 A foo/.hgsub
35 A foo/.hgsub
36 A foo/bar/z.txt
36 A foo/bar/z.txt
37 A foo/y.txt
37 A foo/y.txt
38 A x.txt
38 A x.txt
39
39
40 Test recursive diff without committing anything:
40 Test recursive diff without committing anything:
41
41
42 $ hg diff --nodates -S foo
42 $ hg diff --nodates -S foo
43 diff -r 000000000000 foo/.hgsub
43 diff -r 000000000000 foo/.hgsub
44 --- /dev/null
44 --- /dev/null
45 +++ b/foo/.hgsub
45 +++ b/foo/.hgsub
46 @@ -0,0 +1,1 @@
46 @@ -0,0 +1,1 @@
47 +bar = bar
47 +bar = bar
48 diff -r 000000000000 foo/y.txt
48 diff -r 000000000000 foo/y.txt
49 --- /dev/null
49 --- /dev/null
50 +++ b/foo/y.txt
50 +++ b/foo/y.txt
51 @@ -0,0 +1,1 @@
51 @@ -0,0 +1,1 @@
52 +y1
52 +y1
53 diff -r 000000000000 foo/bar/z.txt
53 diff -r 000000000000 foo/bar/z.txt
54 --- /dev/null
54 --- /dev/null
55 +++ b/foo/bar/z.txt
55 +++ b/foo/bar/z.txt
56 @@ -0,0 +1,1 @@
56 @@ -0,0 +1,1 @@
57 +z1
57 +z1
58
58
59 Commits:
59 Commits:
60
60
61 $ hg commit -m fails
61 $ hg commit -m fails
62 abort: uncommitted changes in subrepo foo
62 abort: uncommitted changes in subrepo foo
63 (use --subrepos for recursive commit)
63 (use --subrepos for recursive commit)
64 [255]
64 [255]
65
65
66 The --subrepos flag overwrite the config setting:
66 The --subrepos flag overwrite the config setting:
67
67
68 $ hg commit -m 0-0-0 --config ui.commitsubrepos=No --subrepos
68 $ hg commit -m 0-0-0 --config ui.commitsubrepos=No --subrepos
69 committing subrepository foo
69 committing subrepository foo
70 committing subrepository foo/bar (glob)
70 committing subrepository foo/bar (glob)
71
71
72 $ cd foo
72 $ cd foo
73 $ echo y2 >> y.txt
73 $ echo y2 >> y.txt
74 $ hg commit -m 0-1-0
74 $ hg commit -m 0-1-0
75
75
76 $ cd bar
76 $ cd bar
77 $ echo z2 >> z.txt
77 $ echo z2 >> z.txt
78 $ hg commit -m 0-1-1
78 $ hg commit -m 0-1-1
79
79
80 $ cd ..
80 $ cd ..
81 $ hg commit -m 0-2-1
81 $ hg commit -m 0-2-1
82 committing subrepository bar
83
82
84 $ cd ..
83 $ cd ..
85 $ hg commit -m 1-2-1
84 $ hg commit -m 1-2-1
86 committing subrepository foo
87
85
88 Change working directory:
86 Change working directory:
89
87
90 $ echo y3 >> foo/y.txt
88 $ echo y3 >> foo/y.txt
91 $ echo z3 >> foo/bar/z.txt
89 $ echo z3 >> foo/bar/z.txt
92 $ hg status -S
90 $ hg status -S
93 M foo/bar/z.txt
91 M foo/bar/z.txt
94 M foo/y.txt
92 M foo/y.txt
95 $ hg diff --nodates -S
93 $ hg diff --nodates -S
96 diff -r d254738c5f5e foo/y.txt
94 diff -r d254738c5f5e foo/y.txt
97 --- a/foo/y.txt
95 --- a/foo/y.txt
98 +++ b/foo/y.txt
96 +++ b/foo/y.txt
99 @@ -1,2 +1,3 @@
97 @@ -1,2 +1,3 @@
100 y1
98 y1
101 y2
99 y2
102 +y3
100 +y3
103 diff -r 9647f22de499 foo/bar/z.txt
101 diff -r 9647f22de499 foo/bar/z.txt
104 --- a/foo/bar/z.txt
102 --- a/foo/bar/z.txt
105 +++ b/foo/bar/z.txt
103 +++ b/foo/bar/z.txt
106 @@ -1,2 +1,3 @@
104 @@ -1,2 +1,3 @@
107 z1
105 z1
108 z2
106 z2
109 +z3
107 +z3
110
108
111 Status call crossing repository boundaries:
109 Status call crossing repository boundaries:
112
110
113 $ hg status -S foo/bar/z.txt
111 $ hg status -S foo/bar/z.txt
114 M foo/bar/z.txt
112 M foo/bar/z.txt
115 $ hg status -S -I 'foo/?.txt'
113 $ hg status -S -I 'foo/?.txt'
116 M foo/y.txt
114 M foo/y.txt
117 $ hg status -S -I '**/?.txt'
115 $ hg status -S -I '**/?.txt'
118 M foo/bar/z.txt
116 M foo/bar/z.txt
119 M foo/y.txt
117 M foo/y.txt
120 $ hg diff --nodates -S -I '**/?.txt'
118 $ hg diff --nodates -S -I '**/?.txt'
121 diff -r d254738c5f5e foo/y.txt
119 diff -r d254738c5f5e foo/y.txt
122 --- a/foo/y.txt
120 --- a/foo/y.txt
123 +++ b/foo/y.txt
121 +++ b/foo/y.txt
124 @@ -1,2 +1,3 @@
122 @@ -1,2 +1,3 @@
125 y1
123 y1
126 y2
124 y2
127 +y3
125 +y3
128 diff -r 9647f22de499 foo/bar/z.txt
126 diff -r 9647f22de499 foo/bar/z.txt
129 --- a/foo/bar/z.txt
127 --- a/foo/bar/z.txt
130 +++ b/foo/bar/z.txt
128 +++ b/foo/bar/z.txt
131 @@ -1,2 +1,3 @@
129 @@ -1,2 +1,3 @@
132 z1
130 z1
133 z2
131 z2
134 +z3
132 +z3
135
133
136 Status from within a subdirectory:
134 Status from within a subdirectory:
137
135
138 $ mkdir dir
136 $ mkdir dir
139 $ cd dir
137 $ cd dir
140 $ echo a1 > a.txt
138 $ echo a1 > a.txt
141 $ hg status -S
139 $ hg status -S
142 M foo/bar/z.txt
140 M foo/bar/z.txt
143 M foo/y.txt
141 M foo/y.txt
144 ? dir/a.txt
142 ? dir/a.txt
145 $ hg diff --nodates -S
143 $ hg diff --nodates -S
146 diff -r d254738c5f5e foo/y.txt
144 diff -r d254738c5f5e foo/y.txt
147 --- a/foo/y.txt
145 --- a/foo/y.txt
148 +++ b/foo/y.txt
146 +++ b/foo/y.txt
149 @@ -1,2 +1,3 @@
147 @@ -1,2 +1,3 @@
150 y1
148 y1
151 y2
149 y2
152 +y3
150 +y3
153 diff -r 9647f22de499 foo/bar/z.txt
151 diff -r 9647f22de499 foo/bar/z.txt
154 --- a/foo/bar/z.txt
152 --- a/foo/bar/z.txt
155 +++ b/foo/bar/z.txt
153 +++ b/foo/bar/z.txt
156 @@ -1,2 +1,3 @@
154 @@ -1,2 +1,3 @@
157 z1
155 z1
158 z2
156 z2
159 +z3
157 +z3
160
158
161 Status with relative path:
159 Status with relative path:
162
160
163 $ hg status -S ..
161 $ hg status -S ..
164 M ../foo/bar/z.txt
162 M ../foo/bar/z.txt
165 M ../foo/y.txt
163 M ../foo/y.txt
166 ? a.txt
164 ? a.txt
167 $ hg diff --nodates -S ..
165 $ hg diff --nodates -S ..
168 diff -r d254738c5f5e foo/y.txt
166 diff -r d254738c5f5e foo/y.txt
169 --- a/foo/y.txt
167 --- a/foo/y.txt
170 +++ b/foo/y.txt
168 +++ b/foo/y.txt
171 @@ -1,2 +1,3 @@
169 @@ -1,2 +1,3 @@
172 y1
170 y1
173 y2
171 y2
174 +y3
172 +y3
175 diff -r 9647f22de499 foo/bar/z.txt
173 diff -r 9647f22de499 foo/bar/z.txt
176 --- a/foo/bar/z.txt
174 --- a/foo/bar/z.txt
177 +++ b/foo/bar/z.txt
175 +++ b/foo/bar/z.txt
178 @@ -1,2 +1,3 @@
176 @@ -1,2 +1,3 @@
179 z1
177 z1
180 z2
178 z2
181 +z3
179 +z3
182 $ cd ..
180 $ cd ..
183
181
184 Cleanup and final commit:
182 Cleanup and final commit:
185
183
186 $ rm -r dir
184 $ rm -r dir
187 $ hg commit --subrepos -m 2-3-2
185 $ hg commit --subrepos -m 2-3-2
188 committing subrepository foo
186 committing subrepository foo
189 committing subrepository foo/bar (glob)
187 committing subrepository foo/bar (glob)
190
188
191 Test explicit path commands within subrepos: add/forget
189 Test explicit path commands within subrepos: add/forget
192 $ echo z1 > foo/bar/z2.txt
190 $ echo z1 > foo/bar/z2.txt
193 $ hg status -S
191 $ hg status -S
194 ? foo/bar/z2.txt
192 ? foo/bar/z2.txt
195 $ hg add foo/bar/z2.txt
193 $ hg add foo/bar/z2.txt
196 $ hg status -S
194 $ hg status -S
197 A foo/bar/z2.txt
195 A foo/bar/z2.txt
198 This is expected to forget the file, but is currently broken
196 This is expected to forget the file, but is currently broken
199 $ hg forget foo/bar/z2.txt
197 $ hg forget foo/bar/z2.txt
200 $ hg status -S
198 $ hg status -S
201 ? foo/bar/z2.txt
199 ? foo/bar/z2.txt
202 $ rm foo/bar/z2.txt
200 $ rm foo/bar/z2.txt
203
201
204 Log with the relationships between repo and its subrepo:
202 Log with the relationships between repo and its subrepo:
205
203
206 $ hg log --template '{rev}:{node|short} {desc}\n'
204 $ hg log --template '{rev}:{node|short} {desc}\n'
207 2:1326fa26d0c0 2-3-2
205 2:1326fa26d0c0 2-3-2
208 1:4b3c9ff4f66b 1-2-1
206 1:4b3c9ff4f66b 1-2-1
209 0:23376cbba0d8 0-0-0
207 0:23376cbba0d8 0-0-0
210
208
211 $ hg -R foo log --template '{rev}:{node|short} {desc}\n'
209 $ hg -R foo log --template '{rev}:{node|short} {desc}\n'
212 3:65903cebad86 2-3-2
210 3:65903cebad86 2-3-2
213 2:d254738c5f5e 0-2-1
211 2:d254738c5f5e 0-2-1
214 1:8629ce7dcc39 0-1-0
212 1:8629ce7dcc39 0-1-0
215 0:af048e97ade2 0-0-0
213 0:af048e97ade2 0-0-0
216
214
217 $ hg -R foo/bar log --template '{rev}:{node|short} {desc}\n'
215 $ hg -R foo/bar log --template '{rev}:{node|short} {desc}\n'
218 2:31ecbdafd357 2-3-2
216 2:31ecbdafd357 2-3-2
219 1:9647f22de499 0-1-1
217 1:9647f22de499 0-1-1
220 0:4904098473f9 0-0-0
218 0:4904098473f9 0-0-0
221
219
222 Status between revisions:
220 Status between revisions:
223
221
224 $ hg status -S
222 $ hg status -S
225 $ hg status -S --rev 0:1
223 $ hg status -S --rev 0:1
226 M .hgsubstate
224 M .hgsubstate
227 M foo/.hgsubstate
225 M foo/.hgsubstate
228 M foo/bar/z.txt
226 M foo/bar/z.txt
229 M foo/y.txt
227 M foo/y.txt
230 $ hg diff --nodates -S -I '**/?.txt' --rev 0:1
228 $ hg diff --nodates -S -I '**/?.txt' --rev 0:1
231 diff -r af048e97ade2 -r d254738c5f5e foo/y.txt
229 diff -r af048e97ade2 -r d254738c5f5e foo/y.txt
232 --- a/foo/y.txt
230 --- a/foo/y.txt
233 +++ b/foo/y.txt
231 +++ b/foo/y.txt
234 @@ -1,1 +1,2 @@
232 @@ -1,1 +1,2 @@
235 y1
233 y1
236 +y2
234 +y2
237 diff -r 4904098473f9 -r 9647f22de499 foo/bar/z.txt
235 diff -r 4904098473f9 -r 9647f22de499 foo/bar/z.txt
238 --- a/foo/bar/z.txt
236 --- a/foo/bar/z.txt
239 +++ b/foo/bar/z.txt
237 +++ b/foo/bar/z.txt
240 @@ -1,1 +1,2 @@
238 @@ -1,1 +1,2 @@
241 z1
239 z1
242 +z2
240 +z2
243
241
244 Enable progress extension for archive tests:
242 Enable progress extension for archive tests:
245
243
246 $ cp $HGRCPATH $HGRCPATH.no-progress
244 $ cp $HGRCPATH $HGRCPATH.no-progress
247 $ cat >> $HGRCPATH <<EOF
245 $ cat >> $HGRCPATH <<EOF
248 > [extensions]
246 > [extensions]
249 > progress =
247 > progress =
250 > [progress]
248 > [progress]
251 > assume-tty = 1
249 > assume-tty = 1
252 > delay = 0
250 > delay = 0
253 > format = topic bar number
251 > format = topic bar number
254 > refresh = 0
252 > refresh = 0
255 > width = 60
253 > width = 60
256 > EOF
254 > EOF
257
255
258 Test archiving to a directory tree (the doubled lines in the output
256 Test archiving to a directory tree (the doubled lines in the output
259 only show up in the test output, not in real usage):
257 only show up in the test output, not in real usage):
260
258
261 $ hg archive --subrepos ../archive 2>&1 | $TESTDIR/filtercr.py
259 $ hg archive --subrepos ../archive 2>&1 | $TESTDIR/filtercr.py
262
260
263 archiving [ ] 0/3
261 archiving [ ] 0/3
264 archiving [ ] 0/3
262 archiving [ ] 0/3
265 archiving [=============> ] 1/3
263 archiving [=============> ] 1/3
266 archiving [=============> ] 1/3
264 archiving [=============> ] 1/3
267 archiving [===========================> ] 2/3
265 archiving [===========================> ] 2/3
268 archiving [===========================> ] 2/3
266 archiving [===========================> ] 2/3
269 archiving [==========================================>] 3/3
267 archiving [==========================================>] 3/3
270 archiving [==========================================>] 3/3
268 archiving [==========================================>] 3/3
271
269
272 archiving (foo) [ ] 0/3
270 archiving (foo) [ ] 0/3
273 archiving (foo) [ ] 0/3
271 archiving (foo) [ ] 0/3
274 archiving (foo) [===========> ] 1/3
272 archiving (foo) [===========> ] 1/3
275 archiving (foo) [===========> ] 1/3
273 archiving (foo) [===========> ] 1/3
276 archiving (foo) [=======================> ] 2/3
274 archiving (foo) [=======================> ] 2/3
277 archiving (foo) [=======================> ] 2/3
275 archiving (foo) [=======================> ] 2/3
278 archiving (foo) [====================================>] 3/3
276 archiving (foo) [====================================>] 3/3
279 archiving (foo) [====================================>] 3/3
277 archiving (foo) [====================================>] 3/3
280
278
281 archiving (foo/bar) [ ] 0/1 (glob)
279 archiving (foo/bar) [ ] 0/1 (glob)
282 archiving (foo/bar) [ ] 0/1 (glob)
280 archiving (foo/bar) [ ] 0/1 (glob)
283 archiving (foo/bar) [================================>] 1/1 (glob)
281 archiving (foo/bar) [================================>] 1/1 (glob)
284 archiving (foo/bar) [================================>] 1/1 (glob)
282 archiving (foo/bar) [================================>] 1/1 (glob)
285 \r (esc)
283 \r (esc)
286 $ find ../archive | sort
284 $ find ../archive | sort
287 ../archive
285 ../archive
288 ../archive/.hg_archival.txt
286 ../archive/.hg_archival.txt
289 ../archive/.hgsub
287 ../archive/.hgsub
290 ../archive/.hgsubstate
288 ../archive/.hgsubstate
291 ../archive/foo
289 ../archive/foo
292 ../archive/foo/.hgsub
290 ../archive/foo/.hgsub
293 ../archive/foo/.hgsubstate
291 ../archive/foo/.hgsubstate
294 ../archive/foo/bar
292 ../archive/foo/bar
295 ../archive/foo/bar/z.txt
293 ../archive/foo/bar/z.txt
296 ../archive/foo/y.txt
294 ../archive/foo/y.txt
297 ../archive/x.txt
295 ../archive/x.txt
298
296
299 Test archiving to zip file (unzip output is unstable):
297 Test archiving to zip file (unzip output is unstable):
300
298
301 $ hg archive --subrepos ../archive.zip 2>&1 | $TESTDIR/filtercr.py
299 $ hg archive --subrepos ../archive.zip 2>&1 | $TESTDIR/filtercr.py
302
300
303 archiving [ ] 0/3
301 archiving [ ] 0/3
304 archiving [ ] 0/3
302 archiving [ ] 0/3
305 archiving [=============> ] 1/3
303 archiving [=============> ] 1/3
306 archiving [=============> ] 1/3
304 archiving [=============> ] 1/3
307 archiving [===========================> ] 2/3
305 archiving [===========================> ] 2/3
308 archiving [===========================> ] 2/3
306 archiving [===========================> ] 2/3
309 archiving [==========================================>] 3/3
307 archiving [==========================================>] 3/3
310 archiving [==========================================>] 3/3
308 archiving [==========================================>] 3/3
311
309
312 archiving (foo) [ ] 0/3
310 archiving (foo) [ ] 0/3
313 archiving (foo) [ ] 0/3
311 archiving (foo) [ ] 0/3
314 archiving (foo) [===========> ] 1/3
312 archiving (foo) [===========> ] 1/3
315 archiving (foo) [===========> ] 1/3
313 archiving (foo) [===========> ] 1/3
316 archiving (foo) [=======================> ] 2/3
314 archiving (foo) [=======================> ] 2/3
317 archiving (foo) [=======================> ] 2/3
315 archiving (foo) [=======================> ] 2/3
318 archiving (foo) [====================================>] 3/3
316 archiving (foo) [====================================>] 3/3
319 archiving (foo) [====================================>] 3/3
317 archiving (foo) [====================================>] 3/3
320
318
321 archiving (foo/bar) [ ] 0/1 (glob)
319 archiving (foo/bar) [ ] 0/1 (glob)
322 archiving (foo/bar) [ ] 0/1 (glob)
320 archiving (foo/bar) [ ] 0/1 (glob)
323 archiving (foo/bar) [================================>] 1/1 (glob)
321 archiving (foo/bar) [================================>] 1/1 (glob)
324 archiving (foo/bar) [================================>] 1/1 (glob)
322 archiving (foo/bar) [================================>] 1/1 (glob)
325 \r (esc)
323 \r (esc)
326
324
327 Test archiving a revision that references a subrepo that is not yet
325 Test archiving a revision that references a subrepo that is not yet
328 cloned:
326 cloned:
329
327
330 $ hg clone -U . ../empty
328 $ hg clone -U . ../empty
331 $ cd ../empty
329 $ cd ../empty
332 $ hg archive --subrepos -r tip ../archive.tar.gz 2>&1 | $TESTDIR/filtercr.py
330 $ hg archive --subrepos -r tip ../archive.tar.gz 2>&1 | $TESTDIR/filtercr.py
333
331
334 archiving [ ] 0/3
332 archiving [ ] 0/3
335 archiving [ ] 0/3
333 archiving [ ] 0/3
336 archiving [=============> ] 1/3
334 archiving [=============> ] 1/3
337 archiving [=============> ] 1/3
335 archiving [=============> ] 1/3
338 archiving [===========================> ] 2/3
336 archiving [===========================> ] 2/3
339 archiving [===========================> ] 2/3
337 archiving [===========================> ] 2/3
340 archiving [==========================================>] 3/3
338 archiving [==========================================>] 3/3
341 archiving [==========================================>] 3/3
339 archiving [==========================================>] 3/3
342
340
343 archiving (foo) [ ] 0/3
341 archiving (foo) [ ] 0/3
344 archiving (foo) [ ] 0/3
342 archiving (foo) [ ] 0/3
345 archiving (foo) [===========> ] 1/3
343 archiving (foo) [===========> ] 1/3
346 archiving (foo) [===========> ] 1/3
344 archiving (foo) [===========> ] 1/3
347 archiving (foo) [=======================> ] 2/3
345 archiving (foo) [=======================> ] 2/3
348 archiving (foo) [=======================> ] 2/3
346 archiving (foo) [=======================> ] 2/3
349 archiving (foo) [====================================>] 3/3
347 archiving (foo) [====================================>] 3/3
350 archiving (foo) [====================================>] 3/3
348 archiving (foo) [====================================>] 3/3
351
349
352 archiving (foo/bar) [ ] 0/1 (glob)
350 archiving (foo/bar) [ ] 0/1 (glob)
353 archiving (foo/bar) [ ] 0/1 (glob)
351 archiving (foo/bar) [ ] 0/1 (glob)
354 archiving (foo/bar) [================================>] 1/1 (glob)
352 archiving (foo/bar) [================================>] 1/1 (glob)
355 archiving (foo/bar) [================================>] 1/1 (glob)
353 archiving (foo/bar) [================================>] 1/1 (glob)
356
354
357 cloning subrepo foo from $TESTTMP/repo/foo
355 cloning subrepo foo from $TESTTMP/repo/foo
358 cloning subrepo foo/bar from $TESTTMP/repo/foo/bar (glob)
356 cloning subrepo foo/bar from $TESTTMP/repo/foo/bar (glob)
359
357
360 The newly cloned subrepos contain no working copy:
358 The newly cloned subrepos contain no working copy:
361
359
362 $ hg -R foo summary
360 $ hg -R foo summary
363 parent: -1:000000000000 (no revision checked out)
361 parent: -1:000000000000 (no revision checked out)
364 branch: default
362 branch: default
365 commit: (clean)
363 commit: (clean)
366 update: 4 new changesets (update)
364 update: 4 new changesets (update)
367
365
368 Disable progress extension and cleanup:
366 Disable progress extension and cleanup:
369
367
370 $ mv $HGRCPATH.no-progress $HGRCPATH
368 $ mv $HGRCPATH.no-progress $HGRCPATH
371
369
372 Test archiving when there is a directory in the way for a subrepo
370 Test archiving when there is a directory in the way for a subrepo
373 created by archive:
371 created by archive:
374
372
375 $ hg clone -U . ../almost-empty
373 $ hg clone -U . ../almost-empty
376 $ cd ../almost-empty
374 $ cd ../almost-empty
377 $ mkdir foo
375 $ mkdir foo
378 $ echo f > foo/f
376 $ echo f > foo/f
379 $ hg archive --subrepos -r tip archive
377 $ hg archive --subrepos -r tip archive
380 cloning subrepo foo from $TESTTMP/empty/foo
378 cloning subrepo foo from $TESTTMP/empty/foo
381 abort: destination '$TESTTMP/almost-empty/foo' is not empty (glob)
379 abort: destination '$TESTTMP/almost-empty/foo' is not empty (glob)
382 [255]
380 [255]
383
381
384 Clone and test outgoing:
382 Clone and test outgoing:
385
383
386 $ cd ..
384 $ cd ..
387 $ hg clone repo repo2
385 $ hg clone repo repo2
388 updating to branch default
386 updating to branch default
389 cloning subrepo foo from $TESTTMP/repo/foo
387 cloning subrepo foo from $TESTTMP/repo/foo
390 cloning subrepo foo/bar from $TESTTMP/repo/foo/bar (glob)
388 cloning subrepo foo/bar from $TESTTMP/repo/foo/bar (glob)
391 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
389 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
392 $ cd repo2
390 $ cd repo2
393 $ hg outgoing -S
391 $ hg outgoing -S
394 comparing with $TESTTMP/repo (glob)
392 comparing with $TESTTMP/repo (glob)
395 searching for changes
393 searching for changes
396 no changes found
394 no changes found
397 comparing with $TESTTMP/repo/foo
395 comparing with $TESTTMP/repo/foo
398 searching for changes
396 searching for changes
399 no changes found
397 no changes found
400 comparing with $TESTTMP/repo/foo/bar
398 comparing with $TESTTMP/repo/foo/bar
401 searching for changes
399 searching for changes
402 no changes found
400 no changes found
403 [1]
401 [1]
404
402
405 Make nested change:
403 Make nested change:
406
404
407 $ echo y4 >> foo/y.txt
405 $ echo y4 >> foo/y.txt
408 $ hg diff --nodates -S
406 $ hg diff --nodates -S
409 diff -r 65903cebad86 foo/y.txt
407 diff -r 65903cebad86 foo/y.txt
410 --- a/foo/y.txt
408 --- a/foo/y.txt
411 +++ b/foo/y.txt
409 +++ b/foo/y.txt
412 @@ -1,3 +1,4 @@
410 @@ -1,3 +1,4 @@
413 y1
411 y1
414 y2
412 y2
415 y3
413 y3
416 +y4
414 +y4
417 $ hg commit --subrepos -m 3-4-2
415 $ hg commit --subrepos -m 3-4-2
418 committing subrepository foo
416 committing subrepository foo
419 $ hg outgoing -S
417 $ hg outgoing -S
420 comparing with $TESTTMP/repo (glob)
418 comparing with $TESTTMP/repo (glob)
421 searching for changes
419 searching for changes
422 changeset: 3:2655b8ecc4ee
420 changeset: 3:2655b8ecc4ee
423 tag: tip
421 tag: tip
424 user: test
422 user: test
425 date: Thu Jan 01 00:00:00 1970 +0000
423 date: Thu Jan 01 00:00:00 1970 +0000
426 summary: 3-4-2
424 summary: 3-4-2
427
425
428 comparing with $TESTTMP/repo/foo
426 comparing with $TESTTMP/repo/foo
429 searching for changes
427 searching for changes
430 changeset: 4:e96193d6cb36
428 changeset: 4:e96193d6cb36
431 tag: tip
429 tag: tip
432 user: test
430 user: test
433 date: Thu Jan 01 00:00:00 1970 +0000
431 date: Thu Jan 01 00:00:00 1970 +0000
434 summary: 3-4-2
432 summary: 3-4-2
435
433
436 comparing with $TESTTMP/repo/foo/bar
434 comparing with $TESTTMP/repo/foo/bar
437 searching for changes
435 searching for changes
438 no changes found
436 no changes found
439
437
440
438
441 Switch to original repo and setup default path:
439 Switch to original repo and setup default path:
442
440
443 $ cd ../repo
441 $ cd ../repo
444 $ echo '[paths]' >> .hg/hgrc
442 $ echo '[paths]' >> .hg/hgrc
445 $ echo 'default = ../repo2' >> .hg/hgrc
443 $ echo 'default = ../repo2' >> .hg/hgrc
446
444
447 Test incoming:
445 Test incoming:
448
446
449 $ hg incoming -S
447 $ hg incoming -S
450 comparing with $TESTTMP/repo2 (glob)
448 comparing with $TESTTMP/repo2 (glob)
451 searching for changes
449 searching for changes
452 changeset: 3:2655b8ecc4ee
450 changeset: 3:2655b8ecc4ee
453 tag: tip
451 tag: tip
454 user: test
452 user: test
455 date: Thu Jan 01 00:00:00 1970 +0000
453 date: Thu Jan 01 00:00:00 1970 +0000
456 summary: 3-4-2
454 summary: 3-4-2
457
455
458 comparing with $TESTTMP/repo2/foo
456 comparing with $TESTTMP/repo2/foo
459 searching for changes
457 searching for changes
460 changeset: 4:e96193d6cb36
458 changeset: 4:e96193d6cb36
461 tag: tip
459 tag: tip
462 user: test
460 user: test
463 date: Thu Jan 01 00:00:00 1970 +0000
461 date: Thu Jan 01 00:00:00 1970 +0000
464 summary: 3-4-2
462 summary: 3-4-2
465
463
466 comparing with $TESTTMP/repo2/foo/bar
464 comparing with $TESTTMP/repo2/foo/bar
467 searching for changes
465 searching for changes
468 no changes found
466 no changes found
469
467
470 $ hg incoming -S --bundle incoming.hg
468 $ hg incoming -S --bundle incoming.hg
471 abort: cannot combine --bundle and --subrepos
469 abort: cannot combine --bundle and --subrepos
472 [255]
470 [255]
473
471
474 Test missing subrepo:
472 Test missing subrepo:
475
473
476 $ rm -r foo
474 $ rm -r foo
477 $ hg status -S
475 $ hg status -S
478 warning: error "unknown revision '65903cebad86f1a84bd4f1134f62fa7dcb7a1c98'" in subrepository "foo"
476 warning: error "unknown revision '65903cebad86f1a84bd4f1134f62fa7dcb7a1c98'" in subrepository "foo"
479
477
480 Issue2619: IndexError: list index out of range on hg add with subrepos
478 Issue2619: IndexError: list index out of range on hg add with subrepos
481 The subrepo must sorts after the explicit filename.
479 The subrepo must sorts after the explicit filename.
482
480
483 $ cd ..
481 $ cd ..
484 $ hg init test
482 $ hg init test
485 $ cd test
483 $ cd test
486 $ hg init x
484 $ hg init x
487 $ echo "x = x" >> .hgsub
485 $ echo "x = x" >> .hgsub
488 $ hg add .hgsub
486 $ hg add .hgsub
489 $ touch a x/a
487 $ touch a x/a
490 $ hg add a x/a
488 $ hg add a x/a
@@ -1,106 +1,105 b''
1 $ "$TESTDIR/hghave" serve || exit 80
1 $ "$TESTDIR/hghave" serve || exit 80
2
2
3 Preparing the subrepository 'sub'
3 Preparing the subrepository 'sub'
4
4
5 $ hg init sub
5 $ hg init sub
6 $ echo sub > sub/sub
6 $ echo sub > sub/sub
7 $ hg add -R sub
7 $ hg add -R sub
8 adding sub/sub (glob)
8 adding sub/sub (glob)
9 $ hg commit -R sub -m "sub import"
9 $ hg commit -R sub -m "sub import"
10
10
11 Preparing the 'main' repo which depends on the subrepo 'sub'
11 Preparing the 'main' repo which depends on the subrepo 'sub'
12
12
13 $ hg init main
13 $ hg init main
14 $ echo main > main/main
14 $ echo main > main/main
15 $ echo "sub = ../sub" > main/.hgsub
15 $ echo "sub = ../sub" > main/.hgsub
16 $ hg clone sub main/sub
16 $ hg clone sub main/sub
17 updating to branch default
17 updating to branch default
18 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
18 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
19 $ hg add -R main
19 $ hg add -R main
20 adding main/.hgsub (glob)
20 adding main/.hgsub (glob)
21 adding main/main (glob)
21 adding main/main (glob)
22 $ hg commit -R main -m "main import"
22 $ hg commit -R main -m "main import"
23 committing subrepository sub
24
23
25 Cleaning both repositories, just as a clone -U
24 Cleaning both repositories, just as a clone -U
26
25
27 $ hg up -C -R sub null
26 $ hg up -C -R sub null
28 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
27 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
29 $ hg up -C -R main null
28 $ hg up -C -R main null
30 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
29 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
31 $ rm -rf main/sub
30 $ rm -rf main/sub
32
31
33 Serving them both using hgweb
32 Serving them both using hgweb
34
33
35 $ printf '[paths]\n/main = main\nsub = sub\n' > webdir.conf
34 $ printf '[paths]\n/main = main\nsub = sub\n' > webdir.conf
36 $ hg serve --webdir-conf webdir.conf -a localhost -p $HGPORT \
35 $ hg serve --webdir-conf webdir.conf -a localhost -p $HGPORT \
37 > -A /dev/null -E /dev/null --pid-file hg.pid -d
36 > -A /dev/null -E /dev/null --pid-file hg.pid -d
38 $ cat hg.pid >> $DAEMON_PIDS
37 $ cat hg.pid >> $DAEMON_PIDS
39
38
40 Clone main from hgweb
39 Clone main from hgweb
41
40
42 $ hg clone "http://localhost:$HGPORT/main" cloned
41 $ hg clone "http://localhost:$HGPORT/main" cloned
43 requesting all changes
42 requesting all changes
44 adding changesets
43 adding changesets
45 adding manifests
44 adding manifests
46 adding file changes
45 adding file changes
47 added 1 changesets with 3 changes to 3 files
46 added 1 changesets with 3 changes to 3 files
48 updating to branch default
47 updating to branch default
49 cloning subrepo sub from http://localhost:$HGPORT/sub
48 cloning subrepo sub from http://localhost:$HGPORT/sub
50 requesting all changes
49 requesting all changes
51 adding changesets
50 adding changesets
52 adding manifests
51 adding manifests
53 adding file changes
52 adding file changes
54 added 1 changesets with 1 changes to 1 files
53 added 1 changesets with 1 changes to 1 files
55 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
54 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
56
55
57 Checking cloned repo ids
56 Checking cloned repo ids
58
57
59 $ hg id -R cloned
58 $ hg id -R cloned
60 fdfeeb3e979e tip
59 fdfeeb3e979e tip
61 $ hg id -R cloned/sub
60 $ hg id -R cloned/sub
62 863c1745b441 tip
61 863c1745b441 tip
63
62
64 subrepo debug for 'main' clone
63 subrepo debug for 'main' clone
65
64
66 $ hg debugsub -R cloned
65 $ hg debugsub -R cloned
67 path sub
66 path sub
68 source ../sub
67 source ../sub
69 revision 863c1745b441bd97a8c4a096e87793073f4fb215
68 revision 863c1745b441bd97a8c4a096e87793073f4fb215
70
69
71 $ "$TESTDIR/killdaemons.py"
70 $ "$TESTDIR/killdaemons.py"
72
71
73 subrepo paths with ssh urls
72 subrepo paths with ssh urls
74
73
75 $ cp $TESTDIR/dummyssh $BINDIR/ssh
74 $ cp $TESTDIR/dummyssh $BINDIR/ssh
76
75
77 $ hg clone ssh://user@dummy/cloned sshclone
76 $ hg clone ssh://user@dummy/cloned sshclone
78 requesting all changes
77 requesting all changes
79 adding changesets
78 adding changesets
80 adding manifests
79 adding manifests
81 adding file changes
80 adding file changes
82 added 1 changesets with 3 changes to 3 files
81 added 1 changesets with 3 changes to 3 files
83 updating to branch default
82 updating to branch default
84 cloning subrepo sub from ssh://user@dummy/sub
83 cloning subrepo sub from ssh://user@dummy/sub
85 requesting all changes
84 requesting all changes
86 adding changesets
85 adding changesets
87 adding manifests
86 adding manifests
88 adding file changes
87 adding file changes
89 added 1 changesets with 1 changes to 1 files
88 added 1 changesets with 1 changes to 1 files
90 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
91
90
92 $ hg -R sshclone push ssh://user@dummy/$TESTTMP/cloned
91 $ hg -R sshclone push ssh://user@dummy/$TESTTMP/cloned
93 pushing to ssh://user@dummy/$TESTTMP/cloned
92 pushing to ssh://user@dummy/$TESTTMP/cloned
94 pushing subrepo sub to ssh://user@dummy/$TESTTMP/sub
93 pushing subrepo sub to ssh://user@dummy/$TESTTMP/sub
95 searching for changes
94 searching for changes
96 no changes found
95 no changes found
97 searching for changes
96 searching for changes
98 no changes found
97 no changes found
99 [1]
98 [1]
100
99
101 $ cat dummylog
100 $ cat dummylog
102 Got arguments 1:user@dummy 2:hg -R cloned serve --stdio
101 Got arguments 1:user@dummy 2:hg -R cloned serve --stdio
103 Got arguments 1:user@dummy 2:hg -R sub serve --stdio
102 Got arguments 1:user@dummy 2:hg -R sub serve --stdio
104 Got arguments 1:user@dummy 2:hg -R $TESTTMP/cloned serve --stdio
103 Got arguments 1:user@dummy 2:hg -R $TESTTMP/cloned serve --stdio
105 Got arguments 1:user@dummy 2:hg -R $TESTTMP/sub serve --stdio
104 Got arguments 1:user@dummy 2:hg -R $TESTTMP/sub serve --stdio
106 $ rm $BINDIR/ssh
105 $ rm $BINDIR/ssh
@@ -1,545 +1,537 b''
1 $ "$TESTDIR/hghave" svn15 || exit 80
1 $ "$TESTDIR/hghave" svn15 || exit 80
2
2
3 $ fix_path()
3 $ fix_path()
4 > {
4 > {
5 > tr '\\' /
5 > tr '\\' /
6 > }
6 > }
7
7
8 SVN wants all paths to start with a slash. Unfortunately, Windows ones
8 SVN wants all paths to start with a slash. Unfortunately, Windows ones
9 don't. Handle that.
9 don't. Handle that.
10
10
11 $ escapedwd=`pwd | fix_path`
11 $ escapedwd=`pwd | fix_path`
12 $ expr "$escapedwd" : '\/' > /dev/null || escapedwd="/$escapedwd"
12 $ expr "$escapedwd" : '\/' > /dev/null || escapedwd="/$escapedwd"
13 $ escapedwd=`python -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$escapedwd"`
13 $ escapedwd=`python -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$escapedwd"`
14
14
15 create subversion repo
15 create subversion repo
16
16
17 $ SVNREPO="file://$escapedwd/svn-repo"
17 $ SVNREPO="file://$escapedwd/svn-repo"
18 $ WCROOT="`pwd`/svn-wc"
18 $ WCROOT="`pwd`/svn-wc"
19 $ svnadmin create svn-repo
19 $ svnadmin create svn-repo
20 $ svn co "$SVNREPO" svn-wc
20 $ svn co "$SVNREPO" svn-wc
21 Checked out revision 0.
21 Checked out revision 0.
22 $ cd svn-wc
22 $ cd svn-wc
23 $ mkdir src
23 $ mkdir src
24 $ echo alpha > src/alpha
24 $ echo alpha > src/alpha
25 $ svn add src
25 $ svn add src
26 A src
26 A src
27 A src/alpha
27 A src/alpha
28 $ mkdir externals
28 $ mkdir externals
29 $ echo other > externals/other
29 $ echo other > externals/other
30 $ svn add externals
30 $ svn add externals
31 A externals
31 A externals
32 A externals/other
32 A externals/other
33 $ svn ci -m 'Add alpha'
33 $ svn ci -m 'Add alpha'
34 Adding externals
34 Adding externals
35 Adding externals/other
35 Adding externals/other
36 Adding src
36 Adding src
37 Adding src/alpha
37 Adding src/alpha
38 Transmitting file data ..
38 Transmitting file data ..
39 Committed revision 1.
39 Committed revision 1.
40 $ svn up -q
40 $ svn up -q
41 $ echo "externals -r1 $SVNREPO/externals" > extdef
41 $ echo "externals -r1 $SVNREPO/externals" > extdef
42 $ svn propset -F extdef svn:externals src
42 $ svn propset -F extdef svn:externals src
43 property 'svn:externals' set on 'src'
43 property 'svn:externals' set on 'src'
44 $ svn ci -m 'Setting externals'
44 $ svn ci -m 'Setting externals'
45 Sending src
45 Sending src
46
46
47 Committed revision 2.
47 Committed revision 2.
48 $ cd ..
48 $ cd ..
49
49
50 create hg repo
50 create hg repo
51
51
52 $ mkdir sub
52 $ mkdir sub
53 $ cd sub
53 $ cd sub
54 $ hg init t
54 $ hg init t
55 $ cd t
55 $ cd t
56
56
57 first revision, no sub
57 first revision, no sub
58
58
59 $ echo a > a
59 $ echo a > a
60 $ hg ci -Am0
60 $ hg ci -Am0
61 adding a
61 adding a
62
62
63 add first svn sub with leading whitespaces
63 add first svn sub with leading whitespaces
64
64
65 $ echo "s = [svn] $SVNREPO/src" >> .hgsub
65 $ echo "s = [svn] $SVNREPO/src" >> .hgsub
66 $ echo "subdir/s = [svn] $SVNREPO/src" >> .hgsub
66 $ echo "subdir/s = [svn] $SVNREPO/src" >> .hgsub
67 $ svn co --quiet "$SVNREPO"/src s
67 $ svn co --quiet "$SVNREPO"/src s
68 $ mkdir subdir
68 $ mkdir subdir
69 $ svn co --quiet "$SVNREPO"/src subdir/s
69 $ svn co --quiet "$SVNREPO"/src subdir/s
70 $ hg add .hgsub
70 $ hg add .hgsub
71 $ hg ci -m1
71 $ hg ci -m1
72 committing subrepository s
73 committing subrepository subdir/s
74
72
75 make sure we avoid empty commits (issue2445)
73 make sure we avoid empty commits (issue2445)
76
74
77 $ hg sum
75 $ hg sum
78 parent: 1:* tip (glob)
76 parent: 1:* tip (glob)
79 1
77 1
80 branch: default
78 branch: default
81 commit: (clean)
79 commit: (clean)
82 update: (current)
80 update: (current)
83 $ hg ci -moops
81 $ hg ci -moops
84 nothing changed
82 nothing changed
85 [1]
83 [1]
86
84
87 debugsub
85 debugsub
88
86
89 $ hg debugsub
87 $ hg debugsub
90 path s
88 path s
91 source file://*/svn-repo/src (glob)
89 source file://*/svn-repo/src (glob)
92 revision 2
90 revision 2
93 path subdir/s
91 path subdir/s
94 source file://*/svn-repo/src (glob)
92 source file://*/svn-repo/src (glob)
95 revision 2
93 revision 2
96
94
97 change file in svn and hg, commit
95 change file in svn and hg, commit
98
96
99 $ echo a >> a
97 $ echo a >> a
100 $ echo alpha >> s/alpha
98 $ echo alpha >> s/alpha
101 $ hg sum
99 $ hg sum
102 parent: 1:* tip (glob)
100 parent: 1:* tip (glob)
103 1
101 1
104 branch: default
102 branch: default
105 commit: 1 modified, 1 subrepos
103 commit: 1 modified, 1 subrepos
106 update: (current)
104 update: (current)
107 $ hg commit --subrepos -m 'Message!' | grep -v Updating
105 $ hg commit --subrepos -m 'Message!' | grep -v Updating
108 committing subrepository s
106 committing subrepository s
109 Sending*s/alpha (glob)
107 Sending*s/alpha (glob)
110 Transmitting file data .
108 Transmitting file data .
111 Committed revision 3.
109 Committed revision 3.
112
110
113 Fetching external item into '*s/externals'* (glob)
111 Fetching external item into '*s/externals'* (glob)
114 External at revision 1.
112 External at revision 1.
115
113
116 At revision 3.
114 At revision 3.
117 $ hg debugsub
115 $ hg debugsub
118 path s
116 path s
119 source file://*/svn-repo/src (glob)
117 source file://*/svn-repo/src (glob)
120 revision 3
118 revision 3
121 path subdir/s
119 path subdir/s
122 source file://*/svn-repo/src (glob)
120 source file://*/svn-repo/src (glob)
123 revision 2
121 revision 2
124
122
125 add an unrelated revision in svn and update the subrepo to without
123 add an unrelated revision in svn and update the subrepo to without
126 bringing any changes.
124 bringing any changes.
127
125
128 $ svn mkdir "$SVNREPO/unrelated" -m 'create unrelated'
126 $ svn mkdir "$SVNREPO/unrelated" -m 'create unrelated'
129
127
130 Committed revision 4.
128 Committed revision 4.
131 $ svn up -q s
129 $ svn up -q s
132 $ hg sum
130 $ hg sum
133 parent: 2:* tip (glob)
131 parent: 2:* tip (glob)
134 Message!
132 Message!
135 branch: default
133 branch: default
136 commit: (clean)
134 commit: (clean)
137 update: (current)
135 update: (current)
138
136
139 $ echo a > s/a
137 $ echo a > s/a
140
138
141 should be empty despite change to s/a
139 should be empty despite change to s/a
142
140
143 $ hg st
141 $ hg st
144
142
145 add a commit from svn
143 add a commit from svn
146
144
147 $ cd "$WCROOT"/src
145 $ cd "$WCROOT"/src
148 $ svn up -q
146 $ svn up -q
149 $ echo xyz >> alpha
147 $ echo xyz >> alpha
150 $ svn propset svn:mime-type 'text/xml' alpha
148 $ svn propset svn:mime-type 'text/xml' alpha
151 property 'svn:mime-type' set on 'alpha'
149 property 'svn:mime-type' set on 'alpha'
152 $ svn ci -m 'amend a from svn'
150 $ svn ci -m 'amend a from svn'
153 Sending *alpha (glob)
151 Sending *alpha (glob)
154 Transmitting file data .
152 Transmitting file data .
155 Committed revision 5.
153 Committed revision 5.
156 $ cd ../../sub/t
154 $ cd ../../sub/t
157
155
158 this commit from hg will fail
156 this commit from hg will fail
159
157
160 $ echo zzz >> s/alpha
158 $ echo zzz >> s/alpha
161 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
159 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
162 committing subrepository s
160 committing subrepository s
163 abort: svn:*Commit failed (details follow): (glob)
161 abort: svn:*Commit failed (details follow): (glob)
164 [255]
162 [255]
165 $ svn revert -q s/alpha
163 $ svn revert -q s/alpha
166
164
167 this commit fails because of meta changes
165 this commit fails because of meta changes
168
166
169 $ svn propset svn:mime-type 'text/html' s/alpha
167 $ svn propset svn:mime-type 'text/html' s/alpha
170 property 'svn:mime-type' set on 's/alpha'
168 property 'svn:mime-type' set on 's/alpha'
171 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
169 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
172 committing subrepository s
170 committing subrepository s
173 abort: svn:*Commit failed (details follow): (glob)
171 abort: svn:*Commit failed (details follow): (glob)
174 [255]
172 [255]
175 $ svn revert -q s/alpha
173 $ svn revert -q s/alpha
176
174
177 this commit fails because of externals changes
175 this commit fails because of externals changes
178
176
179 $ echo zzz > s/externals/other
177 $ echo zzz > s/externals/other
180 $ hg ci --subrepos -m 'amend externals from hg'
178 $ hg ci --subrepos -m 'amend externals from hg'
181 committing subrepository s
179 committing subrepository s
182 abort: cannot commit svn externals
180 abort: cannot commit svn externals
183 [255]
181 [255]
184 $ hg diff --subrepos -r 1:2 | grep -v diff
182 $ hg diff --subrepos -r 1:2 | grep -v diff
185 --- a/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
183 --- a/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
186 +++ b/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
184 +++ b/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
187 @@ -1,2 +1,2 @@
185 @@ -1,2 +1,2 @@
188 -2 s
186 -2 s
189 +3 s
187 +3 s
190 2 subdir/s
188 2 subdir/s
191 --- a/a Thu Jan 01 00:00:00 1970 +0000
189 --- a/a Thu Jan 01 00:00:00 1970 +0000
192 +++ b/a Thu Jan 01 00:00:00 1970 +0000
190 +++ b/a Thu Jan 01 00:00:00 1970 +0000
193 @@ -1,1 +1,2 @@
191 @@ -1,1 +1,2 @@
194 a
192 a
195 +a
193 +a
196 $ svn revert -q s/externals/other
194 $ svn revert -q s/externals/other
197
195
198 this commit fails because of externals meta changes
196 this commit fails because of externals meta changes
199
197
200 $ svn propset svn:mime-type 'text/html' s/externals/other
198 $ svn propset svn:mime-type 'text/html' s/externals/other
201 property 'svn:mime-type' set on 's/externals/other'
199 property 'svn:mime-type' set on 's/externals/other'
202 $ hg ci --subrepos -m 'amend externals from hg'
200 $ hg ci --subrepos -m 'amend externals from hg'
203 committing subrepository s
201 committing subrepository s
204 abort: cannot commit svn externals
202 abort: cannot commit svn externals
205 [255]
203 [255]
206 $ svn revert -q s/externals/other
204 $ svn revert -q s/externals/other
207
205
208 clone
206 clone
209
207
210 $ cd ..
208 $ cd ..
211 $ hg clone t tc | fix_path
209 $ hg clone t tc | fix_path
212 updating to branch default
210 updating to branch default
213 A tc/s/alpha
211 A tc/s/alpha
214 U tc/s
212 U tc/s
215
213
216 Fetching external item into 'tc/s/externals'* (glob)
214 Fetching external item into 'tc/s/externals'* (glob)
217 A tc/s/externals/other
215 A tc/s/externals/other
218 Checked out external at revision 1.
216 Checked out external at revision 1.
219
217
220 Checked out revision 3.
218 Checked out revision 3.
221 A tc/subdir/s/alpha
219 A tc/subdir/s/alpha
222 U tc/subdir/s
220 U tc/subdir/s
223
221
224 Fetching external item into 'tc/subdir/s/externals'* (glob)
222 Fetching external item into 'tc/subdir/s/externals'* (glob)
225 A tc/subdir/s/externals/other
223 A tc/subdir/s/externals/other
226 Checked out external at revision 1.
224 Checked out external at revision 1.
227
225
228 Checked out revision 2.
226 Checked out revision 2.
229 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
227 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
230 $ cd tc
228 $ cd tc
231
229
232 debugsub in clone
230 debugsub in clone
233
231
234 $ hg debugsub
232 $ hg debugsub
235 path s
233 path s
236 source file://*/svn-repo/src (glob)
234 source file://*/svn-repo/src (glob)
237 revision 3
235 revision 3
238 path subdir/s
236 path subdir/s
239 source file://*/svn-repo/src (glob)
237 source file://*/svn-repo/src (glob)
240 revision 2
238 revision 2
241
239
242 verify subrepo is contained within the repo directory
240 verify subrepo is contained within the repo directory
243
241
244 $ python -c "import os.path; print os.path.exists('s')"
242 $ python -c "import os.path; print os.path.exists('s')"
245 True
243 True
246
244
247 update to nullrev (must delete the subrepo)
245 update to nullrev (must delete the subrepo)
248
246
249 $ hg up null
247 $ hg up null
250 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
248 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
251 $ ls
249 $ ls
252
250
253 Check hg update --clean
251 Check hg update --clean
254 $ cd $TESTTMP/sub/t
252 $ cd $TESTTMP/sub/t
255 $ cd s
253 $ cd s
256 $ echo c0 > alpha
254 $ echo c0 > alpha
257 $ echo c1 > f1
255 $ echo c1 > f1
258 $ echo c1 > f2
256 $ echo c1 > f2
259 $ svn add f1 -q
257 $ svn add f1 -q
260 $ svn status | sort
258 $ svn status | sort
261
259
262 ? * a (glob)
260 ? * a (glob)
263 ? * f2 (glob)
261 ? * f2 (glob)
264 A * f1 (glob)
262 A * f1 (glob)
265 M * alpha (glob)
263 M * alpha (glob)
266 Performing status on external item at 'externals'* (glob)
264 Performing status on external item at 'externals'* (glob)
267 X * externals (glob)
265 X * externals (glob)
268 $ cd ../..
266 $ cd ../..
269 $ hg -R t update -C
267 $ hg -R t update -C
270
268
271 Fetching external item into 't/s/externals'* (glob)
269 Fetching external item into 't/s/externals'* (glob)
272 Checked out external at revision 1.
270 Checked out external at revision 1.
273
271
274 Checked out revision 3.
272 Checked out revision 3.
275 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
273 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
276 $ cd t/s
274 $ cd t/s
277 $ svn status
275 $ svn status
278 ? * a (glob)
276 ? * a (glob)
279 X * externals (glob)
277 X * externals (glob)
280 ? * f1 (glob)
278 ? * f1 (glob)
281 ? * f2 (glob)
279 ? * f2 (glob)
282
280
283 Performing status on external item at 'externals'* (glob)
281 Performing status on external item at 'externals'* (glob)
284
282
285 Sticky subrepositories, no changes
283 Sticky subrepositories, no changes
286 $ cd $TESTTMP/sub/t
284 $ cd $TESTTMP/sub/t
287 $ hg id -n
285 $ hg id -n
288 2
286 2
289 $ cd s
287 $ cd s
290 $ svnversion
288 $ svnversion
291 3
289 3
292 $ cd ..
290 $ cd ..
293 $ hg update 1
291 $ hg update 1
294 U *s/alpha (glob)
292 U *s/alpha (glob)
295
293
296 Fetching external item into '*s/externals'* (glob)
294 Fetching external item into '*s/externals'* (glob)
297 Checked out external at revision 1.
295 Checked out external at revision 1.
298
296
299 Checked out revision 2.
297 Checked out revision 2.
300 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
298 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
301 $ hg id -n
299 $ hg id -n
302 1
300 1
303 $ cd s
301 $ cd s
304 $ svnversion
302 $ svnversion
305 2
303 2
306 $ cd ..
304 $ cd ..
307
305
308 Sticky subrepositorys, file changes
306 Sticky subrepositorys, file changes
309 $ touch s/f1
307 $ touch s/f1
310 $ cd s
308 $ cd s
311 $ svn add f1
309 $ svn add f1
312 A f1
310 A f1
313 $ cd ..
311 $ cd ..
314 $ hg id -n
312 $ hg id -n
315 1
313 1
316 $ cd s
314 $ cd s
317 $ svnversion
315 $ svnversion
318 2M
316 2M
319 $ cd ..
317 $ cd ..
320 $ hg update tip
318 $ hg update tip
321 subrepository sources for s differ
319 subrepository sources for s differ
322 use (l)ocal source (2) or (r)emote source (3)?
320 use (l)ocal source (2) or (r)emote source (3)?
323 l
321 l
324 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
322 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
325 $ hg id -n
323 $ hg id -n
326 2+
324 2+
327 $ cd s
325 $ cd s
328 $ svnversion
326 $ svnversion
329 2M
327 2M
330 $ cd ..
328 $ cd ..
331 $ hg update --clean tip
329 $ hg update --clean tip
332 U *s/alpha (glob)
330 U *s/alpha (glob)
333
331
334 Fetching external item into '*s/externals'* (glob)
332 Fetching external item into '*s/externals'* (glob)
335 Checked out external at revision 1.
333 Checked out external at revision 1.
336
334
337 Checked out revision 3.
335 Checked out revision 3.
338 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
336 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
339
337
340 Sticky subrepository, revision updates
338 Sticky subrepository, revision updates
341 $ hg id -n
339 $ hg id -n
342 2
340 2
343 $ cd s
341 $ cd s
344 $ svnversion
342 $ svnversion
345 3
343 3
346 $ cd ..
344 $ cd ..
347 $ cd s
345 $ cd s
348 $ svn update -qr 1
346 $ svn update -qr 1
349 $ cd ..
347 $ cd ..
350 $ hg update 1
348 $ hg update 1
351 subrepository sources for s differ (in checked out version)
349 subrepository sources for s differ (in checked out version)
352 use (l)ocal source (1) or (r)emote source (2)?
350 use (l)ocal source (1) or (r)emote source (2)?
353 l
351 l
354 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
352 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
355 $ hg id -n
353 $ hg id -n
356 1+
354 1+
357 $ cd s
355 $ cd s
358 $ svnversion
356 $ svnversion
359 1
357 1
360 $ cd ..
358 $ cd ..
361
359
362 Sticky subrepository, file changes and revision updates
360 Sticky subrepository, file changes and revision updates
363 $ touch s/f1
361 $ touch s/f1
364 $ cd s
362 $ cd s
365 $ svn add f1
363 $ svn add f1
366 A f1
364 A f1
367 $ svnversion
365 $ svnversion
368 1M
366 1M
369 $ cd ..
367 $ cd ..
370 $ hg id -n
368 $ hg id -n
371 1+
369 1+
372 $ hg update tip
370 $ hg update tip
373 subrepository sources for s differ
371 subrepository sources for s differ
374 use (l)ocal source (1) or (r)emote source (3)?
372 use (l)ocal source (1) or (r)emote source (3)?
375 l
373 l
376 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
374 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 $ hg id -n
375 $ hg id -n
378 2
376 2
379 $ cd s
377 $ cd s
380 $ svnversion
378 $ svnversion
381 1M
379 1M
382 $ cd ..
380 $ cd ..
383
381
384 Sticky repository, update --clean
382 Sticky repository, update --clean
385 $ hg update --clean tip | grep -v s/externals/other
383 $ hg update --clean tip | grep -v s/externals/other
386 U *s/alpha (glob)
384 U *s/alpha (glob)
387 U *s (glob)
385 U *s (glob)
388
386
389 Fetching external item into '*s/externals'* (glob)
387 Fetching external item into '*s/externals'* (glob)
390 Checked out external at revision 1.
388 Checked out external at revision 1.
391
389
392 Checked out revision 3.
390 Checked out revision 3.
393 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
391 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
394 $ hg id -n
392 $ hg id -n
395 2
393 2
396 $ cd s
394 $ cd s
397 $ svnversion
395 $ svnversion
398 3
396 3
399 $ cd ..
397 $ cd ..
400
398
401 Test subrepo already at intended revision:
399 Test subrepo already at intended revision:
402 $ cd s
400 $ cd s
403 $ svn update -qr 2
401 $ svn update -qr 2
404 $ cd ..
402 $ cd ..
405 $ hg update 1
403 $ hg update 1
406 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
404 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
407 $ hg id -n
405 $ hg id -n
408 1+
406 1+
409 $ cd s
407 $ cd s
410 $ svnversion
408 $ svnversion
411 2
409 2
412 $ cd ..
410 $ cd ..
413
411
414 Test case where subversion would fail to update the subrepo because there
412 Test case where subversion would fail to update the subrepo because there
415 are unknown directories being replaced by tracked ones (happens with rebase).
413 are unknown directories being replaced by tracked ones (happens with rebase).
416
414
417 $ cd $WCROOT/src
415 $ cd $WCROOT/src
418 $ mkdir dir
416 $ mkdir dir
419 $ echo epsilon.py > dir/epsilon.py
417 $ echo epsilon.py > dir/epsilon.py
420 $ svn add dir
418 $ svn add dir
421 A dir
419 A dir
422 A dir/epsilon.py
420 A dir/epsilon.py
423 $ svn ci -m 'Add dir/epsilon.py'
421 $ svn ci -m 'Add dir/epsilon.py'
424 Adding *dir (glob)
422 Adding *dir (glob)
425 Adding *dir/epsilon.py (glob)
423 Adding *dir/epsilon.py (glob)
426 Transmitting file data .
424 Transmitting file data .
427 Committed revision 6.
425 Committed revision 6.
428 $ cd ../..
426 $ cd ../..
429 $ hg init rebaserepo
427 $ hg init rebaserepo
430 $ cd rebaserepo
428 $ cd rebaserepo
431 $ svn co -r5 --quiet "$SVNREPO"/src s
429 $ svn co -r5 --quiet "$SVNREPO"/src s
432 $ echo "s = [svn] $SVNREPO/src" >> .hgsub
430 $ echo "s = [svn] $SVNREPO/src" >> .hgsub
433 $ hg add .hgsub
431 $ hg add .hgsub
434 $ hg ci -m addsub
432 $ hg ci -m addsub
435 committing subrepository s
436 $ echo a > a
433 $ echo a > a
437 $ hg ci -Am adda
434 $ hg ci -Am adda
438 adding a
435 adding a
439 $ hg up 0
436 $ hg up 0
440 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
437 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
441 $ svn up -qr6 s
438 $ svn up -qr6 s
442 $ hg ci -m updatesub
439 $ hg ci -m updatesub
443 committing subrepository s
444 created new head
440 created new head
445 $ echo pyc > s/dir/epsilon.pyc
441 $ echo pyc > s/dir/epsilon.pyc
446 $ hg up 1
442 $ hg up 1
447 D *s/dir (glob)
443 D *s/dir (glob)
448
444
449 Fetching external item into '*s/externals'* (glob)
445 Fetching external item into '*s/externals'* (glob)
450 Checked out external at revision 1.
446 Checked out external at revision 1.
451
447
452 Checked out revision 5.
448 Checked out revision 5.
453 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
449 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
454 $ if "$TESTDIR/hghave" -q svn15; then
450 $ if "$TESTDIR/hghave" -q svn15; then
455 > hg up 2 >/dev/null 2>&1 || echo update failed
451 > hg up 2 >/dev/null 2>&1 || echo update failed
456 > fi
452 > fi
457
453
458 Modify one of the externals to point to a different path so we can
454 Modify one of the externals to point to a different path so we can
459 test having obstructions when switching branches on checkout:
455 test having obstructions when switching branches on checkout:
460 $ hg checkout tip
456 $ hg checkout tip
461 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
457 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 $ echo "obstruct = [svn] $SVNREPO/externals" >> .hgsub
458 $ echo "obstruct = [svn] $SVNREPO/externals" >> .hgsub
463 $ svn co -r5 --quiet "$SVNREPO"/externals obstruct
459 $ svn co -r5 --quiet "$SVNREPO"/externals obstruct
464 $ hg commit -m 'Start making obstructed working copy'
460 $ hg commit -m 'Start making obstructed working copy'
465 committing subrepository obstruct
466 $ hg book other
461 $ hg book other
467 $ hg co -r 'p1(tip)'
462 $ hg co -r 'p1(tip)'
468 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
463 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
469 $ echo "obstruct = [svn] $SVNREPO/src" >> .hgsub
464 $ echo "obstruct = [svn] $SVNREPO/src" >> .hgsub
470 $ svn co -r5 --quiet "$SVNREPO"/src obstruct
465 $ svn co -r5 --quiet "$SVNREPO"/src obstruct
471 $ hg commit -m 'Other branch which will be obstructed'
466 $ hg commit -m 'Other branch which will be obstructed'
472 committing subrepository obstruct
473 created new head
467 created new head
474
468
475 Switching back to the head where we have another path mapped to the
469 Switching back to the head where we have another path mapped to the
476 same subrepo should work if the subrepo is clean.
470 same subrepo should work if the subrepo is clean.
477 $ hg co other
471 $ hg co other
478 A *obstruct/other (glob)
472 A *obstruct/other (glob)
479 Checked out revision 1.
473 Checked out revision 1.
480 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
474 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
481
475
482 This is surprising, but is also correct based on the current code:
476 This is surprising, but is also correct based on the current code:
483 $ echo "updating should (maybe) fail" > obstruct/other
477 $ echo "updating should (maybe) fail" > obstruct/other
484 $ hg co tip
478 $ hg co tip
485 abort: crosses branches (merge branches or use --clean to discard changes)
479 abort: crosses branches (merge branches or use --clean to discard changes)
486 [255]
480 [255]
487
481
488 Point to a Subversion branch which has since been deleted and recreated
482 Point to a Subversion branch which has since been deleted and recreated
489 First, create that condition in the repository.
483 First, create that condition in the repository.
490
484
491 $ hg ci --subrepos -m cleanup | grep -v Updating
485 $ hg ci --subrepos -m cleanup | grep -v Updating
492 committing subrepository obstruct
486 committing subrepository obstruct
493 Sending obstruct/other
487 Sending obstruct/other
494 Transmitting file data .
488 Transmitting file data .
495 Committed revision 7.
489 Committed revision 7.
496 At revision 7.
490 At revision 7.
497 $ svn mkdir -m "baseline" $SVNREPO/trunk
491 $ svn mkdir -m "baseline" $SVNREPO/trunk
498
492
499 Committed revision 8.
493 Committed revision 8.
500 $ svn copy -m "initial branch" $SVNREPO/trunk $SVNREPO/branch
494 $ svn copy -m "initial branch" $SVNREPO/trunk $SVNREPO/branch
501
495
502 Committed revision 9.
496 Committed revision 9.
503 $ svn co --quiet "$SVNREPO"/branch tempwc
497 $ svn co --quiet "$SVNREPO"/branch tempwc
504 $ cd tempwc
498 $ cd tempwc
505 $ echo "something old" > somethingold
499 $ echo "something old" > somethingold
506 $ svn add somethingold
500 $ svn add somethingold
507 A somethingold
501 A somethingold
508 $ svn ci -m 'Something old'
502 $ svn ci -m 'Something old'
509 Adding somethingold
503 Adding somethingold
510 Transmitting file data .
504 Transmitting file data .
511 Committed revision 10.
505 Committed revision 10.
512 $ svn rm -m "remove branch" $SVNREPO/branch
506 $ svn rm -m "remove branch" $SVNREPO/branch
513
507
514 Committed revision 11.
508 Committed revision 11.
515 $ svn copy -m "recreate branch" $SVNREPO/trunk $SVNREPO/branch
509 $ svn copy -m "recreate branch" $SVNREPO/trunk $SVNREPO/branch
516
510
517 Committed revision 12.
511 Committed revision 12.
518 $ svn up -q
512 $ svn up -q
519 $ echo "something new" > somethingnew
513 $ echo "something new" > somethingnew
520 $ svn add somethingnew
514 $ svn add somethingnew
521 A somethingnew
515 A somethingnew
522 $ svn ci -m 'Something new'
516 $ svn ci -m 'Something new'
523 Adding somethingnew
517 Adding somethingnew
524 Transmitting file data .
518 Transmitting file data .
525 Committed revision 13.
519 Committed revision 13.
526 $ cd ..
520 $ cd ..
527 $ rm -rf tempwc
521 $ rm -rf tempwc
528 $ svn co "$SVNREPO/branch"@10 recreated
522 $ svn co "$SVNREPO/branch"@10 recreated
529 A recreated/somethingold
523 A recreated/somethingold
530 Checked out revision 10.
524 Checked out revision 10.
531 $ echo "recreated = [svn] $SVNREPO/branch" >> .hgsub
525 $ echo "recreated = [svn] $SVNREPO/branch" >> .hgsub
532 $ hg ci -m addsub
526 $ hg ci -m addsub
533 committing subrepository recreated
534 $ cd recreated
527 $ cd recreated
535 $ svn up -q
528 $ svn up -q
536 $ cd ..
529 $ cd ..
537 $ hg ci -m updatesub
530 $ hg ci -m updatesub
538 committing subrepository recreated
539 $ hg up -r-2
531 $ hg up -r-2
540 D *recreated/somethingnew (glob)
532 D *recreated/somethingnew (glob)
541 A *recreated/somethingold (glob)
533 A *recreated/somethingold (glob)
542 Checked out revision 10.
534 Checked out revision 10.
543 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
535 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
544 $ test -f recreated/somethingold
536 $ test -f recreated/somethingold
545
537
@@ -1,1037 +1,1018 b''
1 Let commit recurse into subrepos by default to match pre-2.0 behavior:
1 Let commit recurse into subrepos by default to match pre-2.0 behavior:
2
2
3 $ echo "[ui]" >> $HGRCPATH
3 $ echo "[ui]" >> $HGRCPATH
4 $ echo "commitsubrepos = Yes" >> $HGRCPATH
4 $ echo "commitsubrepos = Yes" >> $HGRCPATH
5
5
6 $ rm -rf sub
6 $ rm -rf sub
7 $ mkdir sub
7 $ mkdir sub
8 $ cd sub
8 $ cd sub
9 $ hg init t
9 $ hg init t
10 $ cd t
10 $ cd t
11
11
12 first revision, no sub
12 first revision, no sub
13
13
14 $ echo a > a
14 $ echo a > a
15 $ hg ci -Am0
15 $ hg ci -Am0
16 adding a
16 adding a
17
17
18 add first sub
18 add first sub
19
19
20 $ echo s = s > .hgsub
20 $ echo s = s > .hgsub
21 $ hg add .hgsub
21 $ hg add .hgsub
22 $ hg init s
22 $ hg init s
23 $ echo a > s/a
23 $ echo a > s/a
24
24
25 Issue2232: committing a subrepo without .hgsub
25 Issue2232: committing a subrepo without .hgsub
26
26
27 $ hg ci -mbad s
27 $ hg ci -mbad s
28 abort: can't commit subrepos without .hgsub
28 abort: can't commit subrepos without .hgsub
29 [255]
29 [255]
30
30
31 $ hg -R s ci -Ams0
31 $ hg -R s ci -Ams0
32 adding a
32 adding a
33 $ hg sum
33 $ hg sum
34 parent: 0:f7b1eb17ad24 tip
34 parent: 0:f7b1eb17ad24 tip
35 0
35 0
36 branch: default
36 branch: default
37 commit: 1 added, 1 subrepos
37 commit: 1 added, 1 subrepos
38 update: (current)
38 update: (current)
39 $ hg ci -m1
39 $ hg ci -m1
40 committing subrepository s
41
40
42 Revert can't (yet) revert subrepos:
41 Revert can't (yet) revert subrepos:
43
42
44 $ echo b > s/a
43 $ echo b > s/a
45 $ hg revert s
44 $ hg revert s
46 s: reverting subrepos is unsupported
45 s: reverting subrepos is unsupported
47
46
48 Revert currently ignores subrepos by default
47 Revert currently ignores subrepos by default
49
48
50 $ hg revert -a
49 $ hg revert -a
51 $ hg revert -R s -a -C
50 $ hg revert -R s -a -C
52 reverting s/a (glob)
51 reverting s/a (glob)
53
52
54 Issue2022: update -C
53 Issue2022: update -C
55
54
56 $ echo b > s/a
55 $ echo b > s/a
57 $ hg sum
56 $ hg sum
58 parent: 1:7cf8cfea66e4 tip
57 parent: 1:7cf8cfea66e4 tip
59 1
58 1
60 branch: default
59 branch: default
61 commit: 1 subrepos
60 commit: 1 subrepos
62 update: (current)
61 update: (current)
63 $ hg co -C 1
62 $ hg co -C 1
64 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
65 $ hg sum
64 $ hg sum
66 parent: 1:7cf8cfea66e4 tip
65 parent: 1:7cf8cfea66e4 tip
67 1
66 1
68 branch: default
67 branch: default
69 commit: (clean)
68 commit: (clean)
70 update: (current)
69 update: (current)
71
70
72 commands that require a clean repo should respect subrepos
71 commands that require a clean repo should respect subrepos
73
72
74 $ echo b >> s/a
73 $ echo b >> s/a
75 $ hg backout tip
74 $ hg backout tip
76 abort: uncommitted changes in subrepo s
75 abort: uncommitted changes in subrepo s
77 [255]
76 [255]
78 $ hg revert -C -R s s/a
77 $ hg revert -C -R s s/a
79
78
80 add sub sub
79 add sub sub
81
80
82 $ echo ss = ss > s/.hgsub
81 $ echo ss = ss > s/.hgsub
83 $ hg init s/ss
82 $ hg init s/ss
84 $ echo a > s/ss/a
83 $ echo a > s/ss/a
85 $ hg -R s add s/.hgsub
84 $ hg -R s add s/.hgsub
86 $ hg -R s/ss add s/ss/a
85 $ hg -R s/ss add s/ss/a
87 $ hg sum
86 $ hg sum
88 parent: 1:7cf8cfea66e4 tip
87 parent: 1:7cf8cfea66e4 tip
89 1
88 1
90 branch: default
89 branch: default
91 commit: 1 subrepos
90 commit: 1 subrepos
92 update: (current)
91 update: (current)
93 $ hg ci -m2
92 $ hg ci -m2
94 committing subrepository s
93 committing subrepository s
95 committing subrepository s/ss (glob)
94 committing subrepository s/ss (glob)
96 $ hg sum
95 $ hg sum
97 parent: 2:df30734270ae tip
96 parent: 2:df30734270ae tip
98 2
97 2
99 branch: default
98 branch: default
100 commit: (clean)
99 commit: (clean)
101 update: (current)
100 update: (current)
102
101
103 bump sub rev (and check it is ignored by ui.commitsubrepos)
102 bump sub rev (and check it is ignored by ui.commitsubrepos)
104
103
105 $ echo b > s/a
104 $ echo b > s/a
106 $ hg -R s ci -ms1
105 $ hg -R s ci -ms1
107 $ hg --config ui.commitsubrepos=no ci -m3
106 $ hg --config ui.commitsubrepos=no ci -m3
108 committing subrepository s
109
107
110 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
108 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
111
109
112 $ echo c > s/a
110 $ echo c > s/a
113 $ hg --config ui.commitsubrepos=no ci -m4
111 $ hg --config ui.commitsubrepos=no ci -m4
114 abort: uncommitted changes in subrepo s
112 abort: uncommitted changes in subrepo s
115 (use --subrepos for recursive commit)
113 (use --subrepos for recursive commit)
116 [255]
114 [255]
117 $ hg ci -m4
115 $ hg ci -m4
118 committing subrepository s
116 committing subrepository s
119 $ hg tip -R s
117 $ hg tip -R s
120 changeset: 3:1c833a7a9e3a
118 changeset: 3:1c833a7a9e3a
121 tag: tip
119 tag: tip
122 user: test
120 user: test
123 date: Thu Jan 01 00:00:00 1970 +0000
121 date: Thu Jan 01 00:00:00 1970 +0000
124 summary: 4
122 summary: 4
125
123
126
124
127 check caching
125 check caching
128
126
129 $ hg co 0
127 $ hg co 0
130 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
128 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
131 $ hg debugsub
129 $ hg debugsub
132
130
133 restore
131 restore
134
132
135 $ hg co
133 $ hg co
136 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
134 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
137 $ hg debugsub
135 $ hg debugsub
138 path s
136 path s
139 source s
137 source s
140 revision 1c833a7a9e3a4445c711aaf0f012379cd0d4034e
138 revision 1c833a7a9e3a4445c711aaf0f012379cd0d4034e
141
139
142 new branch for merge tests
140 new branch for merge tests
143
141
144 $ hg co 1
142 $ hg co 1
145 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
143 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
146 $ echo t = t >> .hgsub
144 $ echo t = t >> .hgsub
147 $ hg init t
145 $ hg init t
148 $ echo t > t/t
146 $ echo t > t/t
149 $ hg -R t add t
147 $ hg -R t add t
150 adding t/t (glob)
148 adding t/t (glob)
151
149
152 5
150 5
153
151
154 $ hg ci -m5 # add sub
152 $ hg ci -m5 # add sub
155 committing subrepository t
153 committing subrepository t
156 created new head
154 created new head
157 $ echo t2 > t/t
155 $ echo t2 > t/t
158
156
159 6
157 6
160
158
161 $ hg st -R s
159 $ hg st -R s
162 $ hg ci -m6 # change sub
160 $ hg ci -m6 # change sub
163 committing subrepository t
161 committing subrepository t
164 $ hg debugsub
162 $ hg debugsub
165 path s
163 path s
166 source s
164 source s
167 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
165 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
168 path t
166 path t
169 source t
167 source t
170 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
168 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
171 $ echo t3 > t/t
169 $ echo t3 > t/t
172
170
173 7
171 7
174
172
175 $ hg ci -m7 # change sub again for conflict test
173 $ hg ci -m7 # change sub again for conflict test
176 committing subrepository t
174 committing subrepository t
177 $ hg rm .hgsub
175 $ hg rm .hgsub
178
176
179 8
177 8
180
178
181 $ hg ci -m8 # remove sub
179 $ hg ci -m8 # remove sub
182
180
183 merge tests
181 merge tests
184
182
185 $ hg co -C 3
183 $ hg co -C 3
186 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
184 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
187 $ hg merge 5 # test adding
185 $ hg merge 5 # test adding
188 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
186 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 (branch merge, don't forget to commit)
187 (branch merge, don't forget to commit)
190 $ hg debugsub
188 $ hg debugsub
191 path s
189 path s
192 source s
190 source s
193 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
191 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
194 path t
192 path t
195 source t
193 source t
196 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
194 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
197 $ hg ci -m9
195 $ hg ci -m9
198 created new head
196 created new head
199 $ hg merge 6 --debug # test change
197 $ hg merge 6 --debug # test change
200 searching for copies back to rev 2
198 searching for copies back to rev 2
201 resolving manifests
199 resolving manifests
202 overwrite: False, partial: False
200 overwrite: False, partial: False
203 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
201 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
204 .hgsubstate: versions differ -> m
202 .hgsubstate: versions differ -> m
205 updating: .hgsubstate 1/1 files (100.00%)
203 updating: .hgsubstate 1/1 files (100.00%)
206 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
204 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
207 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
205 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
208 getting subrepo t
206 getting subrepo t
209 resolving manifests
207 resolving manifests
210 overwrite: True, partial: False
208 overwrite: True, partial: False
211 ancestor: 60ca1237c194+, local: 60ca1237c194+, remote: 6747d179aa9a
209 ancestor: 60ca1237c194+, local: 60ca1237c194+, remote: 6747d179aa9a
212 t: remote is newer -> g
210 t: remote is newer -> g
213 updating: t 1/1 files (100.00%)
211 updating: t 1/1 files (100.00%)
214 getting t
212 getting t
215 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
216 (branch merge, don't forget to commit)
214 (branch merge, don't forget to commit)
217 $ hg debugsub
215 $ hg debugsub
218 path s
216 path s
219 source s
217 source s
220 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
218 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
221 path t
219 path t
222 source t
220 source t
223 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
221 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
224 $ echo conflict > t/t
222 $ echo conflict > t/t
225 $ hg ci -m10
223 $ hg ci -m10
226 committing subrepository t
224 committing subrepository t
227 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
225 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
228 searching for copies back to rev 2
226 searching for copies back to rev 2
229 resolving manifests
227 resolving manifests
230 overwrite: False, partial: False
228 overwrite: False, partial: False
231 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
229 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
232 .hgsubstate: versions differ -> m
230 .hgsubstate: versions differ -> m
233 updating: .hgsubstate 1/1 files (100.00%)
231 updating: .hgsubstate 1/1 files (100.00%)
234 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
232 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
235 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
233 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
236 merging subrepo t
234 merging subrepo t
237 searching for copies back to rev 2
235 searching for copies back to rev 2
238 resolving manifests
236 resolving manifests
239 overwrite: False, partial: False
237 overwrite: False, partial: False
240 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
238 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
241 t: versions differ -> m
239 t: versions differ -> m
242 preserving t for resolve of t
240 preserving t for resolve of t
243 updating: t 1/1 files (100.00%)
241 updating: t 1/1 files (100.00%)
244 picked tool 'internal:merge' for t (binary False symlink False)
242 picked tool 'internal:merge' for t (binary False symlink False)
245 merging t
243 merging t
246 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
244 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
247 warning: conflicts during merge.
245 warning: conflicts during merge.
248 merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
246 merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
249 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
247 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
250 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
248 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
251 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
249 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
252 (branch merge, don't forget to commit)
250 (branch merge, don't forget to commit)
253
251
254 should conflict
252 should conflict
255
253
256 $ cat t/t
254 $ cat t/t
257 <<<<<<< local
255 <<<<<<< local
258 conflict
256 conflict
259 =======
257 =======
260 t3
258 t3
261 >>>>>>> other
259 >>>>>>> other
262
260
263 clone
261 clone
264
262
265 $ cd ..
263 $ cd ..
266 $ hg clone t tc
264 $ hg clone t tc
267 updating to branch default
265 updating to branch default
268 cloning subrepo s from $TESTTMP/sub/t/s (glob)
266 cloning subrepo s from $TESTTMP/sub/t/s (glob)
269 cloning subrepo s/ss from $TESTTMP/sub/t/s/ss (glob)
267 cloning subrepo s/ss from $TESTTMP/sub/t/s/ss (glob)
270 cloning subrepo t from $TESTTMP/sub/t/t (glob)
268 cloning subrepo t from $TESTTMP/sub/t/t (glob)
271 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
269 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
272 $ cd tc
270 $ cd tc
273 $ hg debugsub
271 $ hg debugsub
274 path s
272 path s
275 source s
273 source s
276 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
274 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
277 path t
275 path t
278 source t
276 source t
279 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
277 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
280
278
281 push
279 push
282
280
283 $ echo bah > t/t
281 $ echo bah > t/t
284 $ hg ci -m11
282 $ hg ci -m11
285 committing subrepository t
283 committing subrepository t
286 $ hg push
284 $ hg push
287 pushing to $TESTTMP/sub/t (glob)
285 pushing to $TESTTMP/sub/t (glob)
288 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss (glob)
286 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss (glob)
289 searching for changes
287 searching for changes
290 no changes found
288 no changes found
291 pushing subrepo s to $TESTTMP/sub/t/s (glob)
289 pushing subrepo s to $TESTTMP/sub/t/s (glob)
292 searching for changes
290 searching for changes
293 no changes found
291 no changes found
294 pushing subrepo t to $TESTTMP/sub/t/t (glob)
292 pushing subrepo t to $TESTTMP/sub/t/t (glob)
295 searching for changes
293 searching for changes
296 adding changesets
294 adding changesets
297 adding manifests
295 adding manifests
298 adding file changes
296 adding file changes
299 added 1 changesets with 1 changes to 1 files
297 added 1 changesets with 1 changes to 1 files
300 searching for changes
298 searching for changes
301 adding changesets
299 adding changesets
302 adding manifests
300 adding manifests
303 adding file changes
301 adding file changes
304 added 1 changesets with 1 changes to 1 files
302 added 1 changesets with 1 changes to 1 files
305
303
306 push -f
304 push -f
307
305
308 $ echo bah > s/a
306 $ echo bah > s/a
309 $ hg ci -m12
307 $ hg ci -m12
310 committing subrepository s
308 committing subrepository s
311 $ hg push
309 $ hg push
312 pushing to $TESTTMP/sub/t (glob)
310 pushing to $TESTTMP/sub/t (glob)
313 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss (glob)
311 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss (glob)
314 searching for changes
312 searching for changes
315 no changes found
313 no changes found
316 pushing subrepo s to $TESTTMP/sub/t/s (glob)
314 pushing subrepo s to $TESTTMP/sub/t/s (glob)
317 searching for changes
315 searching for changes
318 abort: push creates new remote head 12a213df6fa9!
316 abort: push creates new remote head 12a213df6fa9!
319 (did you forget to merge? use push -f to force)
317 (did you forget to merge? use push -f to force)
320 [255]
318 [255]
321 $ hg push -f
319 $ hg push -f
322 pushing to $TESTTMP/sub/t (glob)
320 pushing to $TESTTMP/sub/t (glob)
323 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss (glob)
321 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss (glob)
324 searching for changes
322 searching for changes
325 no changes found
323 no changes found
326 pushing subrepo s to $TESTTMP/sub/t/s (glob)
324 pushing subrepo s to $TESTTMP/sub/t/s (glob)
327 searching for changes
325 searching for changes
328 adding changesets
326 adding changesets
329 adding manifests
327 adding manifests
330 adding file changes
328 adding file changes
331 added 1 changesets with 1 changes to 1 files (+1 heads)
329 added 1 changesets with 1 changes to 1 files (+1 heads)
332 pushing subrepo t to $TESTTMP/sub/t/t (glob)
330 pushing subrepo t to $TESTTMP/sub/t/t (glob)
333 searching for changes
331 searching for changes
334 no changes found
332 no changes found
335 searching for changes
333 searching for changes
336 adding changesets
334 adding changesets
337 adding manifests
335 adding manifests
338 adding file changes
336 adding file changes
339 added 1 changesets with 1 changes to 1 files
337 added 1 changesets with 1 changes to 1 files
340
338
341 update
339 update
342
340
343 $ cd ../t
341 $ cd ../t
344 $ hg up -C # discard our earlier merge
342 $ hg up -C # discard our earlier merge
345 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
343 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
346 $ echo blah > t/t
344 $ echo blah > t/t
347 $ hg ci -m13
345 $ hg ci -m13
348 committing subrepository t
346 committing subrepository t
349
347
350 pull
348 pull
351
349
352 $ cd ../tc
350 $ cd ../tc
353 $ hg pull
351 $ hg pull
354 pulling from $TESTTMP/sub/t (glob)
352 pulling from $TESTTMP/sub/t (glob)
355 searching for changes
353 searching for changes
356 adding changesets
354 adding changesets
357 adding manifests
355 adding manifests
358 adding file changes
356 adding file changes
359 added 1 changesets with 1 changes to 1 files
357 added 1 changesets with 1 changes to 1 files
360 (run 'hg update' to get a working copy)
358 (run 'hg update' to get a working copy)
361
359
362 should pull t
360 should pull t
363
361
364 $ hg up
362 $ hg up
365 pulling subrepo t from $TESTTMP/sub/t/t (glob)
363 pulling subrepo t from $TESTTMP/sub/t/t (glob)
366 searching for changes
364 searching for changes
367 adding changesets
365 adding changesets
368 adding manifests
366 adding manifests
369 adding file changes
367 adding file changes
370 added 1 changesets with 1 changes to 1 files
368 added 1 changesets with 1 changes to 1 files
371 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
369 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
372 $ cat t/t
370 $ cat t/t
373 blah
371 blah
374
372
375 bogus subrepo path aborts
373 bogus subrepo path aborts
376
374
377 $ echo 'bogus=[boguspath' >> .hgsub
375 $ echo 'bogus=[boguspath' >> .hgsub
378 $ hg ci -m 'bogus subrepo path'
376 $ hg ci -m 'bogus subrepo path'
379 abort: missing ] in subrepo source
377 abort: missing ] in subrepo source
380 [255]
378 [255]
381
379
382 Issue1986: merge aborts when trying to merge a subrepo that
380 Issue1986: merge aborts when trying to merge a subrepo that
383 shouldn't need merging
381 shouldn't need merging
384
382
385 # subrepo layout
383 # subrepo layout
386 #
384 #
387 # o 5 br
385 # o 5 br
388 # /|
386 # /|
389 # o | 4 default
387 # o | 4 default
390 # | |
388 # | |
391 # | o 3 br
389 # | o 3 br
392 # |/|
390 # |/|
393 # o | 2 default
391 # o | 2 default
394 # | |
392 # | |
395 # | o 1 br
393 # | o 1 br
396 # |/
394 # |/
397 # o 0 default
395 # o 0 default
398
396
399 $ cd ..
397 $ cd ..
400 $ rm -rf sub
398 $ rm -rf sub
401 $ hg init main
399 $ hg init main
402 $ cd main
400 $ cd main
403 $ hg init s
401 $ hg init s
404 $ cd s
402 $ cd s
405 $ echo a > a
403 $ echo a > a
406 $ hg ci -Am1
404 $ hg ci -Am1
407 adding a
405 adding a
408 $ hg branch br
406 $ hg branch br
409 marked working directory as branch br
407 marked working directory as branch br
410 (branches are permanent and global, did you want a bookmark?)
408 (branches are permanent and global, did you want a bookmark?)
411 $ echo a >> a
409 $ echo a >> a
412 $ hg ci -m1
410 $ hg ci -m1
413 $ hg up default
411 $ hg up default
414 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
412 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
415 $ echo b > b
413 $ echo b > b
416 $ hg ci -Am1
414 $ hg ci -Am1
417 adding b
415 adding b
418 $ hg up br
416 $ hg up br
419 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
417 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
420 $ hg merge tip
418 $ hg merge tip
421 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
419 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
422 (branch merge, don't forget to commit)
420 (branch merge, don't forget to commit)
423 $ hg ci -m1
421 $ hg ci -m1
424 $ hg up 2
422 $ hg up 2
425 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
423 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 $ echo c > c
424 $ echo c > c
427 $ hg ci -Am1
425 $ hg ci -Am1
428 adding c
426 adding c
429 $ hg up 3
427 $ hg up 3
430 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
428 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
431 $ hg merge 4
429 $ hg merge 4
432 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
430 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
433 (branch merge, don't forget to commit)
431 (branch merge, don't forget to commit)
434 $ hg ci -m1
432 $ hg ci -m1
435
433
436 # main repo layout:
434 # main repo layout:
437 #
435 #
438 # * <-- try to merge default into br again
436 # * <-- try to merge default into br again
439 # .`|
437 # .`|
440 # . o 5 br --> substate = 5
438 # . o 5 br --> substate = 5
441 # . |
439 # . |
442 # o | 4 default --> substate = 4
440 # o | 4 default --> substate = 4
443 # | |
441 # | |
444 # | o 3 br --> substate = 2
442 # | o 3 br --> substate = 2
445 # |/|
443 # |/|
446 # o | 2 default --> substate = 2
444 # o | 2 default --> substate = 2
447 # | |
445 # | |
448 # | o 1 br --> substate = 3
446 # | o 1 br --> substate = 3
449 # |/
447 # |/
450 # o 0 default --> substate = 2
448 # o 0 default --> substate = 2
451
449
452 $ cd ..
450 $ cd ..
453 $ echo 's = s' > .hgsub
451 $ echo 's = s' > .hgsub
454 $ hg -R s up 2
452 $ hg -R s up 2
455 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
453 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
456 $ hg ci -Am1
454 $ hg ci -Am1
457 adding .hgsub
455 adding .hgsub
458 committing subrepository s
459 $ hg branch br
456 $ hg branch br
460 marked working directory as branch br
457 marked working directory as branch br
461 (branches are permanent and global, did you want a bookmark?)
458 (branches are permanent and global, did you want a bookmark?)
462 $ echo b > b
459 $ echo b > b
463 $ hg -R s up 3
460 $ hg -R s up 3
464 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
465 $ hg ci -Am1
462 $ hg ci -Am1
466 adding b
463 adding b
467 committing subrepository s
468 $ hg up default
464 $ hg up default
469 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
465 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
470 $ echo c > c
466 $ echo c > c
471 $ hg ci -Am1
467 $ hg ci -Am1
472 adding c
468 adding c
473 $ hg up 1
469 $ hg up 1
474 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
470 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
475 $ hg merge 2
471 $ hg merge 2
476 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
472 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
477 (branch merge, don't forget to commit)
473 (branch merge, don't forget to commit)
478 $ hg ci -m1
474 $ hg ci -m1
479 $ hg up 2
475 $ hg up 2
480 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
476 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
481 $ hg -R s up 4
477 $ hg -R s up 4
482 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
478 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
483 $ echo d > d
479 $ echo d > d
484 $ hg ci -Am1
480 $ hg ci -Am1
485 adding d
481 adding d
486 committing subrepository s
487 $ hg up 3
482 $ hg up 3
488 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
483 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
489 $ hg -R s up 5
484 $ hg -R s up 5
490 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
485 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
491 $ echo e > e
486 $ echo e > e
492 $ hg ci -Am1
487 $ hg ci -Am1
493 adding e
488 adding e
494 committing subrepository s
495
489
496 $ hg up 5
490 $ hg up 5
497 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
491 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
498 $ hg merge 4 # try to merge default into br again
492 $ hg merge 4 # try to merge default into br again
499 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
493 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
500 (branch merge, don't forget to commit)
494 (branch merge, don't forget to commit)
501 $ cd ..
495 $ cd ..
502
496
503 test subrepo delete from .hgsubstate
497 test subrepo delete from .hgsubstate
504
498
505 $ hg init testdelete
499 $ hg init testdelete
506 $ mkdir testdelete/nested testdelete/nested2
500 $ mkdir testdelete/nested testdelete/nested2
507 $ hg init testdelete/nested
501 $ hg init testdelete/nested
508 $ hg init testdelete/nested2
502 $ hg init testdelete/nested2
509 $ echo test > testdelete/nested/foo
503 $ echo test > testdelete/nested/foo
510 $ echo test > testdelete/nested2/foo
504 $ echo test > testdelete/nested2/foo
511 $ hg -R testdelete/nested add
505 $ hg -R testdelete/nested add
512 adding testdelete/nested/foo (glob)
506 adding testdelete/nested/foo (glob)
513 $ hg -R testdelete/nested2 add
507 $ hg -R testdelete/nested2 add
514 adding testdelete/nested2/foo (glob)
508 adding testdelete/nested2/foo (glob)
515 $ hg -R testdelete/nested ci -m test
509 $ hg -R testdelete/nested ci -m test
516 $ hg -R testdelete/nested2 ci -m test
510 $ hg -R testdelete/nested2 ci -m test
517 $ echo nested = nested > testdelete/.hgsub
511 $ echo nested = nested > testdelete/.hgsub
518 $ echo nested2 = nested2 >> testdelete/.hgsub
512 $ echo nested2 = nested2 >> testdelete/.hgsub
519 $ hg -R testdelete add
513 $ hg -R testdelete add
520 adding testdelete/.hgsub (glob)
514 adding testdelete/.hgsub (glob)
521 $ hg -R testdelete ci -m "nested 1 & 2 added"
515 $ hg -R testdelete ci -m "nested 1 & 2 added"
522 committing subrepository nested
523 committing subrepository nested2
524 $ echo nested = nested > testdelete/.hgsub
516 $ echo nested = nested > testdelete/.hgsub
525 $ hg -R testdelete ci -m "nested 2 deleted"
517 $ hg -R testdelete ci -m "nested 2 deleted"
526 $ cat testdelete/.hgsubstate
518 $ cat testdelete/.hgsubstate
527 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
519 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
528 $ hg -R testdelete remove testdelete/.hgsub
520 $ hg -R testdelete remove testdelete/.hgsub
529 $ hg -R testdelete ci -m ".hgsub deleted"
521 $ hg -R testdelete ci -m ".hgsub deleted"
530 $ cat testdelete/.hgsubstate
522 $ cat testdelete/.hgsubstate
531 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
523 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
532
524
533 test repository cloning
525 test repository cloning
534
526
535 $ mkdir mercurial mercurial2
527 $ mkdir mercurial mercurial2
536 $ hg init nested_absolute
528 $ hg init nested_absolute
537 $ echo test > nested_absolute/foo
529 $ echo test > nested_absolute/foo
538 $ hg -R nested_absolute add
530 $ hg -R nested_absolute add
539 adding nested_absolute/foo (glob)
531 adding nested_absolute/foo (glob)
540 $ hg -R nested_absolute ci -mtest
532 $ hg -R nested_absolute ci -mtest
541 $ cd mercurial
533 $ cd mercurial
542 $ hg init nested_relative
534 $ hg init nested_relative
543 $ echo test2 > nested_relative/foo2
535 $ echo test2 > nested_relative/foo2
544 $ hg -R nested_relative add
536 $ hg -R nested_relative add
545 adding nested_relative/foo2 (glob)
537 adding nested_relative/foo2 (glob)
546 $ hg -R nested_relative ci -mtest2
538 $ hg -R nested_relative ci -mtest2
547 $ hg init main
539 $ hg init main
548 $ echo "nested_relative = ../nested_relative" > main/.hgsub
540 $ echo "nested_relative = ../nested_relative" > main/.hgsub
549 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
541 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
550 $ hg -R main add
542 $ hg -R main add
551 adding main/.hgsub (glob)
543 adding main/.hgsub (glob)
552 $ hg -R main ci -m "add subrepos"
544 $ hg -R main ci -m "add subrepos"
553 committing subrepository nested_absolute
554 committing subrepository nested_relative
555 $ cd ..
545 $ cd ..
556 $ hg clone mercurial/main mercurial2/main
546 $ hg clone mercurial/main mercurial2/main
557 updating to branch default
547 updating to branch default
558 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
548 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
559 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
549 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
560 > mercurial2/main/nested_relative/.hg/hgrc
550 > mercurial2/main/nested_relative/.hg/hgrc
561 [paths]
551 [paths]
562 default = $TESTTMP/sub/mercurial/nested_absolute
552 default = $TESTTMP/sub/mercurial/nested_absolute
563 [paths]
553 [paths]
564 default = $TESTTMP/sub/mercurial/nested_relative
554 default = $TESTTMP/sub/mercurial/nested_relative
565 $ rm -rf mercurial mercurial2
555 $ rm -rf mercurial mercurial2
566
556
567 Issue1977: multirepo push should fail if subrepo push fails
557 Issue1977: multirepo push should fail if subrepo push fails
568
558
569 $ hg init repo
559 $ hg init repo
570 $ hg init repo/s
560 $ hg init repo/s
571 $ echo a > repo/s/a
561 $ echo a > repo/s/a
572 $ hg -R repo/s ci -Am0
562 $ hg -R repo/s ci -Am0
573 adding a
563 adding a
574 $ echo s = s > repo/.hgsub
564 $ echo s = s > repo/.hgsub
575 $ hg -R repo ci -Am1
565 $ hg -R repo ci -Am1
576 adding .hgsub
566 adding .hgsub
577 committing subrepository s
578 $ hg clone repo repo2
567 $ hg clone repo repo2
579 updating to branch default
568 updating to branch default
580 cloning subrepo s from $TESTTMP/sub/repo/s (glob)
569 cloning subrepo s from $TESTTMP/sub/repo/s (glob)
581 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
570 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
582 $ hg -q -R repo2 pull -u
571 $ hg -q -R repo2 pull -u
583 [1]
572 [1]
584 $ echo 1 > repo2/s/a
573 $ echo 1 > repo2/s/a
585 $ hg -R repo2/s ci -m2
574 $ hg -R repo2/s ci -m2
586 $ hg -q -R repo2/s push
575 $ hg -q -R repo2/s push
587 $ hg -R repo2/s up -C 0
576 $ hg -R repo2/s up -C 0
588 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
577 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
589 $ echo 2 > repo2/s/a
578 $ echo 2 > repo2/s/a
590 $ hg -R repo2/s ci -m3
579 $ hg -R repo2/s ci -m3
591 created new head
580 created new head
592 $ hg -R repo2 ci -m3
581 $ hg -R repo2 ci -m3
593 committing subrepository s
594 $ hg -q -R repo2 push
582 $ hg -q -R repo2 push
595 abort: push creates new remote head 9d66565e64e1!
583 abort: push creates new remote head 9d66565e64e1!
596 (did you forget to merge? use push -f to force)
584 (did you forget to merge? use push -f to force)
597 [255]
585 [255]
598 $ hg -R repo update
586 $ hg -R repo update
599 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
587 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
600 $ rm -rf repo2 repo
588 $ rm -rf repo2 repo
601
589
602
590
603 Issue1852 subrepos with relative paths always push/pull relative to default
591 Issue1852 subrepos with relative paths always push/pull relative to default
604
592
605 Prepare a repo with subrepo
593 Prepare a repo with subrepo
606
594
607 $ hg init issue1852a
595 $ hg init issue1852a
608 $ cd issue1852a
596 $ cd issue1852a
609 $ hg init sub/repo
597 $ hg init sub/repo
610 $ echo test > sub/repo/foo
598 $ echo test > sub/repo/foo
611 $ hg -R sub/repo add sub/repo/foo
599 $ hg -R sub/repo add sub/repo/foo
612 $ echo sub/repo = sub/repo > .hgsub
600 $ echo sub/repo = sub/repo > .hgsub
613 $ hg add .hgsub
601 $ hg add .hgsub
614 $ hg ci -mtest
602 $ hg ci -mtest
615 committing subrepository sub/repo (glob)
603 committing subrepository sub/repo (glob)
616 $ echo test >> sub/repo/foo
604 $ echo test >> sub/repo/foo
617 $ hg ci -mtest
605 $ hg ci -mtest
618 committing subrepository sub/repo (glob)
606 committing subrepository sub/repo (glob)
619 $ cd ..
607 $ cd ..
620
608
621 Create repo without default path, pull top repo, and see what happens on update
609 Create repo without default path, pull top repo, and see what happens on update
622
610
623 $ hg init issue1852b
611 $ hg init issue1852b
624 $ hg -R issue1852b pull issue1852a
612 $ hg -R issue1852b pull issue1852a
625 pulling from issue1852a
613 pulling from issue1852a
626 requesting all changes
614 requesting all changes
627 adding changesets
615 adding changesets
628 adding manifests
616 adding manifests
629 adding file changes
617 adding file changes
630 added 2 changesets with 3 changes to 2 files
618 added 2 changesets with 3 changes to 2 files
631 (run 'hg update' to get a working copy)
619 (run 'hg update' to get a working copy)
632 $ hg -R issue1852b update
620 $ hg -R issue1852b update
633 abort: default path for subrepository sub/repo not found (glob)
621 abort: default path for subrepository sub/repo not found (glob)
634 [255]
622 [255]
635
623
636 Pull -u now doesn't help
624 Pull -u now doesn't help
637
625
638 $ hg -R issue1852b pull -u issue1852a
626 $ hg -R issue1852b pull -u issue1852a
639 pulling from issue1852a
627 pulling from issue1852a
640 searching for changes
628 searching for changes
641 no changes found
629 no changes found
642 [1]
630 [1]
643
631
644 Try the same, but with pull -u
632 Try the same, but with pull -u
645
633
646 $ hg init issue1852c
634 $ hg init issue1852c
647 $ hg -R issue1852c pull -r0 -u issue1852a
635 $ hg -R issue1852c pull -r0 -u issue1852a
648 pulling from issue1852a
636 pulling from issue1852a
649 adding changesets
637 adding changesets
650 adding manifests
638 adding manifests
651 adding file changes
639 adding file changes
652 added 1 changesets with 2 changes to 2 files
640 added 1 changesets with 2 changes to 2 files
653 cloning subrepo sub/repo from issue1852a/sub/repo (glob)
641 cloning subrepo sub/repo from issue1852a/sub/repo (glob)
654 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
642 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
655
643
656 Try to push from the other side
644 Try to push from the other side
657
645
658 $ hg -R issue1852a push `pwd`/issue1852c
646 $ hg -R issue1852a push `pwd`/issue1852c
659 pushing to $TESTTMP/sub/issue1852c
647 pushing to $TESTTMP/sub/issue1852c
660 pushing subrepo sub/repo to $TESTTMP/sub/issue1852c/sub/repo (glob)
648 pushing subrepo sub/repo to $TESTTMP/sub/issue1852c/sub/repo (glob)
661 searching for changes
649 searching for changes
662 no changes found
650 no changes found
663 searching for changes
651 searching for changes
664 adding changesets
652 adding changesets
665 adding manifests
653 adding manifests
666 adding file changes
654 adding file changes
667 added 1 changesets with 1 changes to 1 files
655 added 1 changesets with 1 changes to 1 files
668
656
669 Incoming and outgoing should not use the default path:
657 Incoming and outgoing should not use the default path:
670
658
671 $ hg clone -q issue1852a issue1852d
659 $ hg clone -q issue1852a issue1852d
672 $ hg -R issue1852d outgoing --subrepos issue1852c
660 $ hg -R issue1852d outgoing --subrepos issue1852c
673 comparing with issue1852c
661 comparing with issue1852c
674 searching for changes
662 searching for changes
675 no changes found
663 no changes found
676 comparing with issue1852c/sub/repo
664 comparing with issue1852c/sub/repo
677 searching for changes
665 searching for changes
678 no changes found
666 no changes found
679 [1]
667 [1]
680 $ hg -R issue1852d incoming --subrepos issue1852c
668 $ hg -R issue1852d incoming --subrepos issue1852c
681 comparing with issue1852c
669 comparing with issue1852c
682 searching for changes
670 searching for changes
683 no changes found
671 no changes found
684 comparing with issue1852c/sub/repo
672 comparing with issue1852c/sub/repo
685 searching for changes
673 searching for changes
686 no changes found
674 no changes found
687 [1]
675 [1]
688
676
689 Check status of files when none of them belong to the first
677 Check status of files when none of them belong to the first
690 subrepository:
678 subrepository:
691
679
692 $ hg init subrepo-status
680 $ hg init subrepo-status
693 $ cd subrepo-status
681 $ cd subrepo-status
694 $ hg init subrepo-1
682 $ hg init subrepo-1
695 $ hg init subrepo-2
683 $ hg init subrepo-2
696 $ cd subrepo-2
684 $ cd subrepo-2
697 $ touch file
685 $ touch file
698 $ hg add file
686 $ hg add file
699 $ cd ..
687 $ cd ..
700 $ echo subrepo-1 = subrepo-1 > .hgsub
688 $ echo subrepo-1 = subrepo-1 > .hgsub
701 $ echo subrepo-2 = subrepo-2 >> .hgsub
689 $ echo subrepo-2 = subrepo-2 >> .hgsub
702 $ hg add .hgsub
690 $ hg add .hgsub
703 $ hg ci -m 'Added subrepos'
691 $ hg ci -m 'Added subrepos'
704 committing subrepository subrepo-1
705 committing subrepository subrepo-2
692 committing subrepository subrepo-2
706 $ hg st subrepo-2/file
693 $ hg st subrepo-2/file
707
694
708 Check hg update --clean
695 Check hg update --clean
709 $ cd $TESTTMP/sub/t
696 $ cd $TESTTMP/sub/t
710 $ rm -r t/t.orig
697 $ rm -r t/t.orig
711 $ hg status -S --all
698 $ hg status -S --all
712 C .hgsub
699 C .hgsub
713 C .hgsubstate
700 C .hgsubstate
714 C a
701 C a
715 C s/.hgsub
702 C s/.hgsub
716 C s/.hgsubstate
703 C s/.hgsubstate
717 C s/a
704 C s/a
718 C s/ss/a
705 C s/ss/a
719 C t/t
706 C t/t
720 $ echo c1 > s/a
707 $ echo c1 > s/a
721 $ cd s
708 $ cd s
722 $ echo c1 > b
709 $ echo c1 > b
723 $ echo c1 > c
710 $ echo c1 > c
724 $ hg add b
711 $ hg add b
725 $ cd ..
712 $ cd ..
726 $ hg status -S
713 $ hg status -S
727 M s/a
714 M s/a
728 A s/b
715 A s/b
729 ? s/c
716 ? s/c
730 $ hg update -C
717 $ hg update -C
731 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
718 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
732 $ hg status -S
719 $ hg status -S
733 ? s/b
720 ? s/b
734 ? s/c
721 ? s/c
735
722
736 Sticky subrepositories, no changes
723 Sticky subrepositories, no changes
737 $ cd $TESTTMP/sub/t
724 $ cd $TESTTMP/sub/t
738 $ hg id
725 $ hg id
739 925c17564ef8 tip
726 925c17564ef8 tip
740 $ hg -R s id
727 $ hg -R s id
741 12a213df6fa9 tip
728 12a213df6fa9 tip
742 $ hg -R t id
729 $ hg -R t id
743 52c0adc0515a tip
730 52c0adc0515a tip
744 $ hg update 11
731 $ hg update 11
745 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
732 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
746 $ hg id
733 $ hg id
747 365661e5936a
734 365661e5936a
748 $ hg -R s id
735 $ hg -R s id
749 fc627a69481f
736 fc627a69481f
750 $ hg -R t id
737 $ hg -R t id
751 e95bcfa18a35
738 e95bcfa18a35
752
739
753 Sticky subrepositorys, file changes
740 Sticky subrepositorys, file changes
754 $ touch s/f1
741 $ touch s/f1
755 $ touch t/f1
742 $ touch t/f1
756 $ hg add -S s/f1
743 $ hg add -S s/f1
757 $ hg add -S t/f1
744 $ hg add -S t/f1
758 $ hg id
745 $ hg id
759 365661e5936a
746 365661e5936a
760 $ hg -R s id
747 $ hg -R s id
761 fc627a69481f+
748 fc627a69481f+
762 $ hg -R t id
749 $ hg -R t id
763 e95bcfa18a35+
750 e95bcfa18a35+
764 $ hg update tip
751 $ hg update tip
765 subrepository sources for s differ
752 subrepository sources for s differ
766 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
753 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
767 l
754 l
768 subrepository sources for t differ
755 subrepository sources for t differ
769 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
756 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
770 l
757 l
771 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
758 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
772 $ hg id
759 $ hg id
773 925c17564ef8+ tip
760 925c17564ef8+ tip
774 $ hg -R s id
761 $ hg -R s id
775 fc627a69481f+
762 fc627a69481f+
776 $ hg -R t id
763 $ hg -R t id
777 e95bcfa18a35+
764 e95bcfa18a35+
778 $ hg update --clean tip
765 $ hg update --clean tip
779 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
766 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
780
767
781 Sticky subrepository, revision updates
768 Sticky subrepository, revision updates
782 $ hg id
769 $ hg id
783 925c17564ef8 tip
770 925c17564ef8 tip
784 $ hg -R s id
771 $ hg -R s id
785 12a213df6fa9 tip
772 12a213df6fa9 tip
786 $ hg -R t id
773 $ hg -R t id
787 52c0adc0515a tip
774 52c0adc0515a tip
788 $ cd s
775 $ cd s
789 $ hg update -r -2
776 $ hg update -r -2
790 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
777 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
791 $ cd ../t
778 $ cd ../t
792 $ hg update -r 2
779 $ hg update -r 2
793 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
780 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
794 $ cd ..
781 $ cd ..
795 $ hg update 10
782 $ hg update 10
796 subrepository sources for t differ (in checked out version)
783 subrepository sources for t differ (in checked out version)
797 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
784 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
798 l
785 l
799 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
786 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
800 $ hg id
787 $ hg id
801 e45c8b14af55+
788 e45c8b14af55+
802 $ hg -R s id
789 $ hg -R s id
803 1c833a7a9e3a
790 1c833a7a9e3a
804 $ hg -R t id
791 $ hg -R t id
805 7af322bc1198
792 7af322bc1198
806
793
807 Sticky subrepository, file changes and revision updates
794 Sticky subrepository, file changes and revision updates
808 $ touch s/f1
795 $ touch s/f1
809 $ touch t/f1
796 $ touch t/f1
810 $ hg add -S s/f1
797 $ hg add -S s/f1
811 $ hg add -S t/f1
798 $ hg add -S t/f1
812 $ hg id
799 $ hg id
813 e45c8b14af55+
800 e45c8b14af55+
814 $ hg -R s id
801 $ hg -R s id
815 1c833a7a9e3a+
802 1c833a7a9e3a+
816 $ hg -R t id
803 $ hg -R t id
817 7af322bc1198+
804 7af322bc1198+
818 $ hg update tip
805 $ hg update tip
819 subrepository sources for s differ
806 subrepository sources for s differ
820 use (l)ocal source (1c833a7a9e3a) or (r)emote source (12a213df6fa9)?
807 use (l)ocal source (1c833a7a9e3a) or (r)emote source (12a213df6fa9)?
821 l
808 l
822 subrepository sources for t differ
809 subrepository sources for t differ
823 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
810 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
824 l
811 l
825 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
812 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
826 $ hg id
813 $ hg id
827 925c17564ef8 tip
814 925c17564ef8 tip
828 $ hg -R s id
815 $ hg -R s id
829 1c833a7a9e3a+
816 1c833a7a9e3a+
830 $ hg -R t id
817 $ hg -R t id
831 7af322bc1198+
818 7af322bc1198+
832
819
833 Sticky repository, update --clean
820 Sticky repository, update --clean
834 $ hg update --clean tip
821 $ hg update --clean tip
835 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
822 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
836 $ hg id
823 $ hg id
837 925c17564ef8 tip
824 925c17564ef8 tip
838 $ hg -R s id
825 $ hg -R s id
839 12a213df6fa9 tip
826 12a213df6fa9 tip
840 $ hg -R t id
827 $ hg -R t id
841 52c0adc0515a tip
828 52c0adc0515a tip
842
829
843 Test subrepo already at intended revision:
830 Test subrepo already at intended revision:
844 $ cd s
831 $ cd s
845 $ hg update fc627a69481f
832 $ hg update fc627a69481f
846 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
833 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
847 $ cd ..
834 $ cd ..
848 $ hg update 11
835 $ hg update 11
849 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
836 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
850 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
837 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
851 $ hg id -n
838 $ hg id -n
852 11+
839 11+
853 $ hg -R s id
840 $ hg -R s id
854 fc627a69481f
841 fc627a69481f
855 $ hg -R t id
842 $ hg -R t id
856 e95bcfa18a35
843 e95bcfa18a35
857
844
858 Test that removing .hgsubstate doesn't break anything:
845 Test that removing .hgsubstate doesn't break anything:
859
846
860 $ hg rm -f .hgsubstate
847 $ hg rm -f .hgsubstate
861 $ hg ci -mrm
848 $ hg ci -mrm
862 committing subrepository s
849 nothing changed
863 committing subrepository t
850 [1]
864 created new head
865 $ hg log -vr tip
851 $ hg log -vr tip
866 changeset: 14:3941e0aa5236
852 changeset: 13:925c17564ef8
867 tag: tip
853 tag: tip
868 parent: 11:365661e5936a
869 user: test
854 user: test
870 date: Thu Jan 01 00:00:00 1970 +0000
855 date: Thu Jan 01 00:00:00 1970 +0000
856 files: .hgsubstate
871 description:
857 description:
872 rm
858 13
873
859
874
860
875
861
876 Test that removing .hgsub removes .hgsubstate:
862 Test that removing .hgsub removes .hgsubstate:
877
863
878 $ hg rm .hgsub
864 $ hg rm .hgsub
879 $ hg ci -mrm2
865 $ hg ci -mrm2
866 created new head
880 $ hg log -vr tip
867 $ hg log -vr tip
881 changeset: 15:8b31de9d13d1
868 changeset: 14:2400bccd50af
882 tag: tip
869 tag: tip
870 parent: 11:365661e5936a
883 user: test
871 user: test
884 date: Thu Jan 01 00:00:00 1970 +0000
872 date: Thu Jan 01 00:00:00 1970 +0000
885 files: .hgsub .hgsubstate
873 files: .hgsub .hgsubstate
886 description:
874 description:
887 rm2
875 rm2
888
876
889
877
890 Test issue3153: diff -S with deleted subrepos
878 Test issue3153: diff -S with deleted subrepos
891
879
892 $ hg diff --nodates -S -c .
880 $ hg diff --nodates -S -c .
893 diff -r 3941e0aa5236 -r 8b31de9d13d1 .hgsub
881 diff -r 365661e5936a -r 2400bccd50af .hgsub
894 --- a/.hgsub
882 --- a/.hgsub
895 +++ /dev/null
883 +++ /dev/null
896 @@ -1,2 +0,0 @@
884 @@ -1,2 +0,0 @@
897 -s = s
885 -s = s
898 -t = t
886 -t = t
899 diff -r 3941e0aa5236 -r 8b31de9d13d1 .hgsubstate
887 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
900 --- a/.hgsubstate
888 --- a/.hgsubstate
901 +++ /dev/null
889 +++ /dev/null
902 @@ -1,2 +0,0 @@
890 @@ -1,2 +0,0 @@
903 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
891 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
904 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
892 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
905
893
906 Test behavior of add for explicit path in subrepo:
894 Test behavior of add for explicit path in subrepo:
907 $ cd ..
895 $ cd ..
908 $ hg init explicit
896 $ hg init explicit
909 $ cd explicit
897 $ cd explicit
910 $ echo s = s > .hgsub
898 $ echo s = s > .hgsub
911 $ hg add .hgsub
899 $ hg add .hgsub
912 $ hg init s
900 $ hg init s
913 $ hg ci -m0
901 $ hg ci -m0
914 committing subrepository s
915 Adding with an explicit path in a subrepo adds the file
902 Adding with an explicit path in a subrepo adds the file
916 $ echo c1 > f1
903 $ echo c1 > f1
917 $ echo c2 > s/f2
904 $ echo c2 > s/f2
918 $ hg st -S
905 $ hg st -S
919 ? f1
906 ? f1
920 ? s/f2
907 ? s/f2
921 $ hg add s/f2
908 $ hg add s/f2
922 $ hg st -S
909 $ hg st -S
923 A s/f2
910 A s/f2
924 ? f1
911 ? f1
925 $ hg ci -R s -m0
912 $ hg ci -R s -m0
926 $ hg ci -Am1
913 $ hg ci -Am1
927 adding f1
914 adding f1
928 committing subrepository s
929 Adding with an explicit path in a subrepo with -S has the same behavior
915 Adding with an explicit path in a subrepo with -S has the same behavior
930 $ echo c3 > f3
916 $ echo c3 > f3
931 $ echo c4 > s/f4
917 $ echo c4 > s/f4
932 $ hg st -S
918 $ hg st -S
933 ? f3
919 ? f3
934 ? s/f4
920 ? s/f4
935 $ hg add -S s/f4
921 $ hg add -S s/f4
936 $ hg st -S
922 $ hg st -S
937 A s/f4
923 A s/f4
938 ? f3
924 ? f3
939 $ hg ci -R s -m1
925 $ hg ci -R s -m1
940 $ hg ci -Ama2
926 $ hg ci -Ama2
941 adding f3
927 adding f3
942 committing subrepository s
943 Adding without a path or pattern silently ignores subrepos
928 Adding without a path or pattern silently ignores subrepos
944 $ echo c5 > f5
929 $ echo c5 > f5
945 $ echo c6 > s/f6
930 $ echo c6 > s/f6
946 $ echo c7 > s/f7
931 $ echo c7 > s/f7
947 $ hg st -S
932 $ hg st -S
948 ? f5
933 ? f5
949 ? s/f6
934 ? s/f6
950 ? s/f7
935 ? s/f7
951 $ hg add
936 $ hg add
952 adding f5
937 adding f5
953 $ hg st -S
938 $ hg st -S
954 A f5
939 A f5
955 ? s/f6
940 ? s/f6
956 ? s/f7
941 ? s/f7
957 $ hg ci -R s -Am2
942 $ hg ci -R s -Am2
958 adding f6
943 adding f6
959 adding f7
944 adding f7
960 $ hg ci -m3
945 $ hg ci -m3
961 committing subrepository s
962 Adding without a path or pattern with -S also adds files in subrepos
946 Adding without a path or pattern with -S also adds files in subrepos
963 $ echo c8 > f8
947 $ echo c8 > f8
964 $ echo c9 > s/f9
948 $ echo c9 > s/f9
965 $ echo c10 > s/f10
949 $ echo c10 > s/f10
966 $ hg st -S
950 $ hg st -S
967 ? f8
951 ? f8
968 ? s/f10
952 ? s/f10
969 ? s/f9
953 ? s/f9
970 $ hg add -S
954 $ hg add -S
971 adding f8
955 adding f8
972 adding s/f10 (glob)
956 adding s/f10 (glob)
973 adding s/f9 (glob)
957 adding s/f9 (glob)
974 $ hg st -S
958 $ hg st -S
975 A f8
959 A f8
976 A s/f10
960 A s/f10
977 A s/f9
961 A s/f9
978 $ hg ci -R s -m3
962 $ hg ci -R s -m3
979 $ hg ci -m4
963 $ hg ci -m4
980 committing subrepository s
981 Adding with a pattern silently ignores subrepos
964 Adding with a pattern silently ignores subrepos
982 $ echo c11 > fm11
965 $ echo c11 > fm11
983 $ echo c12 > fn12
966 $ echo c12 > fn12
984 $ echo c13 > s/fm13
967 $ echo c13 > s/fm13
985 $ echo c14 > s/fn14
968 $ echo c14 > s/fn14
986 $ hg st -S
969 $ hg st -S
987 ? fm11
970 ? fm11
988 ? fn12
971 ? fn12
989 ? s/fm13
972 ? s/fm13
990 ? s/fn14
973 ? s/fn14
991 $ hg add 'glob:**fm*'
974 $ hg add 'glob:**fm*'
992 adding fm11
975 adding fm11
993 $ hg st -S
976 $ hg st -S
994 A fm11
977 A fm11
995 ? fn12
978 ? fn12
996 ? s/fm13
979 ? s/fm13
997 ? s/fn14
980 ? s/fn14
998 $ hg ci -R s -Am4
981 $ hg ci -R s -Am4
999 adding fm13
982 adding fm13
1000 adding fn14
983 adding fn14
1001 $ hg ci -Am5
984 $ hg ci -Am5
1002 adding fn12
985 adding fn12
1003 committing subrepository s
1004 Adding with a pattern with -S also adds matches in subrepos
986 Adding with a pattern with -S also adds matches in subrepos
1005 $ echo c15 > fm15
987 $ echo c15 > fm15
1006 $ echo c16 > fn16
988 $ echo c16 > fn16
1007 $ echo c17 > s/fm17
989 $ echo c17 > s/fm17
1008 $ echo c18 > s/fn18
990 $ echo c18 > s/fn18
1009 $ hg st -S
991 $ hg st -S
1010 ? fm15
992 ? fm15
1011 ? fn16
993 ? fn16
1012 ? s/fm17
994 ? s/fm17
1013 ? s/fn18
995 ? s/fn18
1014 $ hg add -S 'glob:**fm*'
996 $ hg add -S 'glob:**fm*'
1015 adding fm15
997 adding fm15
1016 adding s/fm17 (glob)
998 adding s/fm17 (glob)
1017 $ hg st -S
999 $ hg st -S
1018 A fm15
1000 A fm15
1019 A s/fm17
1001 A s/fm17
1020 ? fn16
1002 ? fn16
1021 ? s/fn18
1003 ? s/fn18
1022 $ hg ci -R s -Am5
1004 $ hg ci -R s -Am5
1023 adding fn18
1005 adding fn18
1024 $ hg ci -Am6
1006 $ hg ci -Am6
1025 adding fn16
1007 adding fn16
1026 committing subrepository s
1027
1008
1028 Test behavior of forget for explicit path in subrepo:
1009 Test behavior of forget for explicit path in subrepo:
1029 Forgetting an explicit path in a subrepo untracks the file
1010 Forgetting an explicit path in a subrepo untracks the file
1030 $ echo c19 > s/f19
1011 $ echo c19 > s/f19
1031 $ hg add s/f19
1012 $ hg add s/f19
1032 $ hg st -S
1013 $ hg st -S
1033 A s/f19
1014 A s/f19
1034 $ hg forget s/f19
1015 $ hg forget s/f19
1035 $ hg st -S
1016 $ hg st -S
1036 ? s/f19
1017 ? s/f19
1037 $ rm s/f19
1018 $ rm s/f19
General Comments 0
You need to be logged in to leave comments. Login now