1#!/usr/bin/env python
2
3r"""
4Create index files that can be displayed as web pages in a given directory
5and all its sub-directories. There are options to exclude certain files and
6sub-directories.
7"""
8
9import argparse
10import os
11import sys
12
13
14def main(i_raw_args):
15    l_args = parse_args(i_raw_args)
16    create_index_file(l_args.logs_dir_path, "/", l_args.exclude)
17
18
19def create_index_file(i_dir_path, i_pretty_dir_path, i_exclude_list):
20    r"""
21    Create HTML index files for a given directory and all its sub-directories.
22
23    Description of argument(s):
24    i_dir_path          The directory to generate an index file for.
25    i_pretty_dir_path   A pretty version of i_dir_path that can be shown to
26                        readers of the HTML page. For example, if i_dir_path
27                        is set to '/home/johndoe/logs/`, the caller may wish
28                        to only show '/logs/' in the HTML index pages.
29    i_exclude_list      A Python list of files and directories to exclude from
30    """
31
32    l_index_file_path = os.path.join(i_dir_path, "index.html")
33    l_sub_dir_list = os.listdir(i_dir_path)
34
35    # Created a sorted list of sub-directories in this directory
36    l_dirs = sorted(
37        [
38            d
39            for d in l_sub_dir_list
40            if os.path.isdir(os.path.join(i_dir_path, d))
41            and d not in i_exclude_list
42        ]
43    )
44
45    # Create a sorted list of files in this directory
46    l_files = sorted(
47        [
48            f
49            for f in l_sub_dir_list
50            if not os.path.isdir(os.path.join(i_dir_path, f))
51            and f not in i_exclude_list
52        ]
53    )
54
55    # Open up the index file we're going to write to.
56    with open(l_index_file_path, "w+") as l_index_file:
57        l_index_file.write(
58            "<html>\n<head><title>"
59            + i_pretty_dir_path
60            + "</title></head>\n<body>\n<h2>OpenBMC Logs</h2>\n<h3>"
61            + i_pretty_dir_path
62            + "</h3>\n"
63        )
64
65        # Only show the link to go up a directory if this is not the root.
66        if not i_pretty_dir_path == "/":
67            l_index_file.write(
68                '<a href=".."><img src="/dir.png"> ..</a><br>\n'
69            )
70
71        # List directories first.
72        for l_dir in l_dirs:
73            l_index_file.write(
74                '<a href="%s"><img src="/dir.png"> %s</a><br>\n'
75                % (l_dir, l_dir)
76            )
77            create_index_file(
78                os.path.join(i_dir_path, l_dir),
79                i_pretty_dir_path + l_dir + "/",
80                i_exclude_list,
81            )
82
83        # List files second.
84        for l_file in l_files:
85            l_index_file.write(
86                '<a href="%s"><img src="/file.png"> %s</a><br>\n'
87                % (l_file, l_file)
88            )
89
90        l_index_file.write("</body>\n</html>")
91
92
93def parse_args(i_raw_args):
94    r"""
95    Parse the given list as command-line arguments and return an object with
96    the argument values.
97
98    Description of argument(s):
99    i_raw_args  A list of command-line arguments, usually taken from
100                sys.argv[1:].
101    """
102
103    parser = argparse.ArgumentParser(
104        description=(
105            "%(prog)s will create index files that can be displayed "
106            "as web pages in a given directory and all its "
107            "sub-directories."
108        ),
109        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
110    )
111    parser.add_argument(
112        "logs_dir_path",
113        help="Directory containing the logs that should be uploaded.",
114    )
115    parser.add_argument(
116        "--exclude",
117        nargs="+",
118        default=[".git", "index.html"],
119        help="A space-delimited list of files to exclude from the index.",
120    )
121    return parser.parse_args(i_raw_args)
122
123
124if __name__ == "__main__":
125    main(sys.argv[1:])
126