summaryrefslogtreecommitdiffstats
path: root/scripts/gerrit/Build_ref_cleaner/Build_ref_cleaner.py
blob: e1da6bb069a4d8f16c2a427482862c4420d3ad81 (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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Copyright (C) 2023-2025 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

import subprocess
import time
import datetime
import os
# Sleep time after every 1000 build refs (in seconds)
_sleeptime = 1
# Determine how many months worth of refs should be kept
_months = 3
# List of folders which subfolders need cleaning of build refs
"""_
clean_these = ["../test", "../git_testrepo"] # Test
"""
_clean_these = ["installer-framework",
                "pyside",
                "qt",
                "qt-apps",
                "qt-extensions",
                "qt-labs",
                "qt3dstudio",
                "qtqa",
                "qtsdk",
                "tqtc-boot2qt",
                "yocto",
                "license-tools",
                ]

def run_git_command(command, path_to_folder = None, splitter = "", index = 1, return_output = True):
    """
    Runs git commands in python as a subprocess
    Returns the output of the git command as a list of the lines it produces

    Parameters

    command (list): git command without the word git
    for example if you want to run "git status" give "status" as the parameter
    splitter (str): choose a string used for splitting lines (default = "")
    index (int): choose the index of the split line you want to save (default = 1)
    """
    full_command = ["git"] + command

    result = subprocess.run(full_command, cwd=path_to_folder, capture_output=True)
    temp = result.stdout
    if (return_output):
        stdout = temp.decode('utf-8')
        output_lines = stdout.splitlines()
        output_list = []
        for line in output_lines:
            if "refs/builds/" in line:
                output_list.append(line.split(splitter)[index])
        return output_list
    return 0

def get_git_folders(root_folder):
    print("checking {}".format(root_folder))
    git_dirs = []

    for (dirpath, subdirs, _) in os.walk(root_folder):
        for dir in subdirs:
            full_path = os.path.join(dirpath, dir)
            if dir.endswith(".git"):
                git_dirs.append(full_path)

    return git_dirs

def remove_old_builds(path_for_command, months_old, splitter):
    """
    This function removes all the builds in path (in git_command after ls-remove)
    that are older than {months_old} months and also those builds which do not
    correspond to the naming scheme (files should be named with the count in seconds
    from 1.1.1970 to the date the file was created)
    All files which name corresponds to a time in the future will also be removed.

    Parameters

    path_for_command (str): path which specifies the execution location for the git command

    months_old (int): number of months the which determines
        how old the oldest files to keep should be

    splitter (str): used for splitting the output of ls-remote
        into the sha1 and path inside the run_git_command function
    """
    not_deleted = []
    deleted = ""
    filePaths = run_git_command(["show-ref"], path_for_command, splitter)
    reference_age = int(time.time()) - int(60*60*24*30*months_old)
    timestamp = datetime.datetime.fromtimestamp(time.time()).strftime('%Y/%m/%d %H:%M:%S')
    print(timestamp + " Deleting old builds from " + path_for_command + " older than " +
           str(reference_age) + " seconds " + "(" + str(months_old) + " months)")

    for i, filePath in enumerate(filePaths):
        # Report the percentage of refs covered and which refs were removed
        # in the current repo after every 1000 refs
        if i % 1000 == 0:
            print(deleted)
            print("{} complete".format(str(round(i/float(len(filePaths))*100.0, 2)) + "%"))
            time.sleep(_sleeptime)
            deleted = ""
        # Extract the ref name from the filePath variable
        _, file = filePath.rsplit("/", 1)
        # Determine if the ref name is valid and if the ref should be deleted or not
        if file.isdigit() and (int(file) < reference_age or
                               int(file) > int(time.time()) + int(60*60*24*30*months_old)):
            run_git_command(["update-ref", "-d", filePath], path_for_command, return_output=False)
            deleted += filePath + " removed\n"
        elif file.isdigit() and (int(file) > reference_age):
            not_deleted.append(filePath)
        else:
            run_git_command(["update-ref", "-d", filePath], path_for_command, return_output=False)
            deleted += filePath + " removed\n"
    print(deleted)
    print("100%" + "complete")
    timestamp = datetime.datetime.fromtimestamp(time.time()).strftime('%Y/%m/%d %H:%M:%S')
    print(timestamp + " Old builds deleted")
    return not_deleted

def main():
    for folder in _clean_these:
        if ".git" in folder:
            print("Removing old build refs from " + folder)
            remove_old_builds(folder, _months, " ")
        else:
            git_folders = get_git_folders(folder)
            for git_folder in git_folders:
                print("Removing old build refs from " + git_folder)
                remove_old_builds(git_folder, _months, " ")
    return 0

if __name__ == "__main__":
    main()