File size: 4,931 Bytes
76684fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env python3

import importlib.metadata
import re
import os

# 解析包的版本规范
def parse_package_spec(spec):
    """
    解析包名和版本规范。
    返回 (name, operator, version)。
    """
    match = re.match(r'^([^=<>!~]+)\s*([=<>!~]+)\s*(.+)$', spec)
    if match:
        name, op, version = match.groups()
        return name.strip(), op.strip(), version.strip()
    else:
        return spec.strip(), None, None

# 获取已安装包的版本
def get_installed_versions(packages):
    installed_versions = {}
    for pkg in packages:
        name, _, _ = parse_package_spec(pkg)
        try:
            installed_version = importlib.metadata.version(name)
            installed_versions[name] = installed_version
        except importlib.metadata.PackageNotFoundError:
            print(f"包 {name} 未安装。")
            continue
    return installed_versions

# 读取现有的 requirements.txt
def read_requirements(file_path='requirements.txt'):
    req_versions = {}
    if os.path.exists(file_path):
        with open(file_path, 'r') as f:
            for line in f:
                line = line.strip()
                if not line or line.startswith('#'):
                    continue
                name, op, version_spec = parse_package_spec(line)
                if op and version_spec:
                    req_versions[name] = f"{op}{version_spec}"
                else:
                    req_versions[name] = None  # 未指定版本
    return req_versions

# 合并包信息
def merge_requirements(installed_versions, req_versions):
    merged_requirements = []
    conflict_detected = False
    processed_packages = set()

    for name, installed_version in installed_versions.items():
        if name in req_versions:
            req_version_spec = req_versions[name]
            if req_version_spec:
                # 检查版本是否匹配
                version_match = False
                # 支持多种版本操作符
                ops = ['==', '>=', '<=', '>', '<', '!=', '~=']
                for op in ops:
                    if req_version_spec.startswith(op):
                        req_op = op
                        req_ver = req_version_spec[len(op):]
                        break
                else:
                    req_op = None
                    req_ver = None

                if req_op == '==':
                    if req_ver == installed_version:
                        merged_requirements.append(f"{name}=={installed_version}")
                    else:
                        # 版本冲突
                        merged_requirements.append(f"<<<<<<< HEAD")
                        merged_requirements.append(f"{name}{req_version_spec}")
                        merged_requirements.append(f"=======")
                        merged_requirements.append(f"{name}=={installed_version}")
                        merged_requirements.append(f">>>>>>> Merged version")
                        conflict_detected = True
                else:
                    # 如果 requirements.txt 中有版本规范但不是 '=='
                    # 可以根据需要调整此逻辑
                    # 这里假设只在 '==' 时进行严格匹配
                    # 其他情况下认为没有冲突
                    merged_requirements.append(f"{name}{req_version_spec}")
            else:
                # requirements.txt 未指定版本,直接覆盖为已安装版本
                merged_requirements.append(f"{name}=={installed_version}")
            processed_packages.add(name)
        else:
            # 包不在 requirements.txt 中,添加已安装版本
            merged_requirements.append(f"{name}=={installed_version}")
            processed_packages.add(name)

    # 添加 requirements.txt 中未处理的包
    for name, version_spec in req_versions.items():
        if name not in processed_packages:
            if version_spec:
                merged_requirements.append(f"{name}{version_spec}")
            else:
                merged_requirements.append(f"{name}")

    return merged_requirements, conflict_detected

def main():
    # 读取现有的 requirements.txt 获取包列表
    req_versions = read_requirements('requirements.txt')
    packages = list(req_versions.keys())

    # 获取已安装包的版本
    installed_versions = get_installed_versions(packages)

    # 合并包信息
    merged_requirements, conflict_detected = merge_requirements(installed_versions, req_versions)

    # 将合并结果写回 requirements.txt
    with open('requirements.txt', 'w') as f:
        for line in merged_requirements:
            f.write(line + '\n')

    if conflict_detected:
        print("requirements.txt 已更新,存在版本冲突。请手动解决冲突标记。")
    else:
        print("requirements.txt 已更新,无版本冲突。")

if __name__ == "__main__":
    main()