47 _abssource = subrepoutil._abssource |
47 _abssource = subrepoutil._abssource |
48 propertycache = util.propertycache |
48 propertycache = util.propertycache |
49 |
49 |
50 |
50 |
51 def _expandedabspath(path): |
51 def _expandedabspath(path): |
52 ''' |
52 """ |
53 get a path or url and if it is a path expand it and return an absolute path |
53 get a path or url and if it is a path expand it and return an absolute path |
54 ''' |
54 """ |
55 expandedpath = util.urllocalpath(util.expandpath(path)) |
55 expandedpath = util.urllocalpath(util.expandpath(path)) |
56 u = util.url(expandedpath) |
56 u = util.url(expandedpath) |
57 if not u.scheme: |
57 if not u.scheme: |
58 path = util.normpath(os.path.abspath(u.path)) |
58 path = util.normpath(os.path.abspath(u.path)) |
59 return path |
59 return path |
266 return _(b'uncommitted changes in subrepository "%s"') % subrelpath( |
266 return _(b'uncommitted changes in subrepository "%s"') % subrelpath( |
267 self |
267 self |
268 ) |
268 ) |
269 |
269 |
270 def bailifchanged(self, ignoreupdate=False, hint=None): |
270 def bailifchanged(self, ignoreupdate=False, hint=None): |
271 """raise Abort if subrepository is ``dirty()`` |
271 """raise Abort if subrepository is ``dirty()``""" |
272 """ |
|
273 dirtyreason = self.dirtyreason(ignoreupdate=ignoreupdate, missing=True) |
272 dirtyreason = self.dirtyreason(ignoreupdate=ignoreupdate, missing=True) |
274 if dirtyreason: |
273 if dirtyreason: |
275 raise error.Abort(dirtyreason, hint=hint) |
274 raise error.Abort(dirtyreason, hint=hint) |
276 |
275 |
277 def basestate(self): |
276 def basestate(self): |
289 new state of the subrepo. |
288 new state of the subrepo. |
290 """ |
289 """ |
291 raise NotImplementedError |
290 raise NotImplementedError |
292 |
291 |
293 def phase(self, state): |
292 def phase(self, state): |
294 """returns phase of specified state in the subrepository. |
293 """returns phase of specified state in the subrepository.""" |
295 """ |
|
296 return phases.public |
294 return phases.public |
297 |
295 |
298 def remove(self): |
296 def remove(self): |
299 """remove the subrepo |
297 """remove the subrepo |
300 |
298 |
382 progress.increment() |
380 progress.increment() |
383 progress.complete() |
381 progress.complete() |
384 return total |
382 return total |
385 |
383 |
386 def walk(self, match): |
384 def walk(self, match): |
387 ''' |
385 """ |
388 walk recursively through the directory tree, finding all files |
386 walk recursively through the directory tree, finding all files |
389 matched by the match function |
387 matched by the match function |
390 ''' |
388 """ |
391 |
389 |
392 def forget(self, match, prefix, uipathfn, dryrun, interactive): |
390 def forget(self, match, prefix, uipathfn, dryrun, interactive): |
393 return ([], []) |
391 return ([], []) |
394 |
392 |
395 def removefiles( |
393 def removefiles( |
421 |
419 |
422 def shortid(self, revid): |
420 def shortid(self, revid): |
423 return revid |
421 return revid |
424 |
422 |
425 def unshare(self): |
423 def unshare(self): |
426 ''' |
424 """ |
427 convert this repository from shared to normal storage. |
425 convert this repository from shared to normal storage. |
428 ''' |
426 """ |
429 |
427 |
430 def verify(self, onpush=False): |
428 def verify(self, onpush=False): |
431 """verify the revision of this repository that is held in `_state` is |
429 """verify the revision of this repository that is held in `_state` is |
432 present and not hidden. Return 0 on success or warning, 1 on any |
430 present and not hidden. Return 0 on success or warning, 1 on any |
433 error. In the case of ``onpush``, warnings or errors will raise an |
431 error. In the case of ``onpush``, warnings or errors will raise an |
435 """ |
433 """ |
436 return 0 |
434 return 0 |
437 |
435 |
438 @propertycache |
436 @propertycache |
439 def wvfs(self): |
437 def wvfs(self): |
440 """return vfs to access the working directory of this subrepository |
438 """return vfs to access the working directory of this subrepository""" |
441 """ |
|
442 return vfsmod.vfs(self._ctx.repo().wvfs.join(self._path)) |
439 return vfsmod.vfs(self._ctx.repo().wvfs.join(self._path)) |
443 |
440 |
444 @propertycache |
441 @propertycache |
445 def _relpath(self): |
442 def _relpath(self): |
446 """return path to this subrepository as seen from outermost repository |
443 """return path to this subrepository as seen from outermost repository""" |
447 """ |
|
448 return self.wvfs.reljoin(reporelpath(self._ctx.repo()), self._path) |
444 return self.wvfs.reljoin(reporelpath(self._ctx.repo()), self._path) |
449 |
445 |
450 |
446 |
451 class hgsubrepo(abstractsubrepo): |
447 class hgsubrepo(abstractsubrepo): |
452 def __init__(self, ctx, path, state, allowcreate): |
448 def __init__(self, ctx, path, state, allowcreate): |
501 # the cached and current pull states have a different size |
497 # the cached and current pull states have a different size |
502 clean = next(itercache, None) is None |
498 clean = next(itercache, None) is None |
503 return clean |
499 return clean |
504 |
500 |
505 def _calcstorehash(self, remotepath): |
501 def _calcstorehash(self, remotepath): |
506 '''calculate a unique "store hash" |
502 """calculate a unique "store hash" |
507 |
503 |
508 This method is used to to detect when there are changes that may |
504 This method is used to to detect when there are changes that may |
509 require a push to a given remote path.''' |
505 require a push to a given remote path.""" |
510 # sort the files that will be hashed in increasing (likely) file size |
506 # sort the files that will be hashed in increasing (likely) file size |
511 filelist = (b'bookmarks', b'store/phaseroots', b'store/00changelog.i') |
507 filelist = (b'bookmarks', b'store/phaseroots', b'store/00changelog.i') |
512 yield b'# %s\n' % _expandedabspath(remotepath) |
508 yield b'# %s\n' % _expandedabspath(remotepath) |
513 vfs = self._repo.vfs |
509 vfs = self._repo.vfs |
514 for relname in filelist: |
510 for relname in filelist: |
523 '''read the store hash cache for a given remote repository''' |
519 '''read the store hash cache for a given remote repository''' |
524 cachefile = _getstorehashcachename(remotepath) |
520 cachefile = _getstorehashcachename(remotepath) |
525 return self._cachestorehashvfs.tryreadlines(cachefile, b'r') |
521 return self._cachestorehashvfs.tryreadlines(cachefile, b'r') |
526 |
522 |
527 def _cachestorehash(self, remotepath): |
523 def _cachestorehash(self, remotepath): |
528 '''cache the current store hash |
524 """cache the current store hash |
529 |
525 |
530 Each remote repo requires its own store hash cache, because a subrepo |
526 Each remote repo requires its own store hash cache, because a subrepo |
531 store may be "clean" versus a given remote repo, but not versus another |
527 store may be "clean" versus a given remote repo, but not versus another |
532 ''' |
528 """ |
533 cachefile = _getstorehashcachename(remotepath) |
529 cachefile = _getstorehashcachename(remotepath) |
534 with self._repo.lock(): |
530 with self._repo.lock(): |
535 storehash = list(self._calcstorehash(remotepath)) |
531 storehash = list(self._calcstorehash(remotepath)) |
536 vfs = self._cachestorehashvfs |
532 vfs = self._cachestorehashvfs |
537 vfs.writelines(cachefile, storehash, mode=b'wb', notindexed=True) |
533 vfs.writelines(cachefile, storehash, mode=b'wb', notindexed=True) |
538 |
534 |
539 def _getctx(self): |
535 def _getctx(self): |
540 '''fetch the context for this subrepo revision, possibly a workingctx |
536 """fetch the context for this subrepo revision, possibly a workingctx""" |
541 ''' |
|
542 if self._ctx.rev() is None: |
537 if self._ctx.rev() is None: |
543 return self._repo[None] # workingctx if parent is workingctx |
538 return self._repo[None] # workingctx if parent is workingctx |
544 else: |
539 else: |
545 rev = self._state[1] |
540 rev = self._state[1] |
546 return self._repo[rev] |
541 return self._repo[rev] |
1046 self._repo.ui.warn(b'%s\n' % msg) |
1041 self._repo.ui.warn(b'%s\n' % msg) |
1047 return 0 |
1042 return 0 |
1048 |
1043 |
1049 @propertycache |
1044 @propertycache |
1050 def wvfs(self): |
1045 def wvfs(self): |
1051 """return own wvfs for efficiency and consistency |
1046 """return own wvfs for efficiency and consistency""" |
1052 """ |
|
1053 return self._repo.wvfs |
1047 return self._repo.wvfs |
1054 |
1048 |
1055 @propertycache |
1049 @propertycache |
1056 def _relpath(self): |
1050 def _relpath(self): |
1057 """return path to this subrepository as seen from outermost repository |
1051 """return path to this subrepository as seen from outermost repository""" |
1058 """ |
|
1059 # Keep consistent dir separators by avoiding vfs.join(self._path) |
1052 # Keep consistent dir separators by avoiding vfs.join(self._path) |
1060 return reporelpath(self._repo) |
1053 return reporelpath(self._repo) |
1061 |
1054 |
1062 |
1055 |
1063 class svnsubrepo(abstractsubrepo): |
1056 class svnsubrepo(abstractsubrepo): |
1168 path = e.getAttribute('path').encode('utf8') |
1161 path = e.getAttribute('path').encode('utf8') |
1169 if item == 'external': |
1162 if item == 'external': |
1170 externals.append(path) |
1163 externals.append(path) |
1171 elif item == 'missing': |
1164 elif item == 'missing': |
1172 missing.append(path) |
1165 missing.append(path) |
1173 if item not in ( |
1166 if ( |
1174 '', |
1167 item |
1175 'normal', |
1168 not in ( |
1176 'unversioned', |
1169 '', |
1177 'external', |
1170 'normal', |
1178 ) or props not in ('', 'none', 'normal'): |
1171 'unversioned', |
|
1172 'external', |
|
1173 ) |
|
1174 or props not in ('', 'none', 'normal') |
|
1175 ): |
1179 changes.append(path) |
1176 changes.append(path) |
1180 for path in changes: |
1177 for path in changes: |
1181 for ext in externals: |
1178 for ext in externals: |
1182 if path == ext or path.startswith(ext + pycompat.ossep): |
1179 if path == ext or path.startswith(ext + pycompat.ossep): |
1183 return True, True, bool(missing) |
1180 return True, True, bool(missing) |
1382 |
1379 |
1383 return -1 |
1380 return -1 |
1384 |
1381 |
1385 @staticmethod |
1382 @staticmethod |
1386 def _checkversion(out): |
1383 def _checkversion(out): |
1387 '''ensure git version is new enough |
1384 """ensure git version is new enough |
1388 |
1385 |
1389 >>> _checkversion = gitsubrepo._checkversion |
1386 >>> _checkversion = gitsubrepo._checkversion |
1390 >>> _checkversion(b'git version 1.6.0') |
1387 >>> _checkversion(b'git version 1.6.0') |
1391 'ok' |
1388 'ok' |
1392 >>> _checkversion(b'git version 1.8.5') |
1389 >>> _checkversion(b'git version 1.8.5') |
1403 'ok' |
1400 'ok' |
1404 >>> _checkversion(b'git version 12345') |
1401 >>> _checkversion(b'git version 12345') |
1405 'unknown' |
1402 'unknown' |
1406 >>> _checkversion(b'no') |
1403 >>> _checkversion(b'no') |
1407 'unknown' |
1404 'unknown' |
1408 ''' |
1405 """ |
1409 version = gitsubrepo._gitversion(out) |
1406 version = gitsubrepo._gitversion(out) |
1410 # git 1.4.0 can't work at all, but 1.5.X can in at least some cases, |
1407 # git 1.4.0 can't work at all, but 1.5.X can in at least some cases, |
1411 # despite the docstring comment. For now, error on 1.4.0, warn on |
1408 # despite the docstring comment. For now, error on 1.4.0, warn on |
1412 # 1.5.0 but attempt to continue. |
1409 # 1.5.0 but attempt to continue. |
1413 if version == -1: |
1410 if version == -1: |
1514 diff-index only looks at changes to file stat; |
1511 diff-index only looks at changes to file stat; |
1515 this command looks at file contents and updates the stat.""" |
1512 this command looks at file contents and updates the stat.""" |
1516 self._gitcommand([b'update-index', b'-q', b'--refresh']) |
1513 self._gitcommand([b'update-index', b'-q', b'--refresh']) |
1517 |
1514 |
1518 def _gitbranchmap(self): |
1515 def _gitbranchmap(self): |
1519 '''returns 2 things: |
1516 """returns 2 things: |
1520 a map from git branch to revision |
1517 a map from git branch to revision |
1521 a map from revision to branches''' |
1518 a map from revision to branches""" |
1522 branch2rev = {} |
1519 branch2rev = {} |
1523 rev2branch = {} |
1520 rev2branch = {} |
1524 |
1521 |
1525 out = self._gitcommand( |
1522 out = self._gitcommand( |
1526 [b'for-each-ref', b'--format', b'%(objectname) %(refname)'] |
1523 [b'for-each-ref', b'--format', b'%(objectname) %(refname)'] |