aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/patchmetrics-update
blob: 2fa7e4a526458d0c2375a794754030f572c107d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#!/usr/bin/env python3

import json
import pathlib
import argparse
import subprocess
import tempfile
import sys

# Given a git repository and a base to search for layers (either a layer
# directly, or a directory containing layers), run the patchscript and update
# the specified JSON file.

args = argparse.ArgumentParser(description="Update Patch Metrics")
args.add_argument("-j", "--json", required=True, type=pathlib.Path, help="update specified JSON file")
args.add_argument("-s", "--patchscript", required=True, type=pathlib.Path, help="patchreview script to run")
args.add_argument("-r", "--repo", required=True, type=pathlib.Path, help="repository to use (e.g. path/to/poky)")
args.add_argument("-l", "--layer", type=pathlib.Path, help="layer/repository to scan")
args = args.parse_args()

if not args.repo.is_dir():
    print(f"{args.repo} is not a directory")
    sys.exit(1)

if not args.layer.is_dir():
    print(f"{args.layer} is not a directory")
    sys.exit(1)

if not args.patchscript.is_file():
    print(f"{args.patchscript} is not a file")


print("Running patchmetrics-update")

if "meta-openembedded" in args.layer.name:
    # 2023-01-01, arbitarily chosen
    epoch = "1672531200"
else:
    # 2011-04-25, Yocto 1.0 release.
    epoch = "1301074853"

with tempfile.TemporaryDirectory(prefix="patchmetrics-") as tempname:
    tempdir = pathlib.Path(tempname)
    layerdir = tempdir / args.layer.relative_to(args.repo)

    # Create a temporary clone of the repository as we'll be checking out different revisions
    print(f"Making a temporary clone of {args.repo} to {tempdir}")
    subprocess.check_call(["git", "clone", "--quiet", args.repo, tempdir])

    # Identify what revisions need to be analysed. If we reverse the list, keep
    # order, and remove in-place, then iterating through a large number of
    # commits is faster.
    repo_revisions = subprocess.check_output(["git", "rev-list", "--reverse", "--since", epoch, "origin/master"], universal_newlines=True, cwd=tempdir).strip().split()
    revision_count = len(repo_revisions)

    if args.json.exists():
        with open(args.json) as f:
            data = json.load(f)

        seen = set()
        for i in data:
            try:
                repo_revisions.remove(i["commit"])
            except ValueError:
                pass

    new_count = len(repo_revisions)
    print("Found %s, need to scan %d revisions:\n%s" % (revision_count - new_count, new_count, str(repo_revisions)))

    # Run the patchreview script for every revision
    for rev in repo_revisions:
        print("Processing %s" % rev)
        subprocess.check_call(["git", "checkout", "--detach", rev], cwd=tempdir)
        subprocess.check_call([args.patchscript, "--json", args.json, layerdir])

print("Finished patchmetrics-update")