Fix angle_commit.h dependency when git packs refs

If there are too many files in .git/refs/heads/, git packs them in
.git/packed-refs.  This breaks the build as gen/angle/angle_commit.h
depends on .git/refs/heads/<branch-name>.

With this change, when gn is run and the dependency to this file is set
up, it's unpacked from .git/packed-refs if it's missing from
.git/refs/heads/.

One corner case not solved by this change is if a commit is amended with
no changes and git packs the refs (and so the
.git/refs/heads/<branch-name> file goes away), ninja doesn't rerun gn as
it doesn't believe there to be any changes, yet fails the build as the
dependency is now missing.  Running `gn gen` manually fixes the issue.
The issue is automatically fixed when switching branches.

Bug: angleproject:6131
Change-Id: Ie2404e874a5cb3374a652b93faa143acb68eaa19
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3001906
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Shahbaz Youssefi 2021-07-01 22:55:59 -04:00 коммит произвёл Angle LUCI CQ
Родитель 73792a63a9
Коммит 955b4620db
2 изменённых файлов: 44 добавлений и 1 удалений

Просмотреть файл

@ -658,7 +658,17 @@ action("angle_commit_id") {
branch = read_file(".git/HEAD", "string") branch = read_file(".git/HEAD", "string")
result = string_split(branch) result = string_split(branch)
if (result[0] == "ref:") { if (result[0] == "ref:") {
inputs += [ ".git/" + result[1] ] _ref_file = result[1]
# If git has packed the contents of .git/refs/heads/ in .git/packed-refs,
# unpack the head before depending on it.
exec_script("src/commit_id.py",
[
"unpack",
_ref_file,
],
"")
inputs += [ ".git/" + _ref_file ]
} }
} }

Просмотреть файл

@ -12,6 +12,8 @@ import os
usage = """\ usage = """\
Usage: commit_id.py check - check if git is present Usage: commit_id.py check - check if git is present
commit_id.py unpack <ref_file> - check if <ref_file> exists, and if not
create it based on .git/packed-refs
commit_id.py position - print commit position commit_id.py position - print commit position
commit_id.py gen <file_to_write> - generate commit.h""" commit_id.py gen <file_to_write> - generate commit.h"""
@ -25,6 +27,24 @@ def get_commit_position(cwd):
return grab_output('git rev-list HEAD --count', cwd) return grab_output('git rev-list HEAD --count', cwd)
def unpack_ref(ref_file, ref_file_full_path, packed_refs_full_path):
with open(packed_refs_full_path) as fin:
refs = fin.read().strip().split('\n')
# Strip comments
refs = [ref.split(' ') for ref in refs if ref.strip()[0] != '#']
# Parse lines (which are in the format <hash> <ref_file>) and find the input file
refs = [git_hash for (git_hash, file_path) in refs if file_path == ref_file]
assert (len(refs) == 1)
git_hash = refs[0]
with open(ref_file_full_path, 'w') as fout:
fout.write(git_hash + '\n')
if len(sys.argv) < 2: if len(sys.argv) < 2:
sys.exit(usage) sys.exit(usage)
@ -44,6 +64,19 @@ if operation == 'check':
else: else:
print("0") print("0")
sys.exit(0) sys.exit(0)
elif operation == 'unpack':
if len(sys.argv) < 3:
sys.exit(usage)
ref_file = sys.argv[2]
ref_file_full_path = os.path.join(cwd, '.git', ref_file)
ref_file_exists = os.path.exists(ref_file_full_path)
if not ref_file_exists:
packed_refs_full_path = os.path.join(cwd, '.git', 'packed-refs')
unpack_ref(ref_file, ref_file_full_path, packed_refs_full_path)
sys.exit(0)
elif operation == 'position': elif operation == 'position':
if git_dir_exists: if git_dir_exists:
print(get_commit_position(cwd)) print(get_commit_position(cwd))