Skip to content

Commit

Permalink
Attempt to git fetch only specified commit
Browse files Browse the repository at this point in the history
The Git server config setting uploadpack.allowReachableSHA1InWant and
friends allow git fetch to request a particular commit, which is more
efficient than fetching all refs and then checking out the commit
locally. Attempt to do this, and fall back to fetching everything if it
fails.
  • Loading branch information
HackAttack committed Nov 1, 2019
1 parent 63346c5 commit c26902c
Showing 1 changed file with 20 additions and 17 deletions.
37 changes: 20 additions & 17 deletions tools/build_defs/repo/git_worker.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ _GitRepoInfo = provider(
"shallow": "Defines the depth of a fetch. Either empty, --depth=1, or --shallow-since=<>",
"reset_ref": """Reference to use for resetting the git repository.
Either commit hash, tag or branch.""",
"fetch_ref": """Reference for fetching. Can be empty (HEAD), tag or branch.
Can not be a commit hash, since typically it is forbidden by git servers.""",
"fetch_ref": """Reference for fetching.
Either commit hash, tag or branch.""",
"fetch_is_sha": "Whether the fetch_ref is a commit hash.",
"remote": "URL of the git repository to fetch from.",
"init_submodules": """If True, submodules update command will be called after fetching
and resetting to the specified reference.""",
Expand All @@ -49,20 +50,19 @@ def git_repo(ctx, directory):
if ctx.attr.branch:
fail("shallow_since not allowed if a branch is specified; --depth=1 will be used for branches")

shallow = "--depth=1"
if ctx.attr.commit:
# We can not use the commit value in --shallow-since;
# And since we are fetching HEAD in this case, we can not use --depth=1
shallow = ""

# Use shallow-since if given
if ctx.attr.shallow_since:
shallow = "--shallow-since=%s" % ctx.attr.shallow_since
else:
shallow = "--depth=1"

reset_ref = ""
fetch_ref = ""
fetch_is_sha = False
if ctx.attr.commit:
reset_ref = ctx.attr.commit
fetch_ref = ctx.attr.commit
fetch_is_sha = True
elif ctx.attr.tag:
reset_ref = "tags/" + ctx.attr.tag
fetch_ref = "tags/" + ctx.attr.tag + ":tags/" + ctx.attr.tag
Expand All @@ -75,6 +75,7 @@ def git_repo(ctx, directory):
shallow = shallow,
reset_ref = reset_ref,
fetch_ref = fetch_ref,
fetch_is_sha = fetch_is_sha,
remote = ctx.attr.remote,
init_submodules = ctx.attr.init_submodules,
)
Expand Down Expand Up @@ -118,15 +119,19 @@ def add_origin(ctx, git_repo, remote):
_git(ctx, git_repo, "remote", "add", "origin", remote)

def fetch(ctx, git_repo):
if not git_repo.fetch_ref:
# We need to explicitly specify to fetch all branches and tags, otherwise only
# HEAD-reachable is fetched.
args = ["fetch", "origin", git_repo.fetch_ref]
st = _git_maybe_shallow(ctx, git_repo, *args)
if st.return_code == 0:
return
if git_repo.fetch_is_sha:
# Perhaps uploadpack.allowReachableSHA1InWant or similar is not enabled on the server;
# fall back to fetching all branches, tags, and history.
# The semantics of --tags flag of git-fetch have changed in Git 1.9, from 1.9 it means
# "everything that is already specified and all tags"; before 1.9, it used to mean
# "ignore what is specified and fetch all tags".
# The arguments below work correctly for both before 1.9 and after 1.9,
# as we directly specify the list of references to fetch.
_git_maybe_shallow(
_git(
ctx,
git_repo,
"fetch",
Expand All @@ -135,7 +140,7 @@ def fetch(ctx, git_repo):
"refs/tags/*:refs/tags/*",
)
else:
_git_maybe_shallow(ctx, git_repo, "fetch", "origin", git_repo.fetch_ref)
_error(ctx.name, ["git"] + args, st.stderr)

def reset(ctx, git_repo):
_git(ctx, git_repo, "reset", "--hard", git_repo.reset_ref)
Expand Down Expand Up @@ -165,10 +170,8 @@ def _git_maybe_shallow(ctx, git_repo, command, *args):
if git_repo.shallow:
st = _execute(ctx, git_repo, start + [git_repo.shallow] + args_list)
if st.return_code == 0:
return
st = _execute(ctx, git_repo, start + args_list)
if st.return_code != 0:
_error(ctx.name, start + args_list, st.stderr)
return st
return _execute(ctx, git_repo, start + args_list)

def _execute(ctx, git_repo, args):
return ctx.execute(
Expand Down

0 comments on commit c26902c

Please sign in to comment.