pkgmgr-kunrunic 0.1.1.dev4__py3-none-any.whl
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.
- pkgmgr/__init__.py +16 -0
- pkgmgr/__main__.py +5 -0
- pkgmgr/cli.py +320 -0
- pkgmgr/collectors/__init__.py +5 -0
- pkgmgr/collectors/base.py +15 -0
- pkgmgr/collectors/checksums.py +35 -0
- pkgmgr/config.py +408 -0
- pkgmgr/points.py +98 -0
- pkgmgr/release.py +1031 -0
- pkgmgr/shell_integration.py +120 -0
- pkgmgr/snapshot.py +306 -0
- pkgmgr/templates/pkg.yaml.sample +16 -0
- pkgmgr/templates/pkgmgr.yaml.sample +51 -0
- pkgmgr/watch.py +79 -0
- pkgmgr_kunrunic-0.1.1.dev4.dist-info/METADATA +159 -0
- pkgmgr_kunrunic-0.1.1.dev4.dist-info/RECORD +24 -0
- pkgmgr_kunrunic-0.1.1.dev4.dist-info/WHEEL +5 -0
- pkgmgr_kunrunic-0.1.1.dev4.dist-info/entry_points.txt +2 -0
- pkgmgr_kunrunic-0.1.1.dev4.dist-info/licenses/LICENSE +21 -0
- pkgmgr_kunrunic-0.1.1.dev4.dist-info/top_level.txt +3 -0
- plugin/export_cksum.py +354 -0
- plugin/export_pkgstore.py +117 -0
- plugin/export_source_review.py +499 -0
- tools/echo_args.py +15 -0
pkgmgr/__init__.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
"""
|
|
3
|
+
Modernized pkg manager scaffold.
|
|
4
|
+
This package will grow to replace the legacy single-file script.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"cli",
|
|
9
|
+
"config",
|
|
10
|
+
"snapshot",
|
|
11
|
+
"release",
|
|
12
|
+
"watch",
|
|
13
|
+
"points",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
__version__ = "0.1.1.dev4"
|
pkgmgr/__main__.py
ADDED
pkgmgr/cli.py
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
"""CLI entrypoint scaffold for the pkg manager."""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
import argparse
|
|
9
|
+
except Exception:
|
|
10
|
+
argparse = None
|
|
11
|
+
|
|
12
|
+
from . import config, snapshot, release, watch, __version__
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _add_make_config(sub):
|
|
16
|
+
p = sub.add_parser("make-config", help="create a pkgmgr.yaml template to edit")
|
|
17
|
+
p.add_argument(
|
|
18
|
+
"-o",
|
|
19
|
+
"--output",
|
|
20
|
+
default=config.DEFAULT_MAIN_CONFIG,
|
|
21
|
+
help="path to write the main config (default: %(default)s)",
|
|
22
|
+
)
|
|
23
|
+
p.set_defaults(func=_handle_make_config)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _add_install(sub):
|
|
27
|
+
p = sub.add_parser("install", help="prepare environment and collect initial baseline")
|
|
28
|
+
p.add_argument(
|
|
29
|
+
"--config",
|
|
30
|
+
default=None,
|
|
31
|
+
help="config file path (default: auto-discover under %s)" % config.BASE_DIR,
|
|
32
|
+
)
|
|
33
|
+
p.set_defaults(func=_handle_install)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _add_snapshot(sub):
|
|
37
|
+
p = sub.add_parser(
|
|
38
|
+
"snapshot", help="take a snapshot (baseline update after install)"
|
|
39
|
+
)
|
|
40
|
+
p.add_argument(
|
|
41
|
+
"--config",
|
|
42
|
+
default=None,
|
|
43
|
+
help="config file path (default: auto-discover under %s)" % config.BASE_DIR,
|
|
44
|
+
)
|
|
45
|
+
p.set_defaults(func=_handle_snapshot)
|
|
46
|
+
|
|
47
|
+
def _add_actions(sub):
|
|
48
|
+
p = sub.add_parser("actions", help="list actions or run a configured action")
|
|
49
|
+
p.add_argument("name", nargs="?", help="action name to run (omit to list)")
|
|
50
|
+
p.add_argument(
|
|
51
|
+
"action_args",
|
|
52
|
+
nargs=argparse.REMAINDER,
|
|
53
|
+
help="args passed to the action (everything after the name)",
|
|
54
|
+
)
|
|
55
|
+
p.set_defaults(func=_handle_actions)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _add_create_pkg(sub):
|
|
59
|
+
p = sub.add_parser("create-pkg", help="create a pkg folder and template")
|
|
60
|
+
p.add_argument("pkg_id", help="package identifier (e.g. 20240601)")
|
|
61
|
+
p.add_argument(
|
|
62
|
+
"--config",
|
|
63
|
+
default=None,
|
|
64
|
+
help="config file path (default: auto-discover under %s)" % config.BASE_DIR,
|
|
65
|
+
)
|
|
66
|
+
p.set_defaults(func=_handle_create_pkg)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _add_update_pkg(sub):
|
|
70
|
+
p = sub.add_parser("update-pkg", help="collect git keyword hits and checksums for a pkg")
|
|
71
|
+
p.add_argument("pkg_id", help="package identifier to update")
|
|
72
|
+
p.add_argument(
|
|
73
|
+
"-release",
|
|
74
|
+
"--release",
|
|
75
|
+
action="store_true",
|
|
76
|
+
help="finalize the latest release bundle (tar + move to HISTORY)",
|
|
77
|
+
)
|
|
78
|
+
p.add_argument(
|
|
79
|
+
"--config",
|
|
80
|
+
default=None,
|
|
81
|
+
help="config file path (default: auto-discover under %s)" % config.BASE_DIR,
|
|
82
|
+
)
|
|
83
|
+
p.set_defaults(func=_handle_update_pkg)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _add_close_pkg(sub):
|
|
87
|
+
p = sub.add_parser("close-pkg", help="mark a pkg as closed and stop watching")
|
|
88
|
+
p.add_argument("pkg_id", help="package identifier to close")
|
|
89
|
+
p.add_argument(
|
|
90
|
+
"--config",
|
|
91
|
+
default=None,
|
|
92
|
+
help="config file path (default: auto-discover under %s)" % config.BASE_DIR,
|
|
93
|
+
)
|
|
94
|
+
p.set_defaults(func=_handle_close_pkg)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _add_watch(sub):
|
|
98
|
+
p = sub.add_parser("watch", help="start watcher/daemon to monitor pkgs")
|
|
99
|
+
p.add_argument(
|
|
100
|
+
"--config",
|
|
101
|
+
default=None,
|
|
102
|
+
help="config file path (default: auto-discover under %s)" % config.BASE_DIR,
|
|
103
|
+
)
|
|
104
|
+
p.add_argument(
|
|
105
|
+
"--once",
|
|
106
|
+
action="store_true",
|
|
107
|
+
help="run a single poll iteration then exit (useful for cron)",
|
|
108
|
+
)
|
|
109
|
+
p.add_argument("--pkg", help="package id to scope watch/points (optional)")
|
|
110
|
+
p.add_argument(
|
|
111
|
+
"--auto-point",
|
|
112
|
+
action="store_true",
|
|
113
|
+
help="create a checkpoint automatically after changes are handled",
|
|
114
|
+
)
|
|
115
|
+
p.add_argument(
|
|
116
|
+
"--point-label",
|
|
117
|
+
help="label to use when auto-creating a checkpoint (default: watch-auto)",
|
|
118
|
+
)
|
|
119
|
+
p.set_defaults(func=_handle_watch)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _add_collect(sub):
|
|
123
|
+
p = sub.add_parser("collect", help="run collectors for a pkg")
|
|
124
|
+
p.add_argument("--pkg", required=True, help="package identifier")
|
|
125
|
+
p.add_argument(
|
|
126
|
+
"--collector",
|
|
127
|
+
action="append",
|
|
128
|
+
dest="collectors",
|
|
129
|
+
help="specific collectors to run (default: all enabled)",
|
|
130
|
+
)
|
|
131
|
+
p.add_argument(
|
|
132
|
+
"--config",
|
|
133
|
+
default=None,
|
|
134
|
+
help="config file path (default: auto-discover under %s)" % config.BASE_DIR,
|
|
135
|
+
)
|
|
136
|
+
p.set_defaults(func=_handle_collect)
|
|
137
|
+
|
|
138
|
+
def _add_point(sub):
|
|
139
|
+
p = sub.add_parser("point", help="create or list checkpoints for a pkg")
|
|
140
|
+
p.add_argument("--pkg", required=True, help="package identifier")
|
|
141
|
+
p.add_argument("--label", help="optional label for this point")
|
|
142
|
+
p.add_argument(
|
|
143
|
+
"--actions-run",
|
|
144
|
+
action="append",
|
|
145
|
+
dest="actions_run",
|
|
146
|
+
help="actions that were executed before creating this point",
|
|
147
|
+
)
|
|
148
|
+
p.add_argument(
|
|
149
|
+
"--list",
|
|
150
|
+
action="store_true",
|
|
151
|
+
help="list existing points instead of creating a new one",
|
|
152
|
+
)
|
|
153
|
+
p.add_argument(
|
|
154
|
+
"--config",
|
|
155
|
+
default=None,
|
|
156
|
+
help="config file path (default: auto-discover under %s)" % config.BASE_DIR,
|
|
157
|
+
)
|
|
158
|
+
p.set_defaults(func=_handle_point)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def build_parser():
|
|
162
|
+
if argparse is None:
|
|
163
|
+
raise RuntimeError("argparse not available; install argparse")
|
|
164
|
+
parser = argparse.ArgumentParser(
|
|
165
|
+
prog="pkgmgr",
|
|
166
|
+
description="Pkg manager CLI v%s" % __version__,
|
|
167
|
+
)
|
|
168
|
+
# keep %(prog)s for argparse's mapping and append package version
|
|
169
|
+
parser.add_argument("-V", "--version", action="version", version="%(prog)s " + __version__)
|
|
170
|
+
parser.add_argument(
|
|
171
|
+
"--config",
|
|
172
|
+
default=None,
|
|
173
|
+
help="config file path (default: auto-discover under %s)" % config.BASE_DIR,
|
|
174
|
+
)
|
|
175
|
+
sub = parser.add_subparsers(dest="command")
|
|
176
|
+
|
|
177
|
+
_add_make_config(sub)
|
|
178
|
+
_add_install(sub)
|
|
179
|
+
_add_create_pkg(sub)
|
|
180
|
+
_add_update_pkg(sub)
|
|
181
|
+
_add_close_pkg(sub)
|
|
182
|
+
_add_actions(sub)
|
|
183
|
+
return parser
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _handle_make_config(args):
|
|
187
|
+
wrote = config.write_template(args.output)
|
|
188
|
+
return 0 if wrote else 1
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _handle_install(args):
|
|
192
|
+
cfg = config.load_main(args.config)
|
|
193
|
+
existing = []
|
|
194
|
+
readme_path = os.path.join(config.BASE_DIR, "README.txt")
|
|
195
|
+
baseline_path = os.path.join(snapshot.STATE_DIR, "baseline.json")
|
|
196
|
+
if os.path.exists(readme_path):
|
|
197
|
+
existing.append(readme_path)
|
|
198
|
+
if os.path.exists(baseline_path):
|
|
199
|
+
existing.append(baseline_path)
|
|
200
|
+
if existing:
|
|
201
|
+
print("[install] existing install artifacts found:")
|
|
202
|
+
for path in existing:
|
|
203
|
+
print(" - %s" % path)
|
|
204
|
+
print("[install] remove these files to re-run install")
|
|
205
|
+
return 1
|
|
206
|
+
print("[install] step 1/2: shell integration")
|
|
207
|
+
release.ensure_environment()
|
|
208
|
+
print("[install] step 2/2: baseline snapshot")
|
|
209
|
+
progress = snapshot.ProgressReporter("scan")
|
|
210
|
+
snapshot.create_baseline(cfg, prompt_overwrite=True, progress=progress)
|
|
211
|
+
return 0
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _handle_snapshot(args):
|
|
215
|
+
cfg = config.load_main(args.config)
|
|
216
|
+
snapshot.create_snapshot(cfg)
|
|
217
|
+
return 0
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _handle_create_pkg(args):
|
|
221
|
+
cfg = config.load_main(args.config)
|
|
222
|
+
release.create_pkg(cfg, args.pkg_id)
|
|
223
|
+
_run_auto_actions(cfg, "create_pkg", config_path=args.config)
|
|
224
|
+
return 0
|
|
225
|
+
|
|
226
|
+
def _handle_update_pkg(args):
|
|
227
|
+
cfg = config.load_main(args.config)
|
|
228
|
+
if args.release:
|
|
229
|
+
release.finalize_pkg_release(cfg, args.pkg_id)
|
|
230
|
+
_run_auto_actions(cfg, "update_pkg_release", config_path=args.config)
|
|
231
|
+
return 0
|
|
232
|
+
release.update_pkg(cfg, args.pkg_id)
|
|
233
|
+
_run_auto_actions(cfg, "update_pkg", config_path=args.config)
|
|
234
|
+
return 0
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _handle_close_pkg(args):
|
|
238
|
+
cfg = config.load_main(args.config)
|
|
239
|
+
release.close_pkg(cfg, args.pkg_id)
|
|
240
|
+
_run_auto_actions(cfg, "close_pkg", config_path=args.config)
|
|
241
|
+
return 0
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _handle_watch(args):
|
|
245
|
+
cfg = config.load_main(args.config)
|
|
246
|
+
watch.run(
|
|
247
|
+
cfg,
|
|
248
|
+
run_once=args.once,
|
|
249
|
+
pkg_id=args.pkg,
|
|
250
|
+
auto_point=args.auto_point,
|
|
251
|
+
point_label=args.point_label,
|
|
252
|
+
)
|
|
253
|
+
return 0
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _handle_collect(args):
|
|
257
|
+
cfg = config.load_main(args.config)
|
|
258
|
+
release.collect_for_pkg(cfg, args.pkg, args.collectors)
|
|
259
|
+
return 0
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def _handle_actions(args):
|
|
263
|
+
cfg = config.load_main(args.config)
|
|
264
|
+
if not args.name:
|
|
265
|
+
actions = cfg.get("actions", {}) or {}
|
|
266
|
+
if not actions:
|
|
267
|
+
print("[actions] no actions configured")
|
|
268
|
+
return 0
|
|
269
|
+
_print_actions(actions)
|
|
270
|
+
return 0
|
|
271
|
+
release.run_actions(
|
|
272
|
+
cfg, [args.name], extra_args=args.action_args, config_path=args.config
|
|
273
|
+
)
|
|
274
|
+
return 0
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def _run_auto_actions(cfg, event, config_path=None):
|
|
278
|
+
auto_actions = cfg.get("auto_actions") or {}
|
|
279
|
+
names = auto_actions.get(event) or []
|
|
280
|
+
if not names:
|
|
281
|
+
return []
|
|
282
|
+
return release.run_actions(cfg, names, config_path=config_path)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def _print_actions(actions):
|
|
286
|
+
ordered = sorted(actions.keys())
|
|
287
|
+
print("[actions] available:")
|
|
288
|
+
for idx, name in enumerate(ordered, 1):
|
|
289
|
+
entries = actions.get(name) or []
|
|
290
|
+
if isinstance(entries, dict):
|
|
291
|
+
count = 1
|
|
292
|
+
else:
|
|
293
|
+
count = len(entries)
|
|
294
|
+
print(" %d) %s (%d command(s))" % (idx, name, count))
|
|
295
|
+
return ordered
|
|
296
|
+
|
|
297
|
+
def _handle_point(args):
|
|
298
|
+
cfg = config.load_main(args.config)
|
|
299
|
+
if args.list:
|
|
300
|
+
release.list_points(cfg, args.pkg)
|
|
301
|
+
return 0
|
|
302
|
+
release.create_point(cfg, args.pkg, label=args.label, actions_run=args.actions_run)
|
|
303
|
+
return 0
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def main(argv=None):
|
|
307
|
+
argv = argv if argv is not None else sys.argv[1:]
|
|
308
|
+
parser = build_parser()
|
|
309
|
+
if not argv:
|
|
310
|
+
parser.print_help()
|
|
311
|
+
return 0
|
|
312
|
+
args = parser.parse_args(argv)
|
|
313
|
+
if not hasattr(args, "func"):
|
|
314
|
+
parser.print_help()
|
|
315
|
+
return 0
|
|
316
|
+
return args.func(args)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
if __name__ == "__main__":
|
|
320
|
+
sys.exit(main())
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
"""Collector interface definitions."""
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CollectorResult(dict):
|
|
6
|
+
"""Lightweight result mapping for collector outputs."""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Collector:
|
|
10
|
+
"""Base collector contract."""
|
|
11
|
+
|
|
12
|
+
name = "base"
|
|
13
|
+
|
|
14
|
+
def run(self, pkg_ctx, cfg):
|
|
15
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
"""Checksum collector stub."""
|
|
3
|
+
|
|
4
|
+
import hashlib
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from .base import Collector, CollectorResult
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ChecksumsCollector(Collector):
|
|
11
|
+
name = "checksums"
|
|
12
|
+
|
|
13
|
+
def run(self, pkg_ctx, cfg):
|
|
14
|
+
"""
|
|
15
|
+
Placeholder: walk pkg_ctx['paths'] and compute sha256.
|
|
16
|
+
pkg_ctx is expected to contain 'paths' list of absolute file paths.
|
|
17
|
+
"""
|
|
18
|
+
res = CollectorResult()
|
|
19
|
+
paths = pkg_ctx.get("paths", [])
|
|
20
|
+
for path in paths:
|
|
21
|
+
if not os.path.exists(path):
|
|
22
|
+
continue
|
|
23
|
+
res[path] = sha256_of_file(path)
|
|
24
|
+
return res
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def sha256_of_file(path, chunk=1024 * 1024):
|
|
28
|
+
h = hashlib.sha256()
|
|
29
|
+
with open(path, "rb") as f:
|
|
30
|
+
while True:
|
|
31
|
+
b = f.read(chunk)
|
|
32
|
+
if not b:
|
|
33
|
+
break
|
|
34
|
+
h.update(b)
|
|
35
|
+
return h.hexdigest()
|