lbkit 0.9.12__tar.gz → 0.9.14__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.9.12/lbkit.egg-info → lbkit-0.9.14}/PKG-INFO +7 -1
- lbkit-0.9.14/lbkit/__commit__.py +1 -0
- lbkit-0.9.14/lbkit/__init__.py +2 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/cli.py +66 -23
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/template/public.c.mako +3 -4
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/component/arg_parser.py +2 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/component/build.py +3 -1
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/component/template/conanbase.mako +18 -10
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/component/template/deploy.mako +2 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/component/test.py +11 -2
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/misc.py +28 -17
- lbkit-0.9.14/lbkit/upgrade.py +326 -0
- {lbkit-0.9.12 → lbkit-0.9.14/lbkit.egg-info}/PKG-INFO +7 -1
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit.egg-info/SOURCES.txt +1 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit.egg-info/requires.txt +6 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/setup.py +26 -5
- lbkit-0.9.12/lbkit/__commit__.py +0 -1
- lbkit-0.9.12/lbkit/__init__.py +0 -2
- {lbkit-0.9.12 → lbkit-0.9.14}/AUTHORS +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/MANIFEST.in +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/README.md +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/build_conan_parallel.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/ci_robot/__init__.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/.clang-format +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/__init__.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/codegen.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/ctype_defination.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/idf_interface.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/renderer.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/template/client.c.mako +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/template/client.h.mako +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/template/interface.introspect.xml.mako +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/template/public.h.mako +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/template/server.c.mako +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/codegen/template/server.h.mako +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/component/__init__.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/download_cache.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/errors.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/helper.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/lbkit.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/log.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/skill/__init__.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/skill/constants.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/skill/manager.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/__init__.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/config.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/executor.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/image_maker/__init__.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/image_maker/make_image.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/image_maker/make_qemu_image.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/image_maker/make_rockchip_image.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/task.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/task_build_image.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/task_build_manifest.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/task_build_prepare.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/task_build_rootfs.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/task_download.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/template/conanfile.py.mako +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tasks/template/rootfs.py.mako +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/tools.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/ukr/__init__.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/ukr/build.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/utils/__init__.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/utils/env_detector.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/utils/fakeroot.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/utils/images/__init__.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit/utils/images/emmc.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit.egg-info/dependency_links.txt +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit.egg-info/entry_points.txt +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/lbkit.egg-info/top_level.txt +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/setup.cfg +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/test/__init__.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/test/test_codegen.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/test/test_config.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/test/test_helper.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/test/test_permission.py +0 -0
- {lbkit-0.9.12 → lbkit-0.9.14}/test/test_skill.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lbkit
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.14
|
|
4
4
|
Summary: Tools provided by litebmc.com
|
|
5
5
|
Home-page: https://www.litebmc.com
|
|
6
6
|
Author: xuhj@litebmc.com
|
|
@@ -22,6 +22,12 @@ Requires-Dist: inflection
|
|
|
22
22
|
Requires-Dist: meson>=1.4.0
|
|
23
23
|
Requires-Dist: psutil
|
|
24
24
|
Requires-Dist: loguru
|
|
25
|
+
Requires-Dist: pre-commit
|
|
26
|
+
Requires-Dist: black
|
|
27
|
+
Requires-Dist: isort
|
|
28
|
+
Requires-Dist: flake8
|
|
29
|
+
Requires-Dist: flake8-bugbear
|
|
30
|
+
Requires-Dist: flake8-comprehensions
|
|
25
31
|
Dynamic: author
|
|
26
32
|
Dynamic: author-email
|
|
27
33
|
Dynamic: classifier
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__commit__ = '7fd1830'
|
|
@@ -5,46 +5,60 @@
|
|
|
5
5
|
# Free Software Foundation; either version 3 of the License, or (at your
|
|
6
6
|
# option) any later version.
|
|
7
7
|
"""lbkit命令行入口"""
|
|
8
|
+
import argparse
|
|
8
9
|
import inspect
|
|
9
10
|
import os
|
|
10
11
|
import signal
|
|
11
12
|
import sys
|
|
12
|
-
import argparse
|
|
13
13
|
import traceback
|
|
14
|
+
|
|
14
15
|
from lbkit import __version__ as client_version
|
|
16
|
+
|
|
15
17
|
try:
|
|
16
18
|
from lbkit.__commit__ import __commit__ as client_commit
|
|
17
19
|
except ImportError:
|
|
18
20
|
client_commit = ""
|
|
21
|
+
from lbkit import errors, misc
|
|
19
22
|
from lbkit.codegen.codegen import CodeGen
|
|
23
|
+
from lbkit.component.arg_parser import ArgParser
|
|
20
24
|
from lbkit.component.build import BuildComponent
|
|
21
25
|
from lbkit.component.test import TestComponent
|
|
22
|
-
from lbkit.tasks.executor import Executor
|
|
23
|
-
from lbkit.component.arg_parser import ArgParser
|
|
24
26
|
from lbkit.log import Logger
|
|
25
|
-
from lbkit import
|
|
26
|
-
from lbkit import
|
|
27
|
+
from lbkit.skill.manager import sync as skill_sync
|
|
28
|
+
from lbkit.tasks.executor import Executor
|
|
27
29
|
from lbkit.ukr.build import UKRBuild
|
|
30
|
+
from lbkit.upgrade import upgrade as do_upgrade
|
|
28
31
|
from lbkit.utils.env_detector import EnvDetector
|
|
29
|
-
from lbkit.skill.manager import sync as skill_sync
|
|
30
32
|
|
|
31
33
|
log = Logger()
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
def ask_user_yes_no(prompt):
|
|
37
|
+
"""向用户询问是/否问题"""
|
|
38
|
+
while True:
|
|
39
|
+
answer = input(f"{prompt} [y/N]: ").strip().lower()
|
|
40
|
+
if answer in ("y", "yes"):
|
|
41
|
+
return True
|
|
42
|
+
if answer in ("n", "no", ""):
|
|
43
|
+
return False
|
|
44
|
+
print("请输入 y 或 n")
|
|
45
|
+
|
|
46
|
+
|
|
34
47
|
class Command(object):
|
|
35
48
|
"""A single command of the lbkit application, with all the first level commands. Manages the
|
|
36
49
|
parsing of parameters and delegates functionality in collaborators. It can also show the
|
|
37
50
|
help of the tool.
|
|
38
51
|
"""
|
|
52
|
+
|
|
39
53
|
def __init__(self):
|
|
40
54
|
pass
|
|
55
|
+
|
|
41
56
|
def help(self, *args):
|
|
42
57
|
"""
|
|
43
58
|
Shows help for a specific command.
|
|
44
59
|
"""
|
|
45
60
|
|
|
46
|
-
parser = argparse.ArgumentParser(description=self.help.__doc__,
|
|
47
|
-
prog="lbkit help")
|
|
61
|
+
parser = argparse.ArgumentParser(description=self.help.__doc__, prog="lbkit help")
|
|
48
62
|
parser.add_argument("command", help='command', nargs="?")
|
|
49
63
|
args = parser.parse_args(*args)
|
|
50
64
|
if not args.command:
|
|
@@ -115,16 +129,44 @@ class Command(object):
|
|
|
115
129
|
"""
|
|
116
130
|
skill_sync()
|
|
117
131
|
|
|
132
|
+
def upgrade(self, *args):
|
|
133
|
+
"""
|
|
134
|
+
自升级lbkit.
|
|
135
|
+
|
|
136
|
+
通过apt/dnf升级系统包并安装配套的PyPI包
|
|
137
|
+
"""
|
|
138
|
+
do_upgrade(*args)
|
|
139
|
+
|
|
140
|
+
def hooks_path(self, *args):
|
|
141
|
+
"""
|
|
142
|
+
输出 pre-commit hooks 安装路径.
|
|
143
|
+
|
|
144
|
+
供 CI/脚本使用,输出 hooks 目录的绝对路径
|
|
145
|
+
"""
|
|
146
|
+
import os
|
|
147
|
+
|
|
148
|
+
hooks_dir = misc.HOOKS_DIR
|
|
149
|
+
if not os.path.isdir(hooks_dir):
|
|
150
|
+
# fallback: 查找源码树内的 hooks
|
|
151
|
+
import lbkit
|
|
152
|
+
|
|
153
|
+
pkg_dir = os.path.dirname(os.path.dirname(os.path.abspath(lbkit.__file__)))
|
|
154
|
+
candidate = os.path.join(pkg_dir, "pre-commit-hooks")
|
|
155
|
+
if os.path.isdir(candidate):
|
|
156
|
+
hooks_dir = candidate
|
|
157
|
+
print(hooks_dir)
|
|
158
|
+
|
|
118
159
|
def _show_help(self):
|
|
119
160
|
"""
|
|
120
161
|
Prints a summary of all commands.
|
|
121
162
|
"""
|
|
122
|
-
grps = [
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
163
|
+
grps = [
|
|
164
|
+
("Code Generate commands", ["gen"]),
|
|
165
|
+
("Build Component commands", ["build", "test"]),
|
|
166
|
+
("Build Product commands", ["build"]),
|
|
167
|
+
("AI Skill commands", ["skill"]),
|
|
168
|
+
("Misc commands", ["upgrade", "hooks_path", "help"]),
|
|
169
|
+
]
|
|
128
170
|
|
|
129
171
|
def check_all_commands_listed():
|
|
130
172
|
"""Keep updated the main directory, raise if don't"""
|
|
@@ -143,9 +185,9 @@ class Command(object):
|
|
|
143
185
|
print(group_name + ":")
|
|
144
186
|
for name in comm_names:
|
|
145
187
|
# future-proof way to ensure tabular formatting
|
|
146
|
-
output =
|
|
188
|
+
output = fmt % (misc.Color.GREEN + name + misc.Color.RESET_ALL)
|
|
147
189
|
if len(output) < 32:
|
|
148
|
-
space = " "*(32 - len(output))
|
|
190
|
+
space = " " * (32 - len(output))
|
|
149
191
|
output += space
|
|
150
192
|
|
|
151
193
|
# Help will be all the lines up to the first empty one
|
|
@@ -162,15 +204,15 @@ class Command(object):
|
|
|
162
204
|
data.append(line)
|
|
163
205
|
|
|
164
206
|
import textwrap
|
|
165
|
-
|
|
207
|
+
|
|
208
|
+
output += textwrap.fill(' '.join(data), 80, subsequent_indent=" " * (max_len + 2))
|
|
166
209
|
print(output)
|
|
167
210
|
|
|
168
211
|
print("")
|
|
169
212
|
print('LiteBmcKit commands. Type "litebmc <command> -h" for help')
|
|
170
213
|
|
|
171
214
|
def _commands(self):
|
|
172
|
-
"""
|
|
173
|
-
"""
|
|
215
|
+
"""Returns a list of available commands."""
|
|
174
216
|
result = {}
|
|
175
217
|
for m in inspect.getmembers(self, predicate=inspect.ismethod):
|
|
176
218
|
method_name = m[0]
|
|
@@ -181,13 +223,13 @@ class Command(object):
|
|
|
181
223
|
return result
|
|
182
224
|
|
|
183
225
|
def _warn_python_version(self):
|
|
184
|
-
import textwrap
|
|
185
|
-
|
|
186
226
|
width = 70
|
|
187
227
|
version = sys.version_info
|
|
188
228
|
if version.major < 3:
|
|
189
|
-
log.info(
|
|
190
|
-
|
|
229
|
+
log.info(
|
|
230
|
+
"*" * width + "\nPython 2 support has been dropped. It is strongly "
|
|
231
|
+
"recommended to use Python >= 3.0\n" + "*" * width
|
|
232
|
+
)
|
|
191
233
|
|
|
192
234
|
def run(self, *args):
|
|
193
235
|
"""HIDDEN: entry point for executing commands, dispatcher to class
|
|
@@ -248,6 +290,7 @@ def main(args):
|
|
|
248
290
|
# 使能revision功能
|
|
249
291
|
os.environ["CONAN_REVISIONS_ENABLED"] = "1"
|
|
250
292
|
os.makedirs(misc.LOG_DIR, exist_ok=True)
|
|
293
|
+
|
|
251
294
|
def ctrl_c_handler(_, __):
|
|
252
295
|
sys.exit(-3)
|
|
253
296
|
|
|
@@ -434,7 +434,7 @@ ${name} ${name}_decode(GVariant *in)
|
|
|
434
434
|
}
|
|
435
435
|
|
|
436
436
|
const gchar *in_val = g_variant_get_string(in, NULL);
|
|
437
|
-
for (int i = 0; i
|
|
437
|
+
for (int i = 0; i < (int)G_N_ELEMENTS(_${name}StrMap); i++) {
|
|
438
438
|
if (g_strcmp0(in_val, _${name}StrMap[i]) == 0) {
|
|
439
439
|
return (${name})i;
|
|
440
440
|
}
|
|
@@ -494,7 +494,7 @@ gboolean ${name}_validate_odf(yaml_document_t *doc, yaml_node_t *node,
|
|
|
494
494
|
return FALSE;
|
|
495
495
|
}
|
|
496
496
|
const gchar *value = (const gchar *)node->data.scalar.value;
|
|
497
|
-
for (int i = 0; i
|
|
497
|
+
for (int i = 0; i < ${len(enum.values.parameters)}; i++) {
|
|
498
498
|
if (g_strcmp0(value, ${name}_as_string(i)) == 0) {
|
|
499
499
|
return TRUE;
|
|
500
500
|
}
|
|
@@ -502,7 +502,6 @@ gboolean ${name}_validate_odf(yaml_document_t *doc, yaml_node_t *node,
|
|
|
502
502
|
*error_list = g_slist_append(*error_list, g_error_new(ODF_ERROR, ODF_ERROR_PROP_VALIDATE_TYPE_ERROR,
|
|
503
503
|
"the value of property %s is invalid, get %s", prop->str, value));
|
|
504
504
|
return FALSE;
|
|
505
|
-
return FALSE;
|
|
506
505
|
}
|
|
507
506
|
|
|
508
507
|
gboolean ${name}_validate_odf_v(yaml_document_t *doc, yaml_node_t *node,
|
|
@@ -1702,7 +1701,7 @@ ${name} ${name}_load_from_odf(yaml_document_t *doc, yaml_node_t *node)
|
|
|
1702
1701
|
return _${name}_Invalid;
|
|
1703
1702
|
}
|
|
1704
1703
|
|
|
1705
|
-
for (int i = 0; i
|
|
1704
|
+
for (int i = 0; i < (int)G_N_ELEMENTS(_${name}StrMap); i++) {
|
|
1706
1705
|
if (g_strcmp0((const gchar *)node->data.scalar.value, ${name}_as_string(i)) == 0) {
|
|
1707
1706
|
return (${name})i;
|
|
1708
1707
|
}
|
|
@@ -37,6 +37,8 @@ class ArgParser():
|
|
|
37
37
|
help=argparse.SUPPRESS)
|
|
38
38
|
parser.add_argument("--cov", action="store_true",
|
|
39
39
|
help=argparse.SUPPRESS)
|
|
40
|
+
parser.add_argument("--asan", action="store_true",
|
|
41
|
+
help=argparse.SUPPRESS)
|
|
40
42
|
parser.add_argument("--test", action="store_true",
|
|
41
43
|
help=argparse.SUPPRESS)
|
|
42
44
|
parser.add_argument(
|
|
@@ -100,6 +100,8 @@ class BuildComponent():
|
|
|
100
100
|
self.base_cmd += f" -pr:b {self.profile_build}"
|
|
101
101
|
if self.options.cov:
|
|
102
102
|
self.base_cmd += f" -o {self.name}/*:gcov=True"
|
|
103
|
+
if self.options.asan:
|
|
104
|
+
self.base_cmd += f" -o */*:asan=True"
|
|
103
105
|
if self.options.test:
|
|
104
106
|
self.base_cmd += f" -o {self.name}/*:test=True"
|
|
105
107
|
for pkg_option in self.options.pkg_options:
|
|
@@ -278,7 +280,7 @@ class BuildComponent():
|
|
|
278
280
|
tools.exec(graph_cmd, verbose=True)
|
|
279
281
|
bcp = BuildConanParallel(self.orderfile, self.lockfile, self.options.remote)
|
|
280
282
|
bcp.build()
|
|
281
|
-
cmd = f"conan create {self.base_cmd} --build='{self.name}/*'"
|
|
283
|
+
cmd = f"conan create . {self.base_cmd} --build='{self.name}/*'"
|
|
282
284
|
tools.exec(cmd, verbose=True)
|
|
283
285
|
|
|
284
286
|
graph_cmd = f"conan install . {self.base_cmd} --lockfile={self.lockfile} -f json"
|
|
@@ -49,6 +49,7 @@ class LiteBmcConan(ConanFile):
|
|
|
49
49
|
"shared": [False, True],
|
|
50
50
|
% endif
|
|
51
51
|
"gcov": [False, True],
|
|
52
|
+
"asan": [False, True],
|
|
52
53
|
"test": [False, True],
|
|
53
54
|
% if len(pkg.get("options", [])) > 0:
|
|
54
55
|
% for op, ctx in pkg["options"].items():
|
|
@@ -61,6 +62,7 @@ class LiteBmcConan(ConanFile):
|
|
|
61
62
|
"shared": True,
|
|
62
63
|
% endif
|
|
63
64
|
"gcov": False,
|
|
65
|
+
"asan": False,
|
|
64
66
|
"test": False,
|
|
65
67
|
% if len(pkg.get("options", [])) > 0:
|
|
66
68
|
% for op, ctx in pkg["options"].items():
|
|
@@ -184,6 +186,10 @@ class LiteBmcConan(ConanFile):
|
|
|
184
186
|
if self.options.gcov:
|
|
185
187
|
flags.append("-fprofile-arcs")
|
|
186
188
|
flags.append("-ftest-coverage")
|
|
189
|
+
if self.options.asan:
|
|
190
|
+
flags.append("-fsanitize=address")
|
|
191
|
+
flags.append("-fno-omit-frame-pointer")
|
|
192
|
+
flags.append("-g")
|
|
187
193
|
if self.settings.build_type == "Release" and self.settings.arch == "armv8":
|
|
188
194
|
flags.append("-D_FORTIFY_SOURCE=2")
|
|
189
195
|
return flags
|
|
@@ -200,27 +206,27 @@ class LiteBmcConan(ConanFile):
|
|
|
200
206
|
tc.variables["CMAKE_PROJECT_VERSION"] = self.version
|
|
201
207
|
tc.variables["CMAKE_BUILD_TYPE"] = self.settings.build_type
|
|
202
208
|
% if pkg_type == "static-library":
|
|
203
|
-
tc.variables["BUILD_SHARED_LIBS] =
|
|
209
|
+
tc.variables["BUILD_SHARED_LIBS"] = 0
|
|
204
210
|
% elif pkg_type == "shared-libraries":
|
|
205
|
-
tc.variables["BUILD_SHARED_LIBS"] =
|
|
211
|
+
tc.variables["BUILD_SHARED_LIBS"] = 1
|
|
206
212
|
% elif pkg_type == "library":
|
|
207
213
|
if self.options.shared == False:
|
|
208
|
-
tc.variables["BUILD_SHARED_LIBS"] =
|
|
214
|
+
tc.variables["BUILD_SHARED_LIBS"] = 0
|
|
209
215
|
else:
|
|
210
|
-
tc.variables["BUILD_SHARED_LIBS"] =
|
|
216
|
+
tc.variables["BUILD_SHARED_LIBS"] = 1
|
|
211
217
|
% endif
|
|
212
218
|
if self.options.test == True:
|
|
213
|
-
tc.variables["BUILD_TEST"] =
|
|
219
|
+
tc.variables["BUILD_TEST"] = 1
|
|
214
220
|
else:
|
|
215
|
-
tc.variables["BUILD_TEST"] =
|
|
221
|
+
tc.variables["BUILD_TEST"] = 0
|
|
216
222
|
|
|
217
223
|
% if len(pkg.get("options", [])) > 0:
|
|
218
224
|
% for op, value in pkg["options"].items():
|
|
219
225
|
% if type(value["default"]) == type(False):
|
|
220
226
|
if self.options.${op}:
|
|
221
|
-
value =
|
|
227
|
+
value = 1
|
|
222
228
|
else:
|
|
223
|
-
value =
|
|
229
|
+
value = 0
|
|
224
230
|
% elif type(value["default"]) == type(""):
|
|
225
231
|
value = str(self.options.${op})
|
|
226
232
|
% elif type(value["default"]) == type(123):
|
|
@@ -234,8 +240,10 @@ class LiteBmcConan(ConanFile):
|
|
|
234
240
|
tc.preprocessor_definitions["LB_${op.upper()}"] = value
|
|
235
241
|
% endfor
|
|
236
242
|
% endif
|
|
237
|
-
|
|
238
|
-
tc.
|
|
243
|
+
default_flags = self._append_default_flags()
|
|
244
|
+
tc.extra_cflags = default_flags
|
|
245
|
+
tc.extra_cxxflags = default_flags
|
|
246
|
+
tc.extra_ldflags = default_flags
|
|
239
247
|
|
|
240
248
|
tc.generate()
|
|
241
249
|
|
|
@@ -17,6 +17,7 @@ class DeployConan(ConanFile):
|
|
|
17
17
|
}
|
|
18
18
|
options = {
|
|
19
19
|
"gcov": [False, True],
|
|
20
|
+
"asan": [False, True],
|
|
20
21
|
"test": [False, True],
|
|
21
22
|
% if len(pkg.get("options", [])) > 0:
|
|
22
23
|
% for op, ctx in pkg["options"].items():
|
|
@@ -29,6 +30,7 @@ class DeployConan(ConanFile):
|
|
|
29
30
|
"shared": True,
|
|
30
31
|
% endif
|
|
31
32
|
"gcov": False,
|
|
33
|
+
"asan": False,
|
|
32
34
|
"test": False,
|
|
33
35
|
% if len(pkg.get("options", [])) > 0:
|
|
34
36
|
% for op, ctx in pkg["options"].items():
|
|
@@ -62,9 +62,9 @@ class TestComponent():
|
|
|
62
62
|
cmd = f"lcov --compat-libtool -c -q -d {build_folder} -o {coverage_dir}/cover.info"
|
|
63
63
|
tool.exec(cmd)
|
|
64
64
|
for dir in test_src_folder:
|
|
65
|
-
cmd = f"lcov --compat-libtool --ignore-errors unused -r {coverage_dir}/cover.info \"{build_folder}/{dir}/*\" -o {coverage_dir}/cover.info"
|
|
65
|
+
cmd = f"lcov --compat-libtool --ignore-errors unused,inconsistent -r {coverage_dir}/cover.info \"{build_folder}/{dir}/*\" -o {coverage_dir}/cover.info"
|
|
66
66
|
tool.exec(cmd)
|
|
67
|
-
cmd = f"lcov --compat-libtool --ignore-errors unused -r {coverage_dir}/cover.info \"*/include/*\" -o {coverage_dir}/cover.info"
|
|
67
|
+
cmd = f"lcov --compat-libtool --ignore-errors unused,inconsistent -r {coverage_dir}/cover.info \"*/include/*\" -o {coverage_dir}/cover.info"
|
|
68
68
|
tool.exec(cmd)
|
|
69
69
|
cmd = f"genhtml -o {coverage_dir}/html --legend {coverage_dir}/cover.info"
|
|
70
70
|
tool.exec(cmd)
|
|
@@ -184,6 +184,10 @@ class TestComponent():
|
|
|
184
184
|
build = BuildComponent(self.build_parser, self.origin_args)
|
|
185
185
|
build.run()
|
|
186
186
|
|
|
187
|
+
if hasattr(build.options, 'asan') and build.options.asan:
|
|
188
|
+
os.environ.setdefault("ASAN_OPTIONS", "halt_on_error=1:detect_leaks=1")
|
|
189
|
+
log.info("ASAN enabled, ASAN_OPTIONS=" + os.environ["ASAN_OPTIONS"])
|
|
190
|
+
|
|
187
191
|
self._make_ld_library_path(build.rootfs_dir)
|
|
188
192
|
self._make_dbus_session(build.rootfs_dir)
|
|
189
193
|
|
|
@@ -213,6 +217,11 @@ class TestComponent():
|
|
|
213
217
|
return 0
|
|
214
218
|
|
|
215
219
|
log.success("call test method...")
|
|
220
|
+
# 为增加可定位性,测试时将日志写入文件,等级定为debug
|
|
221
|
+
if os.environ.get("LOG_LEVEL") is None:
|
|
222
|
+
os.environ["LOG_LEVEL"] = "debug"
|
|
223
|
+
if os.environ.get("LOG_TYPE") is None:
|
|
224
|
+
os.environ["LOG_TYPE"] = "file"
|
|
216
225
|
ret = test.test()
|
|
217
226
|
if ret is not None:
|
|
218
227
|
if isinstance(ret, unittest.TestResult) and (len(ret.errors) > 0 or len(ret.failures) > 0):
|
|
@@ -4,28 +4,31 @@
|
|
|
4
4
|
# under the terms of the GNU General Public License as published by the
|
|
5
5
|
# Free Software Foundation; either version 3 of the License, or (at your
|
|
6
6
|
# option) any later version.
|
|
7
|
-
import os
|
|
8
7
|
import argparse
|
|
9
|
-
import
|
|
8
|
+
import fcntl
|
|
10
9
|
import json
|
|
11
|
-
import
|
|
10
|
+
import os
|
|
12
11
|
import re
|
|
13
|
-
import
|
|
14
|
-
import fcntl
|
|
12
|
+
import textwrap
|
|
15
13
|
from pathlib import Path
|
|
16
14
|
from string import Template
|
|
15
|
+
|
|
16
|
+
import requests
|
|
17
|
+
import yaml
|
|
17
18
|
from colorama import Fore, Style
|
|
18
|
-
from jsonschema import
|
|
19
|
-
|
|
19
|
+
from jsonschema import ValidationError, validate
|
|
20
|
+
|
|
21
|
+
from lbkit.errors import HttpRequestException, PackageConfigException
|
|
20
22
|
|
|
21
23
|
LOG_DIR = os.path.join(Path.home(), ".cache", "lbkit", "log")
|
|
22
24
|
DOWNLOAD_CACHE_DIR = os.path.join(Path.home(), ".cache", "litebmc", "download")
|
|
23
25
|
TARGETS_DIR = "/usr/share/litebmc/targets"
|
|
26
|
+
HOOKS_DIR = "/usr/share/litebmc/pre-commit-hooks"
|
|
24
27
|
|
|
25
28
|
|
|
26
29
|
class Color(object):
|
|
27
|
-
"""
|
|
28
|
-
|
|
30
|
+
"""Wrapper around colorama colors that are undefined in importing"""
|
|
31
|
+
|
|
29
32
|
RED = Fore.RED # @UndefinedVariable
|
|
30
33
|
WHITE = Fore.WHITE # @UndefinedVariable
|
|
31
34
|
CYAN = Fore.CYAN # @UndefinedVariable
|
|
@@ -40,9 +43,9 @@ class Color(object):
|
|
|
40
43
|
BRIGHT_BLUE = Style.BRIGHT + Fore.BLUE # @UndefinedVariable
|
|
41
44
|
BRIGHT_YELLOW = Style.BRIGHT + Fore.YELLOW # @UndefinedVariable
|
|
42
45
|
BRIGHT_GREEN = Style.BRIGHT + Fore.GREEN # @UndefinedVariable
|
|
43
|
-
BRIGHT_CYAN = Style.BRIGHT + Fore.CYAN
|
|
44
|
-
BRIGHT_WHITE = Style.BRIGHT + Fore.WHITE
|
|
45
|
-
BRIGHT_MAGENTA = Style.BRIGHT + Fore.MAGENTA
|
|
46
|
+
BRIGHT_CYAN = Style.BRIGHT + Fore.CYAN # @UndefinedVariable
|
|
47
|
+
BRIGHT_WHITE = Style.BRIGHT + Fore.WHITE # @UndefinedVariable
|
|
48
|
+
BRIGHT_MAGENTA = Style.BRIGHT + Fore.MAGENTA # @UndefinedVariable
|
|
46
49
|
|
|
47
50
|
|
|
48
51
|
if os.environ.get("COLOR_DARK", 0):
|
|
@@ -54,8 +57,10 @@ if os.environ.get("COLOR_DARK", 0):
|
|
|
54
57
|
Color.BRIGHT_YELLOW = Fore.MAGENTA
|
|
55
58
|
Color.BRIGHT_GREEN = Fore.GREEN
|
|
56
59
|
|
|
60
|
+
|
|
57
61
|
class SmartFormatter(argparse.HelpFormatter):
|
|
58
62
|
"""重写HelpFormatter"""
|
|
63
|
+
|
|
59
64
|
def _fill_text(self, text, width, indent):
|
|
60
65
|
"""重写HelpFormatter"""
|
|
61
66
|
text = textwrap.dedent(text)
|
|
@@ -71,6 +76,7 @@ class SmartFormatter(argparse.HelpFormatter):
|
|
|
71
76
|
ret.extend(super()._split_lines(line, width))
|
|
72
77
|
return ret
|
|
73
78
|
|
|
79
|
+
|
|
74
80
|
def get_json_schema_file(yml_file, default_json_schema_file):
|
|
75
81
|
"""使用json schema文件校验yml_file配置文件"""
|
|
76
82
|
with open(yml_file, "r") as fp:
|
|
@@ -80,6 +86,7 @@ def get_json_schema_file(yml_file, default_json_schema_file):
|
|
|
80
86
|
return match.group(1)
|
|
81
87
|
return default_json_schema_file
|
|
82
88
|
|
|
89
|
+
|
|
83
90
|
def load_json_schema(schema_file):
|
|
84
91
|
"""使用json schema文件校验yml_file配置文件"""
|
|
85
92
|
if schema_file.startswith("https://litebmc.com/"):
|
|
@@ -94,6 +101,7 @@ def load_json_schema(schema_file):
|
|
|
94
101
|
tmp = fp.read()
|
|
95
102
|
return json.loads(tmp)
|
|
96
103
|
|
|
104
|
+
|
|
97
105
|
def load_yml_with_json_schema_validate(yml_file, default_json_schema_file, **kwargs):
|
|
98
106
|
"""使用json schema文件校验yml_file配置文件"""
|
|
99
107
|
schema_file = get_json_schema_file(yml_file, default_json_schema_file)
|
|
@@ -110,11 +118,14 @@ def load_yml_with_json_schema_validate(yml_file, default_json_schema_file, **kwa
|
|
|
110
118
|
validate(data, schema)
|
|
111
119
|
return data
|
|
112
120
|
except ValidationError as exc:
|
|
113
|
-
raise PackageConfigException(
|
|
114
|
-
|
|
115
|
-
|
|
121
|
+
raise PackageConfigException(
|
|
122
|
+
f"validate {yml_file} failed, schema file is {schema_file}, "
|
|
123
|
+
f"message: {exc.message}\n"
|
|
124
|
+
"installing redhat.vscode-yaml plugin in vscode will help you write odf files"
|
|
125
|
+
)
|
|
126
|
+
|
|
116
127
|
|
|
117
|
-
class DownloadFlag
|
|
128
|
+
class DownloadFlag:
|
|
118
129
|
@staticmethod
|
|
119
130
|
def clean(filename):
|
|
120
131
|
"""清理文件标记"""
|
|
@@ -152,4 +163,4 @@ class DownloadFlag():
|
|
|
152
163
|
if len(content) == 0:
|
|
153
164
|
return "", ""
|
|
154
165
|
chunk = content.split("|")
|
|
155
|
-
return chunk[0], chunk[1]
|
|
166
|
+
return chunk[0], chunk[1]
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# Copyright (c) 2021-2024 litebmc.com
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or modify it
|
|
4
|
+
# under the terms of the GNU General Public License as published by the
|
|
5
|
+
# Free Software Foundation; either version 3 of the License, or (at your
|
|
6
|
+
# option) any later version.
|
|
7
|
+
"""lbkit 自升级模块"""
|
|
8
|
+
import os
|
|
9
|
+
import subprocess
|
|
10
|
+
import argparse
|
|
11
|
+
import re
|
|
12
|
+
|
|
13
|
+
from packaging.version import Version as PkgVersion
|
|
14
|
+
|
|
15
|
+
from lbkit import __version__ as current_version
|
|
16
|
+
from lbkit.log import Logger
|
|
17
|
+
|
|
18
|
+
log = Logger()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _is_root():
|
|
22
|
+
return os.geteuid() == 0
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _get_installed_deb_version():
|
|
26
|
+
"""获取已安装的 lbkit deb 包版本"""
|
|
27
|
+
result = subprocess.run(
|
|
28
|
+
["dpkg-query", "-W", "-f=${Version}", "lbkit"],
|
|
29
|
+
capture_output=True, text=True
|
|
30
|
+
)
|
|
31
|
+
if result.returncode != 0:
|
|
32
|
+
return None
|
|
33
|
+
return result.stdout.strip() or None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _get_installed_rpm_version():
|
|
37
|
+
"""获取已安装的 lbkit rpm 包版本"""
|
|
38
|
+
result = subprocess.run(
|
|
39
|
+
["rpm", "-q", "--queryformat", "%{VERSION}", "lbkit"],
|
|
40
|
+
capture_output=True, text=True
|
|
41
|
+
)
|
|
42
|
+
if result.returncode != 0:
|
|
43
|
+
return None
|
|
44
|
+
return result.stdout.strip() or None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _get_apt_candidate_version():
|
|
48
|
+
"""通过 apt-cache 获取 lbkit 的候选升级版本"""
|
|
49
|
+
is_root = _is_root()
|
|
50
|
+
sudo = [] if is_root else ["sudo"]
|
|
51
|
+
|
|
52
|
+
# apt update
|
|
53
|
+
log.info("正在更新软件包列表...")
|
|
54
|
+
subprocess.run(sudo + ["apt", "update", "-qq"],
|
|
55
|
+
check=True, capture_output=True)
|
|
56
|
+
|
|
57
|
+
result = subprocess.run(
|
|
58
|
+
["apt-cache", "policy", "lbkit"],
|
|
59
|
+
capture_output=True, text=True
|
|
60
|
+
)
|
|
61
|
+
if result.returncode != 0:
|
|
62
|
+
return None
|
|
63
|
+
for line in result.stdout.splitlines():
|
|
64
|
+
line = line.strip()
|
|
65
|
+
if line.startswith("候选:") or line.startswith("Candidate:"):
|
|
66
|
+
version = line.split(":", 1)[-1].split(": ", 1)[-1].strip()
|
|
67
|
+
if version:
|
|
68
|
+
return version
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _get_dnf_candidate_version():
|
|
73
|
+
"""通过 dnf 获取 lbkit 的候选升级版本"""
|
|
74
|
+
is_root = _is_root()
|
|
75
|
+
sudo = [] if is_root else ["sudo"]
|
|
76
|
+
|
|
77
|
+
# dnf check-update
|
|
78
|
+
log.info("正在更新软件包列表...")
|
|
79
|
+
subprocess.run(sudo + ["dnf", "makecache", "-q"],
|
|
80
|
+
check=True, capture_output=True)
|
|
81
|
+
|
|
82
|
+
result = subprocess.run(
|
|
83
|
+
sudo + ["dnf", "list", "available", "lbkit"],
|
|
84
|
+
capture_output=True, text=True
|
|
85
|
+
)
|
|
86
|
+
if result.returncode != 0:
|
|
87
|
+
return None
|
|
88
|
+
for line in result.stdout.splitlines():
|
|
89
|
+
line = line.strip()
|
|
90
|
+
if line.startswith("lbkit."):
|
|
91
|
+
parts = line.split()
|
|
92
|
+
if len(parts) >= 2:
|
|
93
|
+
# 格式: lbkit.x86_64 0.9.12 repo_name
|
|
94
|
+
return parts[1]
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _get_pypi_latest_version():
|
|
99
|
+
"""查询 PyPI(或用户配置的镜像源)上 lbkit 的最新版本"""
|
|
100
|
+
try:
|
|
101
|
+
result = subprocess.run(
|
|
102
|
+
[subprocess.sys.executable, "-m", "pip", "index", "versions", "lbkit"],
|
|
103
|
+
capture_output=True, text=True, timeout=15
|
|
104
|
+
)
|
|
105
|
+
if result.returncode != 0:
|
|
106
|
+
log.warn(f"查询 PyPI 版本失败:\n{result.stderr}")
|
|
107
|
+
return None
|
|
108
|
+
# 输出格式: "lbkit (0.9.12)"
|
|
109
|
+
match = re.search(r"lbkit\s*\(([^)]+)\)", result.stdout)
|
|
110
|
+
if match:
|
|
111
|
+
return match.group(1)
|
|
112
|
+
return None
|
|
113
|
+
except Exception as e:
|
|
114
|
+
log.warn(f"查询 PyPI 版本失败: {e}")
|
|
115
|
+
return None
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _install_deb(version):
|
|
119
|
+
"""通过 apt 安装指定版本的 deb 包"""
|
|
120
|
+
is_root = _is_root()
|
|
121
|
+
sudo = [] if is_root else ["sudo"]
|
|
122
|
+
|
|
123
|
+
installed = _get_installed_deb_version()
|
|
124
|
+
if installed == version:
|
|
125
|
+
log.info(f"deb 包已是目标版本 {version}")
|
|
126
|
+
return True
|
|
127
|
+
|
|
128
|
+
log.info(f"正在安装 deb 包: {installed or '未安装'} → {version}")
|
|
129
|
+
result = subprocess.run(
|
|
130
|
+
sudo + ["apt", "install", "-y", "--only-upgrade", f"lbkit={version}"],
|
|
131
|
+
capture_output=True, text=True
|
|
132
|
+
)
|
|
133
|
+
if result.returncode != 0:
|
|
134
|
+
# 指定版本不存在时回退到安装候选版本
|
|
135
|
+
log.warn(f"apt 源中未找到版本 {version},尝试安装候选版本")
|
|
136
|
+
result = subprocess.run(
|
|
137
|
+
sudo + ["apt", "install", "-y", "--only-upgrade", "lbkit"],
|
|
138
|
+
capture_output=True, text=True
|
|
139
|
+
)
|
|
140
|
+
if result.returncode != 0:
|
|
141
|
+
log.error(f"deb 包安装失败:\n{result.stderr}")
|
|
142
|
+
return False
|
|
143
|
+
|
|
144
|
+
new_version = _get_installed_deb_version()
|
|
145
|
+
if new_version:
|
|
146
|
+
log.success(f"deb 包已安装: {new_version}")
|
|
147
|
+
return True
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _install_rpm(version):
|
|
151
|
+
"""通过 dnf 安装指定版本的 rpm 包"""
|
|
152
|
+
is_root = _is_root()
|
|
153
|
+
sudo = [] if is_root else ["sudo"]
|
|
154
|
+
|
|
155
|
+
installed = _get_installed_rpm_version()
|
|
156
|
+
if installed == version:
|
|
157
|
+
log.info(f"rpm 包已是目标版本 {version}")
|
|
158
|
+
return True
|
|
159
|
+
|
|
160
|
+
log.info(f"正在安装 rpm 包: {installed or '未安装'} → {version}")
|
|
161
|
+
result = subprocess.run(
|
|
162
|
+
sudo + ["dnf", "install", "-y", f"lbkit-{version}"],
|
|
163
|
+
capture_output=True, text=True
|
|
164
|
+
)
|
|
165
|
+
if result.returncode != 0:
|
|
166
|
+
log.error(f"rpm 包安装失败:\n{result.stderr}")
|
|
167
|
+
return False
|
|
168
|
+
|
|
169
|
+
new_version = _get_installed_rpm_version()
|
|
170
|
+
if new_version:
|
|
171
|
+
log.success(f"rpm 包已安装: {new_version}")
|
|
172
|
+
return True
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _is_deb_system():
|
|
176
|
+
"""检测是否为 Debian/Ubuntu 系列系统"""
|
|
177
|
+
return os.path.isfile("/etc/debian_version")
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _is_rpm_system():
|
|
181
|
+
"""检测是否为 RHEL/Rocky Linux/CentOS 系列系统"""
|
|
182
|
+
if os.path.isfile("/etc/os-release"):
|
|
183
|
+
with open("/etc/os-release", "r") as fp:
|
|
184
|
+
for line in fp:
|
|
185
|
+
if line.strip().startswith("ID="):
|
|
186
|
+
distro_id = line.strip().split("=", 1)[1].strip('"')
|
|
187
|
+
if distro_id in ("rocky", "centos", "almalinux", "rhel", "fedora"):
|
|
188
|
+
return True
|
|
189
|
+
if line.strip().startswith("ID_LIKE="):
|
|
190
|
+
id_like = line.strip().split("=", 1)[1].strip('"')
|
|
191
|
+
if "rhel" in id_like:
|
|
192
|
+
return True
|
|
193
|
+
return os.path.isfile("/etc/redhat-release")
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _pip_install(version):
|
|
197
|
+
"""安装指定版本的 PyPI 包"""
|
|
198
|
+
is_root = _is_root()
|
|
199
|
+
log.info(f"正在安装 PyPI 包 lbkit=={version}...")
|
|
200
|
+
|
|
201
|
+
cmd = [subprocess.sys.executable, "-m", "pip", "install",
|
|
202
|
+
f"lbkit=={version}", "--break-system-packages"]
|
|
203
|
+
if is_root:
|
|
204
|
+
cmd.append("--break-system-packages")
|
|
205
|
+
else:
|
|
206
|
+
cmd.append("--user")
|
|
207
|
+
|
|
208
|
+
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
209
|
+
if result.returncode != 0:
|
|
210
|
+
log.error(f"PyPI 包安装失败:\n{result.stderr}")
|
|
211
|
+
return False
|
|
212
|
+
log.success(f"PyPI 包 lbkit=={version} 安装完成")
|
|
213
|
+
return True
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def _check_path():
|
|
217
|
+
"""检查 ~/.local/bin 是否在 PATH 中,不在则提示用户"""
|
|
218
|
+
local_bin = os.path.expanduser("~/.local/bin")
|
|
219
|
+
path_env = os.environ.get("PATH", "")
|
|
220
|
+
path_dirs = path_env.split(":")
|
|
221
|
+
|
|
222
|
+
if local_bin in path_dirs:
|
|
223
|
+
return
|
|
224
|
+
|
|
225
|
+
log.warn(f"{local_bin} 不在 PATH 环境变量中")
|
|
226
|
+
log.warn("lbk 命令可能无法直接使用")
|
|
227
|
+
|
|
228
|
+
from lbkit.cli import ask_user_yes_no
|
|
229
|
+
if not ask_user_yes_no(f"是否将 {local_bin} 添加到 ~/.bashrc?"):
|
|
230
|
+
log.info(f"请手动执行: echo 'export PATH=\"{local_bin}:$PATH\"' >> ~/.bashrc")
|
|
231
|
+
return
|
|
232
|
+
|
|
233
|
+
bashrc = os.path.expanduser("~/.bashrc")
|
|
234
|
+
export_line = f'export PATH="{local_bin}:$PATH"\n'
|
|
235
|
+
already_in_bashrc = False
|
|
236
|
+
if os.path.isfile(bashrc):
|
|
237
|
+
with open(bashrc, "r") as f:
|
|
238
|
+
already_in_bashrc = local_bin in f.read()
|
|
239
|
+
|
|
240
|
+
if already_in_bashrc:
|
|
241
|
+
log.info(f"{local_bin} 已在 ~/.bashrc 中,可能是当前 shell 未加载")
|
|
242
|
+
return
|
|
243
|
+
|
|
244
|
+
with open(bashrc, "a") as f:
|
|
245
|
+
f.write("\n# Added by lbkit upgrade\n")
|
|
246
|
+
f.write(export_line)
|
|
247
|
+
log.success(f"已将 {local_bin} 添加到 ~/.bashrc")
|
|
248
|
+
log.info("请执行 source ~/.bashrc 或重新打开终端使配置生效")
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def upgrade(*args):
|
|
252
|
+
"""执行 lbkit 自升级"""
|
|
253
|
+
parser = argparse.ArgumentParser(
|
|
254
|
+
description="自升级lbkit,查询系统包管理器和PyPI可用版本后安装最新版",
|
|
255
|
+
prog="lbkit upgrade"
|
|
256
|
+
)
|
|
257
|
+
parser.parse_args(*args)
|
|
258
|
+
|
|
259
|
+
log.info(f"当前版本: {current_version}")
|
|
260
|
+
|
|
261
|
+
# 检测系统类型
|
|
262
|
+
is_deb = _is_deb_system()
|
|
263
|
+
is_rpm = _is_rpm_system()
|
|
264
|
+
|
|
265
|
+
if not is_deb and not is_rpm:
|
|
266
|
+
log.error("当前系统不是 Debian/Ubuntu 或 RHEL/Rocky Linux 系列,暂不支持自动升级")
|
|
267
|
+
return 1
|
|
268
|
+
|
|
269
|
+
# 1. 查询系统包管理器候选版本
|
|
270
|
+
sys_ver = None
|
|
271
|
+
if is_deb:
|
|
272
|
+
sys_ver = _get_apt_candidate_version()
|
|
273
|
+
if sys_ver:
|
|
274
|
+
log.info(f"apt 可用版本: {sys_ver}")
|
|
275
|
+
else:
|
|
276
|
+
log.warn("apt 源中未找到 lbkit 包")
|
|
277
|
+
elif is_rpm:
|
|
278
|
+
sys_ver = _get_dnf_candidate_version()
|
|
279
|
+
if sys_ver:
|
|
280
|
+
log.info(f"dnf 可用版本: {sys_ver}")
|
|
281
|
+
else:
|
|
282
|
+
log.warn("dnf 源中未找到 lbkit 包")
|
|
283
|
+
|
|
284
|
+
# 2. 查询 PyPI 最新版本
|
|
285
|
+
pypi_ver = _get_pypi_latest_version()
|
|
286
|
+
if pypi_ver:
|
|
287
|
+
log.info(f"PyPI 最新版本: {pypi_ver}")
|
|
288
|
+
else:
|
|
289
|
+
log.warn("无法查询 PyPI 版本")
|
|
290
|
+
|
|
291
|
+
# 3. 取最大版本号
|
|
292
|
+
versions = {}
|
|
293
|
+
if sys_ver:
|
|
294
|
+
versions["system"] = sys_ver
|
|
295
|
+
if pypi_ver:
|
|
296
|
+
versions["pypi"] = pypi_ver
|
|
297
|
+
|
|
298
|
+
if not versions:
|
|
299
|
+
log.error("未找到任何可安装的版本")
|
|
300
|
+
return 1
|
|
301
|
+
|
|
302
|
+
target = max(versions.values(), key=PkgVersion)
|
|
303
|
+
log.info(f"目标版本: {target}")
|
|
304
|
+
|
|
305
|
+
if PkgVersion(target) <= PkgVersion(current_version):
|
|
306
|
+
log.info(f"当前已是最新版本 {current_version}")
|
|
307
|
+
return 0
|
|
308
|
+
|
|
309
|
+
# 4. 安装系统包(如果系统包管理器有可用版本)
|
|
310
|
+
if sys_ver:
|
|
311
|
+
if is_deb:
|
|
312
|
+
if not _install_deb(target):
|
|
313
|
+
return 1
|
|
314
|
+
elif is_rpm:
|
|
315
|
+
if not _install_rpm(target):
|
|
316
|
+
return 1
|
|
317
|
+
|
|
318
|
+
# 5. 安装 PyPI 包
|
|
319
|
+
if not _pip_install(target):
|
|
320
|
+
return 1
|
|
321
|
+
|
|
322
|
+
# 6. 检查 PATH
|
|
323
|
+
_check_path()
|
|
324
|
+
|
|
325
|
+
log.success(f"升级完成: {current_version} → {target}")
|
|
326
|
+
return 0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lbkit
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.14
|
|
4
4
|
Summary: Tools provided by litebmc.com
|
|
5
5
|
Home-page: https://www.litebmc.com
|
|
6
6
|
Author: xuhj@litebmc.com
|
|
@@ -22,6 +22,12 @@ Requires-Dist: inflection
|
|
|
22
22
|
Requires-Dist: meson>=1.4.0
|
|
23
23
|
Requires-Dist: psutil
|
|
24
24
|
Requires-Dist: loguru
|
|
25
|
+
Requires-Dist: pre-commit
|
|
26
|
+
Requires-Dist: black
|
|
27
|
+
Requires-Dist: isort
|
|
28
|
+
Requires-Dist: flake8
|
|
29
|
+
Requires-Dist: flake8-bugbear
|
|
30
|
+
Requires-Dist: flake8-comprehensions
|
|
25
31
|
Dynamic: author
|
|
26
32
|
Dynamic: author-email
|
|
27
33
|
Dynamic: classifier
|
|
@@ -6,17 +6,19 @@
|
|
|
6
6
|
# option) any later version.
|
|
7
7
|
import os
|
|
8
8
|
import re
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
from setuptools import find_packages, setup
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
def load_version():
|
|
12
|
-
"""
|
|
13
|
-
filename = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
|
14
|
-
"lbkit", "__init__.py"))
|
|
14
|
+
"""Loads a file content"""
|
|
15
|
+
filename = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "lbkit", "__init__.py"))
|
|
15
16
|
with open(filename, "rt") as version_file:
|
|
16
17
|
litebmc_init = version_file.read()
|
|
17
18
|
version = re.search(r"__version__ = '([0-9.]+)'", litebmc_init).group(1)
|
|
18
19
|
return version
|
|
19
20
|
|
|
21
|
+
|
|
20
22
|
setup(
|
|
21
23
|
name="lbkit",
|
|
22
24
|
version=load_version(),
|
|
@@ -25,7 +27,26 @@ setup(
|
|
|
25
27
|
description="Tools provided by litebmc.com",
|
|
26
28
|
long_description="build and code generate tools",
|
|
27
29
|
long_description_content_type="text/markdown",
|
|
28
|
-
install_requires=[
|
|
30
|
+
install_requires=[
|
|
31
|
+
"pyyaml",
|
|
32
|
+
"colorama",
|
|
33
|
+
"mako",
|
|
34
|
+
"node-semver>=0.6.1",
|
|
35
|
+
"jsonschema",
|
|
36
|
+
"conan",
|
|
37
|
+
"requests",
|
|
38
|
+
"gitpython",
|
|
39
|
+
"inflection",
|
|
40
|
+
"meson>=1.4.0",
|
|
41
|
+
"psutil",
|
|
42
|
+
"loguru",
|
|
43
|
+
"pre-commit",
|
|
44
|
+
"black",
|
|
45
|
+
"isort",
|
|
46
|
+
"flake8",
|
|
47
|
+
"flake8-bugbear",
|
|
48
|
+
"flake8-comprehensions",
|
|
49
|
+
],
|
|
29
50
|
url="https://www.litebmc.com",
|
|
30
51
|
packages=find_packages(),
|
|
31
52
|
include_package_data=True,
|
lbkit-0.9.12/lbkit/__commit__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__commit__ = 'e5ea324'
|
lbkit-0.9.12/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
|