comparison mercurial/hg.py @ 46663:a4c19a162615

sshpeer: enable+fix warning about sshpeers not being closed explicitly I recommend looking at this with a diff that ignores indentation. The test changes are because localrepo.close() updates some cache, which appears happens earlier now on rollbacks or strips or something. The http changes are because httppeer.close() prints stats with --verbose. Differential Revision: https://phab.mercurial-scm.org/D9999
author Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
date Mon, 15 Feb 2021 14:48:36 -0500
parents 95a615dd77bf
children 66fb04552122
comparison
equal deleted inserted replaced
46662:db8037e38085 46663:a4c19a162615
676 srcpeer = peer(ui, peeropts, source) 676 srcpeer = peer(ui, peeropts, source)
677 else: 677 else:
678 srcpeer = source.peer() # in case we were called with a localrepo 678 srcpeer = source.peer() # in case we were called with a localrepo
679 branches = (None, branch or []) 679 branches = (None, branch or [])
680 origsource = source = srcpeer.url() 680 origsource = source = srcpeer.url()
681 revs, checkout = addbranchrevs(srcpeer, srcpeer, branches, revs) 681 srclock = destlock = cleandir = None
682 682 destpeer = None
683 if dest is None: 683 try:
684 dest = defaultdest(source) 684 revs, checkout = addbranchrevs(srcpeer, srcpeer, branches, revs)
685 if dest: 685
686 ui.status(_(b"destination directory: %s\n") % dest) 686 if dest is None:
687 else: 687 dest = defaultdest(source)
688 dest = ui.expandpath(dest) 688 if dest:
689 689 ui.status(_(b"destination directory: %s\n") % dest)
690 dest = util.urllocalpath(dest) 690 else:
691 source = util.urllocalpath(source) 691 dest = ui.expandpath(dest)
692 692
693 if not dest: 693 dest = util.urllocalpath(dest)
694 raise error.InputError(_(b"empty destination path is not valid")) 694 source = util.urllocalpath(source)
695 695
696 destvfs = vfsmod.vfs(dest, expandpath=True) 696 if not dest:
697 if destvfs.lexists(): 697 raise error.InputError(_(b"empty destination path is not valid"))
698 if not destvfs.isdir(): 698
699 raise error.InputError(_(b"destination '%s' already exists") % dest) 699 destvfs = vfsmod.vfs(dest, expandpath=True)
700 elif destvfs.listdir(): 700 if destvfs.lexists():
701 raise error.InputError(_(b"destination '%s' is not empty") % dest) 701 if not destvfs.isdir():
702 702 raise error.InputError(
703 createopts = {} 703 _(b"destination '%s' already exists") % dest
704 narrow = False
705
706 if storeincludepats is not None:
707 narrowspec.validatepatterns(storeincludepats)
708 narrow = True
709
710 if storeexcludepats is not None:
711 narrowspec.validatepatterns(storeexcludepats)
712 narrow = True
713
714 if narrow:
715 # Include everything by default if only exclusion patterns defined.
716 if storeexcludepats and not storeincludepats:
717 storeincludepats = {b'path:.'}
718
719 createopts[b'narrowfiles'] = True
720
721 if depth:
722 createopts[b'shallowfilestore'] = True
723
724 if srcpeer.capable(b'lfs-serve'):
725 # Repository creation honors the config if it disabled the extension, so
726 # we can't just announce that lfs will be enabled. This check avoids
727 # saying that lfs will be enabled, and then saying it's an unknown
728 # feature. The lfs creation option is set in either case so that a
729 # requirement is added. If the extension is explicitly disabled but the
730 # requirement is set, the clone aborts early, before transferring any
731 # data.
732 createopts[b'lfs'] = True
733
734 if extensions.disabled_help(b'lfs'):
735 ui.status(
736 _(
737 b'(remote is using large file support (lfs), but it is '
738 b'explicitly disabled in the local configuration)\n'
739 ) 704 )
740 ) 705 elif destvfs.listdir():
741 else: 706 raise error.InputError(
742 ui.status( 707 _(b"destination '%s' is not empty") % dest
743 _(
744 b'(remote is using large file support (lfs); lfs will '
745 b'be enabled for this repository)\n'
746 ) 708 )
747 ) 709
748 710 createopts = {}
749 shareopts = shareopts or {} 711 narrow = False
750 sharepool = shareopts.get(b'pool') 712
751 sharenamemode = shareopts.get(b'mode') 713 if storeincludepats is not None:
752 if sharepool and islocal(dest): 714 narrowspec.validatepatterns(storeincludepats)
753 sharepath = None 715 narrow = True
754 if sharenamemode == b'identity': 716
755 # Resolve the name from the initial changeset in the remote 717 if storeexcludepats is not None:
756 # repository. This returns nullid when the remote is empty. It 718 narrowspec.validatepatterns(storeexcludepats)
757 # raises RepoLookupError if revision 0 is filtered or otherwise 719 narrow = True
758 # not available. If we fail to resolve, sharing is not enabled. 720
759 try: 721 if narrow:
760 with srcpeer.commandexecutor() as e: 722 # Include everything by default if only exclusion patterns defined.
761 rootnode = e.callcommand( 723 if storeexcludepats and not storeincludepats:
762 b'lookup', 724 storeincludepats = {b'path:.'}
763 { 725
764 b'key': b'0', 726 createopts[b'narrowfiles'] = True
765 }, 727
766 ).result() 728 if depth:
767 729 createopts[b'shallowfilestore'] = True
768 if rootnode != nullid: 730
769 sharepath = os.path.join(sharepool, hex(rootnode)) 731 if srcpeer.capable(b'lfs-serve'):
770 else: 732 # Repository creation honors the config if it disabled the extension, so
733 # we can't just announce that lfs will be enabled. This check avoids
734 # saying that lfs will be enabled, and then saying it's an unknown
735 # feature. The lfs creation option is set in either case so that a
736 # requirement is added. If the extension is explicitly disabled but the
737 # requirement is set, the clone aborts early, before transferring any
738 # data.
739 createopts[b'lfs'] = True
740
741 if extensions.disabled_help(b'lfs'):
742 ui.status(
743 _(
744 b'(remote is using large file support (lfs), but it is '
745 b'explicitly disabled in the local configuration)\n'
746 )
747 )
748 else:
749 ui.status(
750 _(
751 b'(remote is using large file support (lfs); lfs will '
752 b'be enabled for this repository)\n'
753 )
754 )
755
756 shareopts = shareopts or {}
757 sharepool = shareopts.get(b'pool')
758 sharenamemode = shareopts.get(b'mode')
759 if sharepool and islocal(dest):
760 sharepath = None
761 if sharenamemode == b'identity':
762 # Resolve the name from the initial changeset in the remote
763 # repository. This returns nullid when the remote is empty. It
764 # raises RepoLookupError if revision 0 is filtered or otherwise
765 # not available. If we fail to resolve, sharing is not enabled.
766 try:
767 with srcpeer.commandexecutor() as e:
768 rootnode = e.callcommand(
769 b'lookup',
770 {
771 b'key': b'0',
772 },
773 ).result()
774
775 if rootnode != nullid:
776 sharepath = os.path.join(sharepool, hex(rootnode))
777 else:
778 ui.status(
779 _(
780 b'(not using pooled storage: '
781 b'remote appears to be empty)\n'
782 )
783 )
784 except error.RepoLookupError:
771 ui.status( 785 ui.status(
772 _( 786 _(
773 b'(not using pooled storage: ' 787 b'(not using pooled storage: '
774 b'remote appears to be empty)\n' 788 b'unable to resolve identity of remote)\n'
775 ) 789 )
776 ) 790 )
777 except error.RepoLookupError: 791 elif sharenamemode == b'remote':
792 sharepath = os.path.join(
793 sharepool, hex(hashutil.sha1(source).digest())
794 )
795 else:
796 raise error.Abort(
797 _(b'unknown share naming mode: %s') % sharenamemode
798 )
799
800 # TODO this is a somewhat arbitrary restriction.
801 if narrow:
778 ui.status( 802 ui.status(
779 _( 803 _(b'(pooled storage not supported for narrow clones)\n')
780 b'(not using pooled storage: '
781 b'unable to resolve identity of remote)\n'
782 )
783 ) 804 )
784 elif sharenamemode == b'remote': 805 sharepath = None
785 sharepath = os.path.join( 806
786 sharepool, hex(hashutil.sha1(source).digest()) 807 if sharepath:
787 ) 808 return clonewithshare(
788 else: 809 ui,
789 raise error.Abort( 810 peeropts,
790 _(b'unknown share naming mode: %s') % sharenamemode 811 sharepath,
791 ) 812 source,
792 813 srcpeer,
793 # TODO this is a somewhat arbitrary restriction. 814 dest,
794 if narrow: 815 pull=pull,
795 ui.status(_(b'(pooled storage not supported for narrow clones)\n')) 816 rev=revs,
796 sharepath = None 817 update=update,
797 818 stream=stream,
798 if sharepath: 819 )
799 return clonewithshare( 820
800 ui, 821 srcrepo = srcpeer.local()
801 peeropts, 822
802 sharepath,
803 source,
804 srcpeer,
805 dest,
806 pull=pull,
807 rev=revs,
808 update=update,
809 stream=stream,
810 )
811
812 srclock = destlock = cleandir = None
813 srcrepo = srcpeer.local()
814 try:
815 abspath = origsource 823 abspath = origsource
816 if islocal(origsource): 824 if islocal(origsource):
817 abspath = os.path.abspath(util.urllocalpath(origsource)) 825 abspath = os.path.abspath(util.urllocalpath(origsource))
818 826
819 if islocal(dest): 827 if islocal(dest):
1050 release(srclock, destlock) 1058 release(srclock, destlock)
1051 if cleandir is not None: 1059 if cleandir is not None:
1052 shutil.rmtree(cleandir, True) 1060 shutil.rmtree(cleandir, True)
1053 if srcpeer is not None: 1061 if srcpeer is not None:
1054 srcpeer.close() 1062 srcpeer.close()
1063 if destpeer and destpeer.local() is None:
1064 destpeer.close()
1055 return srcpeer, destpeer 1065 return srcpeer, destpeer
1056 1066
1057 1067
1058 def _showstats(repo, stats, quietempty=False): 1068 def _showstats(repo, stats, quietempty=False):
1059 if quietempty and stats.isempty(): 1069 if quietempty and stats.isempty():
1251 (remoterepo, incomingchangesetlist, displayer) parameters, 1261 (remoterepo, incomingchangesetlist, displayer) parameters,
1252 and is supposed to contain only code that can't be unified. 1262 and is supposed to contain only code that can't be unified.
1253 """ 1263 """
1254 source, branches = parseurl(ui.expandpath(source), opts.get(b'branch')) 1264 source, branches = parseurl(ui.expandpath(source), opts.get(b'branch'))
1255 other = peer(repo, opts, source) 1265 other = peer(repo, opts, source)
1256 ui.status(_(b'comparing with %s\n') % util.hidepassword(source)) 1266 cleanupfn = other.close
1257 revs, checkout = addbranchrevs(repo, other, branches, opts.get(b'rev'))
1258
1259 if revs:
1260 revs = [other.lookup(rev) for rev in revs]
1261 other, chlist, cleanupfn = bundlerepo.getremotechanges(
1262 ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
1263 )
1264 try: 1267 try:
1268 ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
1269 revs, checkout = addbranchrevs(repo, other, branches, opts.get(b'rev'))
1270
1271 if revs:
1272 revs = [other.lookup(rev) for rev in revs]
1273 other, chlist, cleanupfn = bundlerepo.getremotechanges(
1274 ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
1275 )
1276
1265 if not chlist: 1277 if not chlist:
1266 ui.status(_(b"no changes found\n")) 1278 ui.status(_(b"no changes found\n"))
1267 return subreporecurse() 1279 return subreporecurse()
1268 ui.pager(b'incoming') 1280 ui.pager(b'incoming')
1269 displayer = logcmdutil.changesetdisplayer( 1281 displayer = logcmdutil.changesetdisplayer(
1318 revs, checkout = addbranchrevs(repo, repo, branches, opts.get(b'rev')) 1330 revs, checkout = addbranchrevs(repo, repo, branches, opts.get(b'rev'))
1319 if revs: 1331 if revs:
1320 revs = [repo[rev].node() for rev in scmutil.revrange(repo, revs)] 1332 revs = [repo[rev].node() for rev in scmutil.revrange(repo, revs)]
1321 1333
1322 other = peer(repo, opts, dest) 1334 other = peer(repo, opts, dest)
1323 outgoing = discovery.findcommonoutgoing( 1335 try:
1324 repo, other, revs, force=opts.get(b'force') 1336 outgoing = discovery.findcommonoutgoing(
1325 ) 1337 repo, other, revs, force=opts.get(b'force')
1326 o = outgoing.missing 1338 )
1327 if not o: 1339 o = outgoing.missing
1328 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded) 1340 if not o:
1329 return o, other 1341 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
1342 return o, other
1343 except: # re-raises
1344 other.close()
1345 raise
1330 1346
1331 1347
1332 def outgoing(ui, repo, dest, opts): 1348 def outgoing(ui, repo, dest, opts):
1333 def recurse(): 1349 def recurse():
1334 ret = 1 1350 ret = 1
1339 ret = min(ret, sub.outgoing(ui, dest, opts)) 1355 ret = min(ret, sub.outgoing(ui, dest, opts))
1340 return ret 1356 return ret
1341 1357
1342 limit = logcmdutil.getlimit(opts) 1358 limit = logcmdutil.getlimit(opts)
1343 o, other = _outgoing(ui, repo, dest, opts) 1359 o, other = _outgoing(ui, repo, dest, opts)
1344 if not o: 1360 try:
1361 if not o:
1362 cmdutil.outgoinghooks(ui, repo, other, opts, o)
1363 return recurse()
1364
1365 if opts.get(b'newest_first'):
1366 o.reverse()
1367 ui.pager(b'outgoing')
1368 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
1369 count = 0
1370 for n in o:
1371 if limit is not None and count >= limit:
1372 break
1373 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1374 if opts.get(b'no_merges') and len(parents) == 2:
1375 continue
1376 count += 1
1377 displayer.show(repo[n])
1378 displayer.close()
1345 cmdutil.outgoinghooks(ui, repo, other, opts, o) 1379 cmdutil.outgoinghooks(ui, repo, other, opts, o)
1346 return recurse() 1380 recurse()
1347 1381 return 0 # exit code is zero since we found outgoing changes
1348 if opts.get(b'newest_first'): 1382 finally:
1349 o.reverse() 1383 other.close()
1350 ui.pager(b'outgoing')
1351 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
1352 count = 0
1353 for n in o:
1354 if limit is not None and count >= limit:
1355 break
1356 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1357 if opts.get(b'no_merges') and len(parents) == 2:
1358 continue
1359 count += 1
1360 displayer.show(repo[n])
1361 displayer.close()
1362 cmdutil.outgoinghooks(ui, repo, other, opts, o)
1363 recurse()
1364 return 0 # exit code is zero since we found outgoing changes
1365 1384
1366 1385
1367 def verify(repo, level=None): 1386 def verify(repo, level=None):
1368 """verify the consistency of a repository""" 1387 """verify the consistency of a repository"""
1369 ret = verifymod.verify(repo, level=level) 1388 ret = verifymod.verify(repo, level=level)