xref: /llvm-project/llvm/utils/docker/scripts/llvm_checksum/project_tree.py (revision b71edfaa4ec3c998aadb35255ce2f60bba2940b0)
1"""Contains helper functions to compute checksums for LLVM checkouts.
2"""
3from __future__ import absolute_import
4from __future__ import division
5from __future__ import print_function
6
7import logging
8import os
9import os.path
10import sys
11
12
13class LLVMProject(object):
14    """An LLVM project with a descriptive name and a relative checkout path."""
15
16    def __init__(self, name, relpath):
17        self.name = name
18        self.relpath = relpath
19
20    def is_subproject(self, other_project):
21        """Check if self is checked out as a subdirectory of other_project."""
22        return self.relpath.startswith(other_project.relpath)
23
24
25def WalkProjectFiles(checkout_root, all_projects, project, visitor):
26    """Walk over all files inside a project without recursing into subprojects, '.git' and '.svn' subfolders.
27
28    checkout_root: root of the LLVM checkout.
29    all_projects: projects in the LLVM checkout.
30    project: a project to walk the files of. Must be inside all_projects.
31    visitor: a function called on each visited file.
32    """
33    assert project in all_projects
34
35    ignored_paths = set()
36    for other_project in all_projects:
37        if other_project != project and other_project.is_subproject(project):
38            ignored_paths.add(os.path.join(checkout_root, other_project.relpath))
39
40    def raise_error(err):
41        raise err
42
43    project_root = os.path.join(checkout_root, project.relpath)
44    for root, dirs, files in os.walk(project_root, onerror=raise_error):
45        dirs[:] = [
46            d
47            for d in dirs
48            if d != ".svn"
49            and d != ".git"
50            and os.path.join(root, d) not in ignored_paths
51        ]
52        for f in files:
53            visitor(os.path.join(root, f))
54
55
56def CreateLLVMProjects(single_tree_checkout):
57    """Returns a list of LLVMProject instances, describing relative paths of a typical LLVM checkout.
58
59    Args:
60      single_tree_checkout:
61        When True, relative paths for each project points to a typical single
62          source tree checkout.
63        When False, relative paths for each projects points to a separate
64          directory. However, clang-tools-extra is an exception, its relative path
65          will always be 'clang/tools/extra'.
66    """
67    # FIXME: cover all of llvm projects.
68
69    # Projects that reside inside 'projects/' in a single source tree checkout.
70    ORDINARY_PROJECTS = [
71        "compiler-rt",
72        "dragonegg",
73        "libcxx",
74        "libcxxabi",
75        "libunwind",
76        "test-suite",
77    ]
78    # Projects that reside inside 'tools/' in a single source tree checkout.
79    TOOLS_PROJECTS = ["clang", "lld", "lldb"]
80
81    if single_tree_checkout:
82        projects = [LLVMProject("llvm", "")]
83        projects += [
84            LLVMProject(p, os.path.join("projects", p)) for p in ORDINARY_PROJECTS
85        ]
86        projects += [LLVMProject(p, os.path.join("tools", p)) for p in TOOLS_PROJECTS]
87        projects.append(
88            LLVMProject(
89                "clang-tools-extra", os.path.join("tools", "clang", "tools", "extra")
90            )
91        )
92    else:
93        projects = [LLVMProject("llvm", "llvm")]
94        projects += [LLVMProject(p, p) for p in ORDINARY_PROJECTS]
95        projects += [LLVMProject(p, p) for p in TOOLS_PROJECTS]
96        projects.append(
97            LLVMProject("clang-tools-extra", os.path.join("clang", "tools", "extra"))
98        )
99    return projects
100