omdev 0.0.0.dev212__py3-none-any.whl → 0.0.0.dev214__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.
- omdev/.manifests.json +1 -1
- omdev/cc/cdeps.py +34 -1
- omdev/cc/cdeps.toml +19 -2
- omdev/cc/cli.py +13 -1
- omdev/ci/__init__.py +1 -0
- omdev/ci/cache.py +100 -121
- omdev/ci/ci.py +161 -136
- omdev/ci/cli.py +62 -30
- omdev/ci/compose.py +26 -62
- omdev/ci/consts.py +1 -0
- omdev/ci/docker.py +39 -22
- omdev/ci/github/{cacheapi.py → api.py} +1 -2
- omdev/ci/github/bootstrap.py +8 -1
- omdev/ci/github/cache.py +36 -320
- omdev/ci/github/cli.py +9 -5
- omdev/ci/github/client.py +492 -0
- omdev/ci/github/env.py +21 -0
- omdev/ci/requirements.py +0 -1
- omdev/ci/shell.py +0 -1
- omdev/ci/utils.py +2 -14
- omdev/git/shallow.py +1 -1
- omdev/scripts/ci.py +1602 -887
- omdev/scripts/interp.py +23 -0
- omdev/scripts/pyproject.py +23 -0
- omdev/tokens/tokenizert.py +1 -3
- omdev/tools/docker.py +6 -0
- {omdev-0.0.0.dev212.dist-info → omdev-0.0.0.dev214.dist-info}/METADATA +2 -2
- {omdev-0.0.0.dev212.dist-info → omdev-0.0.0.dev214.dist-info}/RECORD +32 -29
- {omdev-0.0.0.dev212.dist-info → omdev-0.0.0.dev214.dist-info}/LICENSE +0 -0
- {omdev-0.0.0.dev212.dist-info → omdev-0.0.0.dev214.dist-info}/WHEEL +0 -0
- {omdev-0.0.0.dev212.dist-info → omdev-0.0.0.dev214.dist-info}/entry_points.txt +0 -0
- {omdev-0.0.0.dev212.dist-info → omdev-0.0.0.dev214.dist-info}/top_level.txt +0 -0
omdev/.manifests.json
CHANGED
omdev/cc/cdeps.py
CHANGED
@@ -5,6 +5,7 @@ import typing as ta
|
|
5
5
|
from omlish import cached
|
6
6
|
from omlish import lang
|
7
7
|
from omlish import marshal as msh
|
8
|
+
from omlish.configs import all as configs
|
8
9
|
|
9
10
|
|
10
11
|
@dc.dataclass(frozen=True)
|
@@ -20,19 +21,51 @@ class Cdep:
|
|
20
21
|
|
21
22
|
#
|
22
23
|
|
24
|
+
sources: ta.Sequence[str] | None = None
|
23
25
|
include: ta.Sequence[str] | None = None
|
24
26
|
|
25
27
|
#
|
26
28
|
|
27
29
|
@dc.dataclass(frozen=True)
|
28
30
|
class Cmake:
|
29
|
-
|
31
|
+
@dc.dataclass(frozen=True)
|
32
|
+
class FetchContent:
|
33
|
+
url: str | None = None
|
34
|
+
|
35
|
+
@dc.dataclass(frozen=True)
|
36
|
+
class Git:
|
37
|
+
repository: str | None = None
|
38
|
+
tag: str | None = None
|
39
|
+
|
40
|
+
git: Git | None = None
|
41
|
+
|
42
|
+
fetch_content: FetchContent | None = None
|
30
43
|
|
31
44
|
cmake: Cmake | None = None
|
32
45
|
|
33
46
|
|
47
|
+
def process_marshaled_cdep(obj: ta.Any) -> ta.Any:
|
48
|
+
obj = configs.processing.matched_rewrite(
|
49
|
+
lambda s: s if isinstance(s, str) else ''.join(s),
|
50
|
+
obj,
|
51
|
+
('sources', None),
|
52
|
+
('include', None),
|
53
|
+
)
|
54
|
+
|
55
|
+
return obj
|
56
|
+
|
57
|
+
|
34
58
|
@cached.function
|
35
59
|
def load_cdeps() -> ta.Mapping[str, Cdep]:
|
36
60
|
src = lang.get_relative_resources(globals=globals())['cdeps.toml'].read_text()
|
37
61
|
dct = tomllib.loads(src)
|
62
|
+
|
63
|
+
dct = {
|
64
|
+
**dct,
|
65
|
+
'deps': {
|
66
|
+
k: process_marshaled_cdep(v)
|
67
|
+
for k, v in dct.get('deps', {}).items()
|
68
|
+
},
|
69
|
+
}
|
70
|
+
|
38
71
|
return msh.unmarshal(dct.get('deps', {}), ta.Mapping[str, Cdep]) # type: ignore
|
omdev/cc/cdeps.toml
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
[deps.httplib]
|
2
|
+
include = ['.']
|
3
|
+
|
4
|
+
[deps.httplib.git]
|
5
|
+
url = 'https://github.com/yhirose/cpp-httplib'
|
6
|
+
rev = 'a7bc00e3307fecdb4d67545e93be7b88cfb1e186'
|
7
|
+
subtrees = ['httplib.h']
|
8
|
+
|
9
|
+
[deps.httplib.cmake.fetch_content.git]
|
10
|
+
repository = 'https://github.com/yhirose/cpp-httplib.git'
|
11
|
+
tag = 'a7bc00e3307fecdb4d67545e93be7b88cfb1e186'
|
12
|
+
|
13
|
+
|
14
|
+
#
|
15
|
+
|
1
16
|
[deps.json]
|
2
17
|
include = ['single_include']
|
3
18
|
|
@@ -6,8 +21,9 @@ url = 'https://github.com/nlohmann/json'
|
|
6
21
|
rev = '9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03'
|
7
22
|
subtrees = ['single_include']
|
8
23
|
|
9
|
-
[deps.json.cmake]
|
10
|
-
|
24
|
+
[deps.json.cmake.fetch_content]
|
25
|
+
url = 'https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz'
|
26
|
+
|
11
27
|
|
12
28
|
#
|
13
29
|
|
@@ -19,6 +35,7 @@ url = 'https://github.com/pybind/pybind11'
|
|
19
35
|
rev = '945e251a6ce7273058b36214d94415e9c9530b8e'
|
20
36
|
subtrees = ['include']
|
21
37
|
|
38
|
+
|
22
39
|
#
|
23
40
|
|
24
41
|
[deps.ut]
|
omdev/cc/cli.py
CHANGED
@@ -18,6 +18,8 @@ Freestanding options:
|
|
18
18
|
TODO:
|
19
19
|
- cext interop
|
20
20
|
- gen cmake
|
21
|
+
- fix CFLAGS/CCFLAGS/CPPFLAGS/CXXFLAGS
|
22
|
+
- jit-gen cmake mode? multi-src builds
|
21
23
|
"""
|
22
24
|
import os
|
23
25
|
import shlex
|
@@ -35,6 +37,7 @@ from .. import magic
|
|
35
37
|
from ..cache import data as dcache
|
36
38
|
from .cdeps import Cdep
|
37
39
|
from .cdeps import load_cdeps
|
40
|
+
from .cdeps import process_marshaled_cdep
|
38
41
|
|
39
42
|
|
40
43
|
class Cli(ap.Cli):
|
@@ -64,16 +67,22 @@ class Cli(ap.Cli):
|
|
64
67
|
if src_magic.key == '@omlish-cdeps':
|
65
68
|
for dep in check.isinstance(src_magic.prepared, ta.Sequence):
|
66
69
|
if isinstance(dep, ta.Mapping):
|
67
|
-
dep =
|
70
|
+
dep = process_marshaled_cdep(dep)
|
71
|
+
dep = msh.unmarshal(dep, Cdep)
|
68
72
|
else:
|
69
73
|
dep = load_cdeps()[check.isinstance(dep, str)]
|
70
74
|
|
75
|
+
if dep.sources:
|
76
|
+
# TODO
|
77
|
+
raise NotImplementedError
|
78
|
+
|
71
79
|
dep_spec = dcache.GitSpec(
|
72
80
|
url=dep.git.url,
|
73
81
|
rev=dep.git.rev,
|
74
82
|
subtrees=dep.git.subtrees,
|
75
83
|
)
|
76
84
|
dep_dir = dcache.default().get(dep_spec)
|
85
|
+
|
77
86
|
for dep_inc in dep.include or []:
|
78
87
|
inc_dir = os.path.join(dep_dir, dep_inc)
|
79
88
|
check.state(os.path.isdir(inc_dir))
|
@@ -96,6 +105,9 @@ class Cli(ap.Cli):
|
|
96
105
|
if cflags := os.environ.get('CFLAGS'):
|
97
106
|
sh_parts.append(cflags) # Explicitly shell-unquoted
|
98
107
|
|
108
|
+
if ldflags := os.environ.get('LDFLAGS'):
|
109
|
+
sh_parts.append(ldflags) # Explicitly shell-unquoted
|
110
|
+
|
99
111
|
sh_parts.extend([
|
100
112
|
'-std=c++20',
|
101
113
|
shlex.quote(os.path.abspath(src_file)),
|
omdev/ci/__init__.py
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
# @omlish-lite
|
omdev/ci/cache.py
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
|
-
# @omlish-lite
|
3
2
|
import abc
|
4
3
|
import os.path
|
5
|
-
import shlex
|
6
4
|
import shutil
|
7
5
|
import typing as ta
|
8
6
|
|
9
|
-
from .
|
7
|
+
from omlish.lite.cached import cached_nullary
|
8
|
+
from omlish.lite.check import check
|
9
|
+
from omlish.lite.logs import log
|
10
|
+
|
11
|
+
from .consts import CI_CACHE_VERSION
|
10
12
|
|
11
13
|
|
12
14
|
##
|
@@ -14,12 +16,35 @@ from .shell import ShellCmd
|
|
14
16
|
|
15
17
|
@abc.abstractmethod
|
16
18
|
class FileCache(abc.ABC):
|
19
|
+
def __init__(
|
20
|
+
self,
|
21
|
+
*,
|
22
|
+
version: int = CI_CACHE_VERSION,
|
23
|
+
) -> None:
|
24
|
+
super().__init__()
|
25
|
+
|
26
|
+
check.isinstance(version, int)
|
27
|
+
check.arg(version >= 0)
|
28
|
+
self._version = version
|
29
|
+
|
30
|
+
@property
|
31
|
+
def version(self) -> int:
|
32
|
+
return self._version
|
33
|
+
|
34
|
+
#
|
35
|
+
|
17
36
|
@abc.abstractmethod
|
18
|
-
def get_file(self, key: str) -> ta.Optional[str]:
|
37
|
+
def get_file(self, key: str) -> ta.Awaitable[ta.Optional[str]]:
|
19
38
|
raise NotImplementedError
|
20
39
|
|
21
40
|
@abc.abstractmethod
|
22
|
-
def put_file(
|
41
|
+
def put_file(
|
42
|
+
self,
|
43
|
+
key: str,
|
44
|
+
file_path: str,
|
45
|
+
*,
|
46
|
+
steal: bool = False,
|
47
|
+
) -> ta.Awaitable[str]:
|
23
48
|
raise NotImplementedError
|
24
49
|
|
25
50
|
|
@@ -27,142 +52,96 @@ class FileCache(abc.ABC):
|
|
27
52
|
|
28
53
|
|
29
54
|
class DirectoryFileCache(FileCache):
|
30
|
-
def __init__(
|
31
|
-
super().__init__()
|
32
|
-
|
33
|
-
self._dir = dir
|
34
|
-
|
35
|
-
#
|
36
|
-
|
37
|
-
def get_cache_file_path(
|
55
|
+
def __init__(
|
38
56
|
self,
|
39
|
-
|
57
|
+
dir: str, # noqa
|
40
58
|
*,
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
59
|
+
no_create: bool = False,
|
60
|
+
no_purge: bool = False,
|
61
|
+
**kwargs: ta.Any,
|
62
|
+
) -> None: # noqa
|
63
|
+
super().__init__(**kwargs)
|
46
64
|
|
47
|
-
|
48
|
-
|
65
|
+
self._dir = dir
|
66
|
+
self._no_create = no_create
|
67
|
+
self._no_purge = no_purge
|
49
68
|
|
50
69
|
#
|
51
70
|
|
52
|
-
|
53
|
-
cache_file_path = self.get_cache_file_path(key)
|
54
|
-
if not os.path.exists(cache_file_path):
|
55
|
-
return None
|
56
|
-
return cache_file_path
|
57
|
-
|
58
|
-
def put_file(self, key: str, file_path: str) -> None:
|
59
|
-
cache_file_path = self.get_cache_file_path(key, make_dirs=True)
|
60
|
-
shutil.copyfile(file_path, cache_file_path)
|
61
|
-
|
62
|
-
|
63
|
-
##
|
64
|
-
|
65
|
-
|
66
|
-
class ShellCache(abc.ABC):
|
67
|
-
@abc.abstractmethod
|
68
|
-
def get_file_cmd(self, key: str) -> ta.Optional[ShellCmd]:
|
69
|
-
raise NotImplementedError
|
70
|
-
|
71
|
-
class PutFileCmdContext(abc.ABC):
|
72
|
-
def __init__(self) -> None:
|
73
|
-
super().__init__()
|
74
|
-
|
75
|
-
self._state: ta.Literal['open', 'committed', 'aborted'] = 'open'
|
76
|
-
|
77
|
-
@property
|
78
|
-
def state(self) -> ta.Literal['open', 'committed', 'aborted']:
|
79
|
-
return self._state
|
71
|
+
VERSION_FILE_NAME = '.ci-cache-version'
|
80
72
|
|
81
|
-
|
73
|
+
@cached_nullary
|
74
|
+
def setup_dir(self) -> None:
|
75
|
+
version_file = os.path.join(self._dir, self.VERSION_FILE_NAME)
|
82
76
|
|
83
|
-
|
84
|
-
|
85
|
-
def cmd(self) -> ShellCmd:
|
86
|
-
raise NotImplementedError
|
77
|
+
if self._no_create:
|
78
|
+
check.state(os.path.isdir(self._dir))
|
87
79
|
|
88
|
-
|
80
|
+
elif not os.path.isdir(self._dir):
|
81
|
+
os.makedirs(self._dir)
|
82
|
+
with open(version_file, 'w') as f:
|
83
|
+
f.write(str(self._version))
|
84
|
+
return
|
89
85
|
|
90
|
-
|
91
|
-
|
86
|
+
with open(version_file) as f:
|
87
|
+
dir_version = int(f.read().strip())
|
92
88
|
|
93
|
-
|
94
|
-
|
95
|
-
self.commit()
|
96
|
-
else:
|
97
|
-
self.abort()
|
89
|
+
if dir_version == self._version:
|
90
|
+
return
|
98
91
|
|
99
|
-
|
92
|
+
if self._no_purge:
|
93
|
+
raise RuntimeError(f'{dir_version=} != {self._version=}')
|
100
94
|
|
101
|
-
|
102
|
-
|
103
|
-
raise
|
95
|
+
dirs = [n for n in sorted(os.listdir(self._dir)) if os.path.isdir(os.path.join(self._dir, n))]
|
96
|
+
if dirs:
|
97
|
+
raise RuntimeError(
|
98
|
+
f'Refusing to remove stale cache dir {self._dir!r} '
|
99
|
+
f'due to present directories: {", ".join(dirs)}',
|
100
|
+
)
|
104
101
|
|
105
|
-
|
106
|
-
if
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
raise RuntimeError(self._state)
|
102
|
+
for n in sorted(os.listdir(self._dir)):
|
103
|
+
if n.startswith('.'):
|
104
|
+
continue
|
105
|
+
fp = os.path.join(self._dir, n)
|
106
|
+
check.state(os.path.isfile(fp))
|
107
|
+
log.debug('Purging stale cache file: %s', fp)
|
108
|
+
os.unlink(fp)
|
113
109
|
|
114
|
-
|
115
|
-
|
116
|
-
@abc.abstractmethod
|
117
|
-
def _abort(self) -> None:
|
118
|
-
raise NotImplementedError
|
119
|
-
|
120
|
-
def abort(self) -> None:
|
121
|
-
if self._state == 'aborted':
|
122
|
-
return
|
123
|
-
elif self._state == 'open':
|
124
|
-
self._abort()
|
125
|
-
self._state = 'committed'
|
126
|
-
else:
|
127
|
-
raise RuntimeError(self._state)
|
128
|
-
|
129
|
-
@abc.abstractmethod
|
130
|
-
def put_file_cmd(self, key: str) -> PutFileCmdContext:
|
131
|
-
raise NotImplementedError
|
110
|
+
os.unlink(version_file)
|
132
111
|
|
112
|
+
with open(version_file, 'w') as f:
|
113
|
+
f.write(str(self._version))
|
133
114
|
|
134
|
-
#
|
115
|
+
#
|
135
116
|
|
117
|
+
def get_cache_file_path(
|
118
|
+
self,
|
119
|
+
key: str,
|
120
|
+
) -> str:
|
121
|
+
self.setup_dir()
|
122
|
+
return os.path.join(self._dir, key)
|
136
123
|
|
137
|
-
|
138
|
-
|
139
|
-
super().__init__()
|
124
|
+
def format_incomplete_file(self, f: str) -> str:
|
125
|
+
return os.path.join(os.path.dirname(f), f'_{os.path.basename(f)}.incomplete')
|
140
126
|
|
141
|
-
|
127
|
+
#
|
142
128
|
|
143
|
-
def
|
144
|
-
|
145
|
-
if
|
129
|
+
async def get_file(self, key: str) -> ta.Optional[str]:
|
130
|
+
cache_file_path = self.get_cache_file_path(key)
|
131
|
+
if not os.path.exists(cache_file_path):
|
146
132
|
return None
|
147
|
-
return
|
148
|
-
|
149
|
-
class _PutFileCmdContext(ShellCache.PutFileCmdContext): # noqa
|
150
|
-
def __init__(self, tf: str, f: str) -> None:
|
151
|
-
super().__init__()
|
152
|
-
|
153
|
-
self._tf = tf
|
154
|
-
self._f = f
|
155
|
-
|
156
|
-
@property
|
157
|
-
def cmd(self) -> ShellCmd:
|
158
|
-
return ShellCmd(f'cat > {shlex.quote(self._tf)}')
|
159
|
-
|
160
|
-
def _commit(self) -> None:
|
161
|
-
os.replace(self._tf, self._f)
|
162
|
-
|
163
|
-
def _abort(self) -> None:
|
164
|
-
os.unlink(self._tf)
|
133
|
+
return cache_file_path
|
165
134
|
|
166
|
-
def
|
167
|
-
|
168
|
-
|
135
|
+
async def put_file(
|
136
|
+
self,
|
137
|
+
key: str,
|
138
|
+
file_path: str,
|
139
|
+
*,
|
140
|
+
steal: bool = False,
|
141
|
+
) -> str:
|
142
|
+
cache_file_path = self.get_cache_file_path(key)
|
143
|
+
if steal:
|
144
|
+
shutil.move(file_path, cache_file_path)
|
145
|
+
else:
|
146
|
+
shutil.copyfile(file_path, cache_file_path)
|
147
|
+
return cache_file_path
|