lbkit 0.8.8__tar.gz → 0.8.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lbkit-0.8.8/lbkit.egg-info → lbkit-0.8.9}/PKG-INFO +1 -1
- lbkit-0.8.9/lbkit/__init__.py +2 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/cli.py +5 -1
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/task_download.py +1 -1
- lbkit-0.8.9/lbkit/ukr/build.py +202 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/utils/env_detector.py +15 -0
- {lbkit-0.8.8 → lbkit-0.8.9/lbkit.egg-info}/PKG-INFO +1 -1
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit.egg-info/SOURCES.txt +2 -0
- lbkit-0.8.9/test/__init__.py +0 -0
- lbkit-0.8.8/lbkit/__init__.py +0 -2
- {lbkit-0.8.8 → lbkit-0.8.9}/AUTHORS +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/LICENSE +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/MANIFEST.in +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/README.md +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/build_conan_parallel.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/ci_robot/__init__.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/ci_robot/gitee.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/__init__.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/codegen.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/ctype_defination.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/idf_interface.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/renderer.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/template/client.c.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/template/client.h.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/template/interface.c.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/template/interface.introspect.xml.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/template/public.c.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/template/public.h.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/template/server.c.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/codegen/template/server.h.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/component/__init__.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/component/arg_parser.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/component/build.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/component/template/conanbase.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/component/template/deploy.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/component/test.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/errors.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/helper.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/lbkit.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/log.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/misc.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/__init__.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/config.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/executor.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/image_maker/__init__.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/image_maker/make_image.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/image_maker/make_qemu_image.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/image_maker/make_rockchip_image.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/task.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/task_build_image.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/task_build_manifest.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/task_build_prepare.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/task_build_rootfs.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/template/conanfile.py.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tasks/template/rootfs.py.mako +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/tools.py +0 -0
- {lbkit-0.8.8/test → lbkit-0.8.9/lbkit/ukr}/__init__.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/utils/__init__.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/utils/images/__init__.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit/utils/images/emmc.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit.egg-info/dependency_links.txt +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit.egg-info/entry_points.txt +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit.egg-info/requires.txt +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/lbkit.egg-info/top_level.txt +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/setup.cfg +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/setup.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/test/test_codegen.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/test/test_config.py +0 -0
- {lbkit-0.8.8 → lbkit-0.8.9}/test/test_helper.py +0 -0
|
@@ -16,6 +16,7 @@ from lbkit.ci_robot.gitee import Gitee
|
|
|
16
16
|
from lbkit.log import Logger
|
|
17
17
|
from lbkit import misc
|
|
18
18
|
from lbkit import errors
|
|
19
|
+
from lbkit.ukr.build import UKRBuild
|
|
19
20
|
from lbkit.utils.env_detector import EnvDetector
|
|
20
21
|
|
|
21
22
|
log = Logger("cli")
|
|
@@ -78,7 +79,10 @@ class Command(object):
|
|
|
78
79
|
组件需要支持多种跨平台构建场景,典型的包括DT(X86-64)、交叉编译(arm64)
|
|
79
80
|
"""
|
|
80
81
|
env = EnvDetector()
|
|
81
|
-
if env.
|
|
82
|
+
if env.ukr:
|
|
83
|
+
ukr = UKRBuild(env)
|
|
84
|
+
ukr.run()
|
|
85
|
+
elif env.component:
|
|
82
86
|
os.chdir(env.component.folder)
|
|
83
87
|
print(os.getcwd())
|
|
84
88
|
arg_parser = ArgParser.new()
|
|
@@ -27,7 +27,7 @@ class DownloadTask():
|
|
|
27
27
|
self.dst = os.path.join(dst_dir, self.file)
|
|
28
28
|
self.dst = os.path.realpath(self.dst)
|
|
29
29
|
if not self.dst.startswith(dst_dir):
|
|
30
|
-
raise Exception("Download {self.file} failed because file contain relative paths")
|
|
30
|
+
raise Exception(f"Download {self.file} failed because file contain relative paths")
|
|
31
31
|
dir = os.path.dirname(self.dst)
|
|
32
32
|
if not os.path.isdir(dir):
|
|
33
33
|
os.makedirs(dir)
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"""组件构建"""
|
|
2
|
+
import os
|
|
3
|
+
import yaml
|
|
4
|
+
import shutil
|
|
5
|
+
import re
|
|
6
|
+
import json
|
|
7
|
+
import tempfile
|
|
8
|
+
from string import Template
|
|
9
|
+
from multiprocessing import Pool
|
|
10
|
+
import traceback
|
|
11
|
+
from argparse import ArgumentParser
|
|
12
|
+
from jsonschema import validate, ValidationError
|
|
13
|
+
from git import Repo
|
|
14
|
+
from git.exc import InvalidGitRepositoryError
|
|
15
|
+
from mako.lookup import TemplateLookup
|
|
16
|
+
from lbkit.misc import Color, load_yml_with_json_schema_validate, get_json_schema_file, load_json_schema
|
|
17
|
+
from lbkit import errors
|
|
18
|
+
from lbkit.codegen.codegen import CodeGen, history_versions
|
|
19
|
+
from lbkit.tools import Tools
|
|
20
|
+
from lbkit.build_conan_parallel import BuildConanParallel
|
|
21
|
+
from lbkit.codegen.codegen import Version
|
|
22
|
+
from lbkit.tasks.task_download import DownloadTask
|
|
23
|
+
from lbkit.misc import DownloadFlag
|
|
24
|
+
from lbkit.tools import Tools
|
|
25
|
+
from lbkit.utils.env_detector import EnvDetector
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
tools = Tools("comp_build")
|
|
29
|
+
log = tools.log
|
|
30
|
+
lb_cwd = os.path.split(os.path.realpath(__file__))[0]
|
|
31
|
+
|
|
32
|
+
class SourceDest():
|
|
33
|
+
def __init__(self, cfg):
|
|
34
|
+
self.source = cfg.get("source")
|
|
35
|
+
self.dest = cfg.get("dest")
|
|
36
|
+
|
|
37
|
+
def copy(self, source_dir, dest_dir, with_template, **kwargs):
|
|
38
|
+
source = os.path.join(source_dir, self.source)
|
|
39
|
+
dest = os.path.join(dest_dir, self.dest)
|
|
40
|
+
if os.path.isfile(dest):
|
|
41
|
+
os.unlink(dest)
|
|
42
|
+
dest_dir = os.path.dirname(dest)
|
|
43
|
+
if not os.path.isdir(dest_dir):
|
|
44
|
+
os.makedirs(dest_dir)
|
|
45
|
+
log.info(f"cp {source} to {dest}")
|
|
46
|
+
if with_template:
|
|
47
|
+
with open(source, "r") as fp:
|
|
48
|
+
template = Template(fp.read())
|
|
49
|
+
content = template.safe_substitute(kwargs)
|
|
50
|
+
with open(dest, "w+") as fp:
|
|
51
|
+
fp.write(content)
|
|
52
|
+
else:
|
|
53
|
+
shutil.copyfile(source, dest)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class BuildGeneral():
|
|
57
|
+
def __init__(self, config, cwd, cfg_key, dir_name):
|
|
58
|
+
self.cwd = cwd
|
|
59
|
+
self.name = cfg_key
|
|
60
|
+
self.work_dir = os.path.join(cwd, ".temp")
|
|
61
|
+
self.output = os.path.join(self.work_dir, "output")
|
|
62
|
+
if not os.path.isdir(self.output):
|
|
63
|
+
os.makedirs(self.output)
|
|
64
|
+
os.chdir(self.work_dir)
|
|
65
|
+
self.arch = config.get("base").get("arch")
|
|
66
|
+
self.cross_compile = config.get("base").get("cross_compile")
|
|
67
|
+
self.cfg = config.get(cfg_key)
|
|
68
|
+
self.dir_name = os.path.realpath(dir_name)
|
|
69
|
+
self.tools = Tools(self.dir_name + ".log")
|
|
70
|
+
|
|
71
|
+
def download(self):
|
|
72
|
+
tmp_file = self.dir_name + ".tar.gz"
|
|
73
|
+
url = self.cfg.get("url")
|
|
74
|
+
sha256 = self.cfg.get("sha256")
|
|
75
|
+
verify = self.cfg.get("verify", True)
|
|
76
|
+
strip_components = self.cfg.get("strip_components")
|
|
77
|
+
cfg = {
|
|
78
|
+
"url": url,
|
|
79
|
+
"file": tmp_file,
|
|
80
|
+
"decompress": {
|
|
81
|
+
"dirname": os.getcwd(),
|
|
82
|
+
"strip_components": strip_components
|
|
83
|
+
},
|
|
84
|
+
"sha256": sha256,
|
|
85
|
+
"verify": verify
|
|
86
|
+
}
|
|
87
|
+
task = DownloadTask(cfg, os.getcwd())
|
|
88
|
+
task.start()
|
|
89
|
+
_, sha = DownloadFlag.read(self.dir_name)
|
|
90
|
+
if sha == sha256:
|
|
91
|
+
return
|
|
92
|
+
cmd = f"tar -xf {task.dst} -C {self.dir_name}"
|
|
93
|
+
if task.strip_components:
|
|
94
|
+
cmd += f" --strip-components={task.strip_components}"
|
|
95
|
+
if os.path.isdir(self.dir_name):
|
|
96
|
+
shutil.rmtree(self.dir_name)
|
|
97
|
+
os.makedirs(self.dir_name)
|
|
98
|
+
self.tools.exec(cmd)
|
|
99
|
+
DownloadFlag.create(self.dir_name, url, sha256)
|
|
100
|
+
|
|
101
|
+
def prepare_defconfig(self):
|
|
102
|
+
defconf = self.cfg.get("defconfig")
|
|
103
|
+
compiler_path=os.path.join(self.work_dir, "toolchain")
|
|
104
|
+
sd = SourceDest(defconf)
|
|
105
|
+
sd.copy(self.cwd, os.path.join(self.work_dir, self.dir_name), True, compiler_path=compiler_path)
|
|
106
|
+
os.environ["ARCH"] = self.arch
|
|
107
|
+
os.environ["CROSS_COMPILE"] = self.cross_compile + "-"
|
|
108
|
+
path = os.environ.get("PATH", "")
|
|
109
|
+
if compiler_path not in path:
|
|
110
|
+
path += ":" + compiler_path + "/bin"
|
|
111
|
+
os.environ["PATH"] = path
|
|
112
|
+
self.defconfig = os.path.basename(sd.dest)
|
|
113
|
+
|
|
114
|
+
def build(self):
|
|
115
|
+
os.chdir(self.dir_name)
|
|
116
|
+
cmd = f"make {self.defconfig}"
|
|
117
|
+
self.tools.exec(cmd, verbose=True)
|
|
118
|
+
if self.name == "compiler":
|
|
119
|
+
cmd = f"make sdk -j" + str(os.cpu_count())
|
|
120
|
+
else:
|
|
121
|
+
cmd = f"make -j" + str(os.cpu_count())
|
|
122
|
+
self.tools.exec(cmd, verbose=True)
|
|
123
|
+
|
|
124
|
+
def tar_files(self):
|
|
125
|
+
os.chdir(self.dir_name)
|
|
126
|
+
cfgs = self.cfg.get("tar", [])
|
|
127
|
+
for cfg in cfgs:
|
|
128
|
+
sd = SourceDest(cfg)
|
|
129
|
+
src = os.path.join(self.dir_name, sd.source)
|
|
130
|
+
dst = os.path.join(self.dir_name, sd.dest)
|
|
131
|
+
cmd = f"tar -czf {dst} -C {src} ."
|
|
132
|
+
self.tools.exec(cmd)
|
|
133
|
+
|
|
134
|
+
def package(self):
|
|
135
|
+
os.chdir(self.dir_name)
|
|
136
|
+
cfgs = self.cfg.get("output", [])
|
|
137
|
+
for cfg in cfgs:
|
|
138
|
+
sd = SourceDest(cfg)
|
|
139
|
+
sd.copy(self.dir_name, self.output, False)
|
|
140
|
+
|
|
141
|
+
def run(self):
|
|
142
|
+
self.download()
|
|
143
|
+
self.prepare_defconfig()
|
|
144
|
+
self.build()
|
|
145
|
+
self.tar_files()
|
|
146
|
+
self.package()
|
|
147
|
+
os.chdir(self.cwd)
|
|
148
|
+
|
|
149
|
+
class BuildCompiler(BuildGeneral):
|
|
150
|
+
def __init__(self, config, cwd):
|
|
151
|
+
super().__init__(config, cwd, "compiler", "buildroot")
|
|
152
|
+
|
|
153
|
+
def package(self):
|
|
154
|
+
super().package()
|
|
155
|
+
cfgs = self.cfg.get("output", [])
|
|
156
|
+
for cfg in cfgs:
|
|
157
|
+
sd = SourceDest(cfg)
|
|
158
|
+
dest = os.path.join(self.output, sd.dest)
|
|
159
|
+
install_path = os.path.join(self.work_dir, "toolchain")
|
|
160
|
+
if os.path.isdir(install_path):
|
|
161
|
+
shutil.rmtree(install_path)
|
|
162
|
+
os.makedirs(install_path)
|
|
163
|
+
cmd = f"tar -xzf {dest} -C {install_path} --strip-components=1"
|
|
164
|
+
self.tools.exec(cmd)
|
|
165
|
+
|
|
166
|
+
class BuildRootfs(BuildGeneral):
|
|
167
|
+
def __init__(self, config, cwd):
|
|
168
|
+
super().__init__(config, cwd, "buildroot", "buildroot")
|
|
169
|
+
|
|
170
|
+
def build(self):
|
|
171
|
+
os.chdir(self.dir_name)
|
|
172
|
+
shutil.rmtree("output", ignore_errors=True)
|
|
173
|
+
return super().build()
|
|
174
|
+
|
|
175
|
+
class BuildLinux(BuildGeneral):
|
|
176
|
+
def __init__(self, config, cwd):
|
|
177
|
+
super().__init__(config, cwd, "linux", "linux")
|
|
178
|
+
|
|
179
|
+
class BuildUBoot(BuildGeneral):
|
|
180
|
+
def __init__(self, config, cwd):
|
|
181
|
+
super().__init__(config, cwd, "uboot", "uboot")
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class UKRBuild():
|
|
185
|
+
def __init__(self, env_detector: EnvDetector):
|
|
186
|
+
os.chdir(env_detector.ukr.folder)
|
|
187
|
+
self.env_detector = env_detector
|
|
188
|
+
|
|
189
|
+
def run(self):
|
|
190
|
+
cwd = os.getcwd()
|
|
191
|
+
with open("config.yml") as fp:
|
|
192
|
+
cfg = yaml.full_load(fp)
|
|
193
|
+
build = BuildCompiler(cfg, cwd)
|
|
194
|
+
build.run()
|
|
195
|
+
build = BuildRootfs(cfg, cwd)
|
|
196
|
+
build.run()
|
|
197
|
+
build = BuildLinux(cfg, cwd)
|
|
198
|
+
build.run()
|
|
199
|
+
build = BuildUBoot(cfg, cwd)
|
|
200
|
+
build.run()
|
|
201
|
+
cmd = f"tar -czf {cwd}/.temp/output/firmware.tar.gz -C {cwd}/.temp/output/images ."
|
|
202
|
+
tools.exec(cmd)
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import os
|
|
4
4
|
import configparser
|
|
5
5
|
from lbkit.tools import Tools
|
|
6
|
+
from lbkit.misc import load_yml_with_json_schema_validate
|
|
6
7
|
|
|
7
8
|
tools = Tools("EnvDetector")
|
|
8
9
|
log = tools.log
|
|
@@ -19,16 +20,30 @@ class LbkitManifest(object):
|
|
|
19
20
|
self.folder = os.path.realpath(folder)
|
|
20
21
|
self.config = config
|
|
21
22
|
|
|
23
|
+
class UKR(object):
|
|
24
|
+
def __init__(self, folder, config: configparser.ConfigParser):
|
|
25
|
+
self.folder = os.path.realpath(folder)
|
|
26
|
+
self.config = config
|
|
27
|
+
|
|
22
28
|
|
|
23
29
|
class EnvDetector(object):
|
|
24
30
|
def __init__(self):
|
|
25
31
|
"""初始化"""
|
|
26
32
|
self.component: LbkitComponent = None
|
|
27
33
|
self.manifest: LbkitManifest = None
|
|
34
|
+
self.ukr: UKR = None
|
|
28
35
|
self.cwd = os.getcwd()
|
|
29
36
|
"""探测环境"""
|
|
30
37
|
cwd = self.cwd
|
|
31
38
|
while cwd != "/":
|
|
39
|
+
conf_file = os.path.join(cwd, ".lbkit.yml")
|
|
40
|
+
if os.path.isfile(conf_file):
|
|
41
|
+
conf = load_yml_with_json_schema_validate(conf_file, "/usr/share/litebmc/schema/lbk_config.v1.json")
|
|
42
|
+
ukr_conf = conf.get("uboot_kernel_rootfs")
|
|
43
|
+
if ukr_conf:
|
|
44
|
+
folder = ukr_conf.get("folder")
|
|
45
|
+
self.ukr = UKR(os.path.join(cwd, folder), ukr_conf)
|
|
46
|
+
return
|
|
32
47
|
if os.path.isfile(os.path.join(cwd, "manifest.yml")):
|
|
33
48
|
self.manifest = LbkitManifest(cwd, None)
|
|
34
49
|
return
|
|
@@ -54,6 +54,8 @@ lbkit/tasks/image_maker/make_qemu_image.py
|
|
|
54
54
|
lbkit/tasks/image_maker/make_rockchip_image.py
|
|
55
55
|
lbkit/tasks/template/conanfile.py.mako
|
|
56
56
|
lbkit/tasks/template/rootfs.py.mako
|
|
57
|
+
lbkit/ukr/__init__.py
|
|
58
|
+
lbkit/ukr/build.py
|
|
57
59
|
lbkit/utils/__init__.py
|
|
58
60
|
lbkit/utils/env_detector.py
|
|
59
61
|
lbkit/utils/images/__init__.py
|
|
File without changes
|
lbkit-0.8.8/lbkit/__init__.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|