mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 14:58:03 +03:00
git: respect selective pull
Summary: Some git repos (ex. pytorch) has thousands of branches that won't scale well. Change no-argument pull to respect selective pull to mitigate it. Reviewed By: DurhamG Differential Revision: D33485186 fbshipit-source-id: b735704850847c49b0bfeb94972e4bb778e726a4
This commit is contained in:
parent
e6d1d7fa2b
commit
77cb1f9890
@ -1055,6 +1055,14 @@ class remotenames(dict):
|
|||||||
self._node2hoists.setdefault(node[0], []).append(name)
|
self._node2hoists.setdefault(node[0], []).append(name)
|
||||||
return self._node2hoists
|
return self._node2hoists
|
||||||
|
|
||||||
|
def get(self, name):
|
||||||
|
"""Resolve a remote bookmark. Return None if the bookmark does not exist"""
|
||||||
|
nodes = self["bookmarks"].get(name)
|
||||||
|
if nodes:
|
||||||
|
return nodes[0]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def changecount(self):
|
def changecount(self):
|
||||||
return self._changecount
|
return self._changecount
|
||||||
|
@ -4584,6 +4584,8 @@ def pull(ui, repo, source="default", **opts):
|
|||||||
if source == "default":
|
if source == "default":
|
||||||
source = "origin"
|
source = "origin"
|
||||||
refspecs = (opts.get("bookmark") or []) + (opts.get("rev") or [])
|
refspecs = (opts.get("bookmark") or []) + (opts.get("rev") or [])
|
||||||
|
if not refspecs:
|
||||||
|
refspecs = git.defaultpullrefspecs(repo, source)
|
||||||
ret = git.pull(repo, source, refspecs)
|
ret = git.pull(repo, source, refspecs)
|
||||||
if ret == 0 and opts.get("update"):
|
if ret == 0 and opts.get("update"):
|
||||||
# Figure out the node to checkout
|
# Figure out the node to checkout
|
||||||
|
@ -15,9 +15,9 @@ import subprocess
|
|||||||
import bindings
|
import bindings
|
||||||
from edenscm import tracing
|
from edenscm import tracing
|
||||||
|
|
||||||
from . import error, util
|
from . import bookmarks as bookmod, error, util
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
from .node import hex, nullid
|
from .node import bin, hex, nullid
|
||||||
|
|
||||||
GIT_DIR_FILE = "gitdir"
|
GIT_DIR_FILE = "gitdir"
|
||||||
GIT_REQUIREMENT = "git"
|
GIT_REQUIREMENT = "git"
|
||||||
@ -68,7 +68,8 @@ def clone(ui, url, destpath=None, update=True):
|
|||||||
raise error.Abort(_("git clone was not successful"))
|
raise error.Abort(_("git clone was not successful"))
|
||||||
initgit(repo, "git")
|
initgit(repo, "git")
|
||||||
if url:
|
if url:
|
||||||
pull(repo, "origin", [])
|
refspecs = defaultpullrefspecs(repo, "origin")
|
||||||
|
pull(repo, "origin", refspecs)
|
||||||
except Exception:
|
except Exception:
|
||||||
repo = None
|
repo = None
|
||||||
shutil.rmtree(destpath, ignore_errors=True)
|
shutil.rmtree(destpath, ignore_errors=True)
|
||||||
@ -186,6 +187,9 @@ def revparse(repo, revspec):
|
|||||||
|
|
||||||
def pull(repo, source, refspecs):
|
def pull(repo, source, refspecs):
|
||||||
"""Run `git fetch` on the backing repo to perform a pull"""
|
"""Run `git fetch` on the backing repo to perform a pull"""
|
||||||
|
if not refspecs:
|
||||||
|
# Nothing to pull
|
||||||
|
return 0
|
||||||
ret = rungit(
|
ret = rungit(
|
||||||
repo,
|
repo,
|
||||||
["fetch", "--no-write-fetch-head", "--no-tags", "--prune", source] + refspecs,
|
["fetch", "--no-write-fetch-head", "--no-tags", "--prune", source] + refspecs,
|
||||||
@ -212,6 +216,41 @@ def push(repo, dest, pushnode, to, force=False):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def listremote(repo, source, patterns):
|
||||||
|
"""List references of the remote peer
|
||||||
|
Return a dict of name to node.
|
||||||
|
"""
|
||||||
|
out = callgit(repo, ["ls-remote", "--refs", source] + patterns)
|
||||||
|
refs = {}
|
||||||
|
for line in out.splitlines():
|
||||||
|
if b"\t" not in line:
|
||||||
|
continue
|
||||||
|
hexnode, name = line.split(b"\t", 1)
|
||||||
|
refs[name.decode("utf-8")] = bin(hexnode)
|
||||||
|
return refs
|
||||||
|
|
||||||
|
|
||||||
|
def defaultpullrefspecs(repo, source):
|
||||||
|
"""default refspecs for 'git fetch' respecting selective pull"""
|
||||||
|
names = bookmod.selectivepullbookmarknames(repo)
|
||||||
|
|
||||||
|
patterns = ["refs/heads/%s" % name for name in names]
|
||||||
|
listed = listremote(repo, source, patterns)
|
||||||
|
|
||||||
|
refspecs = []
|
||||||
|
for name in names:
|
||||||
|
refspec = "refs/heads/%s" % name
|
||||||
|
remotenode = listed.get(refspec)
|
||||||
|
if repo._remotenames.get("%s/%s" % (source, name)) == remotenode:
|
||||||
|
# not changed, skip
|
||||||
|
continue
|
||||||
|
if remotenode is None:
|
||||||
|
# removed remotely
|
||||||
|
refspec = ":refs/remotes/%s/heads/%s" % (source, name)
|
||||||
|
refspecs.append(refspec)
|
||||||
|
return refspecs
|
||||||
|
|
||||||
|
|
||||||
def callgit(repo, args):
|
def callgit(repo, args):
|
||||||
"""Run git command in the backing git repo, return its output"""
|
"""Run git command in the backing git repo, return its output"""
|
||||||
gitdir = readgitdir(repo)
|
gitdir = readgitdir(repo)
|
||||||
|
@ -22,6 +22,7 @@ autopullpattern=
|
|||||||
disallowedto=^origin/
|
disallowedto=^origin/
|
||||||
disallowhint=please don't specify 'origin/' prefix in remote bookmark's name
|
disallowhint=please don't specify 'origin/' prefix in remote bookmark's name
|
||||||
hoist=origin
|
hoist=origin
|
||||||
|
selectivepulldefault=main,master
|
||||||
|
|
||||||
[smartlog]
|
[smartlog]
|
||||||
names=main,master
|
names=main,master
|
||||||
|
@ -201,11 +201,10 @@ Test clone with flags (--noupdate, --updaterev):
|
|||||||
$ hg log -r . -T '{node|short}\n'
|
$ hg log -r . -T '{node|short}\n'
|
||||||
000000000000
|
000000000000
|
||||||
$ hg bookmarks --remote
|
$ hg bookmarks --remote
|
||||||
origin/foo 5c9a5ee451a8
|
|
||||||
origin/master 3f5848713286
|
origin/master 3f5848713286
|
||||||
$ cd ..
|
$ cd ..
|
||||||
|
|
||||||
$ hg clone "git+file://$TESTTMP/gitrepo" cloned1
|
$ hg clone "git+file://$TESTTMP/gitrepo" cloned1 --config remotenames.selectivepulldefault=foo,master
|
||||||
From file:/*/$TESTTMP/gitrepo (glob)
|
From file:/*/$TESTTMP/gitrepo (glob)
|
||||||
* [new branch] foo -> origin/foo
|
* [new branch] foo -> origin/foo
|
||||||
* [new branch] master -> origin/master
|
* [new branch] master -> origin/master
|
||||||
@ -214,10 +213,9 @@ Test clone with flags (--noupdate, --updaterev):
|
|||||||
5c9a5ee451a8 origin/foo alpha3
|
5c9a5ee451a8 origin/foo alpha3
|
||||||
$ cd ..
|
$ cd ..
|
||||||
|
|
||||||
$ hg clone --updaterev origin/foo "git+file://$TESTTMP/gitrepo" cloned2
|
$ hg clone --updaterev origin/foo "git+file://$TESTTMP/gitrepo" cloned2 --config remotenames.selectivepulldefault=foo
|
||||||
From file:/*/$TESTTMP/gitrepo (glob)
|
From file:/*/$TESTTMP/gitrepo (glob)
|
||||||
* [new branch] foo -> origin/foo
|
* [new branch] foo -> origin/foo
|
||||||
* [new branch] master -> origin/master
|
|
||||||
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||||
$ hg --cwd cloned2 log -r . -T '{node|short} {remotenames} {desc}\n'
|
$ hg --cwd cloned2 log -r . -T '{node|short} {remotenames} {desc}\n'
|
||||||
5c9a5ee451a8 origin/foo alpha3
|
5c9a5ee451a8 origin/foo alpha3
|
||||||
|
Loading…
Reference in New Issue
Block a user