tools: move get-developers out of support/scripts/
authorYann E. MORIN <yann.morin.1998@free.fr>
Sat, 1 Jul 2017 14:31:02 +0000 (16:31 +0200)
committerThomas Petazzoni <thomas.petazzoni@free-electrons.com>
Sat, 1 Jul 2017 15:53:04 +0000 (17:53 +0200)
Move it to the top-level tools/ directory, so that it is easier to
find for users.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Arnout Vandecappelle <arnout@mind.be>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
docs/manual/contribute.txt
support/scripts/get-developers [deleted file]
support/scripts/getdeveloperlib.py [deleted file]
tools/get-developers [new file with mode: 0755]
tools/getdeveloperlib.py [new file with mode: 0644]
tools/readme.txt

index 719032bcc4b1b12f7480678f062f26da030f030d..c10587726c41a5c6964b88c5a5ab65f509f66361 100644 (file)
@@ -295,7 +295,7 @@ information). This tool reads your patches and outputs the appropriate
 +git send-email+ command to use:
 
 ---------------------
-$ ./support/scripts/get-developers outgoing/*
+$ ./tools/get-developers outgoing/*
 ---------------------
 
 Use the output of +get-developers+ to send your patches:
diff --git a/support/scripts/get-developers b/support/scripts/get-developers
deleted file mode 100755 (executable)
index 40ed08f..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python
-
-import argparse
-import getdeveloperlib
-
-def parse_args():
-    parser = argparse.ArgumentParser()
-    parser.add_argument('patches', metavar='P', type=argparse.FileType('r'), nargs='*',
-                        help='list of patches (use - to read patches from stdin)')
-    parser.add_argument('-a', dest='architecture', action='store',
-                        help='find developers in charge of this architecture')
-    parser.add_argument('-p', dest='package', action='store',
-                        help='find developers in charge of this package')
-    parser.add_argument('-c', dest='check', action='store_const',
-                        const=True, help='list files not handled by any developer')
-    return parser.parse_args()
-
-def __main__():
-    devs = getdeveloperlib.parse_developers()
-    if devs is None:
-        sys.exit(1)
-    args = parse_args()
-
-    # Check that only one action is given
-    action = 0
-    if args.architecture is not None:
-        action += 1
-    if args.package is not None:
-        action += 1
-    if args.check:
-        action += 1
-    if len(args.patches) != 0:
-        action += 1
-    if action > 1:
-        print("Cannot do more than one action")
-        return
-    if action == 0:
-        print("No action specified")
-        return
-
-    # Handle the check action
-    if args.check:
-        files = getdeveloperlib.check_developers(devs)
-        for f in files:
-            print(f)
-
-    # Handle the architecture action
-    if args.architecture is not None:
-        for dev in devs:
-            if args.architecture in dev.architectures:
-                print(dev.name)
-        return
-
-    # Handle the package action
-    if args.package is not None:
-        for dev in devs:
-            if args.package in dev.packages:
-                print(dev.name)
-        return
-
-    # Handle the patches action
-    if len(args.patches) != 0:
-        (files, infras) = getdeveloperlib.analyze_patches(args.patches)
-        matching_devs = set()
-        for dev in devs:
-            # See if we have developers matching by package name
-            for f in files:
-                if dev.hasfile(f):
-                    matching_devs.add(dev.name)
-            # See if we have developers matching by package infra
-            for i in infras:
-                if i in dev.infras:
-                    matching_devs.add(dev.name)
-
-        result = "--to buildroot@buildroot.org"
-        for dev in matching_devs:
-            result += " --cc \"%s\"" % dev
-
-        if result != "":
-            print("git send-email %s" % result)
-
-__main__()
-
diff --git a/support/scripts/getdeveloperlib.py b/support/scripts/getdeveloperlib.py
deleted file mode 100644 (file)
index 6519107..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-import sys
-import os
-import re
-import argparse
-import glob
-import subprocess
-
-#
-# Patch parsing functions
-#
-
-FIND_INFRA_IN_PATCH = re.compile("^\+\$\(eval \$\((host-)?([^-]*)-package\)\)$")
-
-def analyze_patch(patch):
-    """Parse one patch and return the list of files modified, added or
-    removed by the patch."""
-    files = set()
-    infras = set()
-    for line in patch:
-        # If the patch is adding a package, find which infra it is
-        m = FIND_INFRA_IN_PATCH.match(line)
-        if m:
-            infras.add(m.group(2))
-        if not line.startswith("+++ "):
-            continue
-        line.strip()
-        fname = line[line.find("/") + 1 : ].strip()
-        if fname == "dev/null":
-            continue
-        files.add(fname)
-    return (files, infras)
-
-FIND_INFRA_IN_MK = re.compile("^\$\(eval \$\((host-)?([^-]*)-package\)\)$")
-
-def fname_get_package_infra(fname):
-    """Checks whether the file name passed as argument is a Buildroot .mk
-    file describing a package, and find the infrastructure it's using."""
-    if not fname.endswith(".mk"):
-        return None
-
-    if not os.path.exists(fname):
-        return None
-
-    with open(fname, "r") as f:
-        for l in f:
-            l = l.strip()
-            m = FIND_INFRA_IN_MK.match(l)
-            if m:
-                return m.group(2)
-    return None
-
-def get_infras(files):
-    """Search in the list of files for .mk files, and collect the package
-    infrastructures used by those .mk files."""
-    infras = set()
-    for fname in files:
-        infra = fname_get_package_infra(fname)
-        if infra:
-            infras.add(infra)
-    return infras
-
-def analyze_patches(patches):
-    """Parse a list of patches and returns the list of files modified,
-    added or removed by the patches, as well as the list of package
-    infrastructures used by those patches (if any)"""
-    allfiles = set()
-    allinfras = set()
-    for patch in patches:
-        (files, infras) = analyze_patch(patch)
-        allfiles = allfiles | files
-        allinfras = allinfras | infras
-    allinfras = allinfras | get_infras(allfiles)
-    return (allfiles, allinfras)
-
-#
-# DEVELOPERS file parsing functions
-#
-
-class Developer:
-    def __init__(self, name, files):
-        self.name = name
-        self.files = files
-        self.packages = parse_developer_packages(files)
-        self.architectures = parse_developer_architectures(files)
-        self.infras = parse_developer_infras(files)
-
-    def hasfile(self, f):
-        f = os.path.abspath(f)
-        for fs in self.files:
-            if f.startswith(fs):
-                return True
-        return False
-
-def parse_developer_packages(fnames):
-    """Given a list of file patterns, travel through the Buildroot source
-    tree to find which packages are implemented by those file
-    patterns, and return a list of those packages."""
-    packages = set()
-    for fname in fnames:
-        for root, dirs, files in os.walk(fname):
-            for f in files:
-                path = os.path.join(root, f)
-                if fname_get_package_infra(path):
-                    pkg = os.path.splitext(f)[0]
-                    packages.add(pkg)
-    return packages
-
-def parse_arches_from_config_in(fname):
-    """Given a path to an arch/Config.in.* file, parse it to get the list
-    of BR2_ARCH values for this architecture."""
-    arches = set()
-    with open(fname, "r") as f:
-        parsing_arches = False
-        for l in f:
-            l = l.strip()
-            if l == "config BR2_ARCH":
-                parsing_arches = True
-                continue
-            if parsing_arches:
-                m = re.match("^\s*default \"([^\"]*)\".*", l)
-                if m:
-                    arches.add(m.group(1))
-                else:
-                    parsing_arches = False
-    return arches
-
-def parse_developer_architectures(fnames):
-    """Given a list of file names, find the ones starting by
-    'arch/Config.in.', and use that to determine the architecture a
-    developer is working on."""
-    arches = set()
-    for fname in fnames:
-        if not re.match("^.*/arch/Config\.in\..*$", fname):
-            continue
-        arches = arches | parse_arches_from_config_in(fname)
-    return arches
-
-def parse_developer_infras(fnames):
-    infras = set()
-    for fname in fnames:
-        m = re.match("^package/pkg-([^.]*).mk$", fname)
-        if m:
-            infras.add(m.group(1))
-    return infras
-
-def parse_developers(basepath=None):
-    """Parse the DEVELOPERS file and return a list of Developer objects."""
-    developers = []
-    linen = 0
-    if basepath == None:
-        basepath = os.getcwd()
-    with open(os.path.join(basepath, "DEVELOPERS"), "r") as f:
-        files = []
-        name = None
-        for l in f:
-            l = l.strip()
-            if l.startswith("#"):
-                continue
-            elif l.startswith("N:"):
-                if name is not None or len(files) != 0:
-                    print("Syntax error in DEVELOPERS file, line %d" % linen)
-                name = l[2:].strip()
-            elif l.startswith("F:"):
-                fname = l[2:].strip()
-                dev_files = glob.glob(os.path.join(basepath, fname))
-                if len(dev_files) == 0:
-                    print("WARNING: '%s' doesn't match any file" % fname)
-                files += dev_files
-            elif l == "":
-                if not name:
-                    continue
-                developers.append(Developer(name, files))
-                files = []
-                name = None
-            else:
-                print("Syntax error in DEVELOPERS file, line %d: '%s'" % (linen, l))
-                return None
-            linen += 1
-    # handle last developer
-    if name is not None:
-        developers.append(Developer(name, files))
-    return developers
-
-def check_developers(developers, basepath=None):
-    """Look at the list of files versioned in Buildroot, and returns the
-    list of files that are not handled by any developer"""
-    if basepath == None:
-        basepath = os.getcwd()
-    cmd = ["git", "--git-dir", os.path.join(basepath, ".git"), "ls-files"]
-    files = subprocess.check_output(cmd).strip().split("\n")
-    unhandled_files = []
-    for f in files:
-        handled = False
-        for d in developers:
-            if d.hasfile(os.path.join(basepath, f)):
-                handled = True
-                break
-        if not handled:
-            unhandled_files.append(f)
-    return unhandled_files
diff --git a/tools/get-developers b/tools/get-developers
new file mode 100755 (executable)
index 0000000..40ed08f
--- /dev/null
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+
+import argparse
+import getdeveloperlib
+
+def parse_args():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('patches', metavar='P', type=argparse.FileType('r'), nargs='*',
+                        help='list of patches (use - to read patches from stdin)')
+    parser.add_argument('-a', dest='architecture', action='store',
+                        help='find developers in charge of this architecture')
+    parser.add_argument('-p', dest='package', action='store',
+                        help='find developers in charge of this package')
+    parser.add_argument('-c', dest='check', action='store_const',
+                        const=True, help='list files not handled by any developer')
+    return parser.parse_args()
+
+def __main__():
+    devs = getdeveloperlib.parse_developers()
+    if devs is None:
+        sys.exit(1)
+    args = parse_args()
+
+    # Check that only one action is given
+    action = 0
+    if args.architecture is not None:
+        action += 1
+    if args.package is not None:
+        action += 1
+    if args.check:
+        action += 1
+    if len(args.patches) != 0:
+        action += 1
+    if action > 1:
+        print("Cannot do more than one action")
+        return
+    if action == 0:
+        print("No action specified")
+        return
+
+    # Handle the check action
+    if args.check:
+        files = getdeveloperlib.check_developers(devs)
+        for f in files:
+            print(f)
+
+    # Handle the architecture action
+    if args.architecture is not None:
+        for dev in devs:
+            if args.architecture in dev.architectures:
+                print(dev.name)
+        return
+
+    # Handle the package action
+    if args.package is not None:
+        for dev in devs:
+            if args.package in dev.packages:
+                print(dev.name)
+        return
+
+    # Handle the patches action
+    if len(args.patches) != 0:
+        (files, infras) = getdeveloperlib.analyze_patches(args.patches)
+        matching_devs = set()
+        for dev in devs:
+            # See if we have developers matching by package name
+            for f in files:
+                if dev.hasfile(f):
+                    matching_devs.add(dev.name)
+            # See if we have developers matching by package infra
+            for i in infras:
+                if i in dev.infras:
+                    matching_devs.add(dev.name)
+
+        result = "--to buildroot@buildroot.org"
+        for dev in matching_devs:
+            result += " --cc \"%s\"" % dev
+
+        if result != "":
+            print("git send-email %s" % result)
+
+__main__()
+
diff --git a/tools/getdeveloperlib.py b/tools/getdeveloperlib.py
new file mode 100644 (file)
index 0000000..6519107
--- /dev/null
@@ -0,0 +1,200 @@
+import sys
+import os
+import re
+import argparse
+import glob
+import subprocess
+
+#
+# Patch parsing functions
+#
+
+FIND_INFRA_IN_PATCH = re.compile("^\+\$\(eval \$\((host-)?([^-]*)-package\)\)$")
+
+def analyze_patch(patch):
+    """Parse one patch and return the list of files modified, added or
+    removed by the patch."""
+    files = set()
+    infras = set()
+    for line in patch:
+        # If the patch is adding a package, find which infra it is
+        m = FIND_INFRA_IN_PATCH.match(line)
+        if m:
+            infras.add(m.group(2))
+        if not line.startswith("+++ "):
+            continue
+        line.strip()
+        fname = line[line.find("/") + 1 : ].strip()
+        if fname == "dev/null":
+            continue
+        files.add(fname)
+    return (files, infras)
+
+FIND_INFRA_IN_MK = re.compile("^\$\(eval \$\((host-)?([^-]*)-package\)\)$")
+
+def fname_get_package_infra(fname):
+    """Checks whether the file name passed as argument is a Buildroot .mk
+    file describing a package, and find the infrastructure it's using."""
+    if not fname.endswith(".mk"):
+        return None
+
+    if not os.path.exists(fname):
+        return None
+
+    with open(fname, "r") as f:
+        for l in f:
+            l = l.strip()
+            m = FIND_INFRA_IN_MK.match(l)
+            if m:
+                return m.group(2)
+    return None
+
+def get_infras(files):
+    """Search in the list of files for .mk files, and collect the package
+    infrastructures used by those .mk files."""
+    infras = set()
+    for fname in files:
+        infra = fname_get_package_infra(fname)
+        if infra:
+            infras.add(infra)
+    return infras
+
+def analyze_patches(patches):
+    """Parse a list of patches and returns the list of files modified,
+    added or removed by the patches, as well as the list of package
+    infrastructures used by those patches (if any)"""
+    allfiles = set()
+    allinfras = set()
+    for patch in patches:
+        (files, infras) = analyze_patch(patch)
+        allfiles = allfiles | files
+        allinfras = allinfras | infras
+    allinfras = allinfras | get_infras(allfiles)
+    return (allfiles, allinfras)
+
+#
+# DEVELOPERS file parsing functions
+#
+
+class Developer:
+    def __init__(self, name, files):
+        self.name = name
+        self.files = files
+        self.packages = parse_developer_packages(files)
+        self.architectures = parse_developer_architectures(files)
+        self.infras = parse_developer_infras(files)
+
+    def hasfile(self, f):
+        f = os.path.abspath(f)
+        for fs in self.files:
+            if f.startswith(fs):
+                return True
+        return False
+
+def parse_developer_packages(fnames):
+    """Given a list of file patterns, travel through the Buildroot source
+    tree to find which packages are implemented by those file
+    patterns, and return a list of those packages."""
+    packages = set()
+    for fname in fnames:
+        for root, dirs, files in os.walk(fname):
+            for f in files:
+                path = os.path.join(root, f)
+                if fname_get_package_infra(path):
+                    pkg = os.path.splitext(f)[0]
+                    packages.add(pkg)
+    return packages
+
+def parse_arches_from_config_in(fname):
+    """Given a path to an arch/Config.in.* file, parse it to get the list
+    of BR2_ARCH values for this architecture."""
+    arches = set()
+    with open(fname, "r") as f:
+        parsing_arches = False
+        for l in f:
+            l = l.strip()
+            if l == "config BR2_ARCH":
+                parsing_arches = True
+                continue
+            if parsing_arches:
+                m = re.match("^\s*default \"([^\"]*)\".*", l)
+                if m:
+                    arches.add(m.group(1))
+                else:
+                    parsing_arches = False
+    return arches
+
+def parse_developer_architectures(fnames):
+    """Given a list of file names, find the ones starting by
+    'arch/Config.in.', and use that to determine the architecture a
+    developer is working on."""
+    arches = set()
+    for fname in fnames:
+        if not re.match("^.*/arch/Config\.in\..*$", fname):
+            continue
+        arches = arches | parse_arches_from_config_in(fname)
+    return arches
+
+def parse_developer_infras(fnames):
+    infras = set()
+    for fname in fnames:
+        m = re.match("^package/pkg-([^.]*).mk$", fname)
+        if m:
+            infras.add(m.group(1))
+    return infras
+
+def parse_developers(basepath=None):
+    """Parse the DEVELOPERS file and return a list of Developer objects."""
+    developers = []
+    linen = 0
+    if basepath == None:
+        basepath = os.getcwd()
+    with open(os.path.join(basepath, "DEVELOPERS"), "r") as f:
+        files = []
+        name = None
+        for l in f:
+            l = l.strip()
+            if l.startswith("#"):
+                continue
+            elif l.startswith("N:"):
+                if name is not None or len(files) != 0:
+                    print("Syntax error in DEVELOPERS file, line %d" % linen)
+                name = l[2:].strip()
+            elif l.startswith("F:"):
+                fname = l[2:].strip()
+                dev_files = glob.glob(os.path.join(basepath, fname))
+                if len(dev_files) == 0:
+                    print("WARNING: '%s' doesn't match any file" % fname)
+                files += dev_files
+            elif l == "":
+                if not name:
+                    continue
+                developers.append(Developer(name, files))
+                files = []
+                name = None
+            else:
+                print("Syntax error in DEVELOPERS file, line %d: '%s'" % (linen, l))
+                return None
+            linen += 1
+    # handle last developer
+    if name is not None:
+        developers.append(Developer(name, files))
+    return developers
+
+def check_developers(developers, basepath=None):
+    """Look at the list of files versioned in Buildroot, and returns the
+    list of files that are not handled by any developer"""
+    if basepath == None:
+        basepath = os.getcwd()
+    cmd = ["git", "--git-dir", os.path.join(basepath, ".git"), "ls-files"]
+    files = subprocess.check_output(cmd).strip().split("\n")
+    unhandled_files = []
+    for f in files:
+        handled = False
+        for d in developers:
+            if d.hasfile(os.path.join(basepath, f)):
+                handled = True
+                break
+        if not handled:
+            unhandled_files.append(f)
+    return unhandled_files
index 5b418dd41fc0fcc6b40a5856e9a39a828eb8b438..1439a0a99fa0ee4dc70dca66cdd314323d8933b2 100644 (file)
@@ -2,6 +2,11 @@ This directory contains various useful scripts and tools for working
 with Buildroot. You need not add this directory in your PATH to use
 any of those tools, but you may do so if you want.
 
+get-developpers
+    a script to return the list of people interested in a specific part
+    of Buildroot, so they can be Cc:ed on a mail. Accepts a patch as
+    input, a package name or and architecture name.
+
 test-pkg
     a script that tests a specific package against a set of various
     toolchains, with the goal to detect toolchain-related dependencies