##// END OF EJS Templates
subrepo: remove superfluous newline from subrepo prompt
Mads Kiilerich -
r22590:d4c972b9 default
parent child Browse files
Show More
@@ -1,1597 +1,1597
1 1 # subrepo.py - sub-repository handling for Mercurial
2 2 #
3 3 # Copyright 2009-2010 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 import errno, os, re, shutil, posixpath, sys
9 9 import xml.dom.minidom
10 10 import stat, subprocess, tarfile
11 11 from i18n import _
12 12 import config, util, node, error, cmdutil, bookmarks, match as matchmod
13 13 import phases
14 14 import pathutil
15 15 hg = None
16 16 propertycache = util.propertycache
17 17
18 18 nullstate = ('', '', 'empty')
19 19
20 20 def _expandedabspath(path):
21 21 '''
22 22 get a path or url and if it is a path expand it and return an absolute path
23 23 '''
24 24 expandedpath = util.urllocalpath(util.expandpath(path))
25 25 u = util.url(expandedpath)
26 26 if not u.scheme:
27 27 path = util.normpath(os.path.abspath(u.path))
28 28 return path
29 29
30 30 def _getstorehashcachename(remotepath):
31 31 '''get a unique filename for the store hash cache of a remote repository'''
32 32 return util.sha1(_expandedabspath(remotepath)).hexdigest()[0:12]
33 33
34 34 def _calcfilehash(filename):
35 35 data = ''
36 36 if os.path.exists(filename):
37 37 fd = open(filename, 'rb')
38 38 try:
39 39 data = fd.read()
40 40 finally:
41 41 fd.close()
42 42 return util.sha1(data).hexdigest()
43 43
44 44 class SubrepoAbort(error.Abort):
45 45 """Exception class used to avoid handling a subrepo error more than once"""
46 46 def __init__(self, *args, **kw):
47 47 error.Abort.__init__(self, *args, **kw)
48 48 self.subrepo = kw.get('subrepo')
49 49 self.cause = kw.get('cause')
50 50
51 51 def annotatesubrepoerror(func):
52 52 def decoratedmethod(self, *args, **kargs):
53 53 try:
54 54 res = func(self, *args, **kargs)
55 55 except SubrepoAbort, ex:
56 56 # This exception has already been handled
57 57 raise ex
58 58 except error.Abort, ex:
59 59 subrepo = subrelpath(self)
60 60 errormsg = str(ex) + ' ' + _('(in subrepo %s)') % subrepo
61 61 # avoid handling this exception by raising a SubrepoAbort exception
62 62 raise SubrepoAbort(errormsg, hint=ex.hint, subrepo=subrepo,
63 63 cause=sys.exc_info())
64 64 return res
65 65 return decoratedmethod
66 66
67 67 def state(ctx, ui):
68 68 """return a state dict, mapping subrepo paths configured in .hgsub
69 69 to tuple: (source from .hgsub, revision from .hgsubstate, kind
70 70 (key in types dict))
71 71 """
72 72 p = config.config()
73 73 def read(f, sections=None, remap=None):
74 74 if f in ctx:
75 75 try:
76 76 data = ctx[f].data()
77 77 except IOError, err:
78 78 if err.errno != errno.ENOENT:
79 79 raise
80 80 # handle missing subrepo spec files as removed
81 81 ui.warn(_("warning: subrepo spec file %s not found\n") % f)
82 82 return
83 83 p.parse(f, data, sections, remap, read)
84 84 else:
85 85 raise util.Abort(_("subrepo spec file %s not found") % f)
86 86
87 87 if '.hgsub' in ctx:
88 88 read('.hgsub')
89 89
90 90 for path, src in ui.configitems('subpaths'):
91 91 p.set('subpaths', path, src, ui.configsource('subpaths', path))
92 92
93 93 rev = {}
94 94 if '.hgsubstate' in ctx:
95 95 try:
96 96 for i, l in enumerate(ctx['.hgsubstate'].data().splitlines()):
97 97 l = l.lstrip()
98 98 if not l:
99 99 continue
100 100 try:
101 101 revision, path = l.split(" ", 1)
102 102 except ValueError:
103 103 raise util.Abort(_("invalid subrepository revision "
104 104 "specifier in .hgsubstate line %d")
105 105 % (i + 1))
106 106 rev[path] = revision
107 107 except IOError, err:
108 108 if err.errno != errno.ENOENT:
109 109 raise
110 110
111 111 def remap(src):
112 112 for pattern, repl in p.items('subpaths'):
113 113 # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub
114 114 # does a string decode.
115 115 repl = repl.encode('string-escape')
116 116 # However, we still want to allow back references to go
117 117 # through unharmed, so we turn r'\\1' into r'\1'. Again,
118 118 # extra escapes are needed because re.sub string decodes.
119 119 repl = re.sub(r'\\\\([0-9]+)', r'\\\1', repl)
120 120 try:
121 121 src = re.sub(pattern, repl, src, 1)
122 122 except re.error, e:
123 123 raise util.Abort(_("bad subrepository pattern in %s: %s")
124 124 % (p.source('subpaths', pattern), e))
125 125 return src
126 126
127 127 state = {}
128 128 for path, src in p[''].items():
129 129 kind = 'hg'
130 130 if src.startswith('['):
131 131 if ']' not in src:
132 132 raise util.Abort(_('missing ] in subrepo source'))
133 133 kind, src = src.split(']', 1)
134 134 kind = kind[1:]
135 135 src = src.lstrip() # strip any extra whitespace after ']'
136 136
137 137 if not util.url(src).isabs():
138 138 parent = _abssource(ctx._repo, abort=False)
139 139 if parent:
140 140 parent = util.url(parent)
141 141 parent.path = posixpath.join(parent.path or '', src)
142 142 parent.path = posixpath.normpath(parent.path)
143 143 joined = str(parent)
144 144 # Remap the full joined path and use it if it changes,
145 145 # else remap the original source.
146 146 remapped = remap(joined)
147 147 if remapped == joined:
148 148 src = remap(src)
149 149 else:
150 150 src = remapped
151 151
152 152 src = remap(src)
153 153 state[util.pconvert(path)] = (src.strip(), rev.get(path, ''), kind)
154 154
155 155 return state
156 156
157 157 def writestate(repo, state):
158 158 """rewrite .hgsubstate in (outer) repo with these subrepo states"""
159 159 lines = ['%s %s\n' % (state[s][1], s) for s in sorted(state)]
160 160 repo.wwrite('.hgsubstate', ''.join(lines), '')
161 161
162 162 def submerge(repo, wctx, mctx, actx, overwrite):
163 163 """delegated from merge.applyupdates: merging of .hgsubstate file
164 164 in working context, merging context and ancestor context"""
165 165 if mctx == actx: # backwards?
166 166 actx = wctx.p1()
167 167 s1 = wctx.substate
168 168 s2 = mctx.substate
169 169 sa = actx.substate
170 170 sm = {}
171 171
172 172 repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx))
173 173
174 174 def debug(s, msg, r=""):
175 175 if r:
176 176 r = "%s:%s:%s" % r
177 177 repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r))
178 178
179 179 for s, l in sorted(s1.iteritems()):
180 180 a = sa.get(s, nullstate)
181 181 ld = l # local state with possible dirty flag for compares
182 182 if wctx.sub(s).dirty():
183 183 ld = (l[0], l[1] + "+")
184 184 if wctx == actx: # overwrite
185 185 a = ld
186 186
187 187 if s in s2:
188 188 r = s2[s]
189 189 if ld == r or r == a: # no change or local is newer
190 190 sm[s] = l
191 191 continue
192 192 elif ld == a: # other side changed
193 193 debug(s, "other changed, get", r)
194 194 wctx.sub(s).get(r, overwrite)
195 195 sm[s] = r
196 196 elif ld[0] != r[0]: # sources differ
197 197 if repo.ui.promptchoice(
198 198 _(' subrepository sources for %s differ\n'
199 199 'use (l)ocal source (%s) or (r)emote source (%s)?'
200 200 '$$ &Local $$ &Remote') % (s, l[0], r[0]), 0):
201 201 debug(s, "prompt changed, get", r)
202 202 wctx.sub(s).get(r, overwrite)
203 203 sm[s] = r
204 204 elif ld[1] == a[1]: # local side is unchanged
205 205 debug(s, "other side changed, get", r)
206 206 wctx.sub(s).get(r, overwrite)
207 207 sm[s] = r
208 208 else:
209 209 debug(s, "both sides changed")
210 210 srepo = wctx.sub(s)
211 211 option = repo.ui.promptchoice(
212 212 _(' subrepository %s diverged (local revision: %s, '
213 213 'remote revision: %s)\n'
214 214 '(M)erge, keep (l)ocal or keep (r)emote?'
215 215 '$$ &Merge $$ &Local $$ &Remote')
216 216 % (s, srepo.shortid(l[1]), srepo.shortid(r[1])), 0)
217 217 if option == 0:
218 218 wctx.sub(s).merge(r)
219 219 sm[s] = l
220 220 debug(s, "merge with", r)
221 221 elif option == 1:
222 222 sm[s] = l
223 223 debug(s, "keep local subrepo revision", l)
224 224 else:
225 225 wctx.sub(s).get(r, overwrite)
226 226 sm[s] = r
227 227 debug(s, "get remote subrepo revision", r)
228 228 elif ld == a: # remote removed, local unchanged
229 229 debug(s, "remote removed, remove")
230 230 wctx.sub(s).remove()
231 231 elif a == nullstate: # not present in remote or ancestor
232 232 debug(s, "local added, keep")
233 233 sm[s] = l
234 234 continue
235 235 else:
236 236 if repo.ui.promptchoice(
237 237 _(' local changed subrepository %s which remote removed\n'
238 238 'use (c)hanged version or (d)elete?'
239 239 '$$ &Changed $$ &Delete') % s, 0):
240 240 debug(s, "prompt remove")
241 241 wctx.sub(s).remove()
242 242
243 243 for s, r in sorted(s2.items()):
244 244 if s in s1:
245 245 continue
246 246 elif s not in sa:
247 247 debug(s, "remote added, get", r)
248 248 mctx.sub(s).get(r)
249 249 sm[s] = r
250 250 elif r != sa[s]:
251 251 if repo.ui.promptchoice(
252 252 _(' remote changed subrepository %s which local removed\n'
253 253 'use (c)hanged version or (d)elete?'
254 254 '$$ &Changed $$ &Delete') % s, 0) == 0:
255 255 debug(s, "prompt recreate", r)
256 256 wctx.sub(s).get(r)
257 257 sm[s] = r
258 258
259 259 # record merged .hgsubstate
260 260 writestate(repo, sm)
261 261 return sm
262 262
263 263 def _updateprompt(ui, sub, dirty, local, remote):
264 264 if dirty:
265 265 msg = (_(' subrepository sources for %s differ\n'
266 'use (l)ocal source (%s) or (r)emote source (%s)?\n'
266 'use (l)ocal source (%s) or (r)emote source (%s)?'
267 267 '$$ &Local $$ &Remote')
268 268 % (subrelpath(sub), local, remote))
269 269 else:
270 270 msg = (_(' subrepository sources for %s differ (in checked out '
271 271 'version)\n'
272 'use (l)ocal source (%s) or (r)emote source (%s)?\n'
272 'use (l)ocal source (%s) or (r)emote source (%s)?'
273 273 '$$ &Local $$ &Remote')
274 274 % (subrelpath(sub), local, remote))
275 275 return ui.promptchoice(msg, 0)
276 276
277 277 def reporelpath(repo):
278 278 """return path to this (sub)repo as seen from outermost repo"""
279 279 parent = repo
280 280 while util.safehasattr(parent, '_subparent'):
281 281 parent = parent._subparent
282 282 return repo.root[len(pathutil.normasprefix(parent.root)):]
283 283
284 284 def subrelpath(sub):
285 285 """return path to this subrepo as seen from outermost repo"""
286 286 if util.safehasattr(sub, '_relpath'):
287 287 return sub._relpath
288 288 if not util.safehasattr(sub, '_repo'):
289 289 return sub._path
290 290 return reporelpath(sub._repo)
291 291
292 292 def _abssource(repo, push=False, abort=True):
293 293 """return pull/push path of repo - either based on parent repo .hgsub info
294 294 or on the top repo config. Abort or return None if no source found."""
295 295 if util.safehasattr(repo, '_subparent'):
296 296 source = util.url(repo._subsource)
297 297 if source.isabs():
298 298 return str(source)
299 299 source.path = posixpath.normpath(source.path)
300 300 parent = _abssource(repo._subparent, push, abort=False)
301 301 if parent:
302 302 parent = util.url(util.pconvert(parent))
303 303 parent.path = posixpath.join(parent.path or '', source.path)
304 304 parent.path = posixpath.normpath(parent.path)
305 305 return str(parent)
306 306 else: # recursion reached top repo
307 307 if util.safehasattr(repo, '_subtoppath'):
308 308 return repo._subtoppath
309 309 if push and repo.ui.config('paths', 'default-push'):
310 310 return repo.ui.config('paths', 'default-push')
311 311 if repo.ui.config('paths', 'default'):
312 312 return repo.ui.config('paths', 'default')
313 313 if repo.sharedpath != repo.path:
314 314 # chop off the .hg component to get the default path form
315 315 return os.path.dirname(repo.sharedpath)
316 316 if abort:
317 317 raise util.Abort(_("default path for subrepository not found"))
318 318
319 319 def _sanitize(ui, path, ignore):
320 320 for dirname, dirs, names in os.walk(path):
321 321 for i, d in enumerate(dirs):
322 322 if d.lower() == ignore:
323 323 del dirs[i]
324 324 break
325 325 if os.path.basename(dirname).lower() != '.hg':
326 326 continue
327 327 for f in names:
328 328 if f.lower() == 'hgrc':
329 329 ui.warn(_("warning: removing potentially hostile 'hgrc' "
330 330 "in '%s'\n") % dirname)
331 331 os.unlink(os.path.join(dirname, f))
332 332
333 333 def subrepo(ctx, path):
334 334 """return instance of the right subrepo class for subrepo in path"""
335 335 # subrepo inherently violates our import layering rules
336 336 # because it wants to make repo objects from deep inside the stack
337 337 # so we manually delay the circular imports to not break
338 338 # scripts that don't use our demand-loading
339 339 global hg
340 340 import hg as h
341 341 hg = h
342 342
343 343 pathutil.pathauditor(ctx._repo.root)(path)
344 344 state = ctx.substate[path]
345 345 if state[2] not in types:
346 346 raise util.Abort(_('unknown subrepo type %s') % state[2])
347 347 return types[state[2]](ctx, path, state[:2])
348 348
349 349 def newcommitphase(ui, ctx):
350 350 commitphase = phases.newcommitphase(ui)
351 351 substate = getattr(ctx, "substate", None)
352 352 if not substate:
353 353 return commitphase
354 354 check = ui.config('phases', 'checksubrepos', 'follow')
355 355 if check not in ('ignore', 'follow', 'abort'):
356 356 raise util.Abort(_('invalid phases.checksubrepos configuration: %s')
357 357 % (check))
358 358 if check == 'ignore':
359 359 return commitphase
360 360 maxphase = phases.public
361 361 maxsub = None
362 362 for s in sorted(substate):
363 363 sub = ctx.sub(s)
364 364 subphase = sub.phase(substate[s][1])
365 365 if maxphase < subphase:
366 366 maxphase = subphase
367 367 maxsub = s
368 368 if commitphase < maxphase:
369 369 if check == 'abort':
370 370 raise util.Abort(_("can't commit in %s phase"
371 371 " conflicting %s from subrepository %s") %
372 372 (phases.phasenames[commitphase],
373 373 phases.phasenames[maxphase], maxsub))
374 374 ui.warn(_("warning: changes are committed in"
375 375 " %s phase from subrepository %s\n") %
376 376 (phases.phasenames[maxphase], maxsub))
377 377 return maxphase
378 378 return commitphase
379 379
380 380 # subrepo classes need to implement the following abstract class:
381 381
382 382 class abstractsubrepo(object):
383 383
384 384 def storeclean(self, path):
385 385 """
386 386 returns true if the repository has not changed since it was last
387 387 cloned from or pushed to a given repository.
388 388 """
389 389 return False
390 390
391 391 def dirty(self, ignoreupdate=False):
392 392 """returns true if the dirstate of the subrepo is dirty or does not
393 393 match current stored state. If ignoreupdate is true, only check
394 394 whether the subrepo has uncommitted changes in its dirstate.
395 395 """
396 396 raise NotImplementedError
397 397
398 398 def basestate(self):
399 399 """current working directory base state, disregarding .hgsubstate
400 400 state and working directory modifications"""
401 401 raise NotImplementedError
402 402
403 403 def checknested(self, path):
404 404 """check if path is a subrepository within this repository"""
405 405 return False
406 406
407 407 def commit(self, text, user, date):
408 408 """commit the current changes to the subrepo with the given
409 409 log message. Use given user and date if possible. Return the
410 410 new state of the subrepo.
411 411 """
412 412 raise NotImplementedError
413 413
414 414 def phase(self, state):
415 415 """returns phase of specified state in the subrepository.
416 416 """
417 417 return phases.public
418 418
419 419 def remove(self):
420 420 """remove the subrepo
421 421
422 422 (should verify the dirstate is not dirty first)
423 423 """
424 424 raise NotImplementedError
425 425
426 426 def get(self, state, overwrite=False):
427 427 """run whatever commands are needed to put the subrepo into
428 428 this state
429 429 """
430 430 raise NotImplementedError
431 431
432 432 def merge(self, state):
433 433 """merge currently-saved state with the new state."""
434 434 raise NotImplementedError
435 435
436 436 def push(self, opts):
437 437 """perform whatever action is analogous to 'hg push'
438 438
439 439 This may be a no-op on some systems.
440 440 """
441 441 raise NotImplementedError
442 442
443 443 def add(self, ui, match, dryrun, listsubrepos, prefix, explicitonly):
444 444 return []
445 445
446 446 def cat(self, ui, match, prefix, **opts):
447 447 return 1
448 448
449 449 def status(self, rev2, **opts):
450 450 return [], [], [], [], [], [], []
451 451
452 452 def diff(self, ui, diffopts, node2, match, prefix, **opts):
453 453 pass
454 454
455 455 def outgoing(self, ui, dest, opts):
456 456 return 1
457 457
458 458 def incoming(self, ui, source, opts):
459 459 return 1
460 460
461 461 def files(self):
462 462 """return filename iterator"""
463 463 raise NotImplementedError
464 464
465 465 def filedata(self, name):
466 466 """return file data"""
467 467 raise NotImplementedError
468 468
469 469 def fileflags(self, name):
470 470 """return file flags"""
471 471 return ''
472 472
473 473 def archive(self, ui, archiver, prefix, match=None):
474 474 if match is not None:
475 475 files = [f for f in self.files() if match(f)]
476 476 else:
477 477 files = self.files()
478 478 total = len(files)
479 479 relpath = subrelpath(self)
480 480 ui.progress(_('archiving (%s)') % relpath, 0,
481 481 unit=_('files'), total=total)
482 482 for i, name in enumerate(files):
483 483 flags = self.fileflags(name)
484 484 mode = 'x' in flags and 0755 or 0644
485 485 symlink = 'l' in flags
486 486 archiver.addfile(os.path.join(prefix, self._path, name),
487 487 mode, symlink, self.filedata(name))
488 488 ui.progress(_('archiving (%s)') % relpath, i + 1,
489 489 unit=_('files'), total=total)
490 490 ui.progress(_('archiving (%s)') % relpath, None)
491 491 return total
492 492
493 493 def walk(self, match):
494 494 '''
495 495 walk recursively through the directory tree, finding all files
496 496 matched by the match function
497 497 '''
498 498 pass
499 499
500 500 def forget(self, ui, match, prefix):
501 501 return ([], [])
502 502
503 503 def revert(self, ui, substate, *pats, **opts):
504 504 ui.warn('%s: reverting %s subrepos is unsupported\n' \
505 505 % (substate[0], substate[2]))
506 506 return []
507 507
508 508 def shortid(self, revid):
509 509 return revid
510 510
511 511 class hgsubrepo(abstractsubrepo):
512 512 def __init__(self, ctx, path, state):
513 513 self._path = path
514 514 self._state = state
515 515 r = ctx._repo
516 516 root = r.wjoin(path)
517 517 create = False
518 518 if not os.path.exists(os.path.join(root, '.hg')):
519 519 create = True
520 520 util.makedirs(root)
521 521 self._repo = hg.repository(r.baseui, root, create=create)
522 522 for s, k in [('ui', 'commitsubrepos')]:
523 523 v = r.ui.config(s, k)
524 524 if v:
525 525 self._repo.ui.setconfig(s, k, v, 'subrepo')
526 526 self._repo.ui.setconfig('ui', '_usedassubrepo', 'True', 'subrepo')
527 527 self._initrepo(r, state[0], create)
528 528
529 529 def storeclean(self, path):
530 530 lock = self._repo.lock()
531 531 try:
532 532 return self._storeclean(path)
533 533 finally:
534 534 lock.release()
535 535
536 536 def _storeclean(self, path):
537 537 clean = True
538 538 itercache = self._calcstorehash(path)
539 539 try:
540 540 for filehash in self._readstorehashcache(path):
541 541 if filehash != itercache.next():
542 542 clean = False
543 543 break
544 544 except StopIteration:
545 545 # the cached and current pull states have a different size
546 546 clean = False
547 547 if clean:
548 548 try:
549 549 itercache.next()
550 550 # the cached and current pull states have a different size
551 551 clean = False
552 552 except StopIteration:
553 553 pass
554 554 return clean
555 555
556 556 def _calcstorehash(self, remotepath):
557 557 '''calculate a unique "store hash"
558 558
559 559 This method is used to to detect when there are changes that may
560 560 require a push to a given remote path.'''
561 561 # sort the files that will be hashed in increasing (likely) file size
562 562 filelist = ('bookmarks', 'store/phaseroots', 'store/00changelog.i')
563 563 yield '# %s\n' % _expandedabspath(remotepath)
564 564 for relname in filelist:
565 565 absname = os.path.normpath(self._repo.join(relname))
566 566 yield '%s = %s\n' % (relname, _calcfilehash(absname))
567 567
568 568 def _getstorehashcachepath(self, remotepath):
569 569 '''get a unique path for the store hash cache'''
570 570 return self._repo.join(os.path.join(
571 571 'cache', 'storehash', _getstorehashcachename(remotepath)))
572 572
573 573 def _readstorehashcache(self, remotepath):
574 574 '''read the store hash cache for a given remote repository'''
575 575 cachefile = self._getstorehashcachepath(remotepath)
576 576 if not os.path.exists(cachefile):
577 577 return ''
578 578 fd = open(cachefile, 'r')
579 579 try:
580 580 pullstate = fd.readlines()
581 581 finally:
582 582 fd.close()
583 583 return pullstate
584 584
585 585 def _cachestorehash(self, remotepath):
586 586 '''cache the current store hash
587 587
588 588 Each remote repo requires its own store hash cache, because a subrepo
589 589 store may be "clean" versus a given remote repo, but not versus another
590 590 '''
591 591 cachefile = self._getstorehashcachepath(remotepath)
592 592 lock = self._repo.lock()
593 593 try:
594 594 storehash = list(self._calcstorehash(remotepath))
595 595 cachedir = os.path.dirname(cachefile)
596 596 if not os.path.exists(cachedir):
597 597 util.makedirs(cachedir, notindexed=True)
598 598 fd = open(cachefile, 'w')
599 599 try:
600 600 fd.writelines(storehash)
601 601 finally:
602 602 fd.close()
603 603 finally:
604 604 lock.release()
605 605
606 606 @annotatesubrepoerror
607 607 def _initrepo(self, parentrepo, source, create):
608 608 self._repo._subparent = parentrepo
609 609 self._repo._subsource = source
610 610
611 611 if create:
612 612 lines = ['[paths]\n']
613 613
614 614 def addpathconfig(key, value):
615 615 if value:
616 616 lines.append('%s = %s\n' % (key, value))
617 617 self._repo.ui.setconfig('paths', key, value, 'subrepo')
618 618
619 619 defpath = _abssource(self._repo, abort=False)
620 620 defpushpath = _abssource(self._repo, True, abort=False)
621 621 addpathconfig('default', defpath)
622 622 if defpath != defpushpath:
623 623 addpathconfig('default-push', defpushpath)
624 624
625 625 fp = self._repo.opener("hgrc", "w", text=True)
626 626 try:
627 627 fp.write(''.join(lines))
628 628 finally:
629 629 fp.close()
630 630
631 631 @annotatesubrepoerror
632 632 def add(self, ui, match, dryrun, listsubrepos, prefix, explicitonly):
633 633 return cmdutil.add(ui, self._repo, match, dryrun, listsubrepos,
634 634 os.path.join(prefix, self._path), explicitonly)
635 635
636 636 @annotatesubrepoerror
637 637 def cat(self, ui, match, prefix, **opts):
638 638 rev = self._state[1]
639 639 ctx = self._repo[rev]
640 640 return cmdutil.cat(ui, self._repo, ctx, match, prefix, **opts)
641 641
642 642 @annotatesubrepoerror
643 643 def status(self, rev2, **opts):
644 644 try:
645 645 rev1 = self._state[1]
646 646 ctx1 = self._repo[rev1]
647 647 ctx2 = self._repo[rev2]
648 648 return self._repo.status(ctx1, ctx2, **opts)
649 649 except error.RepoLookupError, inst:
650 650 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
651 651 % (inst, subrelpath(self)))
652 652 return [], [], [], [], [], [], []
653 653
654 654 @annotatesubrepoerror
655 655 def diff(self, ui, diffopts, node2, match, prefix, **opts):
656 656 try:
657 657 node1 = node.bin(self._state[1])
658 658 # We currently expect node2 to come from substate and be
659 659 # in hex format
660 660 if node2 is not None:
661 661 node2 = node.bin(node2)
662 662 cmdutil.diffordiffstat(ui, self._repo, diffopts,
663 663 node1, node2, match,
664 664 prefix=posixpath.join(prefix, self._path),
665 665 listsubrepos=True, **opts)
666 666 except error.RepoLookupError, inst:
667 667 self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
668 668 % (inst, subrelpath(self)))
669 669
670 670 @annotatesubrepoerror
671 671 def archive(self, ui, archiver, prefix, match=None):
672 672 self._get(self._state + ('hg',))
673 673 total = abstractsubrepo.archive(self, ui, archiver, prefix, match)
674 674 rev = self._state[1]
675 675 ctx = self._repo[rev]
676 676 for subpath in ctx.substate:
677 677 s = subrepo(ctx, subpath)
678 678 submatch = matchmod.narrowmatcher(subpath, match)
679 679 total += s.archive(
680 680 ui, archiver, os.path.join(prefix, self._path), submatch)
681 681 return total
682 682
683 683 @annotatesubrepoerror
684 684 def dirty(self, ignoreupdate=False):
685 685 r = self._state[1]
686 686 if r == '' and not ignoreupdate: # no state recorded
687 687 return True
688 688 w = self._repo[None]
689 689 if r != w.p1().hex() and not ignoreupdate:
690 690 # different version checked out
691 691 return True
692 692 return w.dirty() # working directory changed
693 693
694 694 def basestate(self):
695 695 return self._repo['.'].hex()
696 696
697 697 def checknested(self, path):
698 698 return self._repo._checknested(self._repo.wjoin(path))
699 699
700 700 @annotatesubrepoerror
701 701 def commit(self, text, user, date):
702 702 # don't bother committing in the subrepo if it's only been
703 703 # updated
704 704 if not self.dirty(True):
705 705 return self._repo['.'].hex()
706 706 self._repo.ui.debug("committing subrepo %s\n" % subrelpath(self))
707 707 n = self._repo.commit(text, user, date)
708 708 if not n:
709 709 return self._repo['.'].hex() # different version checked out
710 710 return node.hex(n)
711 711
712 712 @annotatesubrepoerror
713 713 def phase(self, state):
714 714 return self._repo[state].phase()
715 715
716 716 @annotatesubrepoerror
717 717 def remove(self):
718 718 # we can't fully delete the repository as it may contain
719 719 # local-only history
720 720 self._repo.ui.note(_('removing subrepo %s\n') % subrelpath(self))
721 721 hg.clean(self._repo, node.nullid, False)
722 722
723 723 def _get(self, state):
724 724 source, revision, kind = state
725 725 if revision in self._repo.unfiltered():
726 726 return True
727 727 self._repo._subsource = source
728 728 srcurl = _abssource(self._repo)
729 729 other = hg.peer(self._repo, {}, srcurl)
730 730 if len(self._repo) == 0:
731 731 self._repo.ui.status(_('cloning subrepo %s from %s\n')
732 732 % (subrelpath(self), srcurl))
733 733 parentrepo = self._repo._subparent
734 734 shutil.rmtree(self._repo.path)
735 735 other, cloned = hg.clone(self._repo._subparent.baseui, {},
736 736 other, self._repo.root,
737 737 update=False)
738 738 self._repo = cloned.local()
739 739 self._initrepo(parentrepo, source, create=True)
740 740 self._cachestorehash(srcurl)
741 741 else:
742 742 self._repo.ui.status(_('pulling subrepo %s from %s\n')
743 743 % (subrelpath(self), srcurl))
744 744 cleansub = self.storeclean(srcurl)
745 745 remotebookmarks = other.listkeys('bookmarks')
746 746 self._repo.pull(other)
747 747 bookmarks.updatefromremote(self._repo.ui, self._repo,
748 748 remotebookmarks, srcurl)
749 749 if cleansub:
750 750 # keep the repo clean after pull
751 751 self._cachestorehash(srcurl)
752 752 return False
753 753
754 754 @annotatesubrepoerror
755 755 def get(self, state, overwrite=False):
756 756 inrepo = self._get(state)
757 757 source, revision, kind = state
758 758 repo = self._repo
759 759 repo.ui.debug("getting subrepo %s\n" % self._path)
760 760 if inrepo:
761 761 urepo = repo.unfiltered()
762 762 ctx = urepo[revision]
763 763 if ctx.hidden():
764 764 urepo.ui.warn(
765 765 _('revision %s in subrepo %s is hidden\n') \
766 766 % (revision[0:12], self._path))
767 767 repo = urepo
768 768 hg.updaterepo(repo, revision, overwrite)
769 769
770 770 @annotatesubrepoerror
771 771 def merge(self, state):
772 772 self._get(state)
773 773 cur = self._repo['.']
774 774 dst = self._repo[state[1]]
775 775 anc = dst.ancestor(cur)
776 776
777 777 def mergefunc():
778 778 if anc == cur and dst.branch() == cur.branch():
779 779 self._repo.ui.debug("updating subrepo %s\n" % subrelpath(self))
780 780 hg.update(self._repo, state[1])
781 781 elif anc == dst:
782 782 self._repo.ui.debug("skipping subrepo %s\n" % subrelpath(self))
783 783 else:
784 784 self._repo.ui.debug("merging subrepo %s\n" % subrelpath(self))
785 785 hg.merge(self._repo, state[1], remind=False)
786 786
787 787 wctx = self._repo[None]
788 788 if self.dirty():
789 789 if anc != dst:
790 790 if _updateprompt(self._repo.ui, self, wctx.dirty(), cur, dst):
791 791 mergefunc()
792 792 else:
793 793 mergefunc()
794 794 else:
795 795 mergefunc()
796 796
797 797 @annotatesubrepoerror
798 798 def push(self, opts):
799 799 force = opts.get('force')
800 800 newbranch = opts.get('new_branch')
801 801 ssh = opts.get('ssh')
802 802
803 803 # push subrepos depth-first for coherent ordering
804 804 c = self._repo['']
805 805 subs = c.substate # only repos that are committed
806 806 for s in sorted(subs):
807 807 if c.sub(s).push(opts) == 0:
808 808 return False
809 809
810 810 dsturl = _abssource(self._repo, True)
811 811 if not force:
812 812 if self.storeclean(dsturl):
813 813 self._repo.ui.status(
814 814 _('no changes made to subrepo %s since last push to %s\n')
815 815 % (subrelpath(self), dsturl))
816 816 return None
817 817 self._repo.ui.status(_('pushing subrepo %s to %s\n') %
818 818 (subrelpath(self), dsturl))
819 819 other = hg.peer(self._repo, {'ssh': ssh}, dsturl)
820 820 res = self._repo.push(other, force, newbranch=newbranch)
821 821
822 822 # the repo is now clean
823 823 self._cachestorehash(dsturl)
824 824 return res
825 825
826 826 @annotatesubrepoerror
827 827 def outgoing(self, ui, dest, opts):
828 828 return hg.outgoing(ui, self._repo, _abssource(self._repo, True), opts)
829 829
830 830 @annotatesubrepoerror
831 831 def incoming(self, ui, source, opts):
832 832 return hg.incoming(ui, self._repo, _abssource(self._repo, False), opts)
833 833
834 834 @annotatesubrepoerror
835 835 def files(self):
836 836 rev = self._state[1]
837 837 ctx = self._repo[rev]
838 838 return ctx.manifest()
839 839
840 840 def filedata(self, name):
841 841 rev = self._state[1]
842 842 return self._repo[rev][name].data()
843 843
844 844 def fileflags(self, name):
845 845 rev = self._state[1]
846 846 ctx = self._repo[rev]
847 847 return ctx.flags(name)
848 848
849 849 def walk(self, match):
850 850 ctx = self._repo[None]
851 851 return ctx.walk(match)
852 852
853 853 @annotatesubrepoerror
854 854 def forget(self, ui, match, prefix):
855 855 return cmdutil.forget(ui, self._repo, match,
856 856 os.path.join(prefix, self._path), True)
857 857
858 858 @annotatesubrepoerror
859 859 def revert(self, ui, substate, *pats, **opts):
860 860 # reverting a subrepo is a 2 step process:
861 861 # 1. if the no_backup is not set, revert all modified
862 862 # files inside the subrepo
863 863 # 2. update the subrepo to the revision specified in
864 864 # the corresponding substate dictionary
865 865 ui.status(_('reverting subrepo %s\n') % substate[0])
866 866 if not opts.get('no_backup'):
867 867 # Revert all files on the subrepo, creating backups
868 868 # Note that this will not recursively revert subrepos
869 869 # We could do it if there was a set:subrepos() predicate
870 870 opts = opts.copy()
871 871 opts['date'] = None
872 872 opts['rev'] = substate[1]
873 873
874 874 pats = []
875 875 if not opts.get('all'):
876 876 pats = ['set:modified()']
877 877 self.filerevert(ui, *pats, **opts)
878 878
879 879 # Update the repo to the revision specified in the given substate
880 880 self.get(substate, overwrite=True)
881 881
882 882 def filerevert(self, ui, *pats, **opts):
883 883 ctx = self._repo[opts['rev']]
884 884 parents = self._repo.dirstate.parents()
885 885 if opts.get('all'):
886 886 pats = ['set:modified()']
887 887 else:
888 888 pats = []
889 889 cmdutil.revert(ui, self._repo, ctx, parents, *pats, **opts)
890 890
891 891 def shortid(self, revid):
892 892 return revid[:12]
893 893
894 894 class svnsubrepo(abstractsubrepo):
895 895 def __init__(self, ctx, path, state):
896 896 self._path = path
897 897 self._state = state
898 898 self._ctx = ctx
899 899 self._ui = ctx._repo.ui
900 900 self._exe = util.findexe('svn')
901 901 if not self._exe:
902 902 raise util.Abort(_("'svn' executable not found for subrepo '%s'")
903 903 % self._path)
904 904
905 905 def _svncommand(self, commands, filename='', failok=False):
906 906 cmd = [self._exe]
907 907 extrakw = {}
908 908 if not self._ui.interactive():
909 909 # Making stdin be a pipe should prevent svn from behaving
910 910 # interactively even if we can't pass --non-interactive.
911 911 extrakw['stdin'] = subprocess.PIPE
912 912 # Starting in svn 1.5 --non-interactive is a global flag
913 913 # instead of being per-command, but we need to support 1.4 so
914 914 # we have to be intelligent about what commands take
915 915 # --non-interactive.
916 916 if commands[0] in ('update', 'checkout', 'commit'):
917 917 cmd.append('--non-interactive')
918 918 cmd.extend(commands)
919 919 if filename is not None:
920 920 path = os.path.join(self._ctx._repo.origroot, self._path, filename)
921 921 cmd.append(path)
922 922 env = dict(os.environ)
923 923 # Avoid localized output, preserve current locale for everything else.
924 924 lc_all = env.get('LC_ALL')
925 925 if lc_all:
926 926 env['LANG'] = lc_all
927 927 del env['LC_ALL']
928 928 env['LC_MESSAGES'] = 'C'
929 929 p = subprocess.Popen(cmd, bufsize=-1, close_fds=util.closefds,
930 930 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
931 931 universal_newlines=True, env=env, **extrakw)
932 932 stdout, stderr = p.communicate()
933 933 stderr = stderr.strip()
934 934 if not failok:
935 935 if p.returncode:
936 936 raise util.Abort(stderr or 'exited with code %d' % p.returncode)
937 937 if stderr:
938 938 self._ui.warn(stderr + '\n')
939 939 return stdout, stderr
940 940
941 941 @propertycache
942 942 def _svnversion(self):
943 943 output, err = self._svncommand(['--version', '--quiet'], filename=None)
944 944 m = re.search(r'^(\d+)\.(\d+)', output)
945 945 if not m:
946 946 raise util.Abort(_('cannot retrieve svn tool version'))
947 947 return (int(m.group(1)), int(m.group(2)))
948 948
949 949 def _wcrevs(self):
950 950 # Get the working directory revision as well as the last
951 951 # commit revision so we can compare the subrepo state with
952 952 # both. We used to store the working directory one.
953 953 output, err = self._svncommand(['info', '--xml'])
954 954 doc = xml.dom.minidom.parseString(output)
955 955 entries = doc.getElementsByTagName('entry')
956 956 lastrev, rev = '0', '0'
957 957 if entries:
958 958 rev = str(entries[0].getAttribute('revision')) or '0'
959 959 commits = entries[0].getElementsByTagName('commit')
960 960 if commits:
961 961 lastrev = str(commits[0].getAttribute('revision')) or '0'
962 962 return (lastrev, rev)
963 963
964 964 def _wcrev(self):
965 965 return self._wcrevs()[0]
966 966
967 967 def _wcchanged(self):
968 968 """Return (changes, extchanges, missing) where changes is True
969 969 if the working directory was changed, extchanges is
970 970 True if any of these changes concern an external entry and missing
971 971 is True if any change is a missing entry.
972 972 """
973 973 output, err = self._svncommand(['status', '--xml'])
974 974 externals, changes, missing = [], [], []
975 975 doc = xml.dom.minidom.parseString(output)
976 976 for e in doc.getElementsByTagName('entry'):
977 977 s = e.getElementsByTagName('wc-status')
978 978 if not s:
979 979 continue
980 980 item = s[0].getAttribute('item')
981 981 props = s[0].getAttribute('props')
982 982 path = e.getAttribute('path')
983 983 if item == 'external':
984 984 externals.append(path)
985 985 elif item == 'missing':
986 986 missing.append(path)
987 987 if (item not in ('', 'normal', 'unversioned', 'external')
988 988 or props not in ('', 'none', 'normal')):
989 989 changes.append(path)
990 990 for path in changes:
991 991 for ext in externals:
992 992 if path == ext or path.startswith(ext + os.sep):
993 993 return True, True, bool(missing)
994 994 return bool(changes), False, bool(missing)
995 995
996 996 def dirty(self, ignoreupdate=False):
997 997 if not self._wcchanged()[0]:
998 998 if self._state[1] in self._wcrevs() or ignoreupdate:
999 999 return False
1000 1000 return True
1001 1001
1002 1002 def basestate(self):
1003 1003 lastrev, rev = self._wcrevs()
1004 1004 if lastrev != rev:
1005 1005 # Last committed rev is not the same than rev. We would
1006 1006 # like to take lastrev but we do not know if the subrepo
1007 1007 # URL exists at lastrev. Test it and fallback to rev it
1008 1008 # is not there.
1009 1009 try:
1010 1010 self._svncommand(['list', '%s@%s' % (self._state[0], lastrev)])
1011 1011 return lastrev
1012 1012 except error.Abort:
1013 1013 pass
1014 1014 return rev
1015 1015
1016 1016 @annotatesubrepoerror
1017 1017 def commit(self, text, user, date):
1018 1018 # user and date are out of our hands since svn is centralized
1019 1019 changed, extchanged, missing = self._wcchanged()
1020 1020 if not changed:
1021 1021 return self.basestate()
1022 1022 if extchanged:
1023 1023 # Do not try to commit externals
1024 1024 raise util.Abort(_('cannot commit svn externals'))
1025 1025 if missing:
1026 1026 # svn can commit with missing entries but aborting like hg
1027 1027 # seems a better approach.
1028 1028 raise util.Abort(_('cannot commit missing svn entries'))
1029 1029 commitinfo, err = self._svncommand(['commit', '-m', text])
1030 1030 self._ui.status(commitinfo)
1031 1031 newrev = re.search('Committed revision ([0-9]+).', commitinfo)
1032 1032 if not newrev:
1033 1033 if not commitinfo.strip():
1034 1034 # Sometimes, our definition of "changed" differs from
1035 1035 # svn one. For instance, svn ignores missing files
1036 1036 # when committing. If there are only missing files, no
1037 1037 # commit is made, no output and no error code.
1038 1038 raise util.Abort(_('failed to commit svn changes'))
1039 1039 raise util.Abort(commitinfo.splitlines()[-1])
1040 1040 newrev = newrev.groups()[0]
1041 1041 self._ui.status(self._svncommand(['update', '-r', newrev])[0])
1042 1042 return newrev
1043 1043
1044 1044 @annotatesubrepoerror
1045 1045 def remove(self):
1046 1046 if self.dirty():
1047 1047 self._ui.warn(_('not removing repo %s because '
1048 1048 'it has changes.\n') % self._path)
1049 1049 return
1050 1050 self._ui.note(_('removing subrepo %s\n') % self._path)
1051 1051
1052 1052 def onerror(function, path, excinfo):
1053 1053 if function is not os.remove:
1054 1054 raise
1055 1055 # read-only files cannot be unlinked under Windows
1056 1056 s = os.stat(path)
1057 1057 if (s.st_mode & stat.S_IWRITE) != 0:
1058 1058 raise
1059 1059 os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE)
1060 1060 os.remove(path)
1061 1061
1062 1062 path = self._ctx._repo.wjoin(self._path)
1063 1063 shutil.rmtree(path, onerror=onerror)
1064 1064 try:
1065 1065 os.removedirs(os.path.dirname(path))
1066 1066 except OSError:
1067 1067 pass
1068 1068
1069 1069 @annotatesubrepoerror
1070 1070 def get(self, state, overwrite=False):
1071 1071 if overwrite:
1072 1072 self._svncommand(['revert', '--recursive'])
1073 1073 args = ['checkout']
1074 1074 if self._svnversion >= (1, 5):
1075 1075 args.append('--force')
1076 1076 # The revision must be specified at the end of the URL to properly
1077 1077 # update to a directory which has since been deleted and recreated.
1078 1078 args.append('%s@%s' % (state[0], state[1]))
1079 1079 status, err = self._svncommand(args, failok=True)
1080 1080 _sanitize(self._ui, self._ctx._repo.wjoin(self._path), '.svn')
1081 1081 if not re.search('Checked out revision [0-9]+.', status):
1082 1082 if ('is already a working copy for a different URL' in err
1083 1083 and (self._wcchanged()[:2] == (False, False))):
1084 1084 # obstructed but clean working copy, so just blow it away.
1085 1085 self.remove()
1086 1086 self.get(state, overwrite=False)
1087 1087 return
1088 1088 raise util.Abort((status or err).splitlines()[-1])
1089 1089 self._ui.status(status)
1090 1090
1091 1091 @annotatesubrepoerror
1092 1092 def merge(self, state):
1093 1093 old = self._state[1]
1094 1094 new = state[1]
1095 1095 wcrev = self._wcrev()
1096 1096 if new != wcrev:
1097 1097 dirty = old == wcrev or self._wcchanged()[0]
1098 1098 if _updateprompt(self._ui, self, dirty, wcrev, new):
1099 1099 self.get(state, False)
1100 1100
1101 1101 def push(self, opts):
1102 1102 # push is a no-op for SVN
1103 1103 return True
1104 1104
1105 1105 @annotatesubrepoerror
1106 1106 def files(self):
1107 1107 output = self._svncommand(['list', '--recursive', '--xml'])[0]
1108 1108 doc = xml.dom.minidom.parseString(output)
1109 1109 paths = []
1110 1110 for e in doc.getElementsByTagName('entry'):
1111 1111 kind = str(e.getAttribute('kind'))
1112 1112 if kind != 'file':
1113 1113 continue
1114 1114 name = ''.join(c.data for c
1115 1115 in e.getElementsByTagName('name')[0].childNodes
1116 1116 if c.nodeType == c.TEXT_NODE)
1117 1117 paths.append(name.encode('utf-8'))
1118 1118 return paths
1119 1119
1120 1120 def filedata(self, name):
1121 1121 return self._svncommand(['cat'], name)[0]
1122 1122
1123 1123
1124 1124 class gitsubrepo(abstractsubrepo):
1125 1125 def __init__(self, ctx, path, state):
1126 1126 self._state = state
1127 1127 self._ctx = ctx
1128 1128 self._path = path
1129 1129 self._relpath = os.path.join(reporelpath(ctx._repo), path)
1130 1130 self._abspath = ctx._repo.wjoin(path)
1131 1131 self._subparent = ctx._repo
1132 1132 self._ui = ctx._repo.ui
1133 1133 self._ensuregit()
1134 1134
1135 1135 def _ensuregit(self):
1136 1136 try:
1137 1137 self._gitexecutable = 'git'
1138 1138 out, err = self._gitnodir(['--version'])
1139 1139 except OSError, e:
1140 1140 if e.errno != 2 or os.name != 'nt':
1141 1141 raise
1142 1142 self._gitexecutable = 'git.cmd'
1143 1143 out, err = self._gitnodir(['--version'])
1144 1144 versionstatus = self._checkversion(out)
1145 1145 if versionstatus == 'unknown':
1146 1146 self._ui.warn(_('cannot retrieve git version\n'))
1147 1147 elif versionstatus == 'abort':
1148 1148 raise util.Abort(_('git subrepo requires at least 1.6.0 or later'))
1149 1149 elif versionstatus == 'warning':
1150 1150 self._ui.warn(_('git subrepo requires at least 1.6.0 or later\n'))
1151 1151
1152 1152 @staticmethod
1153 1153 def _checkversion(out):
1154 1154 '''ensure git version is new enough
1155 1155
1156 1156 >>> _checkversion = gitsubrepo._checkversion
1157 1157 >>> _checkversion('git version 1.6.0')
1158 1158 'ok'
1159 1159 >>> _checkversion('git version 1.8.5')
1160 1160 'ok'
1161 1161 >>> _checkversion('git version 1.4.0')
1162 1162 'abort'
1163 1163 >>> _checkversion('git version 1.5.0')
1164 1164 'warning'
1165 1165 >>> _checkversion('git version 1.9-rc0')
1166 1166 'ok'
1167 1167 >>> _checkversion('git version 1.9.0.265.g81cdec2')
1168 1168 'ok'
1169 1169 >>> _checkversion('git version 1.9.0.GIT')
1170 1170 'ok'
1171 1171 >>> _checkversion('git version 12345')
1172 1172 'unknown'
1173 1173 >>> _checkversion('no')
1174 1174 'unknown'
1175 1175 '''
1176 1176 m = re.search(r'^git version (\d+)\.(\d+)', out)
1177 1177 if not m:
1178 1178 return 'unknown'
1179 1179 version = (int(m.group(1)), int(m.group(2)))
1180 1180 # git 1.4.0 can't work at all, but 1.5.X can in at least some cases,
1181 1181 # despite the docstring comment. For now, error on 1.4.0, warn on
1182 1182 # 1.5.0 but attempt to continue.
1183 1183 if version < (1, 5):
1184 1184 return 'abort'
1185 1185 elif version < (1, 6):
1186 1186 return 'warning'
1187 1187 return 'ok'
1188 1188
1189 1189 def _gitcommand(self, commands, env=None, stream=False):
1190 1190 return self._gitdir(commands, env=env, stream=stream)[0]
1191 1191
1192 1192 def _gitdir(self, commands, env=None, stream=False):
1193 1193 return self._gitnodir(commands, env=env, stream=stream,
1194 1194 cwd=self._abspath)
1195 1195
1196 1196 def _gitnodir(self, commands, env=None, stream=False, cwd=None):
1197 1197 """Calls the git command
1198 1198
1199 1199 The methods tries to call the git command. versions prior to 1.6.0
1200 1200 are not supported and very probably fail.
1201 1201 """
1202 1202 self._ui.debug('%s: git %s\n' % (self._relpath, ' '.join(commands)))
1203 1203 # unless ui.quiet is set, print git's stderr,
1204 1204 # which is mostly progress and useful info
1205 1205 errpipe = None
1206 1206 if self._ui.quiet:
1207 1207 errpipe = open(os.devnull, 'w')
1208 1208 p = subprocess.Popen([self._gitexecutable] + commands, bufsize=-1,
1209 1209 cwd=cwd, env=env, close_fds=util.closefds,
1210 1210 stdout=subprocess.PIPE, stderr=errpipe)
1211 1211 if stream:
1212 1212 return p.stdout, None
1213 1213
1214 1214 retdata = p.stdout.read().strip()
1215 1215 # wait for the child to exit to avoid race condition.
1216 1216 p.wait()
1217 1217
1218 1218 if p.returncode != 0 and p.returncode != 1:
1219 1219 # there are certain error codes that are ok
1220 1220 command = commands[0]
1221 1221 if command in ('cat-file', 'symbolic-ref'):
1222 1222 return retdata, p.returncode
1223 1223 # for all others, abort
1224 1224 raise util.Abort('git %s error %d in %s' %
1225 1225 (command, p.returncode, self._relpath))
1226 1226
1227 1227 return retdata, p.returncode
1228 1228
1229 1229 def _gitmissing(self):
1230 1230 return not os.path.exists(os.path.join(self._abspath, '.git'))
1231 1231
1232 1232 def _gitstate(self):
1233 1233 return self._gitcommand(['rev-parse', 'HEAD'])
1234 1234
1235 1235 def _gitcurrentbranch(self):
1236 1236 current, err = self._gitdir(['symbolic-ref', 'HEAD', '--quiet'])
1237 1237 if err:
1238 1238 current = None
1239 1239 return current
1240 1240
1241 1241 def _gitremote(self, remote):
1242 1242 out = self._gitcommand(['remote', 'show', '-n', remote])
1243 1243 line = out.split('\n')[1]
1244 1244 i = line.index('URL: ') + len('URL: ')
1245 1245 return line[i:]
1246 1246
1247 1247 def _githavelocally(self, revision):
1248 1248 out, code = self._gitdir(['cat-file', '-e', revision])
1249 1249 return code == 0
1250 1250
1251 1251 def _gitisancestor(self, r1, r2):
1252 1252 base = self._gitcommand(['merge-base', r1, r2])
1253 1253 return base == r1
1254 1254
1255 1255 def _gitisbare(self):
1256 1256 return self._gitcommand(['config', '--bool', 'core.bare']) == 'true'
1257 1257
1258 1258 def _gitupdatestat(self):
1259 1259 """This must be run before git diff-index.
1260 1260 diff-index only looks at changes to file stat;
1261 1261 this command looks at file contents and updates the stat."""
1262 1262 self._gitcommand(['update-index', '-q', '--refresh'])
1263 1263
1264 1264 def _gitbranchmap(self):
1265 1265 '''returns 2 things:
1266 1266 a map from git branch to revision
1267 1267 a map from revision to branches'''
1268 1268 branch2rev = {}
1269 1269 rev2branch = {}
1270 1270
1271 1271 out = self._gitcommand(['for-each-ref', '--format',
1272 1272 '%(objectname) %(refname)'])
1273 1273 for line in out.split('\n'):
1274 1274 revision, ref = line.split(' ')
1275 1275 if (not ref.startswith('refs/heads/') and
1276 1276 not ref.startswith('refs/remotes/')):
1277 1277 continue
1278 1278 if ref.startswith('refs/remotes/') and ref.endswith('/HEAD'):
1279 1279 continue # ignore remote/HEAD redirects
1280 1280 branch2rev[ref] = revision
1281 1281 rev2branch.setdefault(revision, []).append(ref)
1282 1282 return branch2rev, rev2branch
1283 1283
1284 1284 def _gittracking(self, branches):
1285 1285 'return map of remote branch to local tracking branch'
1286 1286 # assumes no more than one local tracking branch for each remote
1287 1287 tracking = {}
1288 1288 for b in branches:
1289 1289 if b.startswith('refs/remotes/'):
1290 1290 continue
1291 1291 bname = b.split('/', 2)[2]
1292 1292 remote = self._gitcommand(['config', 'branch.%s.remote' % bname])
1293 1293 if remote:
1294 1294 ref = self._gitcommand(['config', 'branch.%s.merge' % bname])
1295 1295 tracking['refs/remotes/%s/%s' %
1296 1296 (remote, ref.split('/', 2)[2])] = b
1297 1297 return tracking
1298 1298
1299 1299 def _abssource(self, source):
1300 1300 if '://' not in source:
1301 1301 # recognize the scp syntax as an absolute source
1302 1302 colon = source.find(':')
1303 1303 if colon != -1 and '/' not in source[:colon]:
1304 1304 return source
1305 1305 self._subsource = source
1306 1306 return _abssource(self)
1307 1307
1308 1308 def _fetch(self, source, revision):
1309 1309 if self._gitmissing():
1310 1310 source = self._abssource(source)
1311 1311 self._ui.status(_('cloning subrepo %s from %s\n') %
1312 1312 (self._relpath, source))
1313 1313 self._gitnodir(['clone', source, self._abspath])
1314 1314 if self._githavelocally(revision):
1315 1315 return
1316 1316 self._ui.status(_('pulling subrepo %s from %s\n') %
1317 1317 (self._relpath, self._gitremote('origin')))
1318 1318 # try only origin: the originally cloned repo
1319 1319 self._gitcommand(['fetch'])
1320 1320 if not self._githavelocally(revision):
1321 1321 raise util.Abort(_("revision %s does not exist in subrepo %s\n") %
1322 1322 (revision, self._relpath))
1323 1323
1324 1324 @annotatesubrepoerror
1325 1325 def dirty(self, ignoreupdate=False):
1326 1326 if self._gitmissing():
1327 1327 return self._state[1] != ''
1328 1328 if self._gitisbare():
1329 1329 return True
1330 1330 if not ignoreupdate and self._state[1] != self._gitstate():
1331 1331 # different version checked out
1332 1332 return True
1333 1333 # check for staged changes or modified files; ignore untracked files
1334 1334 self._gitupdatestat()
1335 1335 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
1336 1336 return code == 1
1337 1337
1338 1338 def basestate(self):
1339 1339 return self._gitstate()
1340 1340
1341 1341 @annotatesubrepoerror
1342 1342 def get(self, state, overwrite=False):
1343 1343 source, revision, kind = state
1344 1344 if not revision:
1345 1345 self.remove()
1346 1346 return
1347 1347 self._fetch(source, revision)
1348 1348 # if the repo was set to be bare, unbare it
1349 1349 if self._gitisbare():
1350 1350 self._gitcommand(['config', 'core.bare', 'false'])
1351 1351 if self._gitstate() == revision:
1352 1352 self._gitcommand(['reset', '--hard', 'HEAD'])
1353 1353 return
1354 1354 elif self._gitstate() == revision:
1355 1355 if overwrite:
1356 1356 # first reset the index to unmark new files for commit, because
1357 1357 # reset --hard will otherwise throw away files added for commit,
1358 1358 # not just unmark them.
1359 1359 self._gitcommand(['reset', 'HEAD'])
1360 1360 self._gitcommand(['reset', '--hard', 'HEAD'])
1361 1361 return
1362 1362 branch2rev, rev2branch = self._gitbranchmap()
1363 1363
1364 1364 def checkout(args):
1365 1365 cmd = ['checkout']
1366 1366 if overwrite:
1367 1367 # first reset the index to unmark new files for commit, because
1368 1368 # the -f option will otherwise throw away files added for
1369 1369 # commit, not just unmark them.
1370 1370 self._gitcommand(['reset', 'HEAD'])
1371 1371 cmd.append('-f')
1372 1372 self._gitcommand(cmd + args)
1373 1373 _sanitize(self._ui, self._abspath, '.git')
1374 1374
1375 1375 def rawcheckout():
1376 1376 # no branch to checkout, check it out with no branch
1377 1377 self._ui.warn(_('checking out detached HEAD in subrepo %s\n') %
1378 1378 self._relpath)
1379 1379 self._ui.warn(_('check out a git branch if you intend '
1380 1380 'to make changes\n'))
1381 1381 checkout(['-q', revision])
1382 1382
1383 1383 if revision not in rev2branch:
1384 1384 rawcheckout()
1385 1385 return
1386 1386 branches = rev2branch[revision]
1387 1387 firstlocalbranch = None
1388 1388 for b in branches:
1389 1389 if b == 'refs/heads/master':
1390 1390 # master trumps all other branches
1391 1391 checkout(['refs/heads/master'])
1392 1392 return
1393 1393 if not firstlocalbranch and not b.startswith('refs/remotes/'):
1394 1394 firstlocalbranch = b
1395 1395 if firstlocalbranch:
1396 1396 checkout([firstlocalbranch])
1397 1397 return
1398 1398
1399 1399 tracking = self._gittracking(branch2rev.keys())
1400 1400 # choose a remote branch already tracked if possible
1401 1401 remote = branches[0]
1402 1402 if remote not in tracking:
1403 1403 for b in branches:
1404 1404 if b in tracking:
1405 1405 remote = b
1406 1406 break
1407 1407
1408 1408 if remote not in tracking:
1409 1409 # create a new local tracking branch
1410 1410 local = remote.split('/', 3)[3]
1411 1411 checkout(['-b', local, remote])
1412 1412 elif self._gitisancestor(branch2rev[tracking[remote]], remote):
1413 1413 # When updating to a tracked remote branch,
1414 1414 # if the local tracking branch is downstream of it,
1415 1415 # a normal `git pull` would have performed a "fast-forward merge"
1416 1416 # which is equivalent to updating the local branch to the remote.
1417 1417 # Since we are only looking at branching at update, we need to
1418 1418 # detect this situation and perform this action lazily.
1419 1419 if tracking[remote] != self._gitcurrentbranch():
1420 1420 checkout([tracking[remote]])
1421 1421 self._gitcommand(['merge', '--ff', remote])
1422 1422 _sanitize(self._ui, self._abspath, '.git')
1423 1423 else:
1424 1424 # a real merge would be required, just checkout the revision
1425 1425 rawcheckout()
1426 1426
1427 1427 @annotatesubrepoerror
1428 1428 def commit(self, text, user, date):
1429 1429 if self._gitmissing():
1430 1430 raise util.Abort(_("subrepo %s is missing") % self._relpath)
1431 1431 cmd = ['commit', '-a', '-m', text]
1432 1432 env = os.environ.copy()
1433 1433 if user:
1434 1434 cmd += ['--author', user]
1435 1435 if date:
1436 1436 # git's date parser silently ignores when seconds < 1e9
1437 1437 # convert to ISO8601
1438 1438 env['GIT_AUTHOR_DATE'] = util.datestr(date,
1439 1439 '%Y-%m-%dT%H:%M:%S %1%2')
1440 1440 self._gitcommand(cmd, env=env)
1441 1441 # make sure commit works otherwise HEAD might not exist under certain
1442 1442 # circumstances
1443 1443 return self._gitstate()
1444 1444
1445 1445 @annotatesubrepoerror
1446 1446 def merge(self, state):
1447 1447 source, revision, kind = state
1448 1448 self._fetch(source, revision)
1449 1449 base = self._gitcommand(['merge-base', revision, self._state[1]])
1450 1450 self._gitupdatestat()
1451 1451 out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
1452 1452
1453 1453 def mergefunc():
1454 1454 if base == revision:
1455 1455 self.get(state) # fast forward merge
1456 1456 elif base != self._state[1]:
1457 1457 self._gitcommand(['merge', '--no-commit', revision])
1458 1458 _sanitize(self._ui, self._abspath, '.git')
1459 1459
1460 1460 if self.dirty():
1461 1461 if self._gitstate() != revision:
1462 1462 dirty = self._gitstate() == self._state[1] or code != 0
1463 1463 if _updateprompt(self._ui, self, dirty,
1464 1464 self._state[1][:7], revision[:7]):
1465 1465 mergefunc()
1466 1466 else:
1467 1467 mergefunc()
1468 1468
1469 1469 @annotatesubrepoerror
1470 1470 def push(self, opts):
1471 1471 force = opts.get('force')
1472 1472
1473 1473 if not self._state[1]:
1474 1474 return True
1475 1475 if self._gitmissing():
1476 1476 raise util.Abort(_("subrepo %s is missing") % self._relpath)
1477 1477 # if a branch in origin contains the revision, nothing to do
1478 1478 branch2rev, rev2branch = self._gitbranchmap()
1479 1479 if self._state[1] in rev2branch:
1480 1480 for b in rev2branch[self._state[1]]:
1481 1481 if b.startswith('refs/remotes/origin/'):
1482 1482 return True
1483 1483 for b, revision in branch2rev.iteritems():
1484 1484 if b.startswith('refs/remotes/origin/'):
1485 1485 if self._gitisancestor(self._state[1], revision):
1486 1486 return True
1487 1487 # otherwise, try to push the currently checked out branch
1488 1488 cmd = ['push']
1489 1489 if force:
1490 1490 cmd.append('--force')
1491 1491
1492 1492 current = self._gitcurrentbranch()
1493 1493 if current:
1494 1494 # determine if the current branch is even useful
1495 1495 if not self._gitisancestor(self._state[1], current):
1496 1496 self._ui.warn(_('unrelated git branch checked out '
1497 1497 'in subrepo %s\n') % self._relpath)
1498 1498 return False
1499 1499 self._ui.status(_('pushing branch %s of subrepo %s\n') %
1500 1500 (current.split('/', 2)[2], self._relpath))
1501 1501 ret = self._gitdir(cmd + ['origin', current])
1502 1502 return ret[1] == 0
1503 1503 else:
1504 1504 self._ui.warn(_('no branch checked out in subrepo %s\n'
1505 1505 'cannot push revision %s\n') %
1506 1506 (self._relpath, self._state[1]))
1507 1507 return False
1508 1508
1509 1509 @annotatesubrepoerror
1510 1510 def remove(self):
1511 1511 if self._gitmissing():
1512 1512 return
1513 1513 if self.dirty():
1514 1514 self._ui.warn(_('not removing repo %s because '
1515 1515 'it has changes.\n') % self._relpath)
1516 1516 return
1517 1517 # we can't fully delete the repository as it may contain
1518 1518 # local-only history
1519 1519 self._ui.note(_('removing subrepo %s\n') % self._relpath)
1520 1520 self._gitcommand(['config', 'core.bare', 'true'])
1521 1521 for f in os.listdir(self._abspath):
1522 1522 if f == '.git':
1523 1523 continue
1524 1524 path = os.path.join(self._abspath, f)
1525 1525 if os.path.isdir(path) and not os.path.islink(path):
1526 1526 shutil.rmtree(path)
1527 1527 else:
1528 1528 os.remove(path)
1529 1529
1530 1530 def archive(self, ui, archiver, prefix, match=None):
1531 1531 total = 0
1532 1532 source, revision = self._state
1533 1533 if not revision:
1534 1534 return total
1535 1535 self._fetch(source, revision)
1536 1536
1537 1537 # Parse git's native archive command.
1538 1538 # This should be much faster than manually traversing the trees
1539 1539 # and objects with many subprocess calls.
1540 1540 tarstream = self._gitcommand(['archive', revision], stream=True)
1541 1541 tar = tarfile.open(fileobj=tarstream, mode='r|')
1542 1542 relpath = subrelpath(self)
1543 1543 ui.progress(_('archiving (%s)') % relpath, 0, unit=_('files'))
1544 1544 for i, info in enumerate(tar):
1545 1545 if info.isdir():
1546 1546 continue
1547 1547 if match and not match(info.name):
1548 1548 continue
1549 1549 if info.issym():
1550 1550 data = info.linkname
1551 1551 else:
1552 1552 data = tar.extractfile(info).read()
1553 1553 archiver.addfile(os.path.join(prefix, self._path, info.name),
1554 1554 info.mode, info.issym(), data)
1555 1555 total += 1
1556 1556 ui.progress(_('archiving (%s)') % relpath, i + 1,
1557 1557 unit=_('files'))
1558 1558 ui.progress(_('archiving (%s)') % relpath, None)
1559 1559 return total
1560 1560
1561 1561
1562 1562 @annotatesubrepoerror
1563 1563 def status(self, rev2, **opts):
1564 1564 rev1 = self._state[1]
1565 1565 if self._gitmissing() or not rev1:
1566 1566 # if the repo is missing, return no results
1567 1567 return [], [], [], [], [], [], []
1568 1568 modified, added, removed = [], [], []
1569 1569 self._gitupdatestat()
1570 1570 if rev2:
1571 1571 command = ['diff-tree', rev1, rev2]
1572 1572 else:
1573 1573 command = ['diff-index', rev1]
1574 1574 out = self._gitcommand(command)
1575 1575 for line in out.split('\n'):
1576 1576 tab = line.find('\t')
1577 1577 if tab == -1:
1578 1578 continue
1579 1579 status, f = line[tab - 1], line[tab + 1:]
1580 1580 if status == 'M':
1581 1581 modified.append(f)
1582 1582 elif status == 'A':
1583 1583 added.append(f)
1584 1584 elif status == 'D':
1585 1585 removed.append(f)
1586 1586
1587 1587 deleted = unknown = ignored = clean = []
1588 1588 return modified, added, removed, deleted, unknown, ignored, clean
1589 1589
1590 1590 def shortid(self, revid):
1591 1591 return revid[:7]
1592 1592
1593 1593 types = {
1594 1594 'hg': hgsubrepo,
1595 1595 'svn': svnsubrepo,
1596 1596 'git': gitsubrepo,
1597 1597 }
@@ -1,527 +1,526
1 1 This file focuses mainly on updating largefiles in the working
2 2 directory (and ".hg/largefiles/dirstate")
3 3
4 4 $ cat >> $HGRCPATH <<EOF
5 5 > [ui]
6 6 > merge = internal:fail
7 7 > [extensions]
8 8 > largefiles =
9 9 > EOF
10 10
11 11 $ hg init repo
12 12 $ cd repo
13 13
14 14 $ echo large1 > large1
15 15 $ echo large2 > large2
16 16 $ hg add --large large1 large2
17 17 $ echo normal1 > normal1
18 18 $ hg add normal1
19 19 $ hg commit -m '#0'
20 20 $ echo 'large1 in #1' > large1
21 21 $ echo 'normal1 in #1' > normal1
22 22 $ hg commit -m '#1'
23 23 $ hg update -q -C 0
24 24 $ echo 'large2 in #2' > large2
25 25 $ hg commit -m '#2'
26 26 created new head
27 27
28 28 Test that "hg merge" updates largefiles from "other" correctly
29 29
30 30 (getting largefiles from "other" normally)
31 31
32 32 $ hg status -A large1
33 33 C large1
34 34 $ cat large1
35 35 large1
36 36 $ cat .hglf/large1
37 37 4669e532d5b2c093a78eca010077e708a071bb64
38 38 $ hg merge --config debug.dirstate.delaywrite=2
39 39 getting changed largefiles
40 40 1 largefiles updated, 0 removed
41 41 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 42 (branch merge, don't forget to commit)
43 43 $ hg status -A large1
44 44 M large1
45 45 $ cat large1
46 46 large1 in #1
47 47 $ cat .hglf/large1
48 48 58e24f733a964da346e2407a2bee99d9001184f5
49 49 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
50 50 -4669e532d5b2c093a78eca010077e708a071bb64
51 51 +58e24f733a964da346e2407a2bee99d9001184f5
52 52
53 53 (getting largefiles from "other" via conflict prompt)
54 54
55 55 $ hg update -q -C 2
56 56 $ echo 'large1 in #3' > large1
57 57 $ echo 'normal1 in #3' > normal1
58 58 $ hg commit -m '#3'
59 59 $ cat .hglf/large1
60 60 e5bb990443d6a92aaf7223813720f7566c9dd05b
61 61 $ hg merge --config debug.dirstate.delaywrite=2 --config ui.interactive=True <<EOF
62 62 > o
63 63 > EOF
64 64 largefile large1 has a merge conflict
65 65 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
66 66 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
67 67 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
68 68 merging normal1
69 69 warning: conflicts during merge.
70 70 merging normal1 incomplete! (edit conflicts, then use 'hg resolve --mark')
71 71 getting changed largefiles
72 72 1 largefiles updated, 0 removed
73 73 0 files updated, 1 files merged, 0 files removed, 1 files unresolved
74 74 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
75 75 [1]
76 76 $ hg status -A large1
77 77 M large1
78 78 $ cat large1
79 79 large1 in #1
80 80 $ cat .hglf/large1
81 81 58e24f733a964da346e2407a2bee99d9001184f5
82 82
83 83 Test that "hg revert -r REV" updates largefiles from "REV" correctly
84 84
85 85 $ hg update -q -C 3
86 86 $ hg status -A large1
87 87 C large1
88 88 $ cat large1
89 89 large1 in #3
90 90 $ cat .hglf/large1
91 91 e5bb990443d6a92aaf7223813720f7566c9dd05b
92 92 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
93 93 -4669e532d5b2c093a78eca010077e708a071bb64
94 94 +58e24f733a964da346e2407a2bee99d9001184f5
95 95 $ hg revert --no-backup -r 1 --config debug.dirstate.delaywrite=2 large1
96 96 $ hg status -A large1
97 97 M large1
98 98 $ cat large1
99 99 large1 in #1
100 100 $ cat .hglf/large1
101 101 58e24f733a964da346e2407a2bee99d9001184f5
102 102
103 103 Test that "hg rollback" restores status of largefiles correctly
104 104
105 105 $ hg update -C -q
106 106 $ hg remove large1
107 107 $ test -f .hglf/large1
108 108 [1]
109 109 $ hg forget large2
110 110 $ test -f .hglf/large2
111 111 [1]
112 112 $ echo largeX > largeX
113 113 $ hg add --large largeX
114 114 $ cat .hglf/largeX
115 115
116 116 $ hg commit -m 'will be rollback-ed soon'
117 117 $ echo largeY > largeY
118 118 $ hg add --large largeY
119 119 $ hg status -A large1
120 120 large1: No such file or directory
121 121 $ hg status -A large2
122 122 ? large2
123 123 $ hg status -A largeX
124 124 C largeX
125 125 $ hg status -A largeY
126 126 A largeY
127 127 $ hg rollback
128 128 repository tip rolled back to revision 3 (undo commit)
129 129 working directory now based on revision 3
130 130 $ hg status -A large1
131 131 R large1
132 132 $ test -f .hglf/large1
133 133 [1]
134 134 $ hg status -A large2
135 135 R large2
136 136 $ test -f .hglf/large2
137 137 [1]
138 138 $ hg status -A largeX
139 139 A largeX
140 140 $ cat .hglf/largeX
141 141
142 142 $ hg status -A largeY
143 143 ? largeY
144 144 $ test -f .hglf/largeY
145 145 [1]
146 146
147 147 Test that "hg rollback" restores standins correctly
148 148
149 149 $ hg commit -m 'will be rollback-ed soon'
150 150 $ hg update -q -C 2
151 151 $ cat large1
152 152 large1
153 153 $ cat .hglf/large1
154 154 4669e532d5b2c093a78eca010077e708a071bb64
155 155 $ cat large2
156 156 large2 in #2
157 157 $ cat .hglf/large2
158 158 3cfce6277e7668985707b6887ce56f9f62f6ccd9
159 159
160 160 $ hg rollback -q -f
161 161 $ cat large1
162 162 large1
163 163 $ cat .hglf/large1
164 164 4669e532d5b2c093a78eca010077e708a071bb64
165 165 $ cat large2
166 166 large2 in #2
167 167 $ cat .hglf/large2
168 168 3cfce6277e7668985707b6887ce56f9f62f6ccd9
169 169
170 170 (rollback the parent of the working directory, when the parent of it
171 171 is not branch-tip)
172 172
173 173 $ hg update -q -C 1
174 174 $ cat .hglf/large1
175 175 58e24f733a964da346e2407a2bee99d9001184f5
176 176 $ cat .hglf/large2
177 177 1deebade43c8c498a3c8daddac0244dc55d1331d
178 178
179 179 $ echo normalX > normalX
180 180 $ hg add normalX
181 181 $ hg commit -m 'will be rollback-ed soon'
182 182 $ hg rollback -q
183 183
184 184 $ cat .hglf/large1
185 185 58e24f733a964da346e2407a2bee99d9001184f5
186 186 $ cat .hglf/large2
187 187 1deebade43c8c498a3c8daddac0244dc55d1331d
188 188
189 189 Test that "hg status" shows status of largefiles correctly just after
190 190 automated commit like rebase/transplant
191 191
192 192 $ cat >> .hg/hgrc <<EOF
193 193 > [extensions]
194 194 > rebase =
195 195 > strip =
196 196 > transplant =
197 197 > EOF
198 198 $ hg update -q -C 1
199 199 $ hg remove large1
200 200 $ echo largeX > largeX
201 201 $ hg add --large largeX
202 202 $ hg commit -m '#4'
203 203
204 204 $ hg rebase -s 1 -d 2 --keep
205 205 $ hg status -A large1
206 206 large1: No such file or directory
207 207 $ hg status -A largeX
208 208 C largeX
209 209 $ hg strip -q 5
210 210
211 211 $ hg update -q -C 2
212 212 $ hg transplant -q 1 4
213 213 $ hg status -A large1
214 214 large1: No such file or directory
215 215 $ hg status -A largeX
216 216 C largeX
217 217 $ hg strip -q 5
218 218
219 219 $ hg update -q -C 2
220 220 $ hg transplant -q --merge 1 --merge 4
221 221 $ hg status -A large1
222 222 large1: No such file or directory
223 223 $ hg status -A largeX
224 224 C largeX
225 225 $ hg strip -q 5
226 226
227 227 Test that linear merge can detect modification (and conflict) correctly
228 228
229 229 (linear merge without conflict)
230 230
231 231 $ echo 'large2 for linear merge (no conflict)' > large2
232 232 $ hg update 3 --config debug.dirstate.delaywrite=2
233 233 getting changed largefiles
234 234 1 largefiles updated, 0 removed
235 235 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
236 236 $ hg status -A large2
237 237 M large2
238 238 $ cat large2
239 239 large2 for linear merge (no conflict)
240 240 $ cat .hglf/large2
241 241 9c4bf8f1b33536d6e5f89447e10620cfe52ea710
242 242
243 243 (linear merge with conflict, choosing "other")
244 244
245 245 $ hg update -q -C 2
246 246 $ echo 'large1 for linear merge (conflict)' > large1
247 247 $ hg update 3 --config ui.interactive=True <<EOF
248 248 > o
249 249 > EOF
250 250 largefile large1 has a merge conflict
251 251 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
252 252 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
253 253 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? o
254 254 getting changed largefiles
255 255 1 largefiles updated, 0 removed
256 256 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
257 257 $ hg status -A large1
258 258 C large1
259 259 $ cat large1
260 260 large1 in #3
261 261 $ cat .hglf/large1
262 262 e5bb990443d6a92aaf7223813720f7566c9dd05b
263 263
264 264 (linear merge with conflict, choosing "local")
265 265
266 266 $ hg update -q -C 2
267 267 $ echo 'large1 for linear merge (conflict)' > large1
268 268 $ hg update 3 --config debug.dirstate.delaywrite=2
269 269 largefile large1 has a merge conflict
270 270 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
271 271 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
272 272 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
273 273 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
274 274 $ hg status -A large1
275 275 M large1
276 276 $ cat large1
277 277 large1 for linear merge (conflict)
278 278 $ cat .hglf/large1
279 279 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
280 280
281 281 Test a linear merge to a revision containing same-name normal file
282 282
283 283 $ hg update -q -C 3
284 284 $ hg remove large2
285 285 $ echo 'large2 as normal file' > large2
286 286 $ hg add large2
287 287 $ echo 'large3 as normal file' > large3
288 288 $ hg add large3
289 289 $ hg commit -m '#5'
290 290 $ hg manifest
291 291 .hglf/large1
292 292 large2
293 293 large3
294 294 normal1
295 295
296 296 (modified largefile is already switched to normal)
297 297
298 298 $ hg update -q -C 2
299 299 $ echo 'modified large2 for linear merge' > large2
300 300 $ hg update -q 5
301 301 local changed .hglf/large2 which remote deleted
302 302 use (c)hanged version or (d)elete? c
303 303 remote turned local largefile large2 into a normal file
304 304 keep (l)argefile or use (n)ormal file? l
305 305 $ hg debugdirstate --nodates | grep large2
306 306 a 0 -1 .hglf/large2
307 307 r 0 0 large2
308 308 $ hg status -A large2
309 309 A large2
310 310 $ cat large2
311 311 modified large2 for linear merge
312 312
313 313 (added largefile is already committed as normal)
314 314
315 315 $ hg update -q -C 2
316 316 $ echo 'large3 as large file for linear merge' > large3
317 317 $ hg add --large large3
318 318 $ hg update -q 5
319 319 remote turned local largefile large3 into a normal file
320 320 keep (l)argefile or use (n)ormal file? l
321 321 $ hg debugdirstate --nodates | grep large3
322 322 a 0 -1 .hglf/large3
323 323 r 0 0 large3
324 324 $ hg status -A large3
325 325 A large3
326 326 $ cat large3
327 327 large3 as large file for linear merge
328 328 $ rm -f large3 .hglf/large3
329 329
330 330 Test that the internal linear merging works correctly
331 331 (both heads are stripped to keep pairing of revision number and commit log)
332 332
333 333 $ hg update -q -C 2
334 334 $ hg strip 3 4
335 335 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/9530e27857f7-backup.hg (glob)
336 336 $ mv .hg/strip-backup/9530e27857f7-backup.hg $TESTTMP
337 337
338 338 (internal linear merging at "hg pull --update")
339 339
340 340 $ echo 'large1 for linear merge (conflict)' > large1
341 341 $ echo 'large2 for linear merge (conflict with normal file)' > large2
342 342 $ hg pull --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-backup.hg
343 343 pulling from $TESTTMP/9530e27857f7-backup.hg (glob)
344 344 searching for changes
345 345 adding changesets
346 346 adding manifests
347 347 adding file changes
348 348 added 3 changesets with 5 changes to 5 files
349 349 local changed .hglf/large2 which remote deleted
350 350 use (c)hanged version or (d)elete? c
351 351 remote turned local largefile large2 into a normal file
352 352 keep (l)argefile or use (n)ormal file? l
353 353 largefile large1 has a merge conflict
354 354 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
355 355 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
356 356 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
357 357 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
358 358
359 359 $ hg status -A large1
360 360 M large1
361 361 $ cat large1
362 362 large1 for linear merge (conflict)
363 363 $ cat .hglf/large1
364 364 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
365 365 $ hg status -A large2
366 366 A large2
367 367 $ cat large2
368 368 large2 for linear merge (conflict with normal file)
369 369 $ cat .hglf/large2
370 370 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
371 371
372 372 (internal linear merging at "hg unbundle --update")
373 373
374 374 $ hg update -q -C 2
375 375 $ hg rollback -q
376 376
377 377 $ echo 'large1 for linear merge (conflict)' > large1
378 378 $ echo 'large2 for linear merge (conflict with normal file)' > large2
379 379 $ hg unbundle --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-backup.hg
380 380 adding changesets
381 381 adding manifests
382 382 adding file changes
383 383 added 3 changesets with 5 changes to 5 files
384 384 local changed .hglf/large2 which remote deleted
385 385 use (c)hanged version or (d)elete? c
386 386 remote turned local largefile large2 into a normal file
387 387 keep (l)argefile or use (n)ormal file? l
388 388 largefile large1 has a merge conflict
389 389 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
390 390 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
391 391 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
392 392 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
393 393
394 394 $ hg status -A large1
395 395 M large1
396 396 $ cat large1
397 397 large1 for linear merge (conflict)
398 398 $ cat .hglf/large1
399 399 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
400 400 $ hg status -A large2
401 401 A large2
402 402 $ cat large2
403 403 large2 for linear merge (conflict with normal file)
404 404 $ cat .hglf/large2
405 405 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
406 406
407 407 (internal linear merging in subrepo at "hg update")
408 408
409 409 $ cd ..
410 410 $ hg init subparent
411 411 $ cd subparent
412 412
413 413 $ hg clone -q -u 2 ../repo sub
414 414 $ cat > .hgsub <<EOF
415 415 > sub = sub
416 416 > EOF
417 417 $ hg add .hgsub
418 418 $ hg commit -m '#0@parent'
419 419 $ cat .hgsubstate
420 420 f74e50bd9e5594b7cf1e6c5cbab86ddd25f3ca2f sub
421 421 $ hg -R sub update -q
422 422 $ hg commit -m '#1@parent'
423 423 $ cat .hgsubstate
424 424 d65e59e952a9638e2ce863b41a420ca723dd3e8d sub
425 425 $ hg update -q 0
426 426
427 427 $ echo 'large1 for linear merge (conflict)' > sub/large1
428 428 $ echo 'large2 for linear merge (conflict with normal file)' > sub/large2
429 429 $ hg update --config ui.interactive=True --config debug.dirstate.delaywrite=2 <<EOF
430 430 > m
431 431 > r
432 432 > c
433 433 > l
434 434 > l
435 435 > EOF
436 436 subrepository sub diverged (local revision: f74e50bd9e55, remote revision: d65e59e952a9)
437 437 (M)erge, keep (l)ocal or keep (r)emote? m
438 438 subrepository sources for sub differ (in checked out version)
439 use (l)ocal source (f74e50bd9e55) or (r)emote source (d65e59e952a9)?
440 r
439 use (l)ocal source (f74e50bd9e55) or (r)emote source (d65e59e952a9)? r
441 440 local changed .hglf/large2 which remote deleted
442 441 use (c)hanged version or (d)elete? c
443 442 remote turned local largefile large2 into a normal file
444 443 keep (l)argefile or use (n)ormal file? l
445 444 largefile large1 has a merge conflict
446 445 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
447 446 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
448 447 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
449 448 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
450 449 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
451 450
452 451 $ hg -R sub status -A sub/large1
453 452 M sub/large1
454 453 $ cat sub/large1
455 454 large1 for linear merge (conflict)
456 455 $ cat sub/.hglf/large1
457 456 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
458 457 $ hg -R sub status -A sub/large2
459 458 A sub/large2
460 459 $ cat sub/large2
461 460 large2 for linear merge (conflict with normal file)
462 461 $ cat sub/.hglf/large2
463 462 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
464 463
465 464 $ cd ..
466 465 $ cd repo
467 466
468 467 Test that rebase updates largefiles in the working directory even if
469 468 it is aborted by conflict.
470 469
471 470 $ hg update -q -C 3
472 471 $ cat .hglf/large1
473 472 e5bb990443d6a92aaf7223813720f7566c9dd05b
474 473 $ cat large1
475 474 large1 in #3
476 475 $ hg rebase -s 1 -d 3 --keep --config ui.interactive=True <<EOF
477 476 > o
478 477 > EOF
479 478 largefile large1 has a merge conflict
480 479 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
481 480 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
482 481 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
483 482 merging normal1
484 483 warning: conflicts during merge.
485 484 merging normal1 incomplete! (edit conflicts, then use 'hg resolve --mark')
486 485 unresolved conflicts (see hg resolve, then hg rebase --continue)
487 486 [1]
488 487 $ cat .hglf/large1
489 488 58e24f733a964da346e2407a2bee99d9001184f5
490 489 $ cat large1
491 490 large1 in #1
492 491
493 492 $ hg rebase -q --abort
494 493 rebase aborted
495 494
496 495 Test that transplant updates largefiles, of which standins are safely
497 496 changed, even if it is aborted by conflict of other.
498 497
499 498 $ hg update -q -C 5
500 499 $ cat .hglf/large1
501 500 e5bb990443d6a92aaf7223813720f7566c9dd05b
502 501 $ cat large1
503 502 large1 in #3
504 503 $ hg diff -c 4 .hglf/largeX | grep '^[+-][0-9a-z]'
505 504 +fa44618ea25181aff4f48b70428294790cec9f61
506 505 $ hg transplant 4
507 506 applying 07d6153b5c04
508 507 patching file .hglf/large1
509 508 Hunk #1 FAILED at 0
510 509 1 out of 1 hunks FAILED -- saving rejects to file .hglf/large1.rej
511 510 patch failed to apply
512 511 abort: fix up the merge and run hg transplant --continue
513 512 [255]
514 513 $ hg status -A large1
515 514 C large1
516 515 $ cat .hglf/large1
517 516 e5bb990443d6a92aaf7223813720f7566c9dd05b
518 517 $ cat large1
519 518 large1 in #3
520 519 $ hg status -A largeX
521 520 A largeX
522 521 $ cat .hglf/largeX
523 522 fa44618ea25181aff4f48b70428294790cec9f61
524 523 $ cat largeX
525 524 largeX
526 525
527 526 $ cd ..
@@ -1,664 +1,661
1 1 #require git
2 2
3 3 make git commits repeatable
4 4
5 5 $ echo "[core]" >> $HOME/.gitconfig
6 6 $ echo "autocrlf = false" >> $HOME/.gitconfig
7 7 $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
8 8 $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
9 9 $ GIT_AUTHOR_DATE='1234567891 +0000'; export GIT_AUTHOR_DATE
10 10 $ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
11 11 $ GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
12 12 $ GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
13 13
14 14 root hg repo
15 15
16 16 $ hg init t
17 17 $ cd t
18 18 $ echo a > a
19 19 $ hg add a
20 20 $ hg commit -m a
21 21 $ cd ..
22 22
23 23 new external git repo
24 24
25 25 $ mkdir gitroot
26 26 $ cd gitroot
27 27 $ git init -q
28 28 $ echo g > g
29 29 $ git add g
30 30 $ git commit -q -m g
31 31
32 32 add subrepo clone
33 33
34 34 $ cd ../t
35 35 $ echo 's = [git]../gitroot' > .hgsub
36 36 $ git clone -q ../gitroot s
37 37 $ hg add .hgsub
38 38 $ hg commit -m 'new git subrepo'
39 39 $ hg debugsub
40 40 path s
41 41 source ../gitroot
42 42 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
43 43
44 44 record a new commit from upstream from a different branch
45 45
46 46 $ cd ../gitroot
47 47 $ git checkout -q -b testing
48 48 $ echo gg >> g
49 49 $ git commit -q -a -m gg
50 50
51 51 $ cd ../t/s
52 52 $ git pull -q >/dev/null 2>/dev/null
53 53 $ git checkout -q -b testing origin/testing >/dev/null
54 54
55 55 $ cd ..
56 56 $ hg status --subrepos
57 57 M s/g
58 58 $ hg commit -m 'update git subrepo'
59 59 $ hg debugsub
60 60 path s
61 61 source ../gitroot
62 62 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
63 63
64 64 make $GITROOT pushable, by replacing it with a clone with nothing checked out
65 65
66 66 $ cd ..
67 67 $ git clone gitroot gitrootbare --bare -q
68 68 $ rm -rf gitroot
69 69 $ mv gitrootbare gitroot
70 70
71 71 clone root
72 72
73 73 $ cd t
74 74 $ hg clone . ../tc 2> /dev/null
75 75 updating to branch default
76 76 cloning subrepo s from $TESTTMP/gitroot
77 77 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 78 $ cd ../tc
79 79 $ hg debugsub
80 80 path s
81 81 source ../gitroot
82 82 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
83 83
84 84 update to previous substate
85 85
86 86 $ hg update 1 -q
87 87 $ cat s/g
88 88 g
89 89 $ hg debugsub
90 90 path s
91 91 source ../gitroot
92 92 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
93 93
94 94 clone root, make local change
95 95
96 96 $ cd ../t
97 97 $ hg clone . ../ta 2> /dev/null
98 98 updating to branch default
99 99 cloning subrepo s from $TESTTMP/gitroot
100 100 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
101 101
102 102 $ cd ../ta
103 103 $ echo ggg >> s/g
104 104 $ hg status --subrepos
105 105 M s/g
106 106 $ hg commit --subrepos -m ggg
107 107 committing subrepository s
108 108 $ hg debugsub
109 109 path s
110 110 source ../gitroot
111 111 revision 79695940086840c99328513acbe35f90fcd55e57
112 112
113 113 clone root separately, make different local change
114 114
115 115 $ cd ../t
116 116 $ hg clone . ../tb 2> /dev/null
117 117 updating to branch default
118 118 cloning subrepo s from $TESTTMP/gitroot
119 119 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 120
121 121 $ cd ../tb/s
122 122 $ echo f > f
123 123 $ git add f
124 124 $ cd ..
125 125
126 126 $ hg status --subrepos
127 127 A s/f
128 128 $ hg commit --subrepos -m f
129 129 committing subrepository s
130 130 $ hg debugsub
131 131 path s
132 132 source ../gitroot
133 133 revision aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
134 134
135 135 user b push changes
136 136
137 137 $ hg push 2>/dev/null
138 138 pushing to $TESTTMP/t (glob)
139 139 pushing branch testing of subrepo s
140 140 searching for changes
141 141 adding changesets
142 142 adding manifests
143 143 adding file changes
144 144 added 1 changesets with 1 changes to 1 files
145 145
146 146 user a pulls, merges, commits
147 147
148 148 $ cd ../ta
149 149 $ hg pull
150 150 pulling from $TESTTMP/t (glob)
151 151 searching for changes
152 152 adding changesets
153 153 adding manifests
154 154 adding file changes
155 155 added 1 changesets with 1 changes to 1 files (+1 heads)
156 156 (run 'hg heads' to see heads, 'hg merge' to merge)
157 157 $ hg merge 2>/dev/null
158 158 subrepository s diverged (local revision: 7969594, remote revision: aa84837)
159 159 (M)erge, keep (l)ocal or keep (r)emote? m
160 160 pulling subrepo s from $TESTTMP/gitroot
161 161 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 162 (branch merge, don't forget to commit)
163 163 $ cat s/f
164 164 f
165 165 $ cat s/g
166 166 g
167 167 gg
168 168 ggg
169 169 $ hg commit --subrepos -m 'merge'
170 170 committing subrepository s
171 171 $ hg status --subrepos --rev 1:5
172 172 M .hgsubstate
173 173 M s/g
174 174 A s/f
175 175 $ hg debugsub
176 176 path s
177 177 source ../gitroot
178 178 revision f47b465e1bce645dbf37232a00574aa1546ca8d3
179 179 $ hg push 2>/dev/null
180 180 pushing to $TESTTMP/t (glob)
181 181 pushing branch testing of subrepo s
182 182 searching for changes
183 183 adding changesets
184 184 adding manifests
185 185 adding file changes
186 186 added 2 changesets with 2 changes to 1 files
187 187
188 188 make upstream git changes
189 189
190 190 $ cd ..
191 191 $ git clone -q gitroot gitclone
192 192 $ cd gitclone
193 193 $ echo ff >> f
194 194 $ git commit -q -a -m ff
195 195 $ echo fff >> f
196 196 $ git commit -q -a -m fff
197 197 $ git push origin testing 2>/dev/null
198 198
199 199 make and push changes to hg without updating the subrepo
200 200
201 201 $ cd ../t
202 202 $ hg clone . ../td 2>&1 | egrep -v '^Cloning into|^done\.'
203 203 updating to branch default
204 204 cloning subrepo s from $TESTTMP/gitroot
205 205 checking out detached HEAD in subrepo s
206 206 check out a git branch if you intend to make changes
207 207 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
208 208 $ cd ../td
209 209 $ echo aa >> a
210 210 $ hg commit -m aa
211 211 $ hg push
212 212 pushing to $TESTTMP/t (glob)
213 213 searching for changes
214 214 adding changesets
215 215 adding manifests
216 216 adding file changes
217 217 added 1 changesets with 1 changes to 1 files
218 218
219 219 sync to upstream git, distribute changes
220 220
221 221 $ cd ../ta
222 222 $ hg pull -u -q
223 223 $ cd s
224 224 $ git pull -q >/dev/null 2>/dev/null
225 225 $ cd ..
226 226 $ hg commit -m 'git upstream sync'
227 227 $ hg debugsub
228 228 path s
229 229 source ../gitroot
230 230 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
231 231 $ hg push -q
232 232
233 233 $ cd ../tb
234 234 $ hg pull -q
235 235 $ hg update 2>/dev/null
236 236 pulling subrepo s from $TESTTMP/gitroot
237 237 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
238 238 $ hg debugsub
239 239 path s
240 240 source ../gitroot
241 241 revision 32a343883b74769118bb1d3b4b1fbf9156f4dddc
242 242
243 243 create a new git branch
244 244
245 245 $ cd s
246 246 $ git checkout -b b2
247 247 Switched to a new branch 'b2'
248 248 $ echo a>a
249 249 $ git add a
250 250 $ git commit -qm 'add a'
251 251 $ cd ..
252 252 $ hg commit -m 'add branch in s'
253 253
254 254 pulling new git branch should not create tracking branch named 'origin/b2'
255 255 (issue3870)
256 256 $ cd ../td/s
257 257 $ git remote set-url origin $TESTTMP/tb/s
258 258 $ git branch --no-track oldtesting
259 259 $ cd ..
260 260 $ hg pull -q ../tb
261 261 $ hg up
262 262 From $TESTTMP/tb/s
263 263 * [new branch] b2 -> origin/b2
264 264 Previous HEAD position was f47b465... merge
265 265 Switched to a new branch 'b2'
266 266 pulling subrepo s from $TESTTMP/tb/s
267 267 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
268 268
269 269 update to a revision without the subrepo, keeping the local git repository
270 270
271 271 $ cd ../t
272 272 $ hg up 0
273 273 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
274 274 $ ls -a s
275 275 .
276 276 ..
277 277 .git
278 278
279 279 $ hg up 2
280 280 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
281 281 $ ls -a s
282 282 .
283 283 ..
284 284 .git
285 285 g
286 286
287 287 archive subrepos
288 288
289 289 $ cd ../tc
290 290 $ hg pull -q
291 291 $ hg archive --subrepos -r 5 ../archive 2>/dev/null
292 292 pulling subrepo s from $TESTTMP/gitroot
293 293 $ cd ../archive
294 294 $ cat s/f
295 295 f
296 296 $ cat s/g
297 297 g
298 298 gg
299 299 ggg
300 300
301 301 $ hg -R ../tc archive --subrepo -r 5 -X ../tc/**f ../archive_x 2>/dev/null
302 302 $ find ../archive_x | sort | grep -v pax_global_header
303 303 ../archive_x
304 304 ../archive_x/.hg_archival.txt
305 305 ../archive_x/.hgsub
306 306 ../archive_x/.hgsubstate
307 307 ../archive_x/a
308 308 ../archive_x/s
309 309 ../archive_x/s/g
310 310
311 311 create nested repo
312 312
313 313 $ cd ..
314 314 $ hg init outer
315 315 $ cd outer
316 316 $ echo b>b
317 317 $ hg add b
318 318 $ hg commit -m b
319 319
320 320 $ hg clone ../t inner 2> /dev/null
321 321 updating to branch default
322 322 cloning subrepo s from $TESTTMP/gitroot
323 323 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
324 324 $ echo inner = inner > .hgsub
325 325 $ hg add .hgsub
326 326 $ hg commit -m 'nested sub'
327 327
328 328 nested commit
329 329
330 330 $ echo ffff >> inner/s/f
331 331 $ hg status --subrepos
332 332 M inner/s/f
333 333 $ hg commit --subrepos -m nested
334 334 committing subrepository inner
335 335 committing subrepository inner/s (glob)
336 336
337 337 nested archive
338 338
339 339 $ hg archive --subrepos ../narchive
340 340 $ ls ../narchive/inner/s | grep -v pax_global_header
341 341 f
342 342 g
343 343
344 344 relative source expansion
345 345
346 346 $ cd ..
347 347 $ mkdir d
348 348 $ hg clone t d/t 2> /dev/null
349 349 updating to branch default
350 350 cloning subrepo s from $TESTTMP/gitroot
351 351 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
352 352
353 353 Don't crash if the subrepo is missing
354 354
355 355 $ hg clone t missing -q
356 356 $ cd missing
357 357 $ rm -rf s
358 358 $ hg status -S
359 359 $ hg sum | grep commit
360 360 commit: 1 subrepos
361 361 $ hg push -q
362 362 abort: subrepo s is missing (in subrepo s)
363 363 [255]
364 364 $ hg commit --subrepos -qm missing
365 365 abort: subrepo s is missing (in subrepo s)
366 366 [255]
367 367 $ hg update -C 2> /dev/null
368 368 cloning subrepo s from $TESTTMP/gitroot
369 369 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
370 370 $ hg sum | grep commit
371 371 commit: (clean)
372 372
373 373 Don't crash if the .hgsubstate entry is missing
374 374
375 375 $ hg update 1 -q
376 376 $ hg rm .hgsubstate
377 377 $ hg commit .hgsubstate -m 'no substate'
378 378 nothing changed
379 379 [1]
380 380 $ hg tag -l nosubstate
381 381 $ hg manifest
382 382 .hgsub
383 383 .hgsubstate
384 384 a
385 385
386 386 $ hg status -S
387 387 R .hgsubstate
388 388 $ hg sum | grep commit
389 389 commit: 1 removed, 1 subrepos (new branch head)
390 390
391 391 $ hg commit -m 'restore substate'
392 392 nothing changed
393 393 [1]
394 394 $ hg manifest
395 395 .hgsub
396 396 .hgsubstate
397 397 a
398 398 $ hg sum | grep commit
399 399 commit: 1 removed, 1 subrepos (new branch head)
400 400
401 401 $ hg update -qC nosubstate
402 402 $ ls s
403 403 g
404 404
405 405 issue3109: false positives in git diff-index
406 406
407 407 $ hg update -q
408 408 $ touch -t 200001010000 s/g
409 409 $ hg status --subrepos
410 410 $ touch -t 200001010000 s/g
411 411 $ hg sum | grep commit
412 412 commit: (clean)
413 413
414 414 Check hg update --clean
415 415 $ cd $TESTTMP/ta
416 416 $ echo > s/g
417 417 $ cd s
418 418 $ echo c1 > f1
419 419 $ echo c1 > f2
420 420 $ git add f1
421 421 $ cd ..
422 422 $ hg status -S
423 423 M s/g
424 424 A s/f1
425 425 $ ls s
426 426 f
427 427 f1
428 428 f2
429 429 g
430 430 $ hg update --clean
431 431 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 432 $ hg status -S
433 433 $ ls s
434 434 f
435 435 f1
436 436 f2
437 437 g
438 438
439 439 Sticky subrepositories, no changes
440 440 $ cd $TESTTMP/ta
441 441 $ hg id -n
442 442 7
443 443 $ cd s
444 444 $ git rev-parse HEAD
445 445 32a343883b74769118bb1d3b4b1fbf9156f4dddc
446 446 $ cd ..
447 447 $ hg update 1 > /dev/null 2>&1
448 448 $ hg id -n
449 449 1
450 450 $ cd s
451 451 $ git rev-parse HEAD
452 452 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
453 453 $ cd ..
454 454
455 455 Sticky subrepositories, file changes
456 456 $ touch s/f1
457 457 $ cd s
458 458 $ git add f1
459 459 $ cd ..
460 460 $ hg id -n
461 461 1+
462 462 $ cd s
463 463 $ git rev-parse HEAD
464 464 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
465 465 $ cd ..
466 466 $ hg update 4
467 467 subrepository s diverged (local revision: da5f5b1, remote revision: aa84837)
468 468 (M)erge, keep (l)ocal or keep (r)emote? m
469 469 subrepository sources for s differ
470 use (l)ocal source (da5f5b1) or (r)emote source (aa84837)?
471 l
470 use (l)ocal source (da5f5b1) or (r)emote source (aa84837)? l
472 471 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
473 472 $ hg id -n
474 473 4+
475 474 $ cd s
476 475 $ git rev-parse HEAD
477 476 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
478 477 $ cd ..
479 478 $ hg update --clean tip > /dev/null 2>&1
480 479
481 480 Sticky subrepository, revision updates
482 481 $ hg id -n
483 482 7
484 483 $ cd s
485 484 $ git rev-parse HEAD
486 485 32a343883b74769118bb1d3b4b1fbf9156f4dddc
487 486 $ cd ..
488 487 $ cd s
489 488 $ git checkout aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
490 489 Previous HEAD position was 32a3438... fff
491 490 HEAD is now at aa84837... f
492 491 $ cd ..
493 492 $ hg update 1
494 493 subrepository s diverged (local revision: 32a3438, remote revision: da5f5b1)
495 494 (M)erge, keep (l)ocal or keep (r)emote? m
496 495 subrepository sources for s differ (in checked out version)
497 use (l)ocal source (32a3438) or (r)emote source (da5f5b1)?
498 l
496 use (l)ocal source (32a3438) or (r)emote source (da5f5b1)? l
499 497 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
500 498 $ hg id -n
501 499 1+
502 500 $ cd s
503 501 $ git rev-parse HEAD
504 502 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
505 503 $ cd ..
506 504
507 505 Sticky subrepository, file changes and revision updates
508 506 $ touch s/f1
509 507 $ cd s
510 508 $ git add f1
511 509 $ git rev-parse HEAD
512 510 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
513 511 $ cd ..
514 512 $ hg id -n
515 513 1+
516 514 $ hg update 7
517 515 subrepository s diverged (local revision: 32a3438, remote revision: 32a3438)
518 516 (M)erge, keep (l)ocal or keep (r)emote? m
519 517 subrepository sources for s differ
520 use (l)ocal source (32a3438) or (r)emote source (32a3438)?
521 l
518 use (l)ocal source (32a3438) or (r)emote source (32a3438)? l
522 519 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
523 520 $ hg id -n
524 521 7+
525 522 $ cd s
526 523 $ git rev-parse HEAD
527 524 aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
528 525 $ cd ..
529 526
530 527 Sticky repository, update --clean
531 528 $ hg update --clean tip 2>/dev/null
532 529 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
533 530 $ hg id -n
534 531 7
535 532 $ cd s
536 533 $ git rev-parse HEAD
537 534 32a343883b74769118bb1d3b4b1fbf9156f4dddc
538 535 $ cd ..
539 536
540 537 Test subrepo already at intended revision:
541 538 $ cd s
542 539 $ git checkout 32a343883b74769118bb1d3b4b1fbf9156f4dddc
543 540 HEAD is now at 32a3438... fff
544 541 $ cd ..
545 542 $ hg update 1
546 543 Previous HEAD position was 32a3438... fff
547 544 HEAD is now at da5f5b1... g
548 545 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
549 546 $ hg id -n
550 547 1
551 548 $ cd s
552 549 $ git rev-parse HEAD
553 550 da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
554 551 $ cd ..
555 552
556 553 Test forgetting files, not implemented in git subrepo, used to
557 554 traceback
558 555 #if no-windows
559 556 $ hg forget 'notafile*'
560 557 notafile*: No such file or directory
561 558 [1]
562 559 #else
563 560 $ hg forget 'notafile'
564 561 notafile: * (glob)
565 562 [1]
566 563 #endif
567 564
568 565 $ cd ..
569 566
570 567 Test sanitizing ".hg/hgrc" in subrepo
571 568
572 569 $ cd t
573 570 $ hg tip -q
574 571 7:af6d2edbb0d3
575 572 $ hg update -q -C af6d2edbb0d3
576 573 $ cd s
577 574 $ git checkout -q -b sanitize-test
578 575 $ mkdir .hg
579 576 $ echo '.hg/hgrc in git repo' > .hg/hgrc
580 577 $ mkdir -p sub/.hg
581 578 $ echo 'sub/.hg/hgrc in git repo' > sub/.hg/hgrc
582 579 $ git add .hg sub
583 580 $ git commit -qm 'add .hg/hgrc to be sanitized at hg update'
584 581 $ git push -q origin sanitize-test
585 582 $ cd ..
586 583 $ grep ' s$' .hgsubstate
587 584 32a343883b74769118bb1d3b4b1fbf9156f4dddc s
588 585 $ hg commit -qm 'commit with git revision including .hg/hgrc'
589 586 $ hg parents -q
590 587 8:3473d20bddcf
591 588 $ grep ' s$' .hgsubstate
592 589 c4069473b459cf27fd4d7c2f50c4346b4e936599 s
593 590 $ cd ..
594 591
595 592 $ hg -R tc pull -q
596 593 $ hg -R tc update -q -C 3473d20bddcf 2>&1 | sort
597 594 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/.hg' (glob)
598 595 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/sub/.hg' (glob)
599 596 $ cd tc
600 597 $ hg parents -q
601 598 8:3473d20bddcf
602 599 $ grep ' s$' .hgsubstate
603 600 c4069473b459cf27fd4d7c2f50c4346b4e936599 s
604 601 $ test -f s/.hg/hgrc
605 602 [1]
606 603 $ test -f s/sub/.hg/hgrc
607 604 [1]
608 605 $ cd ..
609 606
610 607 additional test for "git merge --ff" route:
611 608
612 609 $ cd t
613 610 $ hg tip -q
614 611 8:3473d20bddcf
615 612 $ hg update -q -C af6d2edbb0d3
616 613 $ cd s
617 614 $ git checkout -q testing
618 615 $ mkdir .hg
619 616 $ echo '.hg/hgrc in git repo' > .hg/hgrc
620 617 $ mkdir -p sub/.hg
621 618 $ echo 'sub/.hg/hgrc in git repo' > sub/.hg/hgrc
622 619 $ git add .hg sub
623 620 $ git commit -qm 'add .hg/hgrc to be sanitized at hg update (git merge --ff)'
624 621 $ git push -q origin testing
625 622 $ cd ..
626 623 $ grep ' s$' .hgsubstate
627 624 32a343883b74769118bb1d3b4b1fbf9156f4dddc s
628 625 $ hg commit -qm 'commit with git revision including .hg/hgrc'
629 626 $ hg parents -q
630 627 9:ed23f7fe024e
631 628 $ grep ' s$' .hgsubstate
632 629 f262643c1077219fbd3858d54e78ef050ef84fbf s
633 630 $ cd ..
634 631
635 632 $ cd tc
636 633 $ hg update -q -C af6d2edbb0d3
637 634 $ test -f s/.hg/hgrc
638 635 [1]
639 636 $ test -f s/sub/.hg/hgrc
640 637 [1]
641 638 $ cd ..
642 639 $ hg -R tc pull -q
643 640 $ hg -R tc update -q -C ed23f7fe024e 2>&1 | sort
644 641 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/.hg' (glob)
645 642 warning: removing potentially hostile 'hgrc' in '$TESTTMP/tc/s/sub/.hg' (glob)
646 643 $ cd tc
647 644 $ hg parents -q
648 645 9:ed23f7fe024e
649 646 $ grep ' s$' .hgsubstate
650 647 f262643c1077219fbd3858d54e78ef050ef84fbf s
651 648 $ test -f s/.hg/hgrc
652 649 [1]
653 650 $ test -f s/sub/.hg/hgrc
654 651 [1]
655 652
656 653 Test that sanitizing is omitted in meta data area:
657 654
658 655 $ mkdir s/.git/.hg
659 656 $ echo '.hg/hgrc in git metadata area' > s/.git/.hg/hgrc
660 657 $ hg update -q -C af6d2edbb0d3
661 658 checking out detached HEAD in subrepo s
662 659 check out a git branch if you intend to make changes
663 660
664 661 $ cd ..
@@ -1,686 +1,683
1 1 #require svn15
2 2
3 3 $ SVNREPOPATH=`pwd`/svn-repo
4 4 #if windows
5 5 $ SVNREPOURL=file:///`python -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
6 6 #else
7 7 $ SVNREPOURL=file://`python -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
8 8 #endif
9 9
10 10 create subversion repo
11 11
12 12 $ WCROOT="`pwd`/svn-wc"
13 13 $ svnadmin create svn-repo
14 14 $ svn co "$SVNREPOURL" svn-wc
15 15 Checked out revision 0.
16 16 $ cd svn-wc
17 17 $ mkdir src
18 18 $ echo alpha > src/alpha
19 19 $ svn add src
20 20 A src
21 21 A src/alpha (glob)
22 22 $ mkdir externals
23 23 $ echo other > externals/other
24 24 $ svn add externals
25 25 A externals
26 26 A externals/other (glob)
27 27 $ svn ci -m 'Add alpha'
28 28 Adding externals
29 29 Adding externals/other (glob)
30 30 Adding src
31 31 Adding src/alpha (glob)
32 32 Transmitting file data ..
33 33 Committed revision 1.
34 34 $ svn up -q
35 35 $ echo "externals -r1 $SVNREPOURL/externals" > extdef
36 36 $ svn propset -F extdef svn:externals src
37 37 property 'svn:externals' set on 'src'
38 38 $ svn ci -m 'Setting externals'
39 39 Sending src
40 40
41 41 Committed revision 2.
42 42 $ cd ..
43 43
44 44 create hg repo
45 45
46 46 $ mkdir sub
47 47 $ cd sub
48 48 $ hg init t
49 49 $ cd t
50 50
51 51 first revision, no sub
52 52
53 53 $ echo a > a
54 54 $ hg ci -Am0
55 55 adding a
56 56
57 57 add first svn sub with leading whitespaces
58 58
59 59 $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
60 60 $ echo "subdir/s = [svn] $SVNREPOURL/src" >> .hgsub
61 61 $ svn co --quiet "$SVNREPOURL"/src s
62 62 $ mkdir subdir
63 63 $ svn co --quiet "$SVNREPOURL"/src subdir/s
64 64 $ hg add .hgsub
65 65 $ hg ci -m1
66 66
67 67 make sure we avoid empty commits (issue2445)
68 68
69 69 $ hg sum
70 70 parent: 1:* tip (glob)
71 71 1
72 72 branch: default
73 73 commit: (clean)
74 74 update: (current)
75 75 $ hg ci -moops
76 76 nothing changed
77 77 [1]
78 78
79 79 debugsub
80 80
81 81 $ hg debugsub
82 82 path s
83 83 source file://*/svn-repo/src (glob)
84 84 revision 2
85 85 path subdir/s
86 86 source file://*/svn-repo/src (glob)
87 87 revision 2
88 88
89 89 change file in svn and hg, commit
90 90
91 91 $ echo a >> a
92 92 $ echo alpha >> s/alpha
93 93 $ hg sum
94 94 parent: 1:* tip (glob)
95 95 1
96 96 branch: default
97 97 commit: 1 modified, 1 subrepos
98 98 update: (current)
99 99 $ hg commit --subrepos -m 'Message!' | grep -v Updating
100 100 committing subrepository s
101 101 Sending*s/alpha (glob)
102 102 Transmitting file data .
103 103 Committed revision 3.
104 104
105 105 Fetching external item into '*s/externals'* (glob)
106 106 External at revision 1.
107 107
108 108 At revision 3.
109 109 $ hg debugsub
110 110 path s
111 111 source file://*/svn-repo/src (glob)
112 112 revision 3
113 113 path subdir/s
114 114 source file://*/svn-repo/src (glob)
115 115 revision 2
116 116
117 117 missing svn file, commit should fail
118 118
119 119 $ rm s/alpha
120 120 $ hg commit --subrepos -m 'abort on missing file'
121 121 committing subrepository s
122 122 abort: cannot commit missing svn entries (in subrepo s)
123 123 [255]
124 124 $ svn revert s/alpha > /dev/null
125 125
126 126 add an unrelated revision in svn and update the subrepo to without
127 127 bringing any changes.
128 128
129 129 $ svn mkdir "$SVNREPOURL/unrelated" -m 'create unrelated'
130 130
131 131 Committed revision 4.
132 132 $ svn up -q s
133 133 $ hg sum
134 134 parent: 2:* tip (glob)
135 135 Message!
136 136 branch: default
137 137 commit: (clean)
138 138 update: (current)
139 139
140 140 $ echo a > s/a
141 141
142 142 should be empty despite change to s/a
143 143
144 144 $ hg st
145 145
146 146 add a commit from svn
147 147
148 148 $ cd "$WCROOT/src"
149 149 $ svn up -q
150 150 $ echo xyz >> alpha
151 151 $ svn propset svn:mime-type 'text/xml' alpha
152 152 property 'svn:mime-type' set on 'alpha'
153 153 $ svn ci -m 'amend a from svn'
154 154 Sending *alpha (glob)
155 155 Transmitting file data .
156 156 Committed revision 5.
157 157 $ cd ../../sub/t
158 158
159 159 this commit from hg will fail
160 160
161 161 $ echo zzz >> s/alpha
162 162 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
163 163 committing subrepository s
164 164 abort: svn:*Commit failed (details follow): (glob)
165 165 [255]
166 166 $ svn revert -q s/alpha
167 167
168 168 this commit fails because of meta changes
169 169
170 170 $ svn propset svn:mime-type 'text/html' s/alpha
171 171 property 'svn:mime-type' set on 's/alpha' (glob)
172 172 $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
173 173 committing subrepository s
174 174 abort: svn:*Commit failed (details follow): (glob)
175 175 [255]
176 176 $ svn revert -q s/alpha
177 177
178 178 this commit fails because of externals changes
179 179
180 180 $ echo zzz > s/externals/other
181 181 $ hg ci --subrepos -m 'amend externals from hg'
182 182 committing subrepository s
183 183 abort: cannot commit svn externals (in subrepo s)
184 184 [255]
185 185 $ hg diff --subrepos -r 1:2 | grep -v diff
186 186 --- a/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
187 187 +++ b/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
188 188 @@ -1,2 +1,2 @@
189 189 -2 s
190 190 +3 s
191 191 2 subdir/s
192 192 --- a/a Thu Jan 01 00:00:00 1970 +0000
193 193 +++ b/a Thu Jan 01 00:00:00 1970 +0000
194 194 @@ -1,1 +1,2 @@
195 195 a
196 196 +a
197 197 $ svn revert -q s/externals/other
198 198
199 199 this commit fails because of externals meta changes
200 200
201 201 $ svn propset svn:mime-type 'text/html' s/externals/other
202 202 property 'svn:mime-type' set on 's/externals/other' (glob)
203 203 $ hg ci --subrepos -m 'amend externals from hg'
204 204 committing subrepository s
205 205 abort: cannot commit svn externals (in subrepo s)
206 206 [255]
207 207 $ svn revert -q s/externals/other
208 208
209 209 clone
210 210
211 211 $ cd ..
212 212 $ hg clone t tc
213 213 updating to branch default
214 214 A tc/s/alpha (glob)
215 215 U tc/s (glob)
216 216
217 217 Fetching external item into 'tc/s/externals'* (glob)
218 218 A tc/s/externals/other (glob)
219 219 Checked out external at revision 1.
220 220
221 221 Checked out revision 3.
222 222 A tc/subdir/s/alpha (glob)
223 223 U tc/subdir/s (glob)
224 224
225 225 Fetching external item into 'tc/subdir/s/externals'* (glob)
226 226 A tc/subdir/s/externals/other (glob)
227 227 Checked out external at revision 1.
228 228
229 229 Checked out revision 2.
230 230 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
231 231 $ cd tc
232 232
233 233 debugsub in clone
234 234
235 235 $ hg debugsub
236 236 path s
237 237 source file://*/svn-repo/src (glob)
238 238 revision 3
239 239 path subdir/s
240 240 source file://*/svn-repo/src (glob)
241 241 revision 2
242 242
243 243 verify subrepo is contained within the repo directory
244 244
245 245 $ python -c "import os.path; print os.path.exists('s')"
246 246 True
247 247
248 248 update to nullrev (must delete the subrepo)
249 249
250 250 $ hg up null
251 251 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
252 252 $ ls
253 253
254 254 Check hg update --clean
255 255 $ cd "$TESTTMP/sub/t"
256 256 $ cd s
257 257 $ echo c0 > alpha
258 258 $ echo c1 > f1
259 259 $ echo c1 > f2
260 260 $ svn add f1 -q
261 261 $ svn status | sort
262 262
263 263 ? * a (glob)
264 264 ? * f2 (glob)
265 265 A * f1 (glob)
266 266 M * alpha (glob)
267 267 Performing status on external item at 'externals'* (glob)
268 268 X * externals (glob)
269 269 $ cd ../..
270 270 $ hg -R t update -C
271 271
272 272 Fetching external item into 't/s/externals'* (glob)
273 273 Checked out external at revision 1.
274 274
275 275 Checked out revision 3.
276 276 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 277 $ cd t/s
278 278 $ svn status | sort
279 279
280 280 ? * a (glob)
281 281 ? * f1 (glob)
282 282 ? * f2 (glob)
283 283 Performing status on external item at 'externals'* (glob)
284 284 X * externals (glob)
285 285
286 286 Sticky subrepositories, no changes
287 287 $ cd "$TESTTMP/sub/t"
288 288 $ hg id -n
289 289 2
290 290 $ cd s
291 291 $ svnversion
292 292 3
293 293 $ cd ..
294 294 $ hg update 1
295 295 U *s/alpha (glob)
296 296
297 297 Fetching external item into '*s/externals'* (glob)
298 298 Checked out external at revision 1.
299 299
300 300 Checked out revision 2.
301 301 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
302 302 $ hg id -n
303 303 1
304 304 $ cd s
305 305 $ svnversion
306 306 2
307 307 $ cd ..
308 308
309 309 Sticky subrepositories, file changes
310 310 $ touch s/f1
311 311 $ cd s
312 312 $ svn add f1
313 313 A f1
314 314 $ cd ..
315 315 $ hg id -n
316 316 1+
317 317 $ cd s
318 318 $ svnversion
319 319 2M
320 320 $ cd ..
321 321 $ hg update tip
322 322 subrepository s diverged (local revision: 2, remote revision: 3)
323 323 (M)erge, keep (l)ocal or keep (r)emote? m
324 324 subrepository sources for s differ
325 use (l)ocal source (2) or (r)emote source (3)?
326 l
325 use (l)ocal source (2) or (r)emote source (3)? l
327 326 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
328 327 $ hg id -n
329 328 2+
330 329 $ cd s
331 330 $ svnversion
332 331 2M
333 332 $ cd ..
334 333 $ hg update --clean tip
335 334 U *s/alpha (glob)
336 335
337 336 Fetching external item into '*s/externals'* (glob)
338 337 Checked out external at revision 1.
339 338
340 339 Checked out revision 3.
341 340 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
342 341
343 342 Sticky subrepository, revision updates
344 343 $ hg id -n
345 344 2
346 345 $ cd s
347 346 $ svnversion
348 347 3
349 348 $ cd ..
350 349 $ cd s
351 350 $ svn update -qr 1
352 351 $ cd ..
353 352 $ hg update 1
354 353 subrepository s diverged (local revision: 3, remote revision: 2)
355 354 (M)erge, keep (l)ocal or keep (r)emote? m
356 355 subrepository sources for s differ (in checked out version)
357 use (l)ocal source (1) or (r)emote source (2)?
358 l
356 use (l)ocal source (1) or (r)emote source (2)? l
359 357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
360 358 $ hg id -n
361 359 1+
362 360 $ cd s
363 361 $ svnversion
364 362 1
365 363 $ cd ..
366 364
367 365 Sticky subrepository, file changes and revision updates
368 366 $ touch s/f1
369 367 $ cd s
370 368 $ svn add f1
371 369 A f1
372 370 $ svnversion
373 371 1M
374 372 $ cd ..
375 373 $ hg id -n
376 374 1+
377 375 $ hg update tip
378 376 subrepository s diverged (local revision: 3, remote revision: 3)
379 377 (M)erge, keep (l)ocal or keep (r)emote? m
380 378 subrepository sources for s differ
381 use (l)ocal source (1) or (r)emote source (3)?
382 l
379 use (l)ocal source (1) or (r)emote source (3)? l
383 380 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
384 381 $ hg id -n
385 382 2+
386 383 $ cd s
387 384 $ svnversion
388 385 1M
389 386 $ cd ..
390 387
391 388 Sticky repository, update --clean
392 389 $ hg update --clean tip | grep -v 's[/\]externals[/\]other'
393 390 U *s/alpha (glob)
394 391 U *s (glob)
395 392
396 393 Fetching external item into '*s/externals'* (glob)
397 394 Checked out external at revision 1.
398 395
399 396 Checked out revision 3.
400 397 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
401 398 $ hg id -n
402 399 2
403 400 $ cd s
404 401 $ svnversion
405 402 3
406 403 $ cd ..
407 404
408 405 Test subrepo already at intended revision:
409 406 $ cd s
410 407 $ svn update -qr 2
411 408 $ cd ..
412 409 $ hg update 1
413 410 subrepository s diverged (local revision: 3, remote revision: 2)
414 411 (M)erge, keep (l)ocal or keep (r)emote? m
415 412 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
416 413 $ hg id -n
417 414 1+
418 415 $ cd s
419 416 $ svnversion
420 417 2
421 418 $ cd ..
422 419
423 420 Test case where subversion would fail to update the subrepo because there
424 421 are unknown directories being replaced by tracked ones (happens with rebase).
425 422
426 423 $ cd "$WCROOT/src"
427 424 $ mkdir dir
428 425 $ echo epsilon.py > dir/epsilon.py
429 426 $ svn add dir
430 427 A dir
431 428 A dir/epsilon.py (glob)
432 429 $ svn ci -m 'Add dir/epsilon.py'
433 430 Adding *dir (glob)
434 431 Adding *dir/epsilon.py (glob)
435 432 Transmitting file data .
436 433 Committed revision 6.
437 434 $ cd ../..
438 435 $ hg init rebaserepo
439 436 $ cd rebaserepo
440 437 $ svn co -r5 --quiet "$SVNREPOURL"/src s
441 438 $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
442 439 $ hg add .hgsub
443 440 $ hg ci -m addsub
444 441 $ echo a > a
445 442 $ hg ci -Am adda
446 443 adding a
447 444 $ hg up 0
448 445 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
449 446 $ svn up -qr6 s
450 447 $ hg ci -m updatesub
451 448 created new head
452 449 $ echo pyc > s/dir/epsilon.pyc
453 450 $ hg up 1
454 451 D *s/dir (glob)
455 452
456 453 Fetching external item into '*s/externals'* (glob)
457 454 Checked out external at revision 1.
458 455
459 456 Checked out revision 5.
460 457 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 458 $ hg up -q 2
462 459
463 460 Modify one of the externals to point to a different path so we can
464 461 test having obstructions when switching branches on checkout:
465 462 $ hg checkout tip
466 463 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
467 464 $ echo "obstruct = [svn] $SVNREPOURL/externals" >> .hgsub
468 465 $ svn co -r5 --quiet "$SVNREPOURL"/externals obstruct
469 466 $ hg commit -m 'Start making obstructed working copy'
470 467 $ hg book other
471 468 $ hg co -r 'p1(tip)'
472 469 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
473 470 (leaving bookmark other)
474 471 $ echo "obstruct = [svn] $SVNREPOURL/src" >> .hgsub
475 472 $ svn co -r5 --quiet "$SVNREPOURL"/src obstruct
476 473 $ hg commit -m 'Other branch which will be obstructed'
477 474 created new head
478 475
479 476 Switching back to the head where we have another path mapped to the
480 477 same subrepo should work if the subrepo is clean.
481 478 $ hg co other
482 479 A *obstruct/other (glob)
483 480 Checked out revision 1.
484 481 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
485 482 (activating bookmark other)
486 483
487 484 This is surprising, but is also correct based on the current code:
488 485 $ echo "updating should (maybe) fail" > obstruct/other
489 486 $ hg co tip
490 487 abort: uncommitted changes
491 488 (commit or update --clean to discard changes)
492 489 [255]
493 490
494 491 Point to a Subversion branch which has since been deleted and recreated
495 492 First, create that condition in the repository.
496 493
497 494 $ hg ci --subrepos -m cleanup | grep -v Updating
498 495 committing subrepository obstruct
499 496 Sending obstruct/other (glob)
500 497 Transmitting file data .
501 498 Committed revision 7.
502 499 At revision 7.
503 500 $ svn mkdir -m "baseline" $SVNREPOURL/trunk
504 501
505 502 Committed revision 8.
506 503 $ svn copy -m "initial branch" $SVNREPOURL/trunk $SVNREPOURL/branch
507 504
508 505 Committed revision 9.
509 506 $ svn co --quiet "$SVNREPOURL"/branch tempwc
510 507 $ cd tempwc
511 508 $ echo "something old" > somethingold
512 509 $ svn add somethingold
513 510 A somethingold
514 511 $ svn ci -m 'Something old'
515 512 Adding somethingold
516 513 Transmitting file data .
517 514 Committed revision 10.
518 515 $ svn rm -m "remove branch" $SVNREPOURL/branch
519 516
520 517 Committed revision 11.
521 518 $ svn copy -m "recreate branch" $SVNREPOURL/trunk $SVNREPOURL/branch
522 519
523 520 Committed revision 12.
524 521 $ svn up -q
525 522 $ echo "something new" > somethingnew
526 523 $ svn add somethingnew
527 524 A somethingnew
528 525 $ svn ci -m 'Something new'
529 526 Adding somethingnew
530 527 Transmitting file data .
531 528 Committed revision 13.
532 529 $ cd ..
533 530 $ rm -rf tempwc
534 531 $ svn co "$SVNREPOURL/branch"@10 recreated
535 532 A recreated/somethingold (glob)
536 533 Checked out revision 10.
537 534 $ echo "recreated = [svn] $SVNREPOURL/branch" >> .hgsub
538 535 $ hg ci -m addsub
539 536 $ cd recreated
540 537 $ svn up -q
541 538 $ cd ..
542 539 $ hg ci -m updatesub
543 540 $ hg up -r-2
544 541 D *recreated/somethingnew (glob)
545 542 A *recreated/somethingold (glob)
546 543 Checked out revision 10.
547 544 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
548 545 (leaving bookmark other)
549 546 $ test -f recreated/somethingold
550 547
551 548 Test archive
552 549
553 550 $ hg archive -S ../archive-all --debug
554 551 archiving: 0/2 files (0.00%)
555 552 archiving: .hgsub 1/2 files (50.00%)
556 553 archiving: .hgsubstate 2/2 files (100.00%)
557 554 archiving (obstruct): 0/1 files (0.00%)
558 555 archiving (obstruct): 1/1 files (100.00%)
559 556 archiving (recreated): 0/1 files (0.00%)
560 557 archiving (recreated): 1/1 files (100.00%)
561 558 archiving (s): 0/2 files (0.00%)
562 559 archiving (s): 1/2 files (50.00%)
563 560 archiving (s): 2/2 files (100.00%)
564 561
565 562 $ hg archive -S ../archive-exclude --debug -X **old
566 563 archiving: 0/2 files (0.00%)
567 564 archiving: .hgsub 1/2 files (50.00%)
568 565 archiving: .hgsubstate 2/2 files (100.00%)
569 566 archiving (obstruct): 0/1 files (0.00%)
570 567 archiving (obstruct): 1/1 files (100.00%)
571 568 archiving (recreated): 0 files
572 569 archiving (s): 0/2 files (0.00%)
573 570 archiving (s): 1/2 files (50.00%)
574 571 archiving (s): 2/2 files (100.00%)
575 572 $ find ../archive-exclude | sort
576 573 ../archive-exclude
577 574 ../archive-exclude/.hg_archival.txt
578 575 ../archive-exclude/.hgsub
579 576 ../archive-exclude/.hgsubstate
580 577 ../archive-exclude/obstruct
581 578 ../archive-exclude/obstruct/other
582 579 ../archive-exclude/s
583 580 ../archive-exclude/s/alpha
584 581 ../archive-exclude/s/dir
585 582 ../archive-exclude/s/dir/epsilon.py
586 583
587 584 Test forgetting files, not implemented in svn subrepo, used to
588 585 traceback
589 586
590 587 #if no-windows
591 588 $ hg forget 'notafile*'
592 589 notafile*: No such file or directory
593 590 [1]
594 591 #else
595 592 $ hg forget 'notafile'
596 593 notafile: * (glob)
597 594 [1]
598 595 #endif
599 596
600 597 Test a subrepo referencing a just moved svn path. Last commit rev will
601 598 be different from the revision, and the path will be different as
602 599 well.
603 600
604 601 $ cd "$WCROOT"
605 602 $ svn up > /dev/null
606 603 $ mkdir trunk/subdir branches
607 604 $ echo a > trunk/subdir/a
608 605 $ svn add trunk/subdir branches
609 606 A trunk/subdir (glob)
610 607 A trunk/subdir/a (glob)
611 608 A branches
612 609 $ svn ci -m addsubdir
613 610 Adding branches
614 611 Adding trunk/subdir (glob)
615 612 Adding trunk/subdir/a (glob)
616 613 Transmitting file data .
617 614 Committed revision 14.
618 615 $ svn cp -m branchtrunk $SVNREPOURL/trunk $SVNREPOURL/branches/somebranch
619 616
620 617 Committed revision 15.
621 618 $ cd ..
622 619
623 620 $ hg init repo2
624 621 $ cd repo2
625 622 $ svn co $SVNREPOURL/branches/somebranch/subdir
626 623 A subdir/a (glob)
627 624 Checked out revision 15.
628 625 $ echo "subdir = [svn] $SVNREPOURL/branches/somebranch/subdir" > .hgsub
629 626 $ hg add .hgsub
630 627 $ hg ci -m addsub
631 628 $ hg up null
632 629 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
633 630 $ hg up
634 631 A *subdir/a (glob)
635 632 Checked out revision 15.
636 633 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
637 634 $ cd ..
638 635
639 636 Test sanitizing ".hg/hgrc" in subrepo
640 637
641 638 $ cd sub/t
642 639 $ hg update -q -C tip
643 640 $ cd s
644 641 $ mkdir .hg
645 642 $ echo '.hg/hgrc in svn repo' > .hg/hgrc
646 643 $ mkdir -p sub/.hg
647 644 $ echo 'sub/.hg/hgrc in svn repo' > sub/.hg/hgrc
648 645 $ svn add .hg sub
649 646 A .hg
650 647 A .hg/hgrc (glob)
651 648 A sub
652 649 A sub/.hg (glob)
653 650 A sub/.hg/hgrc (glob)
654 651 $ svn ci -m 'add .hg/hgrc to be sanitized at hg update'
655 652 Adding .hg
656 653 Adding .hg/hgrc (glob)
657 654 Adding sub
658 655 Adding sub/.hg (glob)
659 656 Adding sub/.hg/hgrc (glob)
660 657 Transmitting file data ..
661 658 Committed revision 16.
662 659 $ svn up -q
663 660 $ cd ..
664 661 $ hg commit -S -m 'commit with svn revision including .hg/hgrc'
665 662 $ grep ' s$' .hgsubstate
666 663 16 s
667 664 $ cd ..
668 665
669 666 $ hg -R tc pull -u -q 2>&1 | sort
670 667 warning: removing potentially hostile 'hgrc' in '$TESTTMP/sub/tc/s/.hg' (glob)
671 668 warning: removing potentially hostile 'hgrc' in '$TESTTMP/sub/tc/s/sub/.hg' (glob)
672 669 $ cd tc
673 670 $ grep ' s$' .hgsubstate
674 671 16 s
675 672 $ test -f s/.hg/hgrc
676 673 [1]
677 674 $ test -f s/sub/.hg/hgrc
678 675 [1]
679 676
680 677 Test that sanitizing is omitted in meta data area:
681 678
682 679 $ mkdir s/.svn/.hg
683 680 $ echo '.hg/hgrc in svn metadata area' > s/.svn/.hg/hgrc
684 681 $ hg update -q -C '.^1'
685 682
686 683 $ cd ../..
@@ -1,1476 +1,1471
1 1 Let commit recurse into subrepos by default to match pre-2.0 behavior:
2 2
3 3 $ echo "[ui]" >> $HGRCPATH
4 4 $ echo "commitsubrepos = Yes" >> $HGRCPATH
5 5
6 6 $ hg init t
7 7 $ cd t
8 8
9 9 first revision, no sub
10 10
11 11 $ echo a > a
12 12 $ hg ci -Am0
13 13 adding a
14 14
15 15 add first sub
16 16
17 17 $ echo s = s > .hgsub
18 18 $ hg add .hgsub
19 19 $ hg init s
20 20 $ echo a > s/a
21 21
22 22 Issue2232: committing a subrepo without .hgsub
23 23
24 24 $ hg ci -mbad s
25 25 abort: can't commit subrepos without .hgsub
26 26 [255]
27 27
28 28 $ hg -R s ci -Ams0
29 29 adding a
30 30 $ hg sum
31 31 parent: 0:f7b1eb17ad24 tip
32 32 0
33 33 branch: default
34 34 commit: 1 added, 1 subrepos
35 35 update: (current)
36 36 $ hg ci -m1
37 37
38 38 test handling .hgsubstate "added" explicitly.
39 39
40 40 $ hg parents --template '{node}\n{files}\n'
41 41 7cf8cfea66e410e8e3336508dfeec07b3192de51
42 42 .hgsub .hgsubstate
43 43 $ hg rollback -q
44 44 $ hg add .hgsubstate
45 45 $ hg ci -m1
46 46 $ hg parents --template '{node}\n{files}\n'
47 47 7cf8cfea66e410e8e3336508dfeec07b3192de51
48 48 .hgsub .hgsubstate
49 49
50 50 Revert subrepo and test subrepo fileset keyword:
51 51
52 52 $ echo b > s/a
53 53 $ hg revert "set:subrepo('glob:s*')"
54 54 reverting subrepo s
55 55 reverting s/a (glob)
56 56 $ rm s/a.orig
57 57
58 58 Revert subrepo with no backup. The "reverting s/a" line is gone since
59 59 we're really running 'hg update' in the subrepo:
60 60
61 61 $ echo b > s/a
62 62 $ hg revert --no-backup s
63 63 reverting subrepo s
64 64
65 65 Issue2022: update -C
66 66
67 67 $ echo b > s/a
68 68 $ hg sum
69 69 parent: 1:7cf8cfea66e4 tip
70 70 1
71 71 branch: default
72 72 commit: 1 subrepos
73 73 update: (current)
74 74 $ hg co -C 1
75 75 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 76 $ hg sum
77 77 parent: 1:7cf8cfea66e4 tip
78 78 1
79 79 branch: default
80 80 commit: (clean)
81 81 update: (current)
82 82
83 83 commands that require a clean repo should respect subrepos
84 84
85 85 $ echo b >> s/a
86 86 $ hg backout tip
87 87 abort: uncommitted changes in subrepo s
88 88 [255]
89 89 $ hg revert -C -R s s/a
90 90
91 91 add sub sub
92 92
93 93 $ echo ss = ss > s/.hgsub
94 94 $ hg init s/ss
95 95 $ echo a > s/ss/a
96 96 $ hg -R s add s/.hgsub
97 97 $ hg -R s/ss add s/ss/a
98 98 $ hg sum
99 99 parent: 1:7cf8cfea66e4 tip
100 100 1
101 101 branch: default
102 102 commit: 1 subrepos
103 103 update: (current)
104 104 $ hg ci -m2
105 105 committing subrepository s
106 106 committing subrepository s/ss (glob)
107 107 $ hg sum
108 108 parent: 2:df30734270ae tip
109 109 2
110 110 branch: default
111 111 commit: (clean)
112 112 update: (current)
113 113
114 114 test handling .hgsubstate "modified" explicitly.
115 115
116 116 $ hg parents --template '{node}\n{files}\n'
117 117 df30734270ae757feb35e643b7018e818e78a9aa
118 118 .hgsubstate
119 119 $ hg rollback -q
120 120 $ hg status -A .hgsubstate
121 121 M .hgsubstate
122 122 $ hg ci -m2
123 123 $ hg parents --template '{node}\n{files}\n'
124 124 df30734270ae757feb35e643b7018e818e78a9aa
125 125 .hgsubstate
126 126
127 127 bump sub rev (and check it is ignored by ui.commitsubrepos)
128 128
129 129 $ echo b > s/a
130 130 $ hg -R s ci -ms1
131 131 $ hg --config ui.commitsubrepos=no ci -m3
132 132
133 133 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
134 134
135 135 $ echo c > s/a
136 136 $ hg --config ui.commitsubrepos=no ci -m4
137 137 abort: uncommitted changes in subrepo s
138 138 (use --subrepos for recursive commit)
139 139 [255]
140 140 $ hg id
141 141 f6affe3fbfaa+ tip
142 142 $ hg -R s ci -mc
143 143 $ hg id
144 144 f6affe3fbfaa+ tip
145 145 $ echo d > s/a
146 146 $ hg ci -m4
147 147 committing subrepository s
148 148 $ hg tip -R s
149 149 changeset: 4:02dcf1d70411
150 150 tag: tip
151 151 user: test
152 152 date: Thu Jan 01 00:00:00 1970 +0000
153 153 summary: 4
154 154
155 155
156 156 check caching
157 157
158 158 $ hg co 0
159 159 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
160 160 $ hg debugsub
161 161
162 162 restore
163 163
164 164 $ hg co
165 165 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
166 166 $ hg debugsub
167 167 path s
168 168 source s
169 169 revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
170 170
171 171 new branch for merge tests
172 172
173 173 $ hg co 1
174 174 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
175 175 $ echo t = t >> .hgsub
176 176 $ hg init t
177 177 $ echo t > t/t
178 178 $ hg -R t add t
179 179 adding t/t (glob)
180 180
181 181 5
182 182
183 183 $ hg ci -m5 # add sub
184 184 committing subrepository t
185 185 created new head
186 186 $ echo t2 > t/t
187 187
188 188 6
189 189
190 190 $ hg st -R s
191 191 $ hg ci -m6 # change sub
192 192 committing subrepository t
193 193 $ hg debugsub
194 194 path s
195 195 source s
196 196 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
197 197 path t
198 198 source t
199 199 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
200 200 $ echo t3 > t/t
201 201
202 202 7
203 203
204 204 $ hg ci -m7 # change sub again for conflict test
205 205 committing subrepository t
206 206 $ hg rm .hgsub
207 207
208 208 8
209 209
210 210 $ hg ci -m8 # remove sub
211 211
212 212 test handling .hgsubstate "removed" explicitly.
213 213
214 214 $ hg parents --template '{node}\n{files}\n'
215 215 96615c1dad2dc8e3796d7332c77ce69156f7b78e
216 216 .hgsub .hgsubstate
217 217 $ hg rollback -q
218 218 $ hg remove .hgsubstate
219 219 $ hg ci -m8
220 220 $ hg parents --template '{node}\n{files}\n'
221 221 96615c1dad2dc8e3796d7332c77ce69156f7b78e
222 222 .hgsub .hgsubstate
223 223
224 224 merge tests
225 225
226 226 $ hg co -C 3
227 227 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
228 228 $ hg merge 5 # test adding
229 229 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
230 230 (branch merge, don't forget to commit)
231 231 $ hg debugsub
232 232 path s
233 233 source s
234 234 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
235 235 path t
236 236 source t
237 237 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
238 238 $ hg ci -m9
239 239 created new head
240 240 $ hg merge 6 --debug # test change
241 241 searching for copies back to rev 2
242 242 resolving manifests
243 243 branchmerge: True, force: False, partial: False
244 244 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
245 245 .hgsubstate: versions differ -> m
246 246 updating: .hgsubstate 1/1 files (100.00%)
247 247 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
248 248 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
249 249 getting subrepo t
250 250 resolving manifests
251 251 branchmerge: False, force: False, partial: False
252 252 ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
253 253 t: remote is newer -> g
254 254 getting t
255 255 updating: t 1/1 files (100.00%)
256 256 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 257 (branch merge, don't forget to commit)
258 258 $ hg debugsub
259 259 path s
260 260 source s
261 261 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
262 262 path t
263 263 source t
264 264 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
265 265 $ echo conflict > t/t
266 266 $ hg ci -m10
267 267 committing subrepository t
268 268 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
269 269 searching for copies back to rev 2
270 270 resolving manifests
271 271 branchmerge: True, force: False, partial: False
272 272 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
273 273 .hgsubstate: versions differ -> m
274 274 updating: .hgsubstate 1/1 files (100.00%)
275 275 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
276 276 subrepo t: both sides changed
277 277 subrepository t diverged (local revision: 20a0db6fbf6c, remote revision: 7af322bc1198)
278 278 (M)erge, keep (l)ocal or keep (r)emote? m
279 279 merging subrepo t
280 280 searching for copies back to rev 2
281 281 resolving manifests
282 282 branchmerge: True, force: False, partial: False
283 283 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
284 284 preserving t for resolve of t
285 285 t: versions differ -> m
286 286 updating: t 1/1 files (100.00%)
287 287 picked tool 'internal:merge' for t (binary False symlink False)
288 288 merging t
289 289 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
290 290 warning: conflicts during merge.
291 291 merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
292 292 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
293 293 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
294 294 subrepo t: merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
295 295 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
296 296 (branch merge, don't forget to commit)
297 297
298 298 should conflict
299 299
300 300 $ cat t/t
301 301 <<<<<<< local: 20a0db6fbf6c - test: 10
302 302 conflict
303 303 =======
304 304 t3
305 305 >>>>>>> other: 7af322bc1198 - test: 7
306 306
307 307 clone
308 308
309 309 $ cd ..
310 310 $ hg clone t tc
311 311 updating to branch default
312 312 cloning subrepo s from $TESTTMP/t/s
313 313 cloning subrepo s/ss from $TESTTMP/t/s/ss (glob)
314 314 cloning subrepo t from $TESTTMP/t/t
315 315 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
316 316 $ cd tc
317 317 $ hg debugsub
318 318 path s
319 319 source s
320 320 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
321 321 path t
322 322 source t
323 323 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
324 324
325 325 push
326 326
327 327 $ echo bah > t/t
328 328 $ hg ci -m11
329 329 committing subrepository t
330 330 $ hg push
331 331 pushing to $TESTTMP/t (glob)
332 332 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
333 333 no changes made to subrepo s since last push to $TESTTMP/t/s
334 334 pushing subrepo t to $TESTTMP/t/t
335 335 searching for changes
336 336 adding changesets
337 337 adding manifests
338 338 adding file changes
339 339 added 1 changesets with 1 changes to 1 files
340 340 searching for changes
341 341 adding changesets
342 342 adding manifests
343 343 adding file changes
344 344 added 1 changesets with 1 changes to 1 files
345 345
346 346 push -f
347 347
348 348 $ echo bah > s/a
349 349 $ hg ci -m12
350 350 committing subrepository s
351 351 $ hg push
352 352 pushing to $TESTTMP/t (glob)
353 353 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
354 354 pushing subrepo s to $TESTTMP/t/s
355 355 searching for changes
356 356 abort: push creates new remote head 12a213df6fa9! (in subrepo s)
357 357 (merge or see "hg help push" for details about pushing new heads)
358 358 [255]
359 359 $ hg push -f
360 360 pushing to $TESTTMP/t (glob)
361 361 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
362 362 searching for changes
363 363 no changes found
364 364 pushing subrepo s to $TESTTMP/t/s
365 365 searching for changes
366 366 adding changesets
367 367 adding manifests
368 368 adding file changes
369 369 added 1 changesets with 1 changes to 1 files (+1 heads)
370 370 pushing subrepo t to $TESTTMP/t/t
371 371 searching for changes
372 372 no changes found
373 373 searching for changes
374 374 adding changesets
375 375 adding manifests
376 376 adding file changes
377 377 added 1 changesets with 1 changes to 1 files
378 378
379 379 check that unmodified subrepos are not pushed
380 380
381 381 $ hg clone . ../tcc
382 382 updating to branch default
383 383 cloning subrepo s from $TESTTMP/tc/s
384 384 cloning subrepo s/ss from $TESTTMP/tc/s/ss (glob)
385 385 cloning subrepo t from $TESTTMP/tc/t
386 386 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
387 387
388 388 the subrepos on the new clone have nothing to push to its source
389 389
390 390 $ hg push -R ../tcc .
391 391 pushing to .
392 392 no changes made to subrepo s/ss since last push to s/ss (glob)
393 393 no changes made to subrepo s since last push to s
394 394 no changes made to subrepo t since last push to t
395 395 searching for changes
396 396 no changes found
397 397 [1]
398 398
399 399 the subrepos on the source do not have a clean store versus the clone target
400 400 because they were never explicitly pushed to the source
401 401
402 402 $ hg push ../tcc
403 403 pushing to ../tcc
404 404 pushing subrepo s/ss to ../tcc/s/ss (glob)
405 405 searching for changes
406 406 no changes found
407 407 pushing subrepo s to ../tcc/s
408 408 searching for changes
409 409 no changes found
410 410 pushing subrepo t to ../tcc/t
411 411 searching for changes
412 412 no changes found
413 413 searching for changes
414 414 no changes found
415 415 [1]
416 416
417 417 after push their stores become clean
418 418
419 419 $ hg push ../tcc
420 420 pushing to ../tcc
421 421 no changes made to subrepo s/ss since last push to ../tcc/s/ss (glob)
422 422 no changes made to subrepo s since last push to ../tcc/s
423 423 no changes made to subrepo t since last push to ../tcc/t
424 424 searching for changes
425 425 no changes found
426 426 [1]
427 427
428 428 updating a subrepo to a different revision or changing
429 429 its working directory does not make its store dirty
430 430
431 431 $ hg -R s update '.^'
432 432 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
433 433 $ hg push
434 434 pushing to $TESTTMP/t (glob)
435 435 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
436 436 no changes made to subrepo s since last push to $TESTTMP/t/s
437 437 no changes made to subrepo t since last push to $TESTTMP/t/t
438 438 searching for changes
439 439 no changes found
440 440 [1]
441 441 $ echo foo >> s/a
442 442 $ hg push
443 443 pushing to $TESTTMP/t (glob)
444 444 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
445 445 no changes made to subrepo s since last push to $TESTTMP/t/s
446 446 no changes made to subrepo t since last push to $TESTTMP/t/t
447 447 searching for changes
448 448 no changes found
449 449 [1]
450 450 $ hg -R s update -C tip
451 451 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
452 452
453 453 committing into a subrepo makes its store (but not its parent's store) dirty
454 454
455 455 $ echo foo >> s/ss/a
456 456 $ hg -R s/ss commit -m 'test dirty store detection'
457 457 $ hg push
458 458 pushing to $TESTTMP/t (glob)
459 459 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
460 460 searching for changes
461 461 adding changesets
462 462 adding manifests
463 463 adding file changes
464 464 added 1 changesets with 1 changes to 1 files
465 465 no changes made to subrepo s since last push to $TESTTMP/t/s
466 466 no changes made to subrepo t since last push to $TESTTMP/t/t
467 467 searching for changes
468 468 no changes found
469 469 [1]
470 470
471 471 a subrepo store may be clean versus one repo but not versus another
472 472
473 473 $ hg push
474 474 pushing to $TESTTMP/t (glob)
475 475 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
476 476 no changes made to subrepo s since last push to $TESTTMP/t/s
477 477 no changes made to subrepo t since last push to $TESTTMP/t/t
478 478 searching for changes
479 479 no changes found
480 480 [1]
481 481 $ hg push ../tcc
482 482 pushing to ../tcc
483 483 pushing subrepo s/ss to ../tcc/s/ss (glob)
484 484 searching for changes
485 485 adding changesets
486 486 adding manifests
487 487 adding file changes
488 488 added 1 changesets with 1 changes to 1 files
489 489 no changes made to subrepo s since last push to ../tcc/s
490 490 no changes made to subrepo t since last push to ../tcc/t
491 491 searching for changes
492 492 no changes found
493 493 [1]
494 494
495 495 update
496 496
497 497 $ cd ../t
498 498 $ hg up -C # discard our earlier merge
499 499 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
500 500 $ echo blah > t/t
501 501 $ hg ci -m13
502 502 committing subrepository t
503 503
504 504 backout calls revert internally with minimal opts, which should not raise
505 505 KeyError
506 506
507 507 $ hg backout ".^"
508 508 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
509 509 changeset c373c8102e68 backed out, don't forget to commit.
510 510
511 511 $ hg up -C # discard changes
512 512 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
513 513
514 514 pull
515 515
516 516 $ cd ../tc
517 517 $ hg pull
518 518 pulling from $TESTTMP/t (glob)
519 519 searching for changes
520 520 adding changesets
521 521 adding manifests
522 522 adding file changes
523 523 added 1 changesets with 1 changes to 1 files
524 524 (run 'hg update' to get a working copy)
525 525
526 526 should pull t
527 527
528 528 $ hg up
529 529 pulling subrepo t from $TESTTMP/t/t
530 530 searching for changes
531 531 adding changesets
532 532 adding manifests
533 533 adding file changes
534 534 added 1 changesets with 1 changes to 1 files
535 535 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
536 536 $ cat t/t
537 537 blah
538 538
539 539 bogus subrepo path aborts
540 540
541 541 $ echo 'bogus=[boguspath' >> .hgsub
542 542 $ hg ci -m 'bogus subrepo path'
543 543 abort: missing ] in subrepo source
544 544 [255]
545 545
546 546 Issue1986: merge aborts when trying to merge a subrepo that
547 547 shouldn't need merging
548 548
549 549 # subrepo layout
550 550 #
551 551 # o 5 br
552 552 # /|
553 553 # o | 4 default
554 554 # | |
555 555 # | o 3 br
556 556 # |/|
557 557 # o | 2 default
558 558 # | |
559 559 # | o 1 br
560 560 # |/
561 561 # o 0 default
562 562
563 563 $ cd ..
564 564 $ rm -rf sub
565 565 $ hg init main
566 566 $ cd main
567 567 $ hg init s
568 568 $ cd s
569 569 $ echo a > a
570 570 $ hg ci -Am1
571 571 adding a
572 572 $ hg branch br
573 573 marked working directory as branch br
574 574 (branches are permanent and global, did you want a bookmark?)
575 575 $ echo a >> a
576 576 $ hg ci -m1
577 577 $ hg up default
578 578 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
579 579 $ echo b > b
580 580 $ hg ci -Am1
581 581 adding b
582 582 $ hg up br
583 583 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
584 584 $ hg merge tip
585 585 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
586 586 (branch merge, don't forget to commit)
587 587 $ hg ci -m1
588 588 $ hg up 2
589 589 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
590 590 $ echo c > c
591 591 $ hg ci -Am1
592 592 adding c
593 593 $ hg up 3
594 594 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
595 595 $ hg merge 4
596 596 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
597 597 (branch merge, don't forget to commit)
598 598 $ hg ci -m1
599 599
600 600 # main repo layout:
601 601 #
602 602 # * <-- try to merge default into br again
603 603 # .`|
604 604 # . o 5 br --> substate = 5
605 605 # . |
606 606 # o | 4 default --> substate = 4
607 607 # | |
608 608 # | o 3 br --> substate = 2
609 609 # |/|
610 610 # o | 2 default --> substate = 2
611 611 # | |
612 612 # | o 1 br --> substate = 3
613 613 # |/
614 614 # o 0 default --> substate = 2
615 615
616 616 $ cd ..
617 617 $ echo 's = s' > .hgsub
618 618 $ hg -R s up 2
619 619 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
620 620 $ hg ci -Am1
621 621 adding .hgsub
622 622 $ hg branch br
623 623 marked working directory as branch br
624 624 (branches are permanent and global, did you want a bookmark?)
625 625 $ echo b > b
626 626 $ hg -R s up 3
627 627 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
628 628 $ hg ci -Am1
629 629 adding b
630 630 $ hg up default
631 631 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
632 632 $ echo c > c
633 633 $ hg ci -Am1
634 634 adding c
635 635 $ hg up 1
636 636 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
637 637 $ hg merge 2
638 638 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
639 639 (branch merge, don't forget to commit)
640 640 $ hg ci -m1
641 641 $ hg up 2
642 642 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
643 643 $ hg -R s up 4
644 644 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
645 645 $ echo d > d
646 646 $ hg ci -Am1
647 647 adding d
648 648 $ hg up 3
649 649 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
650 650 $ hg -R s up 5
651 651 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
652 652 $ echo e > e
653 653 $ hg ci -Am1
654 654 adding e
655 655
656 656 $ hg up 5
657 657 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
658 658 $ hg merge 4 # try to merge default into br again
659 659 subrepository s diverged (local revision: f8f13b33206e, remote revision: a3f9062a4f88)
660 660 (M)erge, keep (l)ocal or keep (r)emote? m
661 661 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
662 662 (branch merge, don't forget to commit)
663 663 $ cd ..
664 664
665 665 test subrepo delete from .hgsubstate
666 666
667 667 $ hg init testdelete
668 668 $ mkdir testdelete/nested testdelete/nested2
669 669 $ hg init testdelete/nested
670 670 $ hg init testdelete/nested2
671 671 $ echo test > testdelete/nested/foo
672 672 $ echo test > testdelete/nested2/foo
673 673 $ hg -R testdelete/nested add
674 674 adding testdelete/nested/foo (glob)
675 675 $ hg -R testdelete/nested2 add
676 676 adding testdelete/nested2/foo (glob)
677 677 $ hg -R testdelete/nested ci -m test
678 678 $ hg -R testdelete/nested2 ci -m test
679 679 $ echo nested = nested > testdelete/.hgsub
680 680 $ echo nested2 = nested2 >> testdelete/.hgsub
681 681 $ hg -R testdelete add
682 682 adding testdelete/.hgsub (glob)
683 683 $ hg -R testdelete ci -m "nested 1 & 2 added"
684 684 $ echo nested = nested > testdelete/.hgsub
685 685 $ hg -R testdelete ci -m "nested 2 deleted"
686 686 $ cat testdelete/.hgsubstate
687 687 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
688 688 $ hg -R testdelete remove testdelete/.hgsub
689 689 $ hg -R testdelete ci -m ".hgsub deleted"
690 690 $ cat testdelete/.hgsubstate
691 691 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
692 692
693 693 test repository cloning
694 694
695 695 $ mkdir mercurial mercurial2
696 696 $ hg init nested_absolute
697 697 $ echo test > nested_absolute/foo
698 698 $ hg -R nested_absolute add
699 699 adding nested_absolute/foo (glob)
700 700 $ hg -R nested_absolute ci -mtest
701 701 $ cd mercurial
702 702 $ hg init nested_relative
703 703 $ echo test2 > nested_relative/foo2
704 704 $ hg -R nested_relative add
705 705 adding nested_relative/foo2 (glob)
706 706 $ hg -R nested_relative ci -mtest2
707 707 $ hg init main
708 708 $ echo "nested_relative = ../nested_relative" > main/.hgsub
709 709 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
710 710 $ hg -R main add
711 711 adding main/.hgsub (glob)
712 712 $ hg -R main ci -m "add subrepos"
713 713 $ cd ..
714 714 $ hg clone mercurial/main mercurial2/main
715 715 updating to branch default
716 716 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
717 717 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
718 718 > mercurial2/main/nested_relative/.hg/hgrc
719 719 [paths]
720 720 default = $TESTTMP/mercurial/nested_absolute
721 721 [paths]
722 722 default = $TESTTMP/mercurial/nested_relative
723 723 $ rm -rf mercurial mercurial2
724 724
725 725 Issue1977: multirepo push should fail if subrepo push fails
726 726
727 727 $ hg init repo
728 728 $ hg init repo/s
729 729 $ echo a > repo/s/a
730 730 $ hg -R repo/s ci -Am0
731 731 adding a
732 732 $ echo s = s > repo/.hgsub
733 733 $ hg -R repo ci -Am1
734 734 adding .hgsub
735 735 $ hg clone repo repo2
736 736 updating to branch default
737 737 cloning subrepo s from $TESTTMP/repo/s
738 738 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
739 739 $ hg -q -R repo2 pull -u
740 740 $ echo 1 > repo2/s/a
741 741 $ hg -R repo2/s ci -m2
742 742 $ hg -q -R repo2/s push
743 743 $ hg -R repo2/s up -C 0
744 744 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
745 745 $ echo 2 > repo2/s/b
746 746 $ hg -R repo2/s ci -m3 -A
747 747 adding b
748 748 created new head
749 749 $ hg -R repo2 ci -m3
750 750 $ hg -q -R repo2 push
751 751 abort: push creates new remote head cc505f09a8b2! (in subrepo s)
752 752 (merge or see "hg help push" for details about pushing new heads)
753 753 [255]
754 754 $ hg -R repo update
755 755 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
756 756
757 757 test if untracked file is not overwritten
758 758
759 759 $ echo issue3276_ok > repo/s/b
760 760 $ hg -R repo2 push -f -q
761 761 $ hg -R repo update
762 762 b: untracked file differs
763 763 abort: untracked files in working directory differ from files in requested revision (in subrepo s)
764 764 [255]
765 765
766 766 $ cat repo/s/b
767 767 issue3276_ok
768 768 $ rm repo/s/b
769 769 $ hg -R repo revert --all
770 770 reverting repo/.hgsubstate (glob)
771 771 reverting subrepo s
772 772 $ hg -R repo update
773 773 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
774 774 $ cat repo/s/b
775 775 2
776 776 $ rm -rf repo2 repo
777 777
778 778
779 779 Issue1852 subrepos with relative paths always push/pull relative to default
780 780
781 781 Prepare a repo with subrepo
782 782
783 783 $ hg init issue1852a
784 784 $ cd issue1852a
785 785 $ hg init sub/repo
786 786 $ echo test > sub/repo/foo
787 787 $ hg -R sub/repo add sub/repo/foo
788 788 $ echo sub/repo = sub/repo > .hgsub
789 789 $ hg add .hgsub
790 790 $ hg ci -mtest
791 791 committing subrepository sub/repo (glob)
792 792 $ echo test >> sub/repo/foo
793 793 $ hg ci -mtest
794 794 committing subrepository sub/repo (glob)
795 795 $ hg cat sub/repo/foo
796 796 test
797 797 test
798 798 $ mkdir -p tmp/sub/repo
799 799 $ hg cat -r 0 --output tmp/%p_p sub/repo/foo
800 800 $ cat tmp/sub/repo/foo_p
801 801 test
802 802 $ mv sub/repo sub_
803 803 $ hg cat sub/repo/baz
804 804 skipping missing subrepository: sub/repo
805 805 [1]
806 806 $ rm -rf sub/repo
807 807 $ mv sub_ sub/repo
808 808 $ cd ..
809 809
810 810 Create repo without default path, pull top repo, and see what happens on update
811 811
812 812 $ hg init issue1852b
813 813 $ hg -R issue1852b pull issue1852a
814 814 pulling from issue1852a
815 815 requesting all changes
816 816 adding changesets
817 817 adding manifests
818 818 adding file changes
819 819 added 2 changesets with 3 changes to 2 files
820 820 (run 'hg update' to get a working copy)
821 821 $ hg -R issue1852b update
822 822 abort: default path for subrepository not found (in subrepo sub/repo) (glob)
823 823 [255]
824 824
825 825 Ensure a full traceback, not just the SubrepoAbort part
826 826
827 827 $ hg -R issue1852b update --traceback 2>&1 | grep 'raise util\.Abort'
828 828 raise util.Abort(_("default path for subrepository not found"))
829 829
830 830 Pull -u now doesn't help
831 831
832 832 $ hg -R issue1852b pull -u issue1852a
833 833 pulling from issue1852a
834 834 searching for changes
835 835 no changes found
836 836
837 837 Try the same, but with pull -u
838 838
839 839 $ hg init issue1852c
840 840 $ hg -R issue1852c pull -r0 -u issue1852a
841 841 pulling from issue1852a
842 842 adding changesets
843 843 adding manifests
844 844 adding file changes
845 845 added 1 changesets with 2 changes to 2 files
846 846 cloning subrepo sub/repo from issue1852a/sub/repo (glob)
847 847 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
848 848
849 849 Try to push from the other side
850 850
851 851 $ hg -R issue1852a push `pwd`/issue1852c
852 852 pushing to $TESTTMP/issue1852c (glob)
853 853 pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo (glob)
854 854 searching for changes
855 855 no changes found
856 856 searching for changes
857 857 adding changesets
858 858 adding manifests
859 859 adding file changes
860 860 added 1 changesets with 1 changes to 1 files
861 861
862 862 Incoming and outgoing should not use the default path:
863 863
864 864 $ hg clone -q issue1852a issue1852d
865 865 $ hg -R issue1852d outgoing --subrepos issue1852c
866 866 comparing with issue1852c
867 867 searching for changes
868 868 no changes found
869 869 comparing with issue1852c/sub/repo
870 870 searching for changes
871 871 no changes found
872 872 [1]
873 873 $ hg -R issue1852d incoming --subrepos issue1852c
874 874 comparing with issue1852c
875 875 searching for changes
876 876 no changes found
877 877 comparing with issue1852c/sub/repo
878 878 searching for changes
879 879 no changes found
880 880 [1]
881 881
882 882 Check status of files when none of them belong to the first
883 883 subrepository:
884 884
885 885 $ hg init subrepo-status
886 886 $ cd subrepo-status
887 887 $ hg init subrepo-1
888 888 $ hg init subrepo-2
889 889 $ cd subrepo-2
890 890 $ touch file
891 891 $ hg add file
892 892 $ cd ..
893 893 $ echo subrepo-1 = subrepo-1 > .hgsub
894 894 $ echo subrepo-2 = subrepo-2 >> .hgsub
895 895 $ hg add .hgsub
896 896 $ hg ci -m 'Added subrepos'
897 897 committing subrepository subrepo-2
898 898 $ hg st subrepo-2/file
899 899
900 900 Check that share works with subrepo
901 901 $ hg --config extensions.share= share . ../shared
902 902 updating working directory
903 903 cloning subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
904 904 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
905 905 $ test -f ../shared/subrepo-1/.hg/sharedpath
906 906 [1]
907 907 $ hg -R ../shared in
908 908 abort: repository default not found!
909 909 [255]
910 910 $ hg -R ../shared/subrepo-2 showconfig paths
911 911 paths.default=$TESTTMP/subrepo-status/subrepo-2
912 912 $ hg -R ../shared/subrepo-1 sum --remote
913 913 parent: -1:000000000000 tip (empty repository)
914 914 branch: default
915 915 commit: (clean)
916 916 update: (current)
917 917 remote: (synced)
918 918
919 919 Check hg update --clean
920 920 $ cd $TESTTMP/t
921 921 $ rm -r t/t.orig
922 922 $ hg status -S --all
923 923 C .hgsub
924 924 C .hgsubstate
925 925 C a
926 926 C s/.hgsub
927 927 C s/.hgsubstate
928 928 C s/a
929 929 C s/ss/a
930 930 C t/t
931 931 $ echo c1 > s/a
932 932 $ cd s
933 933 $ echo c1 > b
934 934 $ echo c1 > c
935 935 $ hg add b
936 936 $ cd ..
937 937 $ hg status -S
938 938 M s/a
939 939 A s/b
940 940 ? s/c
941 941 $ hg update -C
942 942 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
943 943 $ hg status -S
944 944 ? s/b
945 945 ? s/c
946 946
947 947 Sticky subrepositories, no changes
948 948 $ cd $TESTTMP/t
949 949 $ hg id
950 950 925c17564ef8 tip
951 951 $ hg -R s id
952 952 12a213df6fa9 tip
953 953 $ hg -R t id
954 954 52c0adc0515a tip
955 955 $ hg update 11
956 956 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
957 957 $ hg id
958 958 365661e5936a
959 959 $ hg -R s id
960 960 fc627a69481f
961 961 $ hg -R t id
962 962 e95bcfa18a35
963 963
964 964 Sticky subrepositories, file changes
965 965 $ touch s/f1
966 966 $ touch t/f1
967 967 $ hg add -S s/f1
968 968 $ hg add -S t/f1
969 969 $ hg id
970 970 365661e5936a+
971 971 $ hg -R s id
972 972 fc627a69481f+
973 973 $ hg -R t id
974 974 e95bcfa18a35+
975 975 $ hg update tip
976 976 subrepository s diverged (local revision: fc627a69481f, remote revision: 12a213df6fa9)
977 977 (M)erge, keep (l)ocal or keep (r)emote? m
978 978 subrepository sources for s differ
979 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
980 l
979 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)? l
981 980 subrepository t diverged (local revision: e95bcfa18a35, remote revision: 52c0adc0515a)
982 981 (M)erge, keep (l)ocal or keep (r)emote? m
983 982 subrepository sources for t differ
984 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
985 l
983 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)? l
986 984 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
987 985 $ hg id
988 986 925c17564ef8+ tip
989 987 $ hg -R s id
990 988 fc627a69481f+
991 989 $ hg -R t id
992 990 e95bcfa18a35+
993 991 $ hg update --clean tip
994 992 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
995 993
996 994 Sticky subrepository, revision updates
997 995 $ hg id
998 996 925c17564ef8 tip
999 997 $ hg -R s id
1000 998 12a213df6fa9 tip
1001 999 $ hg -R t id
1002 1000 52c0adc0515a tip
1003 1001 $ cd s
1004 1002 $ hg update -r -2
1005 1003 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1006 1004 $ cd ../t
1007 1005 $ hg update -r 2
1008 1006 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1009 1007 $ cd ..
1010 1008 $ hg update 10
1011 1009 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1012 1010 (M)erge, keep (l)ocal or keep (r)emote? m
1013 1011 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 20a0db6fbf6c)
1014 1012 (M)erge, keep (l)ocal or keep (r)emote? m
1015 1013 subrepository sources for t differ (in checked out version)
1016 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
1017 l
1014 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)? l
1018 1015 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1019 1016 $ hg id
1020 1017 e45c8b14af55+
1021 1018 $ hg -R s id
1022 1019 02dcf1d70411
1023 1020 $ hg -R t id
1024 1021 7af322bc1198
1025 1022
1026 1023 Sticky subrepository, file changes and revision updates
1027 1024 $ touch s/f1
1028 1025 $ touch t/f1
1029 1026 $ hg add -S s/f1
1030 1027 $ hg add -S t/f1
1031 1028 $ hg id
1032 1029 e45c8b14af55+
1033 1030 $ hg -R s id
1034 1031 02dcf1d70411+
1035 1032 $ hg -R t id
1036 1033 7af322bc1198+
1037 1034 $ hg update tip
1038 1035 subrepository s diverged (local revision: 12a213df6fa9, remote revision: 12a213df6fa9)
1039 1036 (M)erge, keep (l)ocal or keep (r)emote? m
1040 1037 subrepository sources for s differ
1041 use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)?
1042 l
1038 use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)? l
1043 1039 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 52c0adc0515a)
1044 1040 (M)erge, keep (l)ocal or keep (r)emote? m
1045 1041 subrepository sources for t differ
1046 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
1047 l
1042 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)? l
1048 1043 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1049 1044 $ hg id
1050 1045 925c17564ef8+ tip
1051 1046 $ hg -R s id
1052 1047 02dcf1d70411+
1053 1048 $ hg -R t id
1054 1049 7af322bc1198+
1055 1050
1056 1051 Sticky repository, update --clean
1057 1052 $ hg update --clean tip
1058 1053 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1059 1054 $ hg id
1060 1055 925c17564ef8 tip
1061 1056 $ hg -R s id
1062 1057 12a213df6fa9 tip
1063 1058 $ hg -R t id
1064 1059 52c0adc0515a tip
1065 1060
1066 1061 Test subrepo already at intended revision:
1067 1062 $ cd s
1068 1063 $ hg update fc627a69481f
1069 1064 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1070 1065 $ cd ..
1071 1066 $ hg update 11
1072 1067 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1073 1068 (M)erge, keep (l)ocal or keep (r)emote? m
1074 1069 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1075 1070 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1076 1071 $ hg id -n
1077 1072 11+
1078 1073 $ hg -R s id
1079 1074 fc627a69481f
1080 1075 $ hg -R t id
1081 1076 e95bcfa18a35
1082 1077
1083 1078 Test that removing .hgsubstate doesn't break anything:
1084 1079
1085 1080 $ hg rm -f .hgsubstate
1086 1081 $ hg ci -mrm
1087 1082 nothing changed
1088 1083 [1]
1089 1084 $ hg log -vr tip
1090 1085 changeset: 13:925c17564ef8
1091 1086 tag: tip
1092 1087 user: test
1093 1088 date: Thu Jan 01 00:00:00 1970 +0000
1094 1089 files: .hgsubstate
1095 1090 description:
1096 1091 13
1097 1092
1098 1093
1099 1094
1100 1095 Test that removing .hgsub removes .hgsubstate:
1101 1096
1102 1097 $ hg rm .hgsub
1103 1098 $ hg ci -mrm2
1104 1099 created new head
1105 1100 $ hg log -vr tip
1106 1101 changeset: 14:2400bccd50af
1107 1102 tag: tip
1108 1103 parent: 11:365661e5936a
1109 1104 user: test
1110 1105 date: Thu Jan 01 00:00:00 1970 +0000
1111 1106 files: .hgsub .hgsubstate
1112 1107 description:
1113 1108 rm2
1114 1109
1115 1110
1116 1111 Test issue3153: diff -S with deleted subrepos
1117 1112
1118 1113 $ hg diff --nodates -S -c .
1119 1114 diff -r 365661e5936a -r 2400bccd50af .hgsub
1120 1115 --- a/.hgsub
1121 1116 +++ /dev/null
1122 1117 @@ -1,2 +0,0 @@
1123 1118 -s = s
1124 1119 -t = t
1125 1120 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
1126 1121 --- a/.hgsubstate
1127 1122 +++ /dev/null
1128 1123 @@ -1,2 +0,0 @@
1129 1124 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1130 1125 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
1131 1126
1132 1127 Test behavior of add for explicit path in subrepo:
1133 1128 $ cd ..
1134 1129 $ hg init explicit
1135 1130 $ cd explicit
1136 1131 $ echo s = s > .hgsub
1137 1132 $ hg add .hgsub
1138 1133 $ hg init s
1139 1134 $ hg ci -m0
1140 1135 Adding with an explicit path in a subrepo adds the file
1141 1136 $ echo c1 > f1
1142 1137 $ echo c2 > s/f2
1143 1138 $ hg st -S
1144 1139 ? f1
1145 1140 ? s/f2
1146 1141 $ hg add s/f2
1147 1142 $ hg st -S
1148 1143 A s/f2
1149 1144 ? f1
1150 1145 $ hg ci -R s -m0
1151 1146 $ hg ci -Am1
1152 1147 adding f1
1153 1148 Adding with an explicit path in a subrepo with -S has the same behavior
1154 1149 $ echo c3 > f3
1155 1150 $ echo c4 > s/f4
1156 1151 $ hg st -S
1157 1152 ? f3
1158 1153 ? s/f4
1159 1154 $ hg add -S s/f4
1160 1155 $ hg st -S
1161 1156 A s/f4
1162 1157 ? f3
1163 1158 $ hg ci -R s -m1
1164 1159 $ hg ci -Ama2
1165 1160 adding f3
1166 1161 Adding without a path or pattern silently ignores subrepos
1167 1162 $ echo c5 > f5
1168 1163 $ echo c6 > s/f6
1169 1164 $ echo c7 > s/f7
1170 1165 $ hg st -S
1171 1166 ? f5
1172 1167 ? s/f6
1173 1168 ? s/f7
1174 1169 $ hg add
1175 1170 adding f5
1176 1171 $ hg st -S
1177 1172 A f5
1178 1173 ? s/f6
1179 1174 ? s/f7
1180 1175 $ hg ci -R s -Am2
1181 1176 adding f6
1182 1177 adding f7
1183 1178 $ hg ci -m3
1184 1179 Adding without a path or pattern with -S also adds files in subrepos
1185 1180 $ echo c8 > f8
1186 1181 $ echo c9 > s/f9
1187 1182 $ echo c10 > s/f10
1188 1183 $ hg st -S
1189 1184 ? f8
1190 1185 ? s/f10
1191 1186 ? s/f9
1192 1187 $ hg add -S
1193 1188 adding f8
1194 1189 adding s/f10 (glob)
1195 1190 adding s/f9 (glob)
1196 1191 $ hg st -S
1197 1192 A f8
1198 1193 A s/f10
1199 1194 A s/f9
1200 1195 $ hg ci -R s -m3
1201 1196 $ hg ci -m4
1202 1197 Adding with a pattern silently ignores subrepos
1203 1198 $ echo c11 > fm11
1204 1199 $ echo c12 > fn12
1205 1200 $ echo c13 > s/fm13
1206 1201 $ echo c14 > s/fn14
1207 1202 $ hg st -S
1208 1203 ? fm11
1209 1204 ? fn12
1210 1205 ? s/fm13
1211 1206 ? s/fn14
1212 1207 $ hg add 'glob:**fm*'
1213 1208 adding fm11
1214 1209 $ hg st -S
1215 1210 A fm11
1216 1211 ? fn12
1217 1212 ? s/fm13
1218 1213 ? s/fn14
1219 1214 $ hg ci -R s -Am4
1220 1215 adding fm13
1221 1216 adding fn14
1222 1217 $ hg ci -Am5
1223 1218 adding fn12
1224 1219 Adding with a pattern with -S also adds matches in subrepos
1225 1220 $ echo c15 > fm15
1226 1221 $ echo c16 > fn16
1227 1222 $ echo c17 > s/fm17
1228 1223 $ echo c18 > s/fn18
1229 1224 $ hg st -S
1230 1225 ? fm15
1231 1226 ? fn16
1232 1227 ? s/fm17
1233 1228 ? s/fn18
1234 1229 $ hg add -S 'glob:**fm*'
1235 1230 adding fm15
1236 1231 adding s/fm17 (glob)
1237 1232 $ hg st -S
1238 1233 A fm15
1239 1234 A s/fm17
1240 1235 ? fn16
1241 1236 ? s/fn18
1242 1237 $ hg ci -R s -Am5
1243 1238 adding fn18
1244 1239 $ hg ci -Am6
1245 1240 adding fn16
1246 1241
1247 1242 Test behavior of forget for explicit path in subrepo:
1248 1243 Forgetting an explicit path in a subrepo untracks the file
1249 1244 $ echo c19 > s/f19
1250 1245 $ hg add s/f19
1251 1246 $ hg st -S
1252 1247 A s/f19
1253 1248 $ hg forget s/f19
1254 1249 $ hg st -S
1255 1250 ? s/f19
1256 1251 $ rm s/f19
1257 1252 $ cd ..
1258 1253
1259 1254 Courtesy phases synchronisation to publishing server does not block the push
1260 1255 (issue3781)
1261 1256
1262 1257 $ cp -r main issue3781
1263 1258 $ cp -r main issue3781-dest
1264 1259 $ cd issue3781-dest/s
1265 1260 $ hg phase tip # show we have draft changeset
1266 1261 5: draft
1267 1262 $ chmod a-w .hg/store/phaseroots # prevent phase push
1268 1263 $ cd ../../issue3781
1269 1264 $ cat >> .hg/hgrc << EOF
1270 1265 > [paths]
1271 1266 > default=../issue3781-dest/
1272 1267 > EOF
1273 1268 $ hg push
1274 1269 pushing to $TESTTMP/issue3781-dest (glob)
1275 1270 pushing subrepo s to $TESTTMP/issue3781-dest/s
1276 1271 searching for changes
1277 1272 no changes found
1278 1273 searching for changes
1279 1274 no changes found
1280 1275 [1]
1281 1276 $ cd ..
1282 1277
1283 1278 Test phase choice for newly created commit with "phases.subrepochecks"
1284 1279 configuration
1285 1280
1286 1281 $ cd t
1287 1282 $ hg update -q -r 12
1288 1283
1289 1284 $ cat >> s/ss/.hg/hgrc <<EOF
1290 1285 > [phases]
1291 1286 > new-commit = secret
1292 1287 > EOF
1293 1288 $ cat >> s/.hg/hgrc <<EOF
1294 1289 > [phases]
1295 1290 > new-commit = draft
1296 1291 > EOF
1297 1292 $ echo phasecheck1 >> s/ss/a
1298 1293 $ hg -R s commit -S --config phases.checksubrepos=abort -m phasecheck1
1299 1294 committing subrepository ss
1300 1295 transaction abort!
1301 1296 rollback completed
1302 1297 abort: can't commit in draft phase conflicting secret from subrepository ss
1303 1298 [255]
1304 1299 $ echo phasecheck2 >> s/ss/a
1305 1300 $ hg -R s commit -S --config phases.checksubrepos=ignore -m phasecheck2
1306 1301 committing subrepository ss
1307 1302 $ hg -R s/ss phase tip
1308 1303 3: secret
1309 1304 $ hg -R s phase tip
1310 1305 6: draft
1311 1306 $ echo phasecheck3 >> s/ss/a
1312 1307 $ hg -R s commit -S -m phasecheck3
1313 1308 committing subrepository ss
1314 1309 warning: changes are committed in secret phase from subrepository ss
1315 1310 $ hg -R s/ss phase tip
1316 1311 4: secret
1317 1312 $ hg -R s phase tip
1318 1313 7: secret
1319 1314
1320 1315 $ cat >> t/.hg/hgrc <<EOF
1321 1316 > [phases]
1322 1317 > new-commit = draft
1323 1318 > EOF
1324 1319 $ cat >> .hg/hgrc <<EOF
1325 1320 > [phases]
1326 1321 > new-commit = public
1327 1322 > EOF
1328 1323 $ echo phasecheck4 >> s/ss/a
1329 1324 $ echo phasecheck4 >> t/t
1330 1325 $ hg commit -S -m phasecheck4
1331 1326 committing subrepository s
1332 1327 committing subrepository s/ss
1333 1328 warning: changes are committed in secret phase from subrepository ss
1334 1329 committing subrepository t
1335 1330 warning: changes are committed in secret phase from subrepository s
1336 1331 created new head
1337 1332 $ hg -R s/ss phase tip
1338 1333 5: secret
1339 1334 $ hg -R s phase tip
1340 1335 8: secret
1341 1336 $ hg -R t phase tip
1342 1337 6: draft
1343 1338 $ hg phase tip
1344 1339 15: secret
1345 1340
1346 1341 $ cd ..
1347 1342
1348 1343
1349 1344 Test that commit --secret works on both repo and subrepo (issue4182)
1350 1345
1351 1346 $ cd main
1352 1347 $ echo secret >> b
1353 1348 $ echo secret >> s/b
1354 1349 $ hg commit --secret --subrepo -m "secret"
1355 1350 committing subrepository s
1356 1351 $ hg phase -r .
1357 1352 6: secret
1358 1353 $ cd s
1359 1354 $ hg phase -r .
1360 1355 6: secret
1361 1356 $ cd ../../
1362 1357
1363 1358 Test "subrepos" template keyword
1364 1359
1365 1360 $ cd t
1366 1361 $ hg update -q 15
1367 1362 $ cat > .hgsub <<EOF
1368 1363 > s = s
1369 1364 > EOF
1370 1365 $ hg commit -m "16"
1371 1366 warning: changes are committed in secret phase from subrepository s
1372 1367
1373 1368 (addition of ".hgsub" itself)
1374 1369
1375 1370 $ hg diff --nodates -c 1 .hgsubstate
1376 1371 diff -r f7b1eb17ad24 -r 7cf8cfea66e4 .hgsubstate
1377 1372 --- /dev/null
1378 1373 +++ b/.hgsubstate
1379 1374 @@ -0,0 +1,1 @@
1380 1375 +e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1381 1376 $ hg log -r 1 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1382 1377 f7b1eb17ad24 000000000000
1383 1378 s
1384 1379
1385 1380 (modification of existing entry)
1386 1381
1387 1382 $ hg diff --nodates -c 2 .hgsubstate
1388 1383 diff -r 7cf8cfea66e4 -r df30734270ae .hgsubstate
1389 1384 --- a/.hgsubstate
1390 1385 +++ b/.hgsubstate
1391 1386 @@ -1,1 +1,1 @@
1392 1387 -e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1393 1388 +dc73e2e6d2675eb2e41e33c205f4bdab4ea5111d s
1394 1389 $ hg log -r 2 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1395 1390 7cf8cfea66e4 000000000000
1396 1391 s
1397 1392
1398 1393 (addition of entry)
1399 1394
1400 1395 $ hg diff --nodates -c 5 .hgsubstate
1401 1396 diff -r 7cf8cfea66e4 -r 1f14a2e2d3ec .hgsubstate
1402 1397 --- a/.hgsubstate
1403 1398 +++ b/.hgsubstate
1404 1399 @@ -1,1 +1,2 @@
1405 1400 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1406 1401 +60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
1407 1402 $ hg log -r 5 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1408 1403 7cf8cfea66e4 000000000000
1409 1404 t
1410 1405
1411 1406 (removal of existing entry)
1412 1407
1413 1408 $ hg diff --nodates -c 16 .hgsubstate
1414 1409 diff -r 8bec38d2bd0b -r f2f70bc3d3c9 .hgsubstate
1415 1410 --- a/.hgsubstate
1416 1411 +++ b/.hgsubstate
1417 1412 @@ -1,2 +1,1 @@
1418 1413 0731af8ca9423976d3743119d0865097c07bdc1b s
1419 1414 -e202dc79b04c88a636ea8913d9182a1346d9b3dc t
1420 1415 $ hg log -r 16 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1421 1416 8bec38d2bd0b 000000000000
1422 1417 t
1423 1418
1424 1419 (merging)
1425 1420
1426 1421 $ hg diff --nodates -c 9 .hgsubstate
1427 1422 diff -r f6affe3fbfaa -r f0d2028bf86d .hgsubstate
1428 1423 --- a/.hgsubstate
1429 1424 +++ b/.hgsubstate
1430 1425 @@ -1,1 +1,2 @@
1431 1426 fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1432 1427 +60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
1433 1428 $ hg log -r 9 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1434 1429 f6affe3fbfaa 1f14a2e2d3ec
1435 1430 t
1436 1431
1437 1432 (removal of ".hgsub" itself)
1438 1433
1439 1434 $ hg diff --nodates -c 8 .hgsubstate
1440 1435 diff -r f94576341bcf -r 96615c1dad2d .hgsubstate
1441 1436 --- a/.hgsubstate
1442 1437 +++ /dev/null
1443 1438 @@ -1,2 +0,0 @@
1444 1439 -e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1445 1440 -7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4 t
1446 1441 $ hg log -r 8 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1447 1442 f94576341bcf 000000000000
1448 1443
1449 1444 Test that '[paths]' is configured correctly at subrepo creation
1450 1445
1451 1446 $ cd $TESTTMP/tc
1452 1447 $ cat > .hgsub <<EOF
1453 1448 > # to clear bogus subrepo path 'bogus=[boguspath'
1454 1449 > s = s
1455 1450 > t = t
1456 1451 > EOF
1457 1452 $ hg update -q --clean null
1458 1453 $ rm -rf s t
1459 1454 $ cat >> .hg/hgrc <<EOF
1460 1455 > [paths]
1461 1456 > default-push = /foo/bar
1462 1457 > EOF
1463 1458 $ hg update -q
1464 1459 $ cat s/.hg/hgrc
1465 1460 [paths]
1466 1461 default = $TESTTMP/t/s
1467 1462 default-push = /foo/bar/s
1468 1463 $ cat s/ss/.hg/hgrc
1469 1464 [paths]
1470 1465 default = $TESTTMP/t/s/ss
1471 1466 default-push = /foo/bar/s/ss
1472 1467 $ cat t/.hg/hgrc
1473 1468 [paths]
1474 1469 default = $TESTTMP/t/t
1475 1470 default-push = /foo/bar/t
1476 1471 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now