aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorGravatar Klaus Aehlig <aehlig@google.com>2018-06-15 06:01:26 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-06-15 06:02:53 -0700
commitb42734f4213e505d9582def4cd25bd510f0909a9 (patch)
treee829f7c821ada256bd5fcab6b8d24132acadd61c /tools
parentf5be981a28fa50ba83391d4cd42a6e8bce07cca0 (diff)
git_repository: return actual commit
Using that repository rules now may return a non-None value, make git_repository return the arguments that make the rule reproducible; in particular, return the actual commit (instead of a tag) and the date of the commit, so support shallow clones. The added test also demonstrates how the `bazel sync` command together with `--experimental_repository_resolved_file` can be used to replay an earlier state of external dependencies. Change-Id: Ifa1cfdfdb5eb299a15b9d0ec7d285dc84c0bcdc0 PiperOrigin-RevId: 200705705
Diffstat (limited to 'tools')
-rw-r--r--tools/build_defs/repo/git.bzl81
1 files changed, 62 insertions, 19 deletions
diff --git a/tools/build_defs/repo/git.bzl b/tools/build_defs/repo/git.bzl
index a46330542c..3663dc804f 100644
--- a/tools/build_defs/repo/git.bzl
+++ b/tools/build_defs/repo/git.bzl
@@ -80,17 +80,37 @@ set -ex
if st.return_code:
fail("error updating submodules %s:\n%s" % (ctx.name, st.stderr))
-def _new_git_repository_implementation(ctx):
- if ((not ctx.attr.build_file and not ctx.attr.build_file_content) or
- (ctx.attr.build_file and ctx.attr.build_file_content)):
- fail("Exactly one of build_file and build_file_content must be provided.")
- _clone_or_update(ctx)
- workspace_and_buildfile(ctx)
- patch(ctx)
-
-def _git_repository_implementation(ctx):
- _clone_or_update(ctx)
- patch(ctx)
+ # After the fact, determine the actual commit and its date
+ actual_commit = ctx.execute([
+ bash_exe,
+ "-c",
+ "(cd '{directory}' && git log -n 1 --pretty='format:%H')".format(
+ directory = ctx.path("."),
+ ),
+ ]).stdout
+ shallow_date = ctx.execute([
+ bash_exe,
+ "-c",
+ "(cd '{directory}' && git log -n 1 --pretty='format:%cd' --date='format:%Y-%d-%m')".format(
+ directory = ctx.path("."),
+ ),
+ ]).stdout
+ return {"commit": actual_commit, "shallow_since": shallow_date}
+
+def _update_commit(orig, keys, override):
+ # Merge the override information into the dict, resulting by taking the
+ # given keys, as well as the name, form orig (if present there).
+ result = {}
+ for key in keys:
+ if getattr(orig, key) != None:
+ result[key] = getattr(orig, key)
+ result["name"] = orig.name
+ result.update(override)
+
+ # remove tag if we found the actual commit
+ if "commit" in result:
+ result.pop("tag", None)
+ return result
_common_attrs = {
"remote": attr.string(mandatory = True),
@@ -106,19 +126,38 @@ _common_attrs = {
"patch_cmds": attr.string_list(default = []),
}
+_new_git_repository_attrs = dict(_common_attrs.items() + {
+ "build_file": attr.label(allow_single_file = True),
+ "build_file_content": attr.string(),
+ "workspace_file": attr.label(),
+ "workspace_file_content": attr.string(),
+}.items())
+
+def _new_git_repository_implementation(ctx):
+ if ((not ctx.attr.build_file and not ctx.attr.build_file_content) or
+ (ctx.attr.build_file and ctx.attr.build_file_content)):
+ fail("Exactly one of build_file and build_file_content must be provided.")
+ update = _clone_or_update(ctx)
+ workspace_and_buildfile(ctx)
+ patch(ctx)
+ return _update_commit(ctx.attr, _new_git_repository_attrs.keys(), update)
+
+def _git_repository_implementation(ctx):
+ update = _clone_or_update(ctx)
+ patch(ctx)
+ return _update_commit(ctx.attr, _common_attrs.keys(), update)
+
new_git_repository = repository_rule(
implementation = _new_git_repository_implementation,
- attrs = dict(_common_attrs.items() + {
- "build_file": attr.label(allow_single_file = True),
- "build_file_content": attr.string(),
- "workspace_file": attr.label(),
- "workspace_file_content": attr.string(),
- }.items()),
+ attrs = _new_git_repository_attrs,
)
"""Clone an external git repository.
Clones a Git repository, checks out the specified tag, or commit, and
-makes its targets available for binding.
+makes its targets available for binding. Also determine the id of the
+commit actually checkted out and its date, and return a dict with paramters
+that provide a reproducible version of this rule (which a tag not necessarily
+is).
Args:
name: A unique name for this rule.
@@ -173,7 +212,11 @@ git_repository = repository_rule(
"""Clone an external git repository.
Clones a Git repository, checks out the specified tag, or commit, and
-makes its targets available for binding.
+makes its targets available for binding. Also determine the id of the
+commit actually checkted out and its date, and return a dict with paramters
+that provide a reproducible version of this rule (which a tag not necessarily
+is).
+
Args:
name: A unique name for this rule.