File size: 1,850 Bytes
60a5d0b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
scanner.py
Project scanning
"""

from __future__ import annotations

from pathlib import Path

from filters import (
    is_probably_binary,
    should_ignore_dir,
    should_ignore_file,
)


def scan_files(
    root: Path,
    extra_ignore_dirs: set[str],
    max_size_mb: float,
    allowed_extensions: set[str] | None,
) -> list[Path]:
    """
    Scan project recursively.
    """

    files = []

    max_bytes = int(max_size_mb * 1024 * 1024)

    for path in root.rglob("*"):

        if path.is_dir():
            continue

        rel_parts = path.relative_to(root).parts[:-1]

        if any(
            should_ignore_dir(
                part,
                extra_ignore_dirs,
            )
            for part in rel_parts
        ):
            continue

        if should_ignore_file(
            path,
            allowed_extensions,
        ):
            continue

        try:

            if path.stat().st_size > max_bytes:
                continue

        except OSError:
            continue

        if is_probably_binary(path):
            continue

        files.append(path)

    files.sort(
        key=lambda p: p.relative_to(root).as_posix()
    )

    return files


def build_tree_text(
    root: Path,
    files: list[Path],
) -> str:
    """
    Render project tree.
    """

    if not files:
        return "(No files found)"

    lines = []

    for file in files:

        rel = file.relative_to(root)

        indent = "    " * (len(rel.parts) - 1)

        lines.append(
            f"{indent}├── {rel.name}"
        )

    return "\n".join(lines)


def total_project_size(
    files: list[Path],
) -> int:
    """
    Sum file sizes.
    """

    total = 0

    for file in files:

        try:
            total += file.stat().st_size

        except OSError:
            pass

    return total