|
|
|
@ -132,7 +132,7 @@ def git_glob(glob): |
|
|
|
|
global gg_cache |
|
|
|
|
if glob in gg_cache: return gg_cache[glob] |
|
|
|
|
r = set(subprocess |
|
|
|
|
.check_output(['git', 'ls-files', glob]) |
|
|
|
|
.check_output(['git', 'ls-files', os.path.join(git_root, glob)]) |
|
|
|
|
.decode('utf-8') |
|
|
|
|
.strip() |
|
|
|
|
.splitlines()) |
|
|
|
@ -150,7 +150,7 @@ def expand_directives(root, directives): |
|
|
|
|
globs[glob].append(directive.who) |
|
|
|
|
# expand owners for intersecting globs |
|
|
|
|
sorted_globs = sorted(globs.keys(), |
|
|
|
|
key=lambda g: len(git_glob(os.path.join(root, g))), |
|
|
|
|
key=lambda g: len(git_glob(full_dir(root, g))), |
|
|
|
|
reverse=True) |
|
|
|
|
out_globs = collections.OrderedDict() |
|
|
|
|
for glob_add in sorted_globs: |
|
|
|
@ -162,8 +162,9 @@ def expand_directives(root, directives): |
|
|
|
|
files_have = git_glob(full_dir(root, glob_have)) |
|
|
|
|
intersect = files_have.intersection(files_add) |
|
|
|
|
if intersect: |
|
|
|
|
for f in files_add: |
|
|
|
|
for f in sorted(files_add): # sorted to ensure merge stability |
|
|
|
|
if f not in intersect: |
|
|
|
|
print("X", root, glob_add, glob_have) |
|
|
|
|
out_globs[os.path.relpath(f, start=root)] = who_add |
|
|
|
|
for who in who_have: |
|
|
|
|
if who not in out_globs[glob_add]: |
|
|
|
@ -182,8 +183,9 @@ def add_parent_to_globs(parent, globs, globs_dir): |
|
|
|
|
intersect = files_parent.intersection(files_child) |
|
|
|
|
gglob_who_orig = gglob_who.copy() |
|
|
|
|
if intersect: |
|
|
|
|
for f in files_child: |
|
|
|
|
for f in sorted(files_child): # sorted to ensure merge stability |
|
|
|
|
if f not in intersect: |
|
|
|
|
print("Y", full_dir(owners.dir, oglob), full_dir(globs_dir, gglob)) |
|
|
|
|
who = gglob_who_orig.copy() |
|
|
|
|
globs[os.path.relpath(f, start=globs_dir)] = who |
|
|
|
|
for who in oglob_who: |
|
|
|
@ -199,6 +201,7 @@ with open(args.out, 'w') as out: |
|
|
|
|
out.write('# Auto-generated by the tools/mkowners/mkowners.py tool\n') |
|
|
|
|
out.write('# Uses OWNERS files in different modules throughout the\n') |
|
|
|
|
out.write('# repository as the source of truth for module ownership.\n') |
|
|
|
|
written_globs = [] |
|
|
|
|
while todo: |
|
|
|
|
head, *todo = todo |
|
|
|
|
if head.parent and not head.parent in done: |
|
|
|
@ -207,6 +210,21 @@ with open(args.out, 'w') as out: |
|
|
|
|
globs = expand_directives(head.dir, head.directives) |
|
|
|
|
add_parent_to_globs(head.parent, globs, head.dir) |
|
|
|
|
for glob, owners in globs.items(): |
|
|
|
|
out.write('/%s %s\n' % ( |
|
|
|
|
full_dir(head.dir, glob), ' '.join(owners))) |
|
|
|
|
skip = False |
|
|
|
|
for glob1, owners1, dir1 in reversed(written_globs): |
|
|
|
|
files = git_glob(full_dir(head.dir, glob)) |
|
|
|
|
files1 = git_glob(full_dir(dir1, glob1)) |
|
|
|
|
intersect = files.intersection(files1) |
|
|
|
|
if files == intersect: |
|
|
|
|
if sorted(owners) == sorted(owners1): |
|
|
|
|
skip = True # nothing new in this rule |
|
|
|
|
break |
|
|
|
|
elif intersect: |
|
|
|
|
# continuing would cause a semantic change since some files are |
|
|
|
|
# affected differently by this rule and CODEOWNERS is order dependent |
|
|
|
|
break |
|
|
|
|
if not skip: |
|
|
|
|
out.write('/%s %s\n' % ( |
|
|
|
|
full_dir(head.dir, glob), ' '.join(owners))) |
|
|
|
|
written_globs.append((glob, owners, head.dir)) |
|
|
|
|
done.add(head.dir) |
|
|
|
|