##// END OF EJS Templates
subrepo: do not report known files inside repositories as unknown
Oleg Stepanov -
r13233:0b30e614 stable
parent child Browse files
Show More
@@ -1,681 +1,681 b''
1 # dirstate.py - working directory tracking for mercurial
1 # dirstate.py - working directory tracking 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 nullid
8 from node import nullid
9 from i18n import _
9 from i18n import _
10 import util, ignore, osutil, parsers
10 import util, ignore, osutil, parsers
11 import struct, os, stat, errno
11 import struct, os, stat, errno
12 import cStringIO
12 import cStringIO
13
13
14 _format = ">cllll"
14 _format = ">cllll"
15 propertycache = util.propertycache
15 propertycache = util.propertycache
16
16
17 def _finddirs(path):
17 def _finddirs(path):
18 pos = path.rfind('/')
18 pos = path.rfind('/')
19 while pos != -1:
19 while pos != -1:
20 yield path[:pos]
20 yield path[:pos]
21 pos = path.rfind('/', 0, pos)
21 pos = path.rfind('/', 0, pos)
22
22
23 def _incdirs(dirs, path):
23 def _incdirs(dirs, path):
24 for base in _finddirs(path):
24 for base in _finddirs(path):
25 if base in dirs:
25 if base in dirs:
26 dirs[base] += 1
26 dirs[base] += 1
27 return
27 return
28 dirs[base] = 1
28 dirs[base] = 1
29
29
30 def _decdirs(dirs, path):
30 def _decdirs(dirs, path):
31 for base in _finddirs(path):
31 for base in _finddirs(path):
32 if dirs[base] > 1:
32 if dirs[base] > 1:
33 dirs[base] -= 1
33 dirs[base] -= 1
34 return
34 return
35 del dirs[base]
35 del dirs[base]
36
36
37 class dirstate(object):
37 class dirstate(object):
38
38
39 def __init__(self, opener, ui, root):
39 def __init__(self, opener, ui, root):
40 '''Create a new dirstate object.
40 '''Create a new dirstate object.
41
41
42 opener is an open()-like callable that can be used to open the
42 opener is an open()-like callable that can be used to open the
43 dirstate file; root is the root of the directory tracked by
43 dirstate file; root is the root of the directory tracked by
44 the dirstate.
44 the dirstate.
45 '''
45 '''
46 self._opener = opener
46 self._opener = opener
47 self._root = root
47 self._root = root
48 self._rootdir = os.path.join(root, '')
48 self._rootdir = os.path.join(root, '')
49 self._dirty = False
49 self._dirty = False
50 self._dirtypl = False
50 self._dirtypl = False
51 self._ui = ui
51 self._ui = ui
52
52
53 @propertycache
53 @propertycache
54 def _map(self):
54 def _map(self):
55 '''Return the dirstate contents as a map from filename to
55 '''Return the dirstate contents as a map from filename to
56 (state, mode, size, time).'''
56 (state, mode, size, time).'''
57 self._read()
57 self._read()
58 return self._map
58 return self._map
59
59
60 @propertycache
60 @propertycache
61 def _copymap(self):
61 def _copymap(self):
62 self._read()
62 self._read()
63 return self._copymap
63 return self._copymap
64
64
65 @propertycache
65 @propertycache
66 def _foldmap(self):
66 def _foldmap(self):
67 f = {}
67 f = {}
68 for name in self._map:
68 for name in self._map:
69 f[os.path.normcase(name)] = name
69 f[os.path.normcase(name)] = name
70 return f
70 return f
71
71
72 @propertycache
72 @propertycache
73 def _branch(self):
73 def _branch(self):
74 try:
74 try:
75 return self._opener("branch").read().strip() or "default"
75 return self._opener("branch").read().strip() or "default"
76 except IOError:
76 except IOError:
77 return "default"
77 return "default"
78
78
79 @propertycache
79 @propertycache
80 def _pl(self):
80 def _pl(self):
81 try:
81 try:
82 st = self._opener("dirstate").read(40)
82 st = self._opener("dirstate").read(40)
83 l = len(st)
83 l = len(st)
84 if l == 40:
84 if l == 40:
85 return st[:20], st[20:40]
85 return st[:20], st[20:40]
86 elif l > 0 and l < 40:
86 elif l > 0 and l < 40:
87 raise util.Abort(_('working directory state appears damaged!'))
87 raise util.Abort(_('working directory state appears damaged!'))
88 except IOError, err:
88 except IOError, err:
89 if err.errno != errno.ENOENT:
89 if err.errno != errno.ENOENT:
90 raise
90 raise
91 return [nullid, nullid]
91 return [nullid, nullid]
92
92
93 @propertycache
93 @propertycache
94 def _dirs(self):
94 def _dirs(self):
95 dirs = {}
95 dirs = {}
96 for f, s in self._map.iteritems():
96 for f, s in self._map.iteritems():
97 if s[0] != 'r':
97 if s[0] != 'r':
98 _incdirs(dirs, f)
98 _incdirs(dirs, f)
99 return dirs
99 return dirs
100
100
101 @propertycache
101 @propertycache
102 def _ignore(self):
102 def _ignore(self):
103 files = [self._join('.hgignore')]
103 files = [self._join('.hgignore')]
104 for name, path in self._ui.configitems("ui"):
104 for name, path in self._ui.configitems("ui"):
105 if name == 'ignore' or name.startswith('ignore.'):
105 if name == 'ignore' or name.startswith('ignore.'):
106 files.append(util.expandpath(path))
106 files.append(util.expandpath(path))
107 return ignore.ignore(self._root, files, self._ui.warn)
107 return ignore.ignore(self._root, files, self._ui.warn)
108
108
109 @propertycache
109 @propertycache
110 def _slash(self):
110 def _slash(self):
111 return self._ui.configbool('ui', 'slash') and os.sep != '/'
111 return self._ui.configbool('ui', 'slash') and os.sep != '/'
112
112
113 @propertycache
113 @propertycache
114 def _checklink(self):
114 def _checklink(self):
115 return util.checklink(self._root)
115 return util.checklink(self._root)
116
116
117 @propertycache
117 @propertycache
118 def _checkexec(self):
118 def _checkexec(self):
119 return util.checkexec(self._root)
119 return util.checkexec(self._root)
120
120
121 @propertycache
121 @propertycache
122 def _checkcase(self):
122 def _checkcase(self):
123 return not util.checkcase(self._join('.hg'))
123 return not util.checkcase(self._join('.hg'))
124
124
125 def _join(self, f):
125 def _join(self, f):
126 # much faster than os.path.join()
126 # much faster than os.path.join()
127 # it's safe because f is always a relative path
127 # it's safe because f is always a relative path
128 return self._rootdir + f
128 return self._rootdir + f
129
129
130 def flagfunc(self, fallback):
130 def flagfunc(self, fallback):
131 if self._checklink:
131 if self._checklink:
132 if self._checkexec:
132 if self._checkexec:
133 def f(x):
133 def f(x):
134 p = self._join(x)
134 p = self._join(x)
135 if os.path.islink(p):
135 if os.path.islink(p):
136 return 'l'
136 return 'l'
137 if util.is_exec(p):
137 if util.is_exec(p):
138 return 'x'
138 return 'x'
139 return ''
139 return ''
140 return f
140 return f
141 def f(x):
141 def f(x):
142 if os.path.islink(self._join(x)):
142 if os.path.islink(self._join(x)):
143 return 'l'
143 return 'l'
144 if 'x' in fallback(x):
144 if 'x' in fallback(x):
145 return 'x'
145 return 'x'
146 return ''
146 return ''
147 return f
147 return f
148 if self._checkexec:
148 if self._checkexec:
149 def f(x):
149 def f(x):
150 if 'l' in fallback(x):
150 if 'l' in fallback(x):
151 return 'l'
151 return 'l'
152 if util.is_exec(self._join(x)):
152 if util.is_exec(self._join(x)):
153 return 'x'
153 return 'x'
154 return ''
154 return ''
155 return f
155 return f
156 return fallback
156 return fallback
157
157
158 def getcwd(self):
158 def getcwd(self):
159 cwd = os.getcwd()
159 cwd = os.getcwd()
160 if cwd == self._root:
160 if cwd == self._root:
161 return ''
161 return ''
162 # self._root ends with a path separator if self._root is '/' or 'C:\'
162 # self._root ends with a path separator if self._root is '/' or 'C:\'
163 rootsep = self._root
163 rootsep = self._root
164 if not util.endswithsep(rootsep):
164 if not util.endswithsep(rootsep):
165 rootsep += os.sep
165 rootsep += os.sep
166 if cwd.startswith(rootsep):
166 if cwd.startswith(rootsep):
167 return cwd[len(rootsep):]
167 return cwd[len(rootsep):]
168 else:
168 else:
169 # we're outside the repo. return an absolute path.
169 # we're outside the repo. return an absolute path.
170 return cwd
170 return cwd
171
171
172 def pathto(self, f, cwd=None):
172 def pathto(self, f, cwd=None):
173 if cwd is None:
173 if cwd is None:
174 cwd = self.getcwd()
174 cwd = self.getcwd()
175 path = util.pathto(self._root, cwd, f)
175 path = util.pathto(self._root, cwd, f)
176 if self._slash:
176 if self._slash:
177 return util.normpath(path)
177 return util.normpath(path)
178 return path
178 return path
179
179
180 def __getitem__(self, key):
180 def __getitem__(self, key):
181 '''Return the current state of key (a filename) in the dirstate.
181 '''Return the current state of key (a filename) in the dirstate.
182
182
183 States are:
183 States are:
184 n normal
184 n normal
185 m needs merging
185 m needs merging
186 r marked for removal
186 r marked for removal
187 a marked for addition
187 a marked for addition
188 ? not tracked
188 ? not tracked
189 '''
189 '''
190 return self._map.get(key, ("?",))[0]
190 return self._map.get(key, ("?",))[0]
191
191
192 def __contains__(self, key):
192 def __contains__(self, key):
193 return key in self._map
193 return key in self._map
194
194
195 def __iter__(self):
195 def __iter__(self):
196 for x in sorted(self._map):
196 for x in sorted(self._map):
197 yield x
197 yield x
198
198
199 def parents(self):
199 def parents(self):
200 return self._pl
200 return self._pl
201
201
202 def branch(self):
202 def branch(self):
203 return self._branch
203 return self._branch
204
204
205 def setparents(self, p1, p2=nullid):
205 def setparents(self, p1, p2=nullid):
206 self._dirty = self._dirtypl = True
206 self._dirty = self._dirtypl = True
207 self._pl = p1, p2
207 self._pl = p1, p2
208
208
209 def setbranch(self, branch):
209 def setbranch(self, branch):
210 if branch in ['tip', '.', 'null']:
210 if branch in ['tip', '.', 'null']:
211 raise util.Abort(_('the name \'%s\' is reserved') % branch)
211 raise util.Abort(_('the name \'%s\' is reserved') % branch)
212 self._branch = branch
212 self._branch = branch
213 self._opener("branch", "w").write(branch + '\n')
213 self._opener("branch", "w").write(branch + '\n')
214
214
215 def _read(self):
215 def _read(self):
216 self._map = {}
216 self._map = {}
217 self._copymap = {}
217 self._copymap = {}
218 try:
218 try:
219 st = self._opener("dirstate").read()
219 st = self._opener("dirstate").read()
220 except IOError, err:
220 except IOError, err:
221 if err.errno != errno.ENOENT:
221 if err.errno != errno.ENOENT:
222 raise
222 raise
223 return
223 return
224 if not st:
224 if not st:
225 return
225 return
226
226
227 p = parsers.parse_dirstate(self._map, self._copymap, st)
227 p = parsers.parse_dirstate(self._map, self._copymap, st)
228 if not self._dirtypl:
228 if not self._dirtypl:
229 self._pl = p
229 self._pl = p
230
230
231 def invalidate(self):
231 def invalidate(self):
232 for a in "_map _copymap _foldmap _branch _pl _dirs _ignore".split():
232 for a in "_map _copymap _foldmap _branch _pl _dirs _ignore".split():
233 if a in self.__dict__:
233 if a in self.__dict__:
234 delattr(self, a)
234 delattr(self, a)
235 self._dirty = False
235 self._dirty = False
236
236
237 def copy(self, source, dest):
237 def copy(self, source, dest):
238 """Mark dest as a copy of source. Unmark dest if source is None."""
238 """Mark dest as a copy of source. Unmark dest if source is None."""
239 if source == dest:
239 if source == dest:
240 return
240 return
241 self._dirty = True
241 self._dirty = True
242 if source is not None:
242 if source is not None:
243 self._copymap[dest] = source
243 self._copymap[dest] = source
244 elif dest in self._copymap:
244 elif dest in self._copymap:
245 del self._copymap[dest]
245 del self._copymap[dest]
246
246
247 def copied(self, file):
247 def copied(self, file):
248 return self._copymap.get(file, None)
248 return self._copymap.get(file, None)
249
249
250 def copies(self):
250 def copies(self):
251 return self._copymap
251 return self._copymap
252
252
253 def _droppath(self, f):
253 def _droppath(self, f):
254 if self[f] not in "?r" and "_dirs" in self.__dict__:
254 if self[f] not in "?r" and "_dirs" in self.__dict__:
255 _decdirs(self._dirs, f)
255 _decdirs(self._dirs, f)
256
256
257 def _addpath(self, f, check=False):
257 def _addpath(self, f, check=False):
258 oldstate = self[f]
258 oldstate = self[f]
259 if check or oldstate == "r":
259 if check or oldstate == "r":
260 if '\r' in f or '\n' in f:
260 if '\r' in f or '\n' in f:
261 raise util.Abort(
261 raise util.Abort(
262 _("'\\n' and '\\r' disallowed in filenames: %r") % f)
262 _("'\\n' and '\\r' disallowed in filenames: %r") % f)
263 if f in self._dirs:
263 if f in self._dirs:
264 raise util.Abort(_('directory %r already in dirstate') % f)
264 raise util.Abort(_('directory %r already in dirstate') % f)
265 # shadows
265 # shadows
266 for d in _finddirs(f):
266 for d in _finddirs(f):
267 if d in self._dirs:
267 if d in self._dirs:
268 break
268 break
269 if d in self._map and self[d] != 'r':
269 if d in self._map and self[d] != 'r':
270 raise util.Abort(
270 raise util.Abort(
271 _('file %r in dirstate clashes with %r') % (d, f))
271 _('file %r in dirstate clashes with %r') % (d, f))
272 if oldstate in "?r" and "_dirs" in self.__dict__:
272 if oldstate in "?r" and "_dirs" in self.__dict__:
273 _incdirs(self._dirs, f)
273 _incdirs(self._dirs, f)
274
274
275 def normal(self, f):
275 def normal(self, f):
276 '''Mark a file normal and clean.'''
276 '''Mark a file normal and clean.'''
277 self._dirty = True
277 self._dirty = True
278 self._addpath(f)
278 self._addpath(f)
279 s = os.lstat(self._join(f))
279 s = os.lstat(self._join(f))
280 self._map[f] = ('n', s.st_mode, s.st_size, int(s.st_mtime))
280 self._map[f] = ('n', s.st_mode, s.st_size, int(s.st_mtime))
281 if f in self._copymap:
281 if f in self._copymap:
282 del self._copymap[f]
282 del self._copymap[f]
283
283
284 def normallookup(self, f):
284 def normallookup(self, f):
285 '''Mark a file normal, but possibly dirty.'''
285 '''Mark a file normal, but possibly dirty.'''
286 if self._pl[1] != nullid and f in self._map:
286 if self._pl[1] != nullid and f in self._map:
287 # if there is a merge going on and the file was either
287 # if there is a merge going on and the file was either
288 # in state 'm' (-1) or coming from other parent (-2) before
288 # in state 'm' (-1) or coming from other parent (-2) before
289 # being removed, restore that state.
289 # being removed, restore that state.
290 entry = self._map[f]
290 entry = self._map[f]
291 if entry[0] == 'r' and entry[2] in (-1, -2):
291 if entry[0] == 'r' and entry[2] in (-1, -2):
292 source = self._copymap.get(f)
292 source = self._copymap.get(f)
293 if entry[2] == -1:
293 if entry[2] == -1:
294 self.merge(f)
294 self.merge(f)
295 elif entry[2] == -2:
295 elif entry[2] == -2:
296 self.otherparent(f)
296 self.otherparent(f)
297 if source:
297 if source:
298 self.copy(source, f)
298 self.copy(source, f)
299 return
299 return
300 if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
300 if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
301 return
301 return
302 self._dirty = True
302 self._dirty = True
303 self._addpath(f)
303 self._addpath(f)
304 self._map[f] = ('n', 0, -1, -1)
304 self._map[f] = ('n', 0, -1, -1)
305 if f in self._copymap:
305 if f in self._copymap:
306 del self._copymap[f]
306 del self._copymap[f]
307
307
308 def otherparent(self, f):
308 def otherparent(self, f):
309 '''Mark as coming from the other parent, always dirty.'''
309 '''Mark as coming from the other parent, always dirty.'''
310 if self._pl[1] == nullid:
310 if self._pl[1] == nullid:
311 raise util.Abort(_("setting %r to other parent "
311 raise util.Abort(_("setting %r to other parent "
312 "only allowed in merges") % f)
312 "only allowed in merges") % f)
313 self._dirty = True
313 self._dirty = True
314 self._addpath(f)
314 self._addpath(f)
315 self._map[f] = ('n', 0, -2, -1)
315 self._map[f] = ('n', 0, -2, -1)
316 if f in self._copymap:
316 if f in self._copymap:
317 del self._copymap[f]
317 del self._copymap[f]
318
318
319 def add(self, f):
319 def add(self, f):
320 '''Mark a file added.'''
320 '''Mark a file added.'''
321 self._dirty = True
321 self._dirty = True
322 self._addpath(f, True)
322 self._addpath(f, True)
323 self._map[f] = ('a', 0, -1, -1)
323 self._map[f] = ('a', 0, -1, -1)
324 if f in self._copymap:
324 if f in self._copymap:
325 del self._copymap[f]
325 del self._copymap[f]
326
326
327 def remove(self, f):
327 def remove(self, f):
328 '''Mark a file removed.'''
328 '''Mark a file removed.'''
329 self._dirty = True
329 self._dirty = True
330 self._droppath(f)
330 self._droppath(f)
331 size = 0
331 size = 0
332 if self._pl[1] != nullid and f in self._map:
332 if self._pl[1] != nullid and f in self._map:
333 # backup the previous state
333 # backup the previous state
334 entry = self._map[f]
334 entry = self._map[f]
335 if entry[0] == 'm': # merge
335 if entry[0] == 'm': # merge
336 size = -1
336 size = -1
337 elif entry[0] == 'n' and entry[2] == -2: # other parent
337 elif entry[0] == 'n' and entry[2] == -2: # other parent
338 size = -2
338 size = -2
339 self._map[f] = ('r', 0, size, 0)
339 self._map[f] = ('r', 0, size, 0)
340 if size == 0 and f in self._copymap:
340 if size == 0 and f in self._copymap:
341 del self._copymap[f]
341 del self._copymap[f]
342
342
343 def merge(self, f):
343 def merge(self, f):
344 '''Mark a file merged.'''
344 '''Mark a file merged.'''
345 self._dirty = True
345 self._dirty = True
346 s = os.lstat(self._join(f))
346 s = os.lstat(self._join(f))
347 self._addpath(f)
347 self._addpath(f)
348 self._map[f] = ('m', s.st_mode, s.st_size, int(s.st_mtime))
348 self._map[f] = ('m', s.st_mode, s.st_size, int(s.st_mtime))
349 if f in self._copymap:
349 if f in self._copymap:
350 del self._copymap[f]
350 del self._copymap[f]
351
351
352 def forget(self, f):
352 def forget(self, f):
353 '''Forget a file.'''
353 '''Forget a file.'''
354 self._dirty = True
354 self._dirty = True
355 try:
355 try:
356 self._droppath(f)
356 self._droppath(f)
357 del self._map[f]
357 del self._map[f]
358 except KeyError:
358 except KeyError:
359 self._ui.warn(_("not in dirstate: %s\n") % f)
359 self._ui.warn(_("not in dirstate: %s\n") % f)
360
360
361 def _normalize(self, path, knownpath):
361 def _normalize(self, path, knownpath):
362 norm_path = os.path.normcase(path)
362 norm_path = os.path.normcase(path)
363 fold_path = self._foldmap.get(norm_path, None)
363 fold_path = self._foldmap.get(norm_path, None)
364 if fold_path is None:
364 if fold_path is None:
365 if knownpath or not os.path.lexists(os.path.join(self._root, path)):
365 if knownpath or not os.path.lexists(os.path.join(self._root, path)):
366 fold_path = path
366 fold_path = path
367 else:
367 else:
368 fold_path = self._foldmap.setdefault(norm_path,
368 fold_path = self._foldmap.setdefault(norm_path,
369 util.fspath(path, self._root))
369 util.fspath(path, self._root))
370 return fold_path
370 return fold_path
371
371
372 def clear(self):
372 def clear(self):
373 self._map = {}
373 self._map = {}
374 if "_dirs" in self.__dict__:
374 if "_dirs" in self.__dict__:
375 delattr(self, "_dirs")
375 delattr(self, "_dirs")
376 self._copymap = {}
376 self._copymap = {}
377 self._pl = [nullid, nullid]
377 self._pl = [nullid, nullid]
378 self._dirty = True
378 self._dirty = True
379
379
380 def rebuild(self, parent, files):
380 def rebuild(self, parent, files):
381 self.clear()
381 self.clear()
382 for f in files:
382 for f in files:
383 if 'x' in files.flags(f):
383 if 'x' in files.flags(f):
384 self._map[f] = ('n', 0777, -1, 0)
384 self._map[f] = ('n', 0777, -1, 0)
385 else:
385 else:
386 self._map[f] = ('n', 0666, -1, 0)
386 self._map[f] = ('n', 0666, -1, 0)
387 self._pl = (parent, nullid)
387 self._pl = (parent, nullid)
388 self._dirty = True
388 self._dirty = True
389
389
390 def write(self):
390 def write(self):
391 if not self._dirty:
391 if not self._dirty:
392 return
392 return
393 st = self._opener("dirstate", "w", atomictemp=True)
393 st = self._opener("dirstate", "w", atomictemp=True)
394
394
395 # use the modification time of the newly created temporary file as the
395 # use the modification time of the newly created temporary file as the
396 # filesystem's notion of 'now'
396 # filesystem's notion of 'now'
397 now = int(util.fstat(st).st_mtime)
397 now = int(util.fstat(st).st_mtime)
398
398
399 cs = cStringIO.StringIO()
399 cs = cStringIO.StringIO()
400 copymap = self._copymap
400 copymap = self._copymap
401 pack = struct.pack
401 pack = struct.pack
402 write = cs.write
402 write = cs.write
403 write("".join(self._pl))
403 write("".join(self._pl))
404 for f, e in self._map.iteritems():
404 for f, e in self._map.iteritems():
405 if e[0] == 'n' and e[3] == now:
405 if e[0] == 'n' and e[3] == now:
406 # The file was last modified "simultaneously" with the current
406 # The file was last modified "simultaneously" with the current
407 # write to dirstate (i.e. within the same second for file-
407 # write to dirstate (i.e. within the same second for file-
408 # systems with a granularity of 1 sec). This commonly happens
408 # systems with a granularity of 1 sec). This commonly happens
409 # for at least a couple of files on 'update'.
409 # for at least a couple of files on 'update'.
410 # The user could change the file without changing its size
410 # The user could change the file without changing its size
411 # within the same second. Invalidate the file's stat data in
411 # within the same second. Invalidate the file's stat data in
412 # dirstate, forcing future 'status' calls to compare the
412 # dirstate, forcing future 'status' calls to compare the
413 # contents of the file. This prevents mistakenly treating such
413 # contents of the file. This prevents mistakenly treating such
414 # files as clean.
414 # files as clean.
415 e = (e[0], 0, -1, -1) # mark entry as 'unset'
415 e = (e[0], 0, -1, -1) # mark entry as 'unset'
416 self._map[f] = e
416 self._map[f] = e
417
417
418 if f in copymap:
418 if f in copymap:
419 f = "%s\0%s" % (f, copymap[f])
419 f = "%s\0%s" % (f, copymap[f])
420 e = pack(_format, e[0], e[1], e[2], e[3], len(f))
420 e = pack(_format, e[0], e[1], e[2], e[3], len(f))
421 write(e)
421 write(e)
422 write(f)
422 write(f)
423 st.write(cs.getvalue())
423 st.write(cs.getvalue())
424 st.rename()
424 st.rename()
425 self._dirty = self._dirtypl = False
425 self._dirty = self._dirtypl = False
426
426
427 def _dirignore(self, f):
427 def _dirignore(self, f):
428 if f == '.':
428 if f == '.':
429 return False
429 return False
430 if self._ignore(f):
430 if self._ignore(f):
431 return True
431 return True
432 for p in _finddirs(f):
432 for p in _finddirs(f):
433 if self._ignore(p):
433 if self._ignore(p):
434 return True
434 return True
435 return False
435 return False
436
436
437 def walk(self, match, subrepos, unknown, ignored):
437 def walk(self, match, subrepos, unknown, ignored):
438 '''
438 '''
439 Walk recursively through the directory tree, finding all files
439 Walk recursively through the directory tree, finding all files
440 matched by match.
440 matched by match.
441
441
442 Return a dict mapping filename to stat-like object (either
442 Return a dict mapping filename to stat-like object (either
443 mercurial.osutil.stat instance or return value of os.stat()).
443 mercurial.osutil.stat instance or return value of os.stat()).
444 '''
444 '''
445
445
446 def fwarn(f, msg):
446 def fwarn(f, msg):
447 self._ui.warn('%s: %s\n' % (self.pathto(f), msg))
447 self._ui.warn('%s: %s\n' % (self.pathto(f), msg))
448 return False
448 return False
449
449
450 def badtype(mode):
450 def badtype(mode):
451 kind = _('unknown')
451 kind = _('unknown')
452 if stat.S_ISCHR(mode):
452 if stat.S_ISCHR(mode):
453 kind = _('character device')
453 kind = _('character device')
454 elif stat.S_ISBLK(mode):
454 elif stat.S_ISBLK(mode):
455 kind = _('block device')
455 kind = _('block device')
456 elif stat.S_ISFIFO(mode):
456 elif stat.S_ISFIFO(mode):
457 kind = _('fifo')
457 kind = _('fifo')
458 elif stat.S_ISSOCK(mode):
458 elif stat.S_ISSOCK(mode):
459 kind = _('socket')
459 kind = _('socket')
460 elif stat.S_ISDIR(mode):
460 elif stat.S_ISDIR(mode):
461 kind = _('directory')
461 kind = _('directory')
462 return _('unsupported file type (type is %s)') % kind
462 return _('unsupported file type (type is %s)') % kind
463
463
464 ignore = self._ignore
464 ignore = self._ignore
465 dirignore = self._dirignore
465 dirignore = self._dirignore
466 if ignored:
466 if ignored:
467 ignore = util.never
467 ignore = util.never
468 dirignore = util.never
468 dirignore = util.never
469 elif not unknown:
469 elif not unknown:
470 # if unknown and ignored are False, skip step 2
470 # if unknown and ignored are False, skip step 2
471 ignore = util.always
471 ignore = util.always
472 dirignore = util.always
472 dirignore = util.always
473
473
474 matchfn = match.matchfn
474 matchfn = match.matchfn
475 badfn = match.bad
475 badfn = match.bad
476 dmap = self._map
476 dmap = self._map
477 normpath = util.normpath
477 normpath = util.normpath
478 listdir = osutil.listdir
478 listdir = osutil.listdir
479 lstat = os.lstat
479 lstat = os.lstat
480 getkind = stat.S_IFMT
480 getkind = stat.S_IFMT
481 dirkind = stat.S_IFDIR
481 dirkind = stat.S_IFDIR
482 regkind = stat.S_IFREG
482 regkind = stat.S_IFREG
483 lnkkind = stat.S_IFLNK
483 lnkkind = stat.S_IFLNK
484 join = self._join
484 join = self._join
485 work = []
485 work = []
486 wadd = work.append
486 wadd = work.append
487
487
488 exact = skipstep3 = False
488 exact = skipstep3 = False
489 if matchfn == match.exact: # match.exact
489 if matchfn == match.exact: # match.exact
490 exact = True
490 exact = True
491 dirignore = util.always # skip step 2
491 dirignore = util.always # skip step 2
492 elif match.files() and not match.anypats(): # match.match, no patterns
492 elif match.files() and not match.anypats(): # match.match, no patterns
493 skipstep3 = True
493 skipstep3 = True
494
494
495 if self._checkcase:
495 if self._checkcase:
496 normalize = self._normalize
496 normalize = self._normalize
497 skipstep3 = False
497 skipstep3 = False
498 else:
498 else:
499 normalize = lambda x, y: x
499 normalize = lambda x, y: x
500
500
501 files = sorted(match.files())
501 files = sorted(match.files())
502 subrepos.sort()
502 subrepos.sort()
503 i, j = 0, 0
503 i, j = 0, 0
504 while i < len(files) and j < len(subrepos):
504 while i < len(files) and j < len(subrepos):
505 subpath = subrepos[j] + "/"
505 subpath = subrepos[j] + "/"
506 if not files[i].startswith(subpath):
506 if files[i] < subpath:
507 i += 1
507 i += 1
508 continue
508 continue
509 while files and files[i].startswith(subpath):
509 while files and files[i].startswith(subpath):
510 del files[i]
510 del files[i]
511 j += 1
511 j += 1
512
512
513 if not files or '.' in files:
513 if not files or '.' in files:
514 files = ['']
514 files = ['']
515 results = dict.fromkeys(subrepos)
515 results = dict.fromkeys(subrepos)
516 results['.hg'] = None
516 results['.hg'] = None
517
517
518 # step 1: find all explicit files
518 # step 1: find all explicit files
519 for ff in files:
519 for ff in files:
520 nf = normalize(normpath(ff), False)
520 nf = normalize(normpath(ff), False)
521 if nf in results:
521 if nf in results:
522 continue
522 continue
523
523
524 try:
524 try:
525 st = lstat(join(nf))
525 st = lstat(join(nf))
526 kind = getkind(st.st_mode)
526 kind = getkind(st.st_mode)
527 if kind == dirkind:
527 if kind == dirkind:
528 skipstep3 = False
528 skipstep3 = False
529 if nf in dmap:
529 if nf in dmap:
530 #file deleted on disk but still in dirstate
530 #file deleted on disk but still in dirstate
531 results[nf] = None
531 results[nf] = None
532 match.dir(nf)
532 match.dir(nf)
533 if not dirignore(nf):
533 if not dirignore(nf):
534 wadd(nf)
534 wadd(nf)
535 elif kind == regkind or kind == lnkkind:
535 elif kind == regkind or kind == lnkkind:
536 results[nf] = st
536 results[nf] = st
537 else:
537 else:
538 badfn(ff, badtype(kind))
538 badfn(ff, badtype(kind))
539 if nf in dmap:
539 if nf in dmap:
540 results[nf] = None
540 results[nf] = None
541 except OSError, inst:
541 except OSError, inst:
542 if nf in dmap: # does it exactly match a file?
542 if nf in dmap: # does it exactly match a file?
543 results[nf] = None
543 results[nf] = None
544 else: # does it match a directory?
544 else: # does it match a directory?
545 prefix = nf + "/"
545 prefix = nf + "/"
546 for fn in dmap:
546 for fn in dmap:
547 if fn.startswith(prefix):
547 if fn.startswith(prefix):
548 match.dir(nf)
548 match.dir(nf)
549 skipstep3 = False
549 skipstep3 = False
550 break
550 break
551 else:
551 else:
552 badfn(ff, inst.strerror)
552 badfn(ff, inst.strerror)
553
553
554 # step 2: visit subdirectories
554 # step 2: visit subdirectories
555 while work:
555 while work:
556 nd = work.pop()
556 nd = work.pop()
557 skip = None
557 skip = None
558 if nd == '.':
558 if nd == '.':
559 nd = ''
559 nd = ''
560 else:
560 else:
561 skip = '.hg'
561 skip = '.hg'
562 try:
562 try:
563 entries = listdir(join(nd), stat=True, skip=skip)
563 entries = listdir(join(nd), stat=True, skip=skip)
564 except OSError, inst:
564 except OSError, inst:
565 if inst.errno == errno.EACCES:
565 if inst.errno == errno.EACCES:
566 fwarn(nd, inst.strerror)
566 fwarn(nd, inst.strerror)
567 continue
567 continue
568 raise
568 raise
569 for f, kind, st in entries:
569 for f, kind, st in entries:
570 nf = normalize(nd and (nd + "/" + f) or f, True)
570 nf = normalize(nd and (nd + "/" + f) or f, True)
571 if nf not in results:
571 if nf not in results:
572 if kind == dirkind:
572 if kind == dirkind:
573 if not ignore(nf):
573 if not ignore(nf):
574 match.dir(nf)
574 match.dir(nf)
575 wadd(nf)
575 wadd(nf)
576 if nf in dmap and matchfn(nf):
576 if nf in dmap and matchfn(nf):
577 results[nf] = None
577 results[nf] = None
578 elif kind == regkind or kind == lnkkind:
578 elif kind == regkind or kind == lnkkind:
579 if nf in dmap:
579 if nf in dmap:
580 if matchfn(nf):
580 if matchfn(nf):
581 results[nf] = st
581 results[nf] = st
582 elif matchfn(nf) and not ignore(nf):
582 elif matchfn(nf) and not ignore(nf):
583 results[nf] = st
583 results[nf] = st
584 elif nf in dmap and matchfn(nf):
584 elif nf in dmap and matchfn(nf):
585 results[nf] = None
585 results[nf] = None
586
586
587 # step 3: report unseen items in the dmap hash
587 # step 3: report unseen items in the dmap hash
588 if not skipstep3 and not exact:
588 if not skipstep3 and not exact:
589 visit = sorted([f for f in dmap if f not in results and matchfn(f)])
589 visit = sorted([f for f in dmap if f not in results and matchfn(f)])
590 for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
590 for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
591 if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
591 if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
592 st = None
592 st = None
593 results[nf] = st
593 results[nf] = st
594 for s in subrepos:
594 for s in subrepos:
595 del results[s]
595 del results[s]
596 del results['.hg']
596 del results['.hg']
597 return results
597 return results
598
598
599 def status(self, match, subrepos, ignored, clean, unknown):
599 def status(self, match, subrepos, ignored, clean, unknown):
600 '''Determine the status of the working copy relative to the
600 '''Determine the status of the working copy relative to the
601 dirstate and return a tuple of lists (unsure, modified, added,
601 dirstate and return a tuple of lists (unsure, modified, added,
602 removed, deleted, unknown, ignored, clean), where:
602 removed, deleted, unknown, ignored, clean), where:
603
603
604 unsure:
604 unsure:
605 files that might have been modified since the dirstate was
605 files that might have been modified since the dirstate was
606 written, but need to be read to be sure (size is the same
606 written, but need to be read to be sure (size is the same
607 but mtime differs)
607 but mtime differs)
608 modified:
608 modified:
609 files that have definitely been modified since the dirstate
609 files that have definitely been modified since the dirstate
610 was written (different size or mode)
610 was written (different size or mode)
611 added:
611 added:
612 files that have been explicitly added with hg add
612 files that have been explicitly added with hg add
613 removed:
613 removed:
614 files that have been explicitly removed with hg remove
614 files that have been explicitly removed with hg remove
615 deleted:
615 deleted:
616 files that have been deleted through other means ("missing")
616 files that have been deleted through other means ("missing")
617 unknown:
617 unknown:
618 files not in the dirstate that are not ignored
618 files not in the dirstate that are not ignored
619 ignored:
619 ignored:
620 files not in the dirstate that are ignored
620 files not in the dirstate that are ignored
621 (by _dirignore())
621 (by _dirignore())
622 clean:
622 clean:
623 files that have definitely not been modified since the
623 files that have definitely not been modified since the
624 dirstate was written
624 dirstate was written
625 '''
625 '''
626 listignored, listclean, listunknown = ignored, clean, unknown
626 listignored, listclean, listunknown = ignored, clean, unknown
627 lookup, modified, added, unknown, ignored = [], [], [], [], []
627 lookup, modified, added, unknown, ignored = [], [], [], [], []
628 removed, deleted, clean = [], [], []
628 removed, deleted, clean = [], [], []
629
629
630 dmap = self._map
630 dmap = self._map
631 ladd = lookup.append # aka "unsure"
631 ladd = lookup.append # aka "unsure"
632 madd = modified.append
632 madd = modified.append
633 aadd = added.append
633 aadd = added.append
634 uadd = unknown.append
634 uadd = unknown.append
635 iadd = ignored.append
635 iadd = ignored.append
636 radd = removed.append
636 radd = removed.append
637 dadd = deleted.append
637 dadd = deleted.append
638 cadd = clean.append
638 cadd = clean.append
639
639
640 lnkkind = stat.S_IFLNK
640 lnkkind = stat.S_IFLNK
641
641
642 for fn, st in self.walk(match, subrepos, listunknown,
642 for fn, st in self.walk(match, subrepos, listunknown,
643 listignored).iteritems():
643 listignored).iteritems():
644 if fn not in dmap:
644 if fn not in dmap:
645 if (listignored or match.exact(fn)) and self._dirignore(fn):
645 if (listignored or match.exact(fn)) and self._dirignore(fn):
646 if listignored:
646 if listignored:
647 iadd(fn)
647 iadd(fn)
648 elif listunknown:
648 elif listunknown:
649 uadd(fn)
649 uadd(fn)
650 continue
650 continue
651
651
652 state, mode, size, time = dmap[fn]
652 state, mode, size, time = dmap[fn]
653
653
654 if not st and state in "nma":
654 if not st and state in "nma":
655 dadd(fn)
655 dadd(fn)
656 elif state == 'n':
656 elif state == 'n':
657 # The "mode & lnkkind != lnkkind or self._checklink"
657 # The "mode & lnkkind != lnkkind or self._checklink"
658 # lines are an expansion of "islink => checklink"
658 # lines are an expansion of "islink => checklink"
659 # where islink means "is this a link?" and checklink
659 # where islink means "is this a link?" and checklink
660 # means "can we check links?".
660 # means "can we check links?".
661 if (size >= 0 and
661 if (size >= 0 and
662 (size != st.st_size
662 (size != st.st_size
663 or ((mode ^ st.st_mode) & 0100 and self._checkexec))
663 or ((mode ^ st.st_mode) & 0100 and self._checkexec))
664 and (mode & lnkkind != lnkkind or self._checklink)
664 and (mode & lnkkind != lnkkind or self._checklink)
665 or size == -2 # other parent
665 or size == -2 # other parent
666 or fn in self._copymap):
666 or fn in self._copymap):
667 madd(fn)
667 madd(fn)
668 elif (time != int(st.st_mtime)
668 elif (time != int(st.st_mtime)
669 and (mode & lnkkind != lnkkind or self._checklink)):
669 and (mode & lnkkind != lnkkind or self._checklink)):
670 ladd(fn)
670 ladd(fn)
671 elif listclean:
671 elif listclean:
672 cadd(fn)
672 cadd(fn)
673 elif state == 'm':
673 elif state == 'm':
674 madd(fn)
674 madd(fn)
675 elif state == 'a':
675 elif state == 'a':
676 aadd(fn)
676 aadd(fn)
677 elif state == 'r':
677 elif state == 'r':
678 radd(fn)
678 radd(fn)
679
679
680 return (lookup, modified, added, removed, deleted, unknown, ignored,
680 return (lookup, modified, added, removed, deleted, unknown, ignored,
681 clean)
681 clean)
@@ -1,658 +1,677 b''
1 $ rm -rf sub
1 $ rm -rf sub
2 $ mkdir sub
2 $ mkdir sub
3 $ cd sub
3 $ cd sub
4 $ hg init t
4 $ hg init t
5 $ cd t
5 $ cd t
6
6
7 first revision, no sub
7 first revision, no sub
8
8
9 $ echo a > a
9 $ echo a > a
10 $ hg ci -Am0
10 $ hg ci -Am0
11 adding a
11 adding a
12
12
13 add first sub
13 add first sub
14
14
15 $ echo s = s > .hgsub
15 $ echo s = s > .hgsub
16 $ hg add .hgsub
16 $ hg add .hgsub
17 $ hg init s
17 $ hg init s
18 $ echo a > s/a
18 $ echo a > s/a
19
19
20 Issue2232: committing a subrepo without .hgsub
20 Issue2232: committing a subrepo without .hgsub
21
21
22 $ hg ci -mbad s
22 $ hg ci -mbad s
23 abort: can't commit subrepos without .hgsub
23 abort: can't commit subrepos without .hgsub
24 [255]
24 [255]
25
25
26 $ hg -R s ci -Ams0
26 $ hg -R s ci -Ams0
27 adding a
27 adding a
28 $ hg sum
28 $ hg sum
29 parent: 0:f7b1eb17ad24 tip
29 parent: 0:f7b1eb17ad24 tip
30 0
30 0
31 branch: default
31 branch: default
32 commit: 1 added, 1 subrepos
32 commit: 1 added, 1 subrepos
33 update: (current)
33 update: (current)
34 $ hg ci -m1
34 $ hg ci -m1
35 committing subrepository s
35 committing subrepository s
36
36
37 Issue2022: update -C
37 Issue2022: update -C
38
38
39 $ echo b > s/a
39 $ echo b > s/a
40 $ hg sum
40 $ hg sum
41 parent: 1:7cf8cfea66e4 tip
41 parent: 1:7cf8cfea66e4 tip
42 1
42 1
43 branch: default
43 branch: default
44 commit: 1 subrepos
44 commit: 1 subrepos
45 update: (current)
45 update: (current)
46 $ hg co -C 1
46 $ hg co -C 1
47 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
47 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 $ hg sum
48 $ hg sum
49 parent: 1:7cf8cfea66e4 tip
49 parent: 1:7cf8cfea66e4 tip
50 1
50 1
51 branch: default
51 branch: default
52 commit: (clean)
52 commit: (clean)
53 update: (current)
53 update: (current)
54
54
55 add sub sub
55 add sub sub
56
56
57 $ echo ss = ss > s/.hgsub
57 $ echo ss = ss > s/.hgsub
58 $ hg init s/ss
58 $ hg init s/ss
59 $ echo a > s/ss/a
59 $ echo a > s/ss/a
60 $ hg -R s add s/.hgsub
60 $ hg -R s add s/.hgsub
61 $ hg -R s/ss add s/ss/a
61 $ hg -R s/ss add s/ss/a
62 $ hg sum
62 $ hg sum
63 parent: 1:7cf8cfea66e4 tip
63 parent: 1:7cf8cfea66e4 tip
64 1
64 1
65 branch: default
65 branch: default
66 commit: 1 subrepos
66 commit: 1 subrepos
67 update: (current)
67 update: (current)
68 $ hg ci -m2
68 $ hg ci -m2
69 committing subrepository s
69 committing subrepository s
70 committing subrepository s/ss
70 committing subrepository s/ss
71 $ hg sum
71 $ hg sum
72 parent: 2:df30734270ae tip
72 parent: 2:df30734270ae tip
73 2
73 2
74 branch: default
74 branch: default
75 commit: (clean)
75 commit: (clean)
76 update: (current)
76 update: (current)
77
77
78 bump sub rev
78 bump sub rev
79
79
80 $ echo b > s/a
80 $ echo b > s/a
81 $ hg -R s ci -ms1
81 $ hg -R s ci -ms1
82 $ hg ci -m3
82 $ hg ci -m3
83 committing subrepository s
83 committing subrepository s
84
84
85 leave sub dirty
85 leave sub dirty
86
86
87 $ echo c > s/a
87 $ echo c > s/a
88 $ hg ci -m4
88 $ hg ci -m4
89 committing subrepository s
89 committing subrepository s
90 $ hg tip -R s
90 $ hg tip -R s
91 changeset: 3:1c833a7a9e3a
91 changeset: 3:1c833a7a9e3a
92 tag: tip
92 tag: tip
93 user: test
93 user: test
94 date: Thu Jan 01 00:00:00 1970 +0000
94 date: Thu Jan 01 00:00:00 1970 +0000
95 summary: 4
95 summary: 4
96
96
97
97
98 check caching
98 check caching
99
99
100 $ hg co 0
100 $ hg co 0
101 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
101 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
102 $ hg debugsub
102 $ hg debugsub
103
103
104 restore
104 restore
105
105
106 $ hg co
106 $ hg co
107 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 $ hg debugsub
108 $ hg debugsub
109 path s
109 path s
110 source s
110 source s
111 revision 1c833a7a9e3a4445c711aaf0f012379cd0d4034e
111 revision 1c833a7a9e3a4445c711aaf0f012379cd0d4034e
112
112
113 new branch for merge tests
113 new branch for merge tests
114
114
115 $ hg co 1
115 $ hg co 1
116 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 $ echo t = t >> .hgsub
117 $ echo t = t >> .hgsub
118 $ hg init t
118 $ hg init t
119 $ echo t > t/t
119 $ echo t > t/t
120 $ hg -R t add t
120 $ hg -R t add t
121 adding t/t
121 adding t/t
122
122
123 5
123 5
124
124
125 $ hg ci -m5 # add sub
125 $ hg ci -m5 # add sub
126 committing subrepository t
126 committing subrepository t
127 created new head
127 created new head
128 $ echo t2 > t/t
128 $ echo t2 > t/t
129
129
130 6
130 6
131
131
132 $ hg st -R s
132 $ hg st -R s
133 $ hg ci -m6 # change sub
133 $ hg ci -m6 # change sub
134 committing subrepository t
134 committing subrepository t
135 $ hg debugsub
135 $ hg debugsub
136 path s
136 path s
137 source s
137 source s
138 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
138 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
139 path t
139 path t
140 source t
140 source t
141 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
141 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
142 $ echo t3 > t/t
142 $ echo t3 > t/t
143
143
144 7
144 7
145
145
146 $ hg ci -m7 # change sub again for conflict test
146 $ hg ci -m7 # change sub again for conflict test
147 committing subrepository t
147 committing subrepository t
148 $ hg rm .hgsub
148 $ hg rm .hgsub
149
149
150 8
150 8
151
151
152 $ hg ci -m8 # remove sub
152 $ hg ci -m8 # remove sub
153
153
154 merge tests
154 merge tests
155
155
156 $ hg co -C 3
156 $ hg co -C 3
157 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
157 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
158 $ hg merge 5 # test adding
158 $ hg merge 5 # test adding
159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 (branch merge, don't forget to commit)
160 (branch merge, don't forget to commit)
161 $ hg debugsub
161 $ hg debugsub
162 path s
162 path s
163 source s
163 source s
164 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
164 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
165 path t
165 path t
166 source t
166 source t
167 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
167 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
168 $ hg ci -m9
168 $ hg ci -m9
169 created new head
169 created new head
170 $ hg merge 6 --debug # test change
170 $ hg merge 6 --debug # test change
171 searching for copies back to rev 2
171 searching for copies back to rev 2
172 resolving manifests
172 resolving manifests
173 overwrite None partial False
173 overwrite None partial False
174 ancestor 1f14a2e2d3ec local f0d2028bf86d+ remote 1831e14459c4
174 ancestor 1f14a2e2d3ec local f0d2028bf86d+ remote 1831e14459c4
175 .hgsubstate: versions differ -> m
175 .hgsubstate: versions differ -> m
176 updating: .hgsubstate 1/1 files (100.00%)
176 updating: .hgsubstate 1/1 files (100.00%)
177 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
177 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
178 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
178 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
179 getting subrepo t
179 getting subrepo t
180 resolving manifests
180 resolving manifests
181 overwrite True partial False
181 overwrite True partial False
182 ancestor 60ca1237c194+ local 60ca1237c194+ remote 6747d179aa9a
182 ancestor 60ca1237c194+ local 60ca1237c194+ remote 6747d179aa9a
183 t: remote is newer -> g
183 t: remote is newer -> g
184 updating: t 1/1 files (100.00%)
184 updating: t 1/1 files (100.00%)
185 getting t
185 getting t
186 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
186 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
187 (branch merge, don't forget to commit)
187 (branch merge, don't forget to commit)
188 $ hg debugsub
188 $ hg debugsub
189 path s
189 path s
190 source s
190 source s
191 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
191 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
192 path t
192 path t
193 source t
193 source t
194 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
194 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
195 $ echo conflict > t/t
195 $ echo conflict > t/t
196 $ hg ci -m10
196 $ hg ci -m10
197 committing subrepository t
197 committing subrepository t
198 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
198 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
199 searching for copies back to rev 2
199 searching for copies back to rev 2
200 resolving manifests
200 resolving manifests
201 overwrite None partial False
201 overwrite None partial False
202 ancestor 1831e14459c4 local e45c8b14af55+ remote f94576341bcf
202 ancestor 1831e14459c4 local e45c8b14af55+ remote f94576341bcf
203 .hgsubstate: versions differ -> m
203 .hgsubstate: versions differ -> m
204 updating: .hgsubstate 1/1 files (100.00%)
204 updating: .hgsubstate 1/1 files (100.00%)
205 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
205 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
206 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
206 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
207 merging subrepo t
207 merging subrepo t
208 searching for copies back to rev 2
208 searching for copies back to rev 2
209 resolving manifests
209 resolving manifests
210 overwrite None partial False
210 overwrite None partial False
211 ancestor 6747d179aa9a local 20a0db6fbf6c+ remote 7af322bc1198
211 ancestor 6747d179aa9a local 20a0db6fbf6c+ remote 7af322bc1198
212 t: versions differ -> m
212 t: versions differ -> m
213 preserving t for resolve of t
213 preserving t for resolve of t
214 updating: t 1/1 files (100.00%)
214 updating: t 1/1 files (100.00%)
215 picked tool 'internal:merge' for t (binary False symlink False)
215 picked tool 'internal:merge' for t (binary False symlink False)
216 merging t
216 merging t
217 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
217 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
218 warning: conflicts during merge.
218 warning: conflicts during merge.
219 merging t failed!
219 merging t failed!
220 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
220 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
221 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
221 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
222 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
222 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
223 (branch merge, don't forget to commit)
223 (branch merge, don't forget to commit)
224
224
225 should conflict
225 should conflict
226
226
227 $ cat t/t
227 $ cat t/t
228 <<<<<<< local
228 <<<<<<< local
229 conflict
229 conflict
230 =======
230 =======
231 t3
231 t3
232 >>>>>>> other
232 >>>>>>> other
233
233
234 clone
234 clone
235
235
236 $ cd ..
236 $ cd ..
237 $ hg clone t tc
237 $ hg clone t tc
238 updating to branch default
238 updating to branch default
239 pulling subrepo s from $TESTTMP/sub/t/s
239 pulling subrepo s from $TESTTMP/sub/t/s
240 requesting all changes
240 requesting all changes
241 adding changesets
241 adding changesets
242 adding manifests
242 adding manifests
243 adding file changes
243 adding file changes
244 added 4 changesets with 5 changes to 3 files
244 added 4 changesets with 5 changes to 3 files
245 pulling subrepo s/ss from $TESTTMP/sub/t/s/ss
245 pulling subrepo s/ss from $TESTTMP/sub/t/s/ss
246 requesting all changes
246 requesting all changes
247 adding changesets
247 adding changesets
248 adding manifests
248 adding manifests
249 adding file changes
249 adding file changes
250 added 1 changesets with 1 changes to 1 files
250 added 1 changesets with 1 changes to 1 files
251 pulling subrepo t from $TESTTMP/sub/t/t
251 pulling subrepo t from $TESTTMP/sub/t/t
252 requesting all changes
252 requesting all changes
253 adding changesets
253 adding changesets
254 adding manifests
254 adding manifests
255 adding file changes
255 adding file changes
256 added 4 changesets with 4 changes to 1 files (+1 heads)
256 added 4 changesets with 4 changes to 1 files (+1 heads)
257 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 $ cd tc
258 $ cd tc
259 $ hg debugsub
259 $ hg debugsub
260 path s
260 path s
261 source s
261 source s
262 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
262 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
263 path t
263 path t
264 source t
264 source t
265 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
265 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
266
266
267 push
267 push
268
268
269 $ echo bah > t/t
269 $ echo bah > t/t
270 $ hg ci -m11
270 $ hg ci -m11
271 committing subrepository t
271 committing subrepository t
272 $ hg push
272 $ hg push
273 pushing to $TESTTMP/sub/t
273 pushing to $TESTTMP/sub/t
274 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
274 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
275 searching for changes
275 searching for changes
276 no changes found
276 no changes found
277 pushing subrepo s to $TESTTMP/sub/t/s
277 pushing subrepo s to $TESTTMP/sub/t/s
278 searching for changes
278 searching for changes
279 no changes found
279 no changes found
280 pushing subrepo t to $TESTTMP/sub/t/t
280 pushing subrepo t to $TESTTMP/sub/t/t
281 searching for changes
281 searching for changes
282 adding changesets
282 adding changesets
283 adding manifests
283 adding manifests
284 adding file changes
284 adding file changes
285 added 1 changesets with 1 changes to 1 files
285 added 1 changesets with 1 changes to 1 files
286 searching for changes
286 searching for changes
287 adding changesets
287 adding changesets
288 adding manifests
288 adding manifests
289 adding file changes
289 adding file changes
290 added 1 changesets with 1 changes to 1 files
290 added 1 changesets with 1 changes to 1 files
291
291
292 push -f
292 push -f
293
293
294 $ echo bah > s/a
294 $ echo bah > s/a
295 $ hg ci -m12
295 $ hg ci -m12
296 committing subrepository s
296 committing subrepository s
297 $ hg push
297 $ hg push
298 pushing to $TESTTMP/sub/t
298 pushing to $TESTTMP/sub/t
299 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
299 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
300 searching for changes
300 searching for changes
301 no changes found
301 no changes found
302 pushing subrepo s to $TESTTMP/sub/t/s
302 pushing subrepo s to $TESTTMP/sub/t/s
303 searching for changes
303 searching for changes
304 abort: push creates new remote heads on branch 'default'!
304 abort: push creates new remote heads on branch 'default'!
305 (did you forget to merge? use push -f to force)
305 (did you forget to merge? use push -f to force)
306 [255]
306 [255]
307 $ hg push -f
307 $ hg push -f
308 pushing to $TESTTMP/sub/t
308 pushing to $TESTTMP/sub/t
309 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
309 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
310 searching for changes
310 searching for changes
311 no changes found
311 no changes found
312 pushing subrepo s to $TESTTMP/sub/t/s
312 pushing subrepo s to $TESTTMP/sub/t/s
313 searching for changes
313 searching for changes
314 adding changesets
314 adding changesets
315 adding manifests
315 adding manifests
316 adding file changes
316 adding file changes
317 added 1 changesets with 1 changes to 1 files (+1 heads)
317 added 1 changesets with 1 changes to 1 files (+1 heads)
318 pushing subrepo t to $TESTTMP/sub/t/t
318 pushing subrepo t to $TESTTMP/sub/t/t
319 searching for changes
319 searching for changes
320 no changes found
320 no changes found
321 searching for changes
321 searching for changes
322 adding changesets
322 adding changesets
323 adding manifests
323 adding manifests
324 adding file changes
324 adding file changes
325 added 1 changesets with 1 changes to 1 files
325 added 1 changesets with 1 changes to 1 files
326
326
327 update
327 update
328
328
329 $ cd ../t
329 $ cd ../t
330 $ hg up -C # discard our earlier merge
330 $ hg up -C # discard our earlier merge
331 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
331 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
332 $ echo blah > t/t
332 $ echo blah > t/t
333 $ hg ci -m13
333 $ hg ci -m13
334 committing subrepository t
334 committing subrepository t
335
335
336 pull
336 pull
337
337
338 $ cd ../tc
338 $ cd ../tc
339 $ hg pull
339 $ hg pull
340 pulling from $TESTTMP/sub/t
340 pulling from $TESTTMP/sub/t
341 searching for changes
341 searching for changes
342 adding changesets
342 adding changesets
343 adding manifests
343 adding manifests
344 adding file changes
344 adding file changes
345 added 1 changesets with 1 changes to 1 files
345 added 1 changesets with 1 changes to 1 files
346 (run 'hg update' to get a working copy)
346 (run 'hg update' to get a working copy)
347
347
348 should pull t
348 should pull t
349
349
350 $ hg up
350 $ hg up
351 pulling subrepo t from $TESTTMP/sub/t/t
351 pulling subrepo t from $TESTTMP/sub/t/t
352 searching for changes
352 searching for changes
353 adding changesets
353 adding changesets
354 adding manifests
354 adding manifests
355 adding file changes
355 adding file changes
356 added 1 changesets with 1 changes to 1 files
356 added 1 changesets with 1 changes to 1 files
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
358 $ cat t/t
358 $ cat t/t
359 blah
359 blah
360
360
361 bogus subrepo path aborts
361 bogus subrepo path aborts
362
362
363 $ echo 'bogus=[boguspath' >> .hgsub
363 $ echo 'bogus=[boguspath' >> .hgsub
364 $ hg ci -m 'bogus subrepo path'
364 $ hg ci -m 'bogus subrepo path'
365 abort: missing ] in subrepo source
365 abort: missing ] in subrepo source
366 [255]
366 [255]
367
367
368 Issue1986: merge aborts when trying to merge a subrepo that
368 Issue1986: merge aborts when trying to merge a subrepo that
369 shouldn't need merging
369 shouldn't need merging
370
370
371 # subrepo layout
371 # subrepo layout
372 #
372 #
373 # o 5 br
373 # o 5 br
374 # /|
374 # /|
375 # o | 4 default
375 # o | 4 default
376 # | |
376 # | |
377 # | o 3 br
377 # | o 3 br
378 # |/|
378 # |/|
379 # o | 2 default
379 # o | 2 default
380 # | |
380 # | |
381 # | o 1 br
381 # | o 1 br
382 # |/
382 # |/
383 # o 0 default
383 # o 0 default
384
384
385 $ cd ..
385 $ cd ..
386 $ rm -rf sub
386 $ rm -rf sub
387 $ hg init main
387 $ hg init main
388 $ cd main
388 $ cd main
389 $ hg init s
389 $ hg init s
390 $ cd s
390 $ cd s
391 $ echo a > a
391 $ echo a > a
392 $ hg ci -Am1
392 $ hg ci -Am1
393 adding a
393 adding a
394 $ hg branch br
394 $ hg branch br
395 marked working directory as branch br
395 marked working directory as branch br
396 $ echo a >> a
396 $ echo a >> a
397 $ hg ci -m1
397 $ hg ci -m1
398 $ hg up default
398 $ hg up default
399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
400 $ echo b > b
400 $ echo b > b
401 $ hg ci -Am1
401 $ hg ci -Am1
402 adding b
402 adding b
403 $ hg up br
403 $ hg up br
404 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
404 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
405 $ hg merge tip
405 $ hg merge tip
406 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
406 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
407 (branch merge, don't forget to commit)
407 (branch merge, don't forget to commit)
408 $ hg ci -m1
408 $ hg ci -m1
409 $ hg up 2
409 $ hg up 2
410 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
410 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
411 $ echo c > c
411 $ echo c > c
412 $ hg ci -Am1
412 $ hg ci -Am1
413 adding c
413 adding c
414 $ hg up 3
414 $ hg up 3
415 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
415 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
416 $ hg merge 4
416 $ hg merge 4
417 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
417 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
418 (branch merge, don't forget to commit)
418 (branch merge, don't forget to commit)
419 $ hg ci -m1
419 $ hg ci -m1
420
420
421 # main repo layout:
421 # main repo layout:
422 #
422 #
423 # * <-- try to merge default into br again
423 # * <-- try to merge default into br again
424 # .`|
424 # .`|
425 # . o 5 br --> substate = 5
425 # . o 5 br --> substate = 5
426 # . |
426 # . |
427 # o | 4 default --> substate = 4
427 # o | 4 default --> substate = 4
428 # | |
428 # | |
429 # | o 3 br --> substate = 2
429 # | o 3 br --> substate = 2
430 # |/|
430 # |/|
431 # o | 2 default --> substate = 2
431 # o | 2 default --> substate = 2
432 # | |
432 # | |
433 # | o 1 br --> substate = 3
433 # | o 1 br --> substate = 3
434 # |/
434 # |/
435 # o 0 default --> substate = 2
435 # o 0 default --> substate = 2
436
436
437 $ cd ..
437 $ cd ..
438 $ echo 's = s' > .hgsub
438 $ echo 's = s' > .hgsub
439 $ hg -R s up 2
439 $ hg -R s up 2
440 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
440 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
441 $ hg ci -Am1
441 $ hg ci -Am1
442 adding .hgsub
442 adding .hgsub
443 committing subrepository s
443 committing subrepository s
444 $ hg branch br
444 $ hg branch br
445 marked working directory as branch br
445 marked working directory as branch br
446 $ echo b > b
446 $ echo b > b
447 $ hg -R s up 3
447 $ hg -R s up 3
448 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
448 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
449 $ hg ci -Am1
449 $ hg ci -Am1
450 adding b
450 adding b
451 committing subrepository s
451 committing subrepository s
452 $ hg up default
452 $ hg up default
453 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
454 $ echo c > c
454 $ echo c > c
455 $ hg ci -Am1
455 $ hg ci -Am1
456 adding c
456 adding c
457 $ hg up 1
457 $ hg up 1
458 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
458 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
459 $ hg merge 2
459 $ hg merge 2
460 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
460 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 (branch merge, don't forget to commit)
461 (branch merge, don't forget to commit)
462 $ hg ci -m1
462 $ hg ci -m1
463 $ hg up 2
463 $ hg up 2
464 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
464 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
465 $ hg -R s up 4
465 $ hg -R s up 4
466 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
466 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
467 $ echo d > d
467 $ echo d > d
468 $ hg ci -Am1
468 $ hg ci -Am1
469 adding d
469 adding d
470 committing subrepository s
470 committing subrepository s
471 $ hg up 3
471 $ hg up 3
472 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
472 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
473 $ hg -R s up 5
473 $ hg -R s up 5
474 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
474 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
475 $ echo e > e
475 $ echo e > e
476 $ hg ci -Am1
476 $ hg ci -Am1
477 adding e
477 adding e
478 committing subrepository s
478 committing subrepository s
479
479
480 $ hg up 5
480 $ hg up 5
481 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
481 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
482 $ hg merge 4 # try to merge default into br again
482 $ hg merge 4 # try to merge default into br again
483 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
483 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
484 (branch merge, don't forget to commit)
484 (branch merge, don't forget to commit)
485 $ cd ..
485 $ cd ..
486
486
487 test subrepo delete from .hgsubstate
487 test subrepo delete from .hgsubstate
488
488
489 $ hg init testdelete
489 $ hg init testdelete
490 $ mkdir testdelete/nested testdelete/nested2
490 $ mkdir testdelete/nested testdelete/nested2
491 $ hg init testdelete/nested
491 $ hg init testdelete/nested
492 $ hg init testdelete/nested2
492 $ hg init testdelete/nested2
493 $ echo test > testdelete/nested/foo
493 $ echo test > testdelete/nested/foo
494 $ echo test > testdelete/nested2/foo
494 $ echo test > testdelete/nested2/foo
495 $ hg -R testdelete/nested add
495 $ hg -R testdelete/nested add
496 adding testdelete/nested/foo
496 adding testdelete/nested/foo
497 $ hg -R testdelete/nested2 add
497 $ hg -R testdelete/nested2 add
498 adding testdelete/nested2/foo
498 adding testdelete/nested2/foo
499 $ hg -R testdelete/nested ci -m test
499 $ hg -R testdelete/nested ci -m test
500 $ hg -R testdelete/nested2 ci -m test
500 $ hg -R testdelete/nested2 ci -m test
501 $ echo nested = nested > testdelete/.hgsub
501 $ echo nested = nested > testdelete/.hgsub
502 $ echo nested2 = nested2 >> testdelete/.hgsub
502 $ echo nested2 = nested2 >> testdelete/.hgsub
503 $ hg -R testdelete add
503 $ hg -R testdelete add
504 adding testdelete/.hgsub
504 adding testdelete/.hgsub
505 $ hg -R testdelete ci -m "nested 1 & 2 added"
505 $ hg -R testdelete ci -m "nested 1 & 2 added"
506 committing subrepository nested
506 committing subrepository nested
507 committing subrepository nested2
507 committing subrepository nested2
508 $ echo nested = nested > testdelete/.hgsub
508 $ echo nested = nested > testdelete/.hgsub
509 $ hg -R testdelete ci -m "nested 2 deleted"
509 $ hg -R testdelete ci -m "nested 2 deleted"
510 $ cat testdelete/.hgsubstate
510 $ cat testdelete/.hgsubstate
511 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
511 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
512 $ hg -R testdelete remove testdelete/.hgsub
512 $ hg -R testdelete remove testdelete/.hgsub
513 $ hg -R testdelete ci -m ".hgsub deleted"
513 $ hg -R testdelete ci -m ".hgsub deleted"
514 $ cat testdelete/.hgsubstate
514 $ cat testdelete/.hgsubstate
515
515
516 test repository cloning
516 test repository cloning
517
517
518 $ mkdir mercurial mercurial2
518 $ mkdir mercurial mercurial2
519 $ hg init nested_absolute
519 $ hg init nested_absolute
520 $ echo test > nested_absolute/foo
520 $ echo test > nested_absolute/foo
521 $ hg -R nested_absolute add
521 $ hg -R nested_absolute add
522 adding nested_absolute/foo
522 adding nested_absolute/foo
523 $ hg -R nested_absolute ci -mtest
523 $ hg -R nested_absolute ci -mtest
524 $ cd mercurial
524 $ cd mercurial
525 $ hg init nested_relative
525 $ hg init nested_relative
526 $ echo test2 > nested_relative/foo2
526 $ echo test2 > nested_relative/foo2
527 $ hg -R nested_relative add
527 $ hg -R nested_relative add
528 adding nested_relative/foo2
528 adding nested_relative/foo2
529 $ hg -R nested_relative ci -mtest2
529 $ hg -R nested_relative ci -mtest2
530 $ hg init main
530 $ hg init main
531 $ echo "nested_relative = ../nested_relative" > main/.hgsub
531 $ echo "nested_relative = ../nested_relative" > main/.hgsub
532 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
532 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
533 $ hg -R main add
533 $ hg -R main add
534 adding main/.hgsub
534 adding main/.hgsub
535 $ hg -R main ci -m "add subrepos"
535 $ hg -R main ci -m "add subrepos"
536 committing subrepository nested_absolute
536 committing subrepository nested_absolute
537 committing subrepository nested_relative
537 committing subrepository nested_relative
538 $ cd ..
538 $ cd ..
539 $ hg clone mercurial/main mercurial2/main
539 $ hg clone mercurial/main mercurial2/main
540 updating to branch default
540 updating to branch default
541 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
541 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
542 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
542 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
543 > mercurial2/main/nested_relative/.hg/hgrc
543 > mercurial2/main/nested_relative/.hg/hgrc
544 [paths]
544 [paths]
545 default = $TESTTMP/sub/mercurial/nested_absolute
545 default = $TESTTMP/sub/mercurial/nested_absolute
546 [paths]
546 [paths]
547 default = $TESTTMP/sub/mercurial/nested_relative
547 default = $TESTTMP/sub/mercurial/nested_relative
548 $ rm -rf mercurial mercurial2
548 $ rm -rf mercurial mercurial2
549
549
550 Issue1977: multirepo push should fail if subrepo push fails
550 Issue1977: multirepo push should fail if subrepo push fails
551
551
552 $ hg init repo
552 $ hg init repo
553 $ hg init repo/s
553 $ hg init repo/s
554 $ echo a > repo/s/a
554 $ echo a > repo/s/a
555 $ hg -R repo/s ci -Am0
555 $ hg -R repo/s ci -Am0
556 adding a
556 adding a
557 $ echo s = s > repo/.hgsub
557 $ echo s = s > repo/.hgsub
558 $ hg -R repo ci -Am1
558 $ hg -R repo ci -Am1
559 adding .hgsub
559 adding .hgsub
560 committing subrepository s
560 committing subrepository s
561 $ hg clone repo repo2
561 $ hg clone repo repo2
562 updating to branch default
562 updating to branch default
563 pulling subrepo s from $TESTTMP/sub/repo/s
563 pulling subrepo s from $TESTTMP/sub/repo/s
564 requesting all changes
564 requesting all changes
565 adding changesets
565 adding changesets
566 adding manifests
566 adding manifests
567 adding file changes
567 adding file changes
568 added 1 changesets with 1 changes to 1 files
568 added 1 changesets with 1 changes to 1 files
569 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
569 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
570 $ hg -q -R repo2 pull -u
570 $ hg -q -R repo2 pull -u
571 $ echo 1 > repo2/s/a
571 $ echo 1 > repo2/s/a
572 $ hg -R repo2/s ci -m2
572 $ hg -R repo2/s ci -m2
573 $ hg -q -R repo2/s push
573 $ hg -q -R repo2/s push
574 $ hg -R repo2/s up -C 0
574 $ hg -R repo2/s up -C 0
575 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
575 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
576 $ echo 2 > repo2/s/a
576 $ echo 2 > repo2/s/a
577 $ hg -R repo2/s ci -m3
577 $ hg -R repo2/s ci -m3
578 created new head
578 created new head
579 $ hg -R repo2 ci -m3
579 $ hg -R repo2 ci -m3
580 committing subrepository s
580 committing subrepository s
581 $ hg -q -R repo2 push
581 $ hg -q -R repo2 push
582 abort: push creates new remote heads on branch 'default'!
582 abort: push creates new remote heads on branch 'default'!
583 (did you forget to merge? use push -f to force)
583 (did you forget to merge? use push -f to force)
584 [255]
584 [255]
585 $ hg -R repo update
585 $ hg -R repo update
586 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
586 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
587 $ rm -rf repo2 repo
587 $ rm -rf repo2 repo
588
588
589
589
590 Issue1852 subrepos with relative paths always push/pull relative to default
590 Issue1852 subrepos with relative paths always push/pull relative to default
591
591
592 Prepare a repo with subrepo
592 Prepare a repo with subrepo
593
593
594 $ hg init issue1852a
594 $ hg init issue1852a
595 $ cd issue1852a
595 $ cd issue1852a
596 $ hg init sub/repo
596 $ hg init sub/repo
597 $ echo test > sub/repo/foo
597 $ echo test > sub/repo/foo
598 $ hg -R sub/repo add sub/repo/foo
598 $ hg -R sub/repo add sub/repo/foo
599 $ echo sub/repo = sub/repo > .hgsub
599 $ echo sub/repo = sub/repo > .hgsub
600 $ hg add .hgsub
600 $ hg add .hgsub
601 $ hg ci -mtest
601 $ hg ci -mtest
602 committing subrepository sub/repo
602 committing subrepository sub/repo
603 $ echo test >> sub/repo/foo
603 $ echo test >> sub/repo/foo
604 $ hg ci -mtest
604 $ hg ci -mtest
605 committing subrepository sub/repo
605 committing subrepository sub/repo
606 $ cd ..
606 $ cd ..
607
607
608 Create repo without default path, pull top repo, and see what happens on update
608 Create repo without default path, pull top repo, and see what happens on update
609
609
610 $ hg init issue1852b
610 $ hg init issue1852b
611 $ hg -R issue1852b pull issue1852a
611 $ hg -R issue1852b pull issue1852a
612 pulling from issue1852a
612 pulling from issue1852a
613 requesting all changes
613 requesting all changes
614 adding changesets
614 adding changesets
615 adding manifests
615 adding manifests
616 adding file changes
616 adding file changes
617 added 2 changesets with 3 changes to 2 files
617 added 2 changesets with 3 changes to 2 files
618 (run 'hg update' to get a working copy)
618 (run 'hg update' to get a working copy)
619 $ hg -R issue1852b update
619 $ hg -R issue1852b update
620 abort: default path for subrepository sub/repo not found
620 abort: default path for subrepository sub/repo not found
621 [255]
621 [255]
622
622
623 Pull -u now doesn't help
623 Pull -u now doesn't help
624
624
625 $ hg -R issue1852b pull -u issue1852a
625 $ hg -R issue1852b pull -u issue1852a
626 pulling from issue1852a
626 pulling from issue1852a
627 searching for changes
627 searching for changes
628 no changes found
628 no changes found
629
629
630 Try the same, but with pull -u
630 Try the same, but with pull -u
631
631
632 $ hg init issue1852c
632 $ hg init issue1852c
633 $ hg -R issue1852c pull -r0 -u issue1852a
633 $ hg -R issue1852c pull -r0 -u issue1852a
634 pulling from issue1852a
634 pulling from issue1852a
635 adding changesets
635 adding changesets
636 adding manifests
636 adding manifests
637 adding file changes
637 adding file changes
638 added 1 changesets with 2 changes to 2 files
638 added 1 changesets with 2 changes to 2 files
639 pulling subrepo sub/repo from issue1852a/sub/repo
639 pulling subrepo sub/repo from issue1852a/sub/repo
640 requesting all changes
640 requesting all changes
641 adding changesets
641 adding changesets
642 adding manifests
642 adding manifests
643 adding file changes
643 adding file changes
644 added 2 changesets with 2 changes to 1 files
644 added 2 changesets with 2 changes to 1 files
645 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
645 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
646
646
647 Try to push from the other side
647 Try to push from the other side
648
648
649 $ hg -R issue1852a push `pwd`/issue1852c
649 $ hg -R issue1852a push `pwd`/issue1852c
650 pushing to $TESTTMP/sub/issue1852c
650 pushing to $TESTTMP/sub/issue1852c
651 pushing subrepo sub/repo to $TESTTMP/sub/issue1852c/sub/repo
651 pushing subrepo sub/repo to $TESTTMP/sub/issue1852c/sub/repo
652 searching for changes
652 searching for changes
653 no changes found
653 no changes found
654 searching for changes
654 searching for changes
655 adding changesets
655 adding changesets
656 adding manifests
656 adding manifests
657 adding file changes
657 adding file changes
658 added 1 changesets with 1 changes to 1 files
658 added 1 changesets with 1 changes to 1 files
659
660 Check status of files when none of them belong to the first
661 subrepository:
662
663 $ hg init subrepo-status
664 $ cd subrepo-status
665 $ hg init subrepo-1
666 $ hg init subrepo-2
667 $ cd subrepo-2
668 $ touch file
669 $ hg add file
670 $ cd ..
671 $ echo subrepo-1 = subrepo-1 > .hgsub
672 $ echo subrepo-2 = subrepo-2 >> .hgsub
673 $ hg add .hgsub
674 $ hg ci -m 'Added subrepos'
675 committing subrepository subrepo-1
676 committing subrepository subrepo-2
677 $ hg st subrepo-2/file
General Comments 0
You need to be logged in to leave comments. Login now