omdev 0.0.0.dev111__tar.gz → 0.0.0.dev113__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.
Potentially problematic release.
This version of omdev might be problematic. Click here for more details.
- {omdev-0.0.0.dev111/omdev.egg-info → omdev-0.0.0.dev113}/PKG-INFO +2 -2
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/.manifests.json +13 -1
- omdev-0.0.0.dev113/omdev/git.py +403 -0
- omdev-0.0.0.dev113/omdev/pycharm/__main__.py +11 -0
- omdev-0.0.0.dev113/omdev/pycharm/cli.py +98 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/scripts/pyproject.py +1421 -1127
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/git.py +54 -0
- omdev-0.0.0.dev113/omdev/tools/pawk/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113/omdev.egg-info}/PKG-INFO +2 -2
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev.egg-info/SOURCES.txt +3 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev.egg-info/requires.txt +1 -1
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/pyproject.toml +2 -2
- omdev-0.0.0.dev111/omdev/git.py +0 -104
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/LICENSE +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/MANIFEST.in +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/README.rst +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/__about__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/amalg/__main__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/amalg/amalg.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/antlr/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/antlr/_antlr/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/antlr/consts.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/antlr/gen.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/bracepy.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/compute/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/compute/cache.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/compute/contexts.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/compute/currents.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/compute/fns.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/compute/resolvers.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/compute/storage.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/compute/types.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/data/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/data/actions.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/data/cache.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/data/consts.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/data/defaults.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/data/manifests.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cache/data/specs.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_boilerplate.cc +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/LICENSE +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/build_ext.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/compilers/options.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/dir_util.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/errors.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/extension.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/file_util.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/modified.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/spawn.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/sysconfig.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/util.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/_distutils/version.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/build.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/cmake.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/importhook.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/magic.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cexts/scan.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/classdot.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cli/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cli/__main__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cli/_pathhack.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cli/clicli.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cli/install.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cli/main.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cli/managers.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cli/types.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/clipboard/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/clipboard/clipboard.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/clipboard/darwin.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/cmake.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/findimports.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/imgur.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/interp/cli.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/interp/providers.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/interp/pyenv.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/interp/standalone.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/interp/system.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/interp/types.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/magic/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/magic/find.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/magic/magic.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/magic/prepare.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/magic/styles.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/manifests/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/manifests/build.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/manifests/load.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/manifests/types.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/mypy/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/packaging/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/packaging/marshal.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/packaging/names.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/packaging/requires.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/packaging/specifiers.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/packaging/versions.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/precheck/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/precheck/base.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/precheck/git.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/precheck/lite.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/precheck/main.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/precheck/manifests.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/precheck/scripts.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/ptk/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/ptk/apps/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/ptk/apps/ncdu.py +0 -0
- {omdev-0.0.0.dev111/omdev/tools/pawk → omdev-0.0.0.dev113/omdev/pycharm}/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/pyproject/__main__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/pyproject/cexts.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/pyproject/cli.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/pyproject/pkg.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/pyproject/reqs.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/revisions.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/scripts/bumpversion.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/scripts/execrss.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/scripts/exectime.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/scripts/importtrace.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/scripts/interp.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/scripts/slowcat.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/scripts/tmpexec.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/secrets.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tokens.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/toml/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/toml/parser.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/toml/writer.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/doc.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/docker.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/importscan.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/mkrelimp.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/notebook.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/pawk/__main__.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/pawk/pawk.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/pip.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/prof.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/qr.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev/wheelfile.py +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev.egg-info/entry_points.txt +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.0.dev111 → omdev-0.0.0.dev113}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev113
|
|
4
4
|
Summary: omdev
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Classifier: Operating System :: POSIX
|
|
13
13
|
Requires-Python: >=3.12
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: omlish==0.0.0.
|
|
15
|
+
Requires-Dist: omlish==0.0.0.dev113
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Requires-Dist: black~=24.10; extra == "all"
|
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
|
@@ -131,6 +131,18 @@
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
},
|
|
134
|
+
{
|
|
135
|
+
"module": ".pycharm.__main__",
|
|
136
|
+
"attr": "_CLI_MODULE",
|
|
137
|
+
"file": "omdev/pycharm/__main__.py",
|
|
138
|
+
"line": 4,
|
|
139
|
+
"value": {
|
|
140
|
+
"$.cli.types.CliModule": {
|
|
141
|
+
"cmd_name": "pycharm",
|
|
142
|
+
"mod_name": "omdev.pycharm.__main__"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
},
|
|
134
146
|
{
|
|
135
147
|
"module": ".pyproject.__main__",
|
|
136
148
|
"attr": "_CLI_MODULE",
|
|
@@ -231,7 +243,7 @@
|
|
|
231
243
|
"module": ".tools.git",
|
|
232
244
|
"attr": "_CLI_MODULE",
|
|
233
245
|
"file": "omdev/tools/git.py",
|
|
234
|
-
"line":
|
|
246
|
+
"line": 182,
|
|
235
247
|
"value": {
|
|
236
248
|
"$.cli.types.CliModule": {
|
|
237
249
|
"cmd_name": "git",
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
|
2
|
+
# @omlish-lite
|
|
3
|
+
"""
|
|
4
|
+
git status
|
|
5
|
+
--porcelain=v1
|
|
6
|
+
--ignore-submodules
|
|
7
|
+
2>/dev/null
|
|
8
|
+
"""
|
|
9
|
+
import dataclasses as dc
|
|
10
|
+
import enum
|
|
11
|
+
import os.path
|
|
12
|
+
import subprocess
|
|
13
|
+
import typing as ta
|
|
14
|
+
|
|
15
|
+
from omlish.lite.check import check_state
|
|
16
|
+
from omlish.lite.subprocesses import subprocess_maybe_shell_wrap_exec
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def git_clone_subtree(
|
|
23
|
+
*,
|
|
24
|
+
base_dir: str,
|
|
25
|
+
repo_url: str,
|
|
26
|
+
repo_dir: str,
|
|
27
|
+
branch: ta.Optional[str] = None,
|
|
28
|
+
rev: ta.Optional[str] = None,
|
|
29
|
+
repo_subtrees: ta.Sequence[str],
|
|
30
|
+
) -> None:
|
|
31
|
+
if not bool(branch) ^ bool(rev):
|
|
32
|
+
raise ValueError('must set branch or rev')
|
|
33
|
+
|
|
34
|
+
if isinstance(repo_subtrees, str):
|
|
35
|
+
raise TypeError(repo_subtrees)
|
|
36
|
+
|
|
37
|
+
git_opts = [
|
|
38
|
+
'-c', 'advice.detachedHead=false',
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
subprocess.check_call(
|
|
42
|
+
subprocess_maybe_shell_wrap_exec(
|
|
43
|
+
'git',
|
|
44
|
+
*git_opts,
|
|
45
|
+
'clone',
|
|
46
|
+
'-n',
|
|
47
|
+
'--depth=1',
|
|
48
|
+
'--filter=tree:0',
|
|
49
|
+
*(['-b', branch] if branch else []),
|
|
50
|
+
'--single-branch',
|
|
51
|
+
repo_url,
|
|
52
|
+
repo_dir,
|
|
53
|
+
),
|
|
54
|
+
cwd=base_dir,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
rd = os.path.join(base_dir, repo_dir)
|
|
58
|
+
subprocess.check_call(
|
|
59
|
+
subprocess_maybe_shell_wrap_exec(
|
|
60
|
+
'git',
|
|
61
|
+
*git_opts,
|
|
62
|
+
'sparse-checkout',
|
|
63
|
+
'set',
|
|
64
|
+
'--no-cone',
|
|
65
|
+
*repo_subtrees,
|
|
66
|
+
),
|
|
67
|
+
cwd=rd,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
subprocess.check_call(
|
|
71
|
+
subprocess_maybe_shell_wrap_exec(
|
|
72
|
+
'git',
|
|
73
|
+
*git_opts,
|
|
74
|
+
'checkout',
|
|
75
|
+
*([rev] if rev else []),
|
|
76
|
+
),
|
|
77
|
+
cwd=rd,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def get_git_revision(
|
|
82
|
+
*,
|
|
83
|
+
cwd: ta.Optional[str] = None,
|
|
84
|
+
) -> ta.Optional[str]:
|
|
85
|
+
subprocess.check_output(subprocess_maybe_shell_wrap_exec('git', '--version'))
|
|
86
|
+
|
|
87
|
+
if cwd is None:
|
|
88
|
+
cwd = os.getcwd()
|
|
89
|
+
|
|
90
|
+
if subprocess.run( # noqa
|
|
91
|
+
subprocess_maybe_shell_wrap_exec(
|
|
92
|
+
'git',
|
|
93
|
+
'rev-parse',
|
|
94
|
+
'--is-inside-work-tree',
|
|
95
|
+
),
|
|
96
|
+
stdout=subprocess.PIPE,
|
|
97
|
+
stderr=subprocess.PIPE,
|
|
98
|
+
).returncode:
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
has_untracked = bool(subprocess.check_output(subprocess_maybe_shell_wrap_exec(
|
|
102
|
+
'git',
|
|
103
|
+
'ls-files',
|
|
104
|
+
'.',
|
|
105
|
+
'--exclude-standard',
|
|
106
|
+
'--others',
|
|
107
|
+
), cwd=cwd).decode().strip())
|
|
108
|
+
|
|
109
|
+
dirty_rev = subprocess.check_output(subprocess_maybe_shell_wrap_exec(
|
|
110
|
+
'git',
|
|
111
|
+
'describe',
|
|
112
|
+
'--match=NeVeRmAtCh',
|
|
113
|
+
'--always',
|
|
114
|
+
'--abbrev=40',
|
|
115
|
+
'--dirty',
|
|
116
|
+
), cwd=cwd).decode().strip()
|
|
117
|
+
|
|
118
|
+
return dirty_rev + ('-untracked' if has_untracked else '')
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
##
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
_GIT_STATUS_LINE_ESCAPE_CODES: ta.Mapping[str, str] = {
|
|
125
|
+
'\\': '\\',
|
|
126
|
+
'"': '"',
|
|
127
|
+
'n': '\n',
|
|
128
|
+
't': '\t',
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def yield_git_status_line_fields(l: str) -> ta.Iterator[str]:
|
|
133
|
+
def find_any(chars: str, start: int = 0) -> int:
|
|
134
|
+
ret = -1
|
|
135
|
+
for c in chars:
|
|
136
|
+
if (found := l.find(c, start)) >= 0 and (ret < 0 or ret > found):
|
|
137
|
+
ret = found
|
|
138
|
+
return ret
|
|
139
|
+
|
|
140
|
+
p = 0
|
|
141
|
+
while True:
|
|
142
|
+
if l[p] == '"':
|
|
143
|
+
p += 1
|
|
144
|
+
s = []
|
|
145
|
+
while (n := find_any('\\"', p)) > 0:
|
|
146
|
+
if (c := l[n]) == '\\':
|
|
147
|
+
s.append(l[p:n])
|
|
148
|
+
s.append(_GIT_STATUS_LINE_ESCAPE_CODES[l[n + 1]])
|
|
149
|
+
p = n + 2
|
|
150
|
+
elif c == '"':
|
|
151
|
+
s.append(l[p:n])
|
|
152
|
+
p = n
|
|
153
|
+
break
|
|
154
|
+
else:
|
|
155
|
+
raise ValueError(l)
|
|
156
|
+
|
|
157
|
+
if l[p] != '"':
|
|
158
|
+
raise ValueError(l)
|
|
159
|
+
|
|
160
|
+
yield ''.join(s)
|
|
161
|
+
|
|
162
|
+
p += 1
|
|
163
|
+
if p == len(l):
|
|
164
|
+
return
|
|
165
|
+
elif l[p] != ' ':
|
|
166
|
+
raise ValueError(l)
|
|
167
|
+
|
|
168
|
+
p += 1
|
|
169
|
+
|
|
170
|
+
else:
|
|
171
|
+
if (e := l.find(' ', p)) < 0:
|
|
172
|
+
yield l[p:]
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
yield l[p:e]
|
|
176
|
+
p = e + 1
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
"""
|
|
180
|
+
When merge is occurring and was successful, or outside of a merge situation, X shows the status of the index and Y shows
|
|
181
|
+
the status of the working tree:
|
|
182
|
+
-------------------------------------------------
|
|
183
|
+
X Y Meaning
|
|
184
|
+
-------------------------------------------------
|
|
185
|
+
[AMD] not updated
|
|
186
|
+
M [ MTD] updated in index
|
|
187
|
+
T [ MTD] type changed in index
|
|
188
|
+
A [ MTD] added to index
|
|
189
|
+
D deleted from index
|
|
190
|
+
R [ MTD] renamed in index
|
|
191
|
+
C [ MTD] copied in index
|
|
192
|
+
[MTARC] index and work tree matches
|
|
193
|
+
[ MTARC] M work tree changed since index
|
|
194
|
+
[ MTARC] T type changed in work tree since index
|
|
195
|
+
[ MTARC] D deleted in work tree
|
|
196
|
+
R renamed in work tree
|
|
197
|
+
C copied in work tree
|
|
198
|
+
|
|
199
|
+
When merge conflict has occurred and has not yet been resolved, X and Y show the state introduced by each head of the
|
|
200
|
+
merge, relative to the common ancestor:
|
|
201
|
+
-------------------------------------------------
|
|
202
|
+
X Y Meaning
|
|
203
|
+
-------------------------------------------------
|
|
204
|
+
D D unmerged, both deleted
|
|
205
|
+
A U unmerged, added by us
|
|
206
|
+
U D unmerged, deleted by them
|
|
207
|
+
U A unmerged, added by them
|
|
208
|
+
D U unmerged, deleted by us
|
|
209
|
+
A A unmerged, both added
|
|
210
|
+
U U unmerged, both modified
|
|
211
|
+
|
|
212
|
+
When path is untracked, X and Y are always the same, since they are unknown to the index:
|
|
213
|
+
-------------------------------------------------
|
|
214
|
+
X Y Meaning
|
|
215
|
+
-------------------------------------------------
|
|
216
|
+
? ? untracked
|
|
217
|
+
! ! ignored
|
|
218
|
+
|
|
219
|
+
Submodules have more state and instead report
|
|
220
|
+
|
|
221
|
+
- M = the submodule has a different HEAD than recorded in the index
|
|
222
|
+
- m = the submodule has modified content
|
|
223
|
+
- ? = the submodule has untracked files
|
|
224
|
+
|
|
225
|
+
This is since modified content or untracked files in a submodule cannot be added via git add in the superproject to
|
|
226
|
+
prepare a commit. m and ? are applied recursively. For example if a nested submodule in a submodule contains an
|
|
227
|
+
untracked file, this is reported as ? as well.
|
|
228
|
+
""" # noqa
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class GitStatusLineState(enum.Enum):
|
|
232
|
+
UNMODIFIED = ' '
|
|
233
|
+
MODIFIED = 'M'
|
|
234
|
+
FILE_TYPE_CHANGED = 'T'
|
|
235
|
+
ADDED = 'A'
|
|
236
|
+
DELETED = 'D'
|
|
237
|
+
RENAMED = 'R'
|
|
238
|
+
COPIED = 'C'
|
|
239
|
+
UPDATED_BUT_UNMERGED = 'U'
|
|
240
|
+
UNTRACKED = '?'
|
|
241
|
+
IGNORED = '!'
|
|
242
|
+
SUBMODULE_MODIFIED_CONTENT = 'm'
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
_EXTRA_UNMERGED_GIT_STATUS_LINE_STATES: ta.FrozenSet[ta.Tuple[GitStatusLineState, GitStatusLineState]] = frozenset([
|
|
246
|
+
(GitStatusLineState.ADDED, GitStatusLineState.ADDED),
|
|
247
|
+
(GitStatusLineState.DELETED, GitStatusLineState.DELETED),
|
|
248
|
+
])
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
@dc.dataclass(frozen=True)
|
|
252
|
+
class GitStatusLine:
|
|
253
|
+
x: GitStatusLineState
|
|
254
|
+
y: GitStatusLineState
|
|
255
|
+
|
|
256
|
+
a: str
|
|
257
|
+
b: ta.Optional[str]
|
|
258
|
+
|
|
259
|
+
@property
|
|
260
|
+
def is_unmerged(self) -> bool:
|
|
261
|
+
return (
|
|
262
|
+
self.x is GitStatusLineState.UPDATED_BUT_UNMERGED or
|
|
263
|
+
self.y is GitStatusLineState.UPDATED_BUT_UNMERGED or
|
|
264
|
+
(self.x, self.y) in _EXTRA_UNMERGED_GIT_STATUS_LINE_STATES
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
def __repr__(self) -> str:
|
|
268
|
+
return (
|
|
269
|
+
f'{self.__class__.__name__}('
|
|
270
|
+
f'x={self.x.name}, '
|
|
271
|
+
f'y={self.y.name}, '
|
|
272
|
+
f'a={self.a!r}' +
|
|
273
|
+
(f', b={self.b!r}' if self.b is not None else '') +
|
|
274
|
+
')'
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def parse_git_status_line(l: str) -> GitStatusLine:
|
|
279
|
+
if len(l) < 3 or l[2] != ' ':
|
|
280
|
+
raise ValueError(l)
|
|
281
|
+
x, y = l[0], l[1]
|
|
282
|
+
|
|
283
|
+
fields = list(yield_git_status_line_fields(l[3:]))
|
|
284
|
+
if len(fields) == 1:
|
|
285
|
+
a, b = fields[0], None
|
|
286
|
+
elif len(fields) == 3:
|
|
287
|
+
check_state(fields[1] == '->', l)
|
|
288
|
+
a, b = fields[0], fields[2]
|
|
289
|
+
else:
|
|
290
|
+
raise ValueError(l)
|
|
291
|
+
|
|
292
|
+
return GitStatusLine(
|
|
293
|
+
GitStatusLineState(x),
|
|
294
|
+
GitStatusLineState(y),
|
|
295
|
+
a,
|
|
296
|
+
b,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class GitStatus(ta.Sequence[GitStatusLine]):
|
|
301
|
+
def __init__(self, lines: ta.Iterable[GitStatusLine]) -> None:
|
|
302
|
+
super().__init__()
|
|
303
|
+
|
|
304
|
+
self._lst = list(lines)
|
|
305
|
+
|
|
306
|
+
by_x: ta.Dict[GitStatusLineState, list[GitStatusLine]] = {}
|
|
307
|
+
by_y: ta.Dict[GitStatusLineState, list[GitStatusLine]] = {}
|
|
308
|
+
|
|
309
|
+
by_a: ta.Dict[str, GitStatusLine] = {}
|
|
310
|
+
by_b: ta.Dict[str, GitStatusLine] = {}
|
|
311
|
+
|
|
312
|
+
for l in self._lst:
|
|
313
|
+
by_x.setdefault(l.x, []).append(l)
|
|
314
|
+
by_y.setdefault(l.y, []).append(l)
|
|
315
|
+
|
|
316
|
+
if l.a in by_a:
|
|
317
|
+
raise KeyError(l.a)
|
|
318
|
+
by_a[l.a] = l
|
|
319
|
+
|
|
320
|
+
if l.b is not None:
|
|
321
|
+
if l.b in by_b:
|
|
322
|
+
raise KeyError(l.b)
|
|
323
|
+
by_b[l.b] = l
|
|
324
|
+
|
|
325
|
+
self._by_x = by_x
|
|
326
|
+
self._by_y = by_y
|
|
327
|
+
|
|
328
|
+
self._by_a = by_a
|
|
329
|
+
self._by_b = by_b
|
|
330
|
+
|
|
331
|
+
self._has_unmerged = any(l.is_unmerged for l in self)
|
|
332
|
+
|
|
333
|
+
#
|
|
334
|
+
|
|
335
|
+
def __iter__(self) -> ta.Iterator[GitStatusLine]:
|
|
336
|
+
return iter(self._lst)
|
|
337
|
+
|
|
338
|
+
def __getitem__(self, index):
|
|
339
|
+
return self._lst[index]
|
|
340
|
+
|
|
341
|
+
def __len__(self) -> int:
|
|
342
|
+
return len(self._lst)
|
|
343
|
+
|
|
344
|
+
#
|
|
345
|
+
|
|
346
|
+
@property
|
|
347
|
+
def by_x(self) -> ta.Mapping[GitStatusLineState, ta.Sequence[GitStatusLine]]:
|
|
348
|
+
return self._by_x
|
|
349
|
+
|
|
350
|
+
@property
|
|
351
|
+
def by_y(self) -> ta.Mapping[GitStatusLineState, ta.Sequence[GitStatusLine]]:
|
|
352
|
+
return self._by_y
|
|
353
|
+
|
|
354
|
+
@property
|
|
355
|
+
def by_a(self) -> ta.Mapping[str, GitStatusLine]:
|
|
356
|
+
return self._by_a
|
|
357
|
+
|
|
358
|
+
@property
|
|
359
|
+
def by_b(self) -> ta.Mapping[str, GitStatusLine]:
|
|
360
|
+
return self._by_b
|
|
361
|
+
|
|
362
|
+
#
|
|
363
|
+
|
|
364
|
+
@property
|
|
365
|
+
def has_unmerged(self) -> bool:
|
|
366
|
+
return self._has_unmerged
|
|
367
|
+
|
|
368
|
+
@property
|
|
369
|
+
def has_staged(self) -> bool:
|
|
370
|
+
return any(l.x != GitStatusLineState.UNMODIFIED for l in self._lst)
|
|
371
|
+
|
|
372
|
+
@property
|
|
373
|
+
def has_dirty(self) -> bool:
|
|
374
|
+
return any(l.y != GitStatusLineState.UNMODIFIED for l in self._lst)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def parse_git_status(s: str) -> GitStatus:
|
|
378
|
+
return GitStatus(parse_git_status_line(l) for l in s.splitlines())
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def get_git_status(
|
|
382
|
+
*,
|
|
383
|
+
cwd: ta.Optional[str] = None,
|
|
384
|
+
ignore_submodules: bool = False,
|
|
385
|
+
verbose: bool = False,
|
|
386
|
+
) -> GitStatus:
|
|
387
|
+
if cwd is None:
|
|
388
|
+
cwd = os.getcwd()
|
|
389
|
+
|
|
390
|
+
proc = subprocess.run( # type: ignore
|
|
391
|
+
subprocess_maybe_shell_wrap_exec(
|
|
392
|
+
'git',
|
|
393
|
+
'status',
|
|
394
|
+
'--porcelain=v1',
|
|
395
|
+
*(['--ignore-submodules'] if ignore_submodules else []),
|
|
396
|
+
),
|
|
397
|
+
cwd=cwd,
|
|
398
|
+
stdout=subprocess.PIPE,
|
|
399
|
+
**(dict(stderr=subprocess.PIPE) if not verbose else {}),
|
|
400
|
+
check=True,
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
return parse_git_status(proc.stdout.decode()) # noqa
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- PyCharm.app/Contents/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_constants.py -> USE_LOW_IMPACT_MONITORING
|
|
4
|
+
"""
|
|
5
|
+
import inspect
|
|
6
|
+
import os.path
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
import tempfile
|
|
10
|
+
|
|
11
|
+
from omlish import argparse as ap
|
|
12
|
+
from omlish.diag.pycharm import get_pycharm_version
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
_DARWIN_OPEN_SCRIPT = """
|
|
16
|
+
tell application "PyCharm"
|
|
17
|
+
activate
|
|
18
|
+
open "{dir}"
|
|
19
|
+
end tell
|
|
20
|
+
return
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
_LINUX_OPEN_SCRIPT = """
|
|
25
|
+
# Check if PyCharm is already running
|
|
26
|
+
if pgrep -x "pycharm.sh" > /dev/null; then
|
|
27
|
+
echo "PyCharm is already running. Opening project..."
|
|
28
|
+
|
|
29
|
+
# Bring PyCharm to the foreground
|
|
30
|
+
wmctrl -a "PyCharm"
|
|
31
|
+
|
|
32
|
+
# Simulate the keyboard shortcut to open a new project
|
|
33
|
+
xdotool key --delay 100 ctrl+shift+a
|
|
34
|
+
xdotool type "$PROJECT_PATH"
|
|
35
|
+
xdotool key Return
|
|
36
|
+
|
|
37
|
+
else
|
|
38
|
+
echo "Starting PyCharm with project..."
|
|
39
|
+
nohup pycharm.sh "$PROJECT_PATH" > /dev/null 2>&1 &
|
|
40
|
+
fi
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class Cli(ap.Cli):
|
|
45
|
+
@ap.command()
|
|
46
|
+
def version(self) -> None:
|
|
47
|
+
print(get_pycharm_version())
|
|
48
|
+
|
|
49
|
+
@ap.command(
|
|
50
|
+
ap.arg('python-exe'),
|
|
51
|
+
ap.arg('args', nargs=ap.REMAINDER),
|
|
52
|
+
)
|
|
53
|
+
def runhack(self) -> int:
|
|
54
|
+
if not os.path.isfile(exe := self.args.python_exe):
|
|
55
|
+
raise FileNotFoundError(exe)
|
|
56
|
+
|
|
57
|
+
from omlish.diag._pycharm import runhack # noqa
|
|
58
|
+
src = inspect.getsource(runhack)
|
|
59
|
+
|
|
60
|
+
src_file = tempfile.mktemp(__package__ + '-runhack') # noqa
|
|
61
|
+
with open(src_file, 'w') as f:
|
|
62
|
+
f.write(src)
|
|
63
|
+
|
|
64
|
+
proc = subprocess.run([exe, src_file, *self.args.args], check=False)
|
|
65
|
+
return proc.returncode
|
|
66
|
+
|
|
67
|
+
@ap.command(
|
|
68
|
+
ap.arg('dir', nargs='?'),
|
|
69
|
+
)
|
|
70
|
+
def open(self) -> None:
|
|
71
|
+
dir = os.path.abspath(self.args.dir or '.') # noqa
|
|
72
|
+
|
|
73
|
+
if (plat := sys.platform) == 'darwin':
|
|
74
|
+
if '"' in dir:
|
|
75
|
+
raise ValueError(dir)
|
|
76
|
+
|
|
77
|
+
scpt_src = _DARWIN_OPEN_SCRIPT.format(dir=dir)
|
|
78
|
+
|
|
79
|
+
scpt_file = tempfile.mktemp(__package__ + '-pycharm-open') # noqa
|
|
80
|
+
with open(scpt_file, 'w') as f:
|
|
81
|
+
f.write(scpt_src)
|
|
82
|
+
|
|
83
|
+
subprocess.check_call(['osascript', scpt_file])
|
|
84
|
+
|
|
85
|
+
elif plat == 'linux':
|
|
86
|
+
# FIXME:
|
|
87
|
+
raise NotImplementedError
|
|
88
|
+
|
|
89
|
+
else:
|
|
90
|
+
raise OSError(plat)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _main() -> None:
|
|
94
|
+
Cli().call_and_exit()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
if __name__ == '__main__':
|
|
98
|
+
_main()
|