7 # Patch parsing functions
10 FIND_INFRA_IN_PATCH = re.compile("^\+\$\(eval \$\((host-)?([^-]*)-package\)\)$")
13 def analyze_patch(patch):
14 """Parse one patch and return the list of files modified, added or
15 removed by the patch."""
19 # If the patch is adding a package, find which infra it is
20 m = FIND_INFRA_IN_PATCH.match(line)
22 infras.add(m.group(2))
23 if not line.startswith("+++ "):
26 fname = line[line.find("/") + 1:].strip()
27 if fname == "dev/null":
30 return (files, infras)
33 FIND_INFRA_IN_MK = re.compile("^\$\(eval \$\((host-)?([^-]*)-package\)\)$")
36 def fname_get_package_infra(fname):
37 """Checks whether the file name passed as argument is a Buildroot .mk
38 file describing a package, and find the infrastructure it's using."""
39 if not fname.endswith(".mk"):
42 if not os.path.exists(fname):
45 with open(fname, "r") as f:
48 m = FIND_INFRA_IN_MK.match(line)
54 def get_infras(files):
55 """Search in the list of files for .mk files, and collect the package
56 infrastructures used by those .mk files."""
59 infra = fname_get_package_infra(fname)
65 def analyze_patches(patches):
66 """Parse a list of patches and returns the list of files modified,
67 added or removed by the patches, as well as the list of package
68 infrastructures used by those patches (if any)"""
72 (files, infras) = analyze_patch(patch)
73 allfiles = allfiles | files
74 allinfras = allinfras | infras
75 allinfras = allinfras | get_infras(allfiles)
76 return (allfiles, allinfras)
80 # DEVELOPERS file parsing functions
84 def __init__(self, name, files):
87 self.packages = parse_developer_packages(files)
88 self.architectures = parse_developer_architectures(files)
89 self.infras = parse_developer_infras(files)
92 f = os.path.abspath(f)
99 def parse_developer_packages(fnames):
100 """Given a list of file patterns, travel through the Buildroot source
101 tree to find which packages are implemented by those file
102 patterns, and return a list of those packages."""
105 for root, dirs, files in os.walk(fname):
107 path = os.path.join(root, f)
108 if fname_get_package_infra(path):
109 pkg = os.path.splitext(f)[0]
114 def parse_arches_from_config_in(fname):
115 """Given a path to an arch/Config.in.* file, parse it to get the list
116 of BR2_ARCH values for this architecture."""
118 with open(fname, "r") as f:
119 parsing_arches = False
122 if line == "config BR2_ARCH":
123 parsing_arches = True
126 m = re.match("^\s*default \"([^\"]*)\".*", line)
128 arches.add(m.group(1))
130 parsing_arches = False
134 def parse_developer_architectures(fnames):
135 """Given a list of file names, find the ones starting by
136 'arch/Config.in.', and use that to determine the architecture a
137 developer is working on."""
140 if not re.match("^.*/arch/Config\.in\..*$", fname):
142 arches = arches | parse_arches_from_config_in(fname)
146 def parse_developer_infras(fnames):
149 m = re.match("^package/pkg-([^.]*).mk$", fname)
151 infras.add(m.group(1))
155 def parse_developers(basepath=None):
156 """Parse the DEVELOPERS file and return a list of Developer objects."""
160 basepath = os.getcwd()
161 with open(os.path.join(basepath, "DEVELOPERS"), "r") as f:
166 if line.startswith("#"):
168 elif line.startswith("N:"):
169 if name is not None or len(files) != 0:
170 print("Syntax error in DEVELOPERS file, line %d" % linen)
171 name = line[2:].strip()
172 elif line.startswith("F:"):
173 fname = line[2:].strip()
174 dev_files = glob.glob(os.path.join(basepath, fname))
175 if len(dev_files) == 0:
176 print("WARNING: '%s' doesn't match any file" % fname)
181 developers.append(Developer(name, files))
185 print("Syntax error in DEVELOPERS file, line %d: '%s'" % (linen, line))
188 # handle last developer
190 developers.append(Developer(name, files))
194 def check_developers(developers, basepath=None):
195 """Look at the list of files versioned in Buildroot, and returns the
196 list of files that are not handled by any developer"""
198 basepath = os.getcwd()
199 cmd = ["git", "--git-dir", os.path.join(basepath, ".git"), "ls-files"]
200 files = subprocess.check_output(cmd).strip().split("\n")
205 if d.hasfile(os.path.join(basepath, f)):
209 unhandled_files.append(f)
210 return unhandled_files