baldwin 0.0.3__py3-none-any.whl → 0.0.5__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.
Potentially problematic release.
This version of baldwin might be problematic. Click here for more details.
- baldwin/__init__.py +1 -1
- baldwin/lib.py +193 -0
- baldwin/main.py +33 -102
- baldwin-0.0.5.dist-info/LICENSE.txt +21 -0
- {baldwin-0.0.3.dist-info → baldwin-0.0.5.dist-info}/METADATA +12 -3
- baldwin-0.0.5.dist-info/RECORD +11 -0
- baldwin/utils.py +0 -67
- baldwin-0.0.3.dist-info/RECORD +0 -10
- {baldwin-0.0.3.dist-info → baldwin-0.0.5.dist-info}/WHEEL +0 -0
- {baldwin-0.0.3.dist-info → baldwin-0.0.5.dist-info}/entry_points.txt +0 -0
baldwin/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""Manage a home directory with Git."""
|
|
2
|
-
__version__ = '0.0.
|
|
2
|
+
__version__ = '0.0.5'
|
baldwin/lib.py
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"""Baldwin library."""
|
|
2
|
+
from collections.abc import Iterable
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import UTC, datetime
|
|
5
|
+
from importlib import resources
|
|
6
|
+
from itertools import chain
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from shlex import quote
|
|
9
|
+
from shutil import which
|
|
10
|
+
from typing import Literal
|
|
11
|
+
import logging
|
|
12
|
+
import os
|
|
13
|
+
import subprocess as sp
|
|
14
|
+
|
|
15
|
+
from binaryornot.check import is_binary
|
|
16
|
+
from git import Actor, Repo
|
|
17
|
+
import platformdirs
|
|
18
|
+
|
|
19
|
+
log = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def git(args: Iterable[str]) -> None:
|
|
23
|
+
"""Front-end to git with git-dir and work-tree passed."""
|
|
24
|
+
# Pass these arguments because of the hgit shortcut
|
|
25
|
+
cmd = ('git', f'--git-dir={get_git_path()}', f'--work-tree={Path.home()}', *args)
|
|
26
|
+
log.debug('Running: %s', ' '.join(quote(x) for x in cmd))
|
|
27
|
+
sp.run(cmd, check=False) # do not use env= because env vars controlling colour will be lost
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def init() -> None:
|
|
31
|
+
"""
|
|
32
|
+
Start tracking a home directory.
|
|
33
|
+
|
|
34
|
+
Does nothing if the Git directory already exists.
|
|
35
|
+
"""
|
|
36
|
+
if (git_path := get_git_path()).exists():
|
|
37
|
+
return
|
|
38
|
+
repo = Repo.init(git_path, expand_vars=False)
|
|
39
|
+
repo.git.execute(('git', 'config', 'commit.gpgsign', 'false'))
|
|
40
|
+
gitattributes = Path.home() / '.gitattributes'
|
|
41
|
+
gitattributes.write_text(resources.read_text('baldwin.resources', 'default_gitattributes.txt'))
|
|
42
|
+
gitignore = Path.home() / '.gitignore'
|
|
43
|
+
gitignore.write_text(resources.read_text('baldwin.resources', 'default_gitignore.txt'))
|
|
44
|
+
repo.index.add([gitattributes, gitignore])
|
|
45
|
+
if jq := which('jq'):
|
|
46
|
+
repo.git.execute(('git', 'config', 'diff.json.textconv', f'"{jq}" -MS .'))
|
|
47
|
+
repo.git.execute(('git', 'config', 'diff.json.cachetextconv', 'true'))
|
|
48
|
+
if (prettier := which('prettier')):
|
|
49
|
+
node_modules_path = (Path(prettier).resolve(strict=True).parent / '..' /
|
|
50
|
+
'..').resolve(strict=True)
|
|
51
|
+
if (node_modules_path / '@prettier/plugin-xml/src/plugin.js').exists():
|
|
52
|
+
repo.git.execute((
|
|
53
|
+
'git', 'config', 'diff.xml.textconv',
|
|
54
|
+
f'"{prettier}" --no-editorconfig --parser xml --xml-whitespace-sensitivity ignore'))
|
|
55
|
+
repo.git.execute(('git', 'config', 'diff.xml.cachetextconv', 'true'))
|
|
56
|
+
repo.git.execute(('git', 'config', 'diff.yaml.textconv',
|
|
57
|
+
f'"{prettier}" --no-editorconfig --parser yaml'))
|
|
58
|
+
repo.git.execute(('git', 'config', 'diff.yaml.cachetextconv', 'true'))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def auto_commit() -> None:
|
|
62
|
+
"""Automated commit of changed and untracked files."""
|
|
63
|
+
repo = get_repo()
|
|
64
|
+
diff_items = [Path.home() / e.a_path for e in repo.index.diff(None)] # pragma: no cover
|
|
65
|
+
items_to_add = [
|
|
66
|
+
*[p for p in diff_items if p.exists()], *[
|
|
67
|
+
x for x in (Path.home() / y
|
|
68
|
+
for y in repo.untracked_files) if x.is_file() and not is_binary(str(x))
|
|
69
|
+
]
|
|
70
|
+
]
|
|
71
|
+
items_to_remove = [p for p in diff_items if not p.exists()] # pragma: no cover
|
|
72
|
+
if items_to_add:
|
|
73
|
+
format_(items_to_add)
|
|
74
|
+
repo.index.add(items_to_add)
|
|
75
|
+
if items_to_remove:
|
|
76
|
+
repo.index.remove(items_to_remove)
|
|
77
|
+
if items_to_add or items_to_remove:
|
|
78
|
+
repo.index.commit(f'Automatic commit @ {datetime.now(tz=UTC).isoformat()}',
|
|
79
|
+
committer=Actor('Auto-commiter', 'hgit@tat.sh'))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass
|
|
83
|
+
class RepoInfo:
|
|
84
|
+
"""General repository information."""
|
|
85
|
+
git_dir_path: Path
|
|
86
|
+
"""Git directory."""
|
|
87
|
+
work_tree_path: Path
|
|
88
|
+
"""Work tree."""
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def repo_info() -> RepoInfo:
|
|
92
|
+
"""Get general repository information."""
|
|
93
|
+
return RepoInfo(git_dir_path=get_git_path(), work_tree_path=Path.home())
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def install_units() -> None:
|
|
97
|
+
"""Install systemd units for automatic committing."""
|
|
98
|
+
bw = which('bw')
|
|
99
|
+
if not bw:
|
|
100
|
+
raise FileNotFoundError
|
|
101
|
+
service_file = Path('~/.config/systemd/user/home-vcs.service').expanduser()
|
|
102
|
+
service_file.write_text(f"""[Unit]
|
|
103
|
+
Description=Home directory VCS commit
|
|
104
|
+
|
|
105
|
+
[Service]
|
|
106
|
+
Type=oneshot
|
|
107
|
+
ExecStart={bw} auto-commit
|
|
108
|
+
""")
|
|
109
|
+
log.debug('Wrote to `%s`.', service_file)
|
|
110
|
+
timer_file = Path('~/.config/systemd/user/home-vcs.timer').expanduser()
|
|
111
|
+
timer_file.write_text("""[Unit]
|
|
112
|
+
Description=Hexahourly trigger for Home directory VCS
|
|
113
|
+
|
|
114
|
+
[Timer]
|
|
115
|
+
OnCalendar=0/6:0:00
|
|
116
|
+
|
|
117
|
+
[Install]
|
|
118
|
+
WantedBy=timers.target
|
|
119
|
+
""")
|
|
120
|
+
log.debug('Wrote to `%s`.', timer_file)
|
|
121
|
+
cmd: tuple[str, ...] = ('systemctl', '--user', 'enable', '--now', 'home-vcs.timer')
|
|
122
|
+
log.debug('Running: %s', ' '.join(quote(x) for x in cmd))
|
|
123
|
+
sp.run(cmd, check=True)
|
|
124
|
+
cmd = ('systemctl', '--user', 'daemon-reload')
|
|
125
|
+
log.debug('Running: %s', ' '.join(quote(x) for x in cmd))
|
|
126
|
+
sp.run(('systemctl', '--user', 'daemon-reload'), check=True)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def get_git_path() -> Path:
|
|
130
|
+
"""
|
|
131
|
+
Get the Git directory (``GIT_DIR``).
|
|
132
|
+
|
|
133
|
+
This path is platform-specific. On Windows, the Roaming AppData directory will be used.
|
|
134
|
+
"""
|
|
135
|
+
return platformdirs.user_data_path('home-git', roaming=True)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def get_repo() -> Repo:
|
|
139
|
+
"""
|
|
140
|
+
Get a :py:class:`git.Repo` object.
|
|
141
|
+
|
|
142
|
+
Also disables GPG signing for the repository.
|
|
143
|
+
"""
|
|
144
|
+
repo = Repo(get_git_path(), expand_vars=False)
|
|
145
|
+
repo.git.execute(('git', 'config', 'commit.gpgsign', 'false'))
|
|
146
|
+
return repo
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def format_(filenames: Iterable[Path | str] | None = None,
|
|
150
|
+
log_level: Literal['silent', 'error', 'warn', 'log', 'debug'] = 'error') -> None:
|
|
151
|
+
"""
|
|
152
|
+
Format untracked and modified files in the repository.
|
|
153
|
+
|
|
154
|
+
Does nothing if Prettier is not in ``PATH``.
|
|
155
|
+
|
|
156
|
+
The following plugins will be detected and enabled if found:
|
|
157
|
+
|
|
158
|
+
* @prettier/plugin-xml
|
|
159
|
+
* prettier-plugin-ini
|
|
160
|
+
* prettier-plugin-sort-json
|
|
161
|
+
* prettier-plugin-toml
|
|
162
|
+
"""
|
|
163
|
+
if filenames is None:
|
|
164
|
+
repo = get_repo()
|
|
165
|
+
filenames = (*(Path.home() / d.a_path for d in repo.index.diff(None)),
|
|
166
|
+
*(x for x in (Path.home() / y for y in repo.untracked_files)
|
|
167
|
+
if x.is_file() and not is_binary(str(x))))
|
|
168
|
+
if not (filenames := list(filenames)):
|
|
169
|
+
return
|
|
170
|
+
with resources.path('baldwin.resources', 'prettier.config.json') as config_file:
|
|
171
|
+
if not (prettier := which('prettier')):
|
|
172
|
+
return
|
|
173
|
+
# Detect plugins
|
|
174
|
+
node_modules_path = (Path(prettier).resolve(strict=True).parent / '..' /
|
|
175
|
+
'..').resolve(strict=True)
|
|
176
|
+
cmd_prefix = (prettier, '--config', str(config_file), '--write',
|
|
177
|
+
'--no-error-on-unmatched-pattern', '--ignore-unknown', '--log-level',
|
|
178
|
+
log_level, *chain(*(('--plugin', str(fp))
|
|
179
|
+
for module in ('@prettier/plugin-xml/src/plugin.js',
|
|
180
|
+
'prettier-plugin-ini/src/plugin.js',
|
|
181
|
+
'prettier-plugin-sort-json/dist/index.js',
|
|
182
|
+
'prettier-plugin-toml/lib/index.cjs')
|
|
183
|
+
if (fp := (node_modules_path / module)).exists())))
|
|
184
|
+
for filename in filenames:
|
|
185
|
+
cmd = (*cmd_prefix, str(filename))
|
|
186
|
+
log.debug('Running: %s', ' '.join(quote(x) for x in cmd))
|
|
187
|
+
sp.run(cmd, check=False)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def set_git_env_vars() -> None:
|
|
191
|
+
"""Set environment variables for Git."""
|
|
192
|
+
os.environ['GIT_DIR'] = str(get_git_path())
|
|
193
|
+
os.environ['GIT_WORK_TREE'] = str(Path.home())
|
baldwin/main.py
CHANGED
|
@@ -1,29 +1,27 @@
|
|
|
1
|
-
from datetime import UTC, datetime
|
|
2
|
-
from importlib import resources
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from shlex import quote
|
|
5
|
-
from shutil import which
|
|
6
1
|
import logging
|
|
7
|
-
import os
|
|
8
|
-
import subprocess as sp
|
|
9
2
|
|
|
10
|
-
from binaryornot.check import is_binary
|
|
11
|
-
from git import Actor, Repo
|
|
12
3
|
import click
|
|
13
4
|
|
|
14
|
-
from .
|
|
5
|
+
from .lib import (
|
|
6
|
+
auto_commit,
|
|
7
|
+
format_,
|
|
8
|
+
git,
|
|
9
|
+
init,
|
|
10
|
+
install_units,
|
|
11
|
+
repo_info,
|
|
12
|
+
set_git_env_vars,
|
|
13
|
+
)
|
|
15
14
|
|
|
16
15
|
log = logging.getLogger(__name__)
|
|
17
16
|
|
|
18
|
-
__all__ = ('baldwin_main', '
|
|
17
|
+
__all__ = ('baldwin_main', 'git_main')
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
@click.group(context_settings={'help_option_names': ('-h', '--help')})
|
|
22
21
|
@click.option('-d', '--debug', help='Enable debug logging.', is_flag=True)
|
|
23
22
|
def baldwin_main(*, debug: bool = False) -> None:
|
|
24
23
|
"""Manage a home directory with Git."""
|
|
25
|
-
|
|
26
|
-
os.environ['GIT_WORK_TREE'] = str(Path.home())
|
|
24
|
+
set_git_env_vars()
|
|
27
25
|
logging.basicConfig(level=logging.DEBUG if debug else logging.ERROR)
|
|
28
26
|
|
|
29
27
|
|
|
@@ -32,113 +30,46 @@ def baldwin_main(*, debug: bool = False) -> None:
|
|
|
32
30
|
'ignore_unknown_options': True
|
|
33
31
|
})
|
|
34
32
|
@click.argument('args', nargs=-1, type=click.UNPROCESSED)
|
|
35
|
-
def
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
log.debug('Running: %s', ' '.join(quote(x) for x in cmd))
|
|
39
|
-
sp.run(cmd, check=False) # do not use env= because env vars controlling colour will be lost
|
|
33
|
+
def git_main(args: tuple[str, ...]) -> None:
|
|
34
|
+
"""Wrap git with git-dir and work-tree passed."""
|
|
35
|
+
git(args)
|
|
40
36
|
|
|
41
37
|
|
|
42
38
|
@click.command(context_settings={'help_option_names': ('-h', '--help')})
|
|
43
|
-
def
|
|
39
|
+
def init_main() -> None:
|
|
44
40
|
"""Start tracking a home directory."""
|
|
45
|
-
|
|
46
|
-
if not git_path.exists():
|
|
47
|
-
repo = Repo.init(git_path, expand_vars=False)
|
|
48
|
-
repo.git.execute(('git', 'config', 'commit.gpgsign', 'false'))
|
|
49
|
-
gitattributes = Path.home() / '.gitattributes'
|
|
50
|
-
gitattributes.write_text(
|
|
51
|
-
resources.read_text('baldwin.resources', 'default_gitattributes.txt'))
|
|
52
|
-
gitignore = Path.home() / '.gitignore'
|
|
53
|
-
gitignore.write_text(resources.read_text('baldwin.resources', 'default_gitignore.txt'))
|
|
54
|
-
repo.index.add([gitattributes, gitignore])
|
|
55
|
-
if which('jq'):
|
|
56
|
-
repo.git.execute(('git', 'config', 'diff.json.textconv', 'jq -MS .'))
|
|
57
|
-
repo.git.execute(('git', 'config', 'diff.json.cachetextconv', 'true'))
|
|
58
|
-
if (prettier := which('prettier')):
|
|
59
|
-
node_modules_path = (Path(prettier).resolve(strict=True).parent / '..' /
|
|
60
|
-
'..').resolve(strict=True)
|
|
61
|
-
if (node_modules_path / '@prettier/plugin-xml/src/plugin.js').exists():
|
|
62
|
-
repo.git.execute(
|
|
63
|
-
('git', 'config', 'diff.xml.textconv',
|
|
64
|
-
'prettier --no-editorconfig --parser xml --xml-whitespace-sensitivity ignore'))
|
|
65
|
-
repo.git.execute(('git', 'config', 'diff.xml.cachetextconv', 'true'))
|
|
66
|
-
repo.git.execute(
|
|
67
|
-
('git', 'config', 'diff.yaml.textconv', 'prettier --no-editorconfig --parser yaml'))
|
|
68
|
-
repo.git.execute(('git', 'config', 'diff.yaml.cachetextconv', 'true'))
|
|
41
|
+
init()
|
|
69
42
|
|
|
70
43
|
|
|
71
44
|
@click.command(context_settings={'help_option_names': ('-h', '--help')})
|
|
72
|
-
def
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
diff_items = repo.index.diff(None)
|
|
76
|
-
items_to_add = [
|
|
77
|
-
*[p for e in diff_items if (p := Path.home() / e.a_path).exists()], *[
|
|
78
|
-
x for x in (Path.home() / y
|
|
79
|
-
for y in repo.untracked_files) if x.is_file() and not is_binary(str(x))
|
|
80
|
-
]
|
|
81
|
-
]
|
|
82
|
-
format_(items_to_add)
|
|
83
|
-
repo.index.add(items_to_add)
|
|
84
|
-
repo.index.remove([p for e in diff_items if not (p := Path.home() / e.a_path).exists()])
|
|
85
|
-
repo.index.commit(f'Automatic commit @ {datetime.now(tz=UTC).isoformat()}',
|
|
86
|
-
committer=Actor('Auto-commiter', 'hgit@tat.sh'))
|
|
45
|
+
def auto_commit_main() -> None:
|
|
46
|
+
"""Automated commit of changed and untracked files."""
|
|
47
|
+
auto_commit()
|
|
87
48
|
|
|
88
49
|
|
|
89
50
|
@click.command(context_settings={'help_option_names': ('-h', '--help')})
|
|
90
51
|
def format_main() -> None:
|
|
91
52
|
"""Format changed and untracked files."""
|
|
92
|
-
|
|
93
|
-
format_(
|
|
94
|
-
(*(Path.home() / d.a_path for d in repo.index.diff(None)),
|
|
95
|
-
*(x for x in (Path.home() / y
|
|
96
|
-
for y in repo.untracked_files) if x.is_file() and not is_binary(str(x)))))
|
|
53
|
+
format_()
|
|
97
54
|
|
|
98
55
|
|
|
99
56
|
@click.command(context_settings={'help_option_names': ('-h', '--help')})
|
|
100
|
-
def
|
|
57
|
+
def info_main() -> None:
|
|
101
58
|
"""Get basic information about the repository."""
|
|
102
|
-
|
|
103
|
-
click.echo(f'
|
|
59
|
+
data = repo_info()
|
|
60
|
+
click.echo(f'git-dir path: {data.git_dir_path}')
|
|
61
|
+
click.echo(f'work-tree path: {data.work_tree_path}')
|
|
104
62
|
|
|
105
63
|
|
|
106
64
|
@click.command(context_settings={'help_option_names': ('-h', '--help')})
|
|
107
|
-
def
|
|
65
|
+
def install_units_main() -> None:
|
|
108
66
|
"""Install systemd units for automatic committing."""
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
Description=Home directory VCS commit
|
|
114
|
-
|
|
115
|
-
[Service]
|
|
116
|
-
Type=oneshot
|
|
117
|
-
ExecStart={bw} auto-commit
|
|
118
|
-
""")
|
|
119
|
-
log.debug('Wrote to `%s`.', service_file)
|
|
120
|
-
timer_file = Path('~/.config/systemd/user/home-vcs.timer').expanduser()
|
|
121
|
-
timer_file.write_text("""[Unit]
|
|
122
|
-
Description=Hexahourly trigger for Home directory VCS
|
|
123
|
-
|
|
124
|
-
[Timer]
|
|
125
|
-
OnCalendar=0/6:0:00
|
|
126
|
-
|
|
127
|
-
[Install]
|
|
128
|
-
WantedBy=timers.target
|
|
129
|
-
""")
|
|
130
|
-
log.debug('Wrote to `%s`.', timer_file)
|
|
131
|
-
cmd: tuple[str, ...] = ('systemctl', '--user', 'enable', '--now', 'home-vcs.timer')
|
|
132
|
-
log.debug('Running: %s', ' '.join(quote(x) for x in cmd))
|
|
133
|
-
sp.run(cmd, check=True)
|
|
134
|
-
cmd = ('systemctl', '--user', 'daemon-reload')
|
|
135
|
-
log.debug('Running: %s', ' '.join(quote(x) for x in cmd))
|
|
136
|
-
sp.run(('systemctl', '--user', 'daemon-reload'), check=True)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
baldwin_main.add_command(auto_commit, 'auto-commit')
|
|
67
|
+
install_units()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
baldwin_main.add_command(auto_commit_main, 'auto-commit')
|
|
140
71
|
baldwin_main.add_command(format_main, 'format')
|
|
141
|
-
baldwin_main.add_command(git)
|
|
142
|
-
baldwin_main.add_command(info)
|
|
143
|
-
baldwin_main.add_command(init)
|
|
144
|
-
baldwin_main.add_command(
|
|
72
|
+
baldwin_main.add_command(git_main, 'git')
|
|
73
|
+
baldwin_main.add_command(info_main, 'info')
|
|
74
|
+
baldwin_main.add_command(init_main, 'init')
|
|
75
|
+
baldwin_main.add_command(install_units_main, 'install-units')
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 baldwin authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: baldwin
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.5
|
|
4
4
|
Summary: Simple tracking of your home directory with easy-to-read diffs.
|
|
5
5
|
Home-page: https://github.com/Tatsh/baldwin
|
|
6
6
|
License: MIT
|
|
@@ -27,6 +27,15 @@ Description-Content-Type: text/markdown
|
|
|
27
27
|
|
|
28
28
|
# Simple home directory versioning
|
|
29
29
|
|
|
30
|
+
[](https://github.com/Tatsh/baldwin/actions/workflows/qa.yml)
|
|
31
|
+
[](https://github.com/Tatsh/baldwin/actions/workflows/tests.yml)
|
|
32
|
+
[](https://coveralls.io/github/Tatsh/baldwin?branch=master)
|
|
33
|
+
[](https://baldwin.readthedocs.io/en/latest/?badge=latest)
|
|
34
|
+

|
|
35
|
+

|
|
36
|
+

|
|
37
|
+

|
|
38
|
+
|
|
30
39
|
This is a conversion of my simple scripts to version my home directory with very specific excludes
|
|
31
40
|
and formatting every file upon commit so that readable diffs can be generated.
|
|
32
41
|
|
|
@@ -65,8 +74,8 @@ In addition to the `bw` command, `hgit` is a shortcut for `bw git`.
|
|
|
65
74
|
bw init
|
|
66
75
|
```
|
|
67
76
|
|
|
68
|
-
Find out where the
|
|
69
|
-
|
|
77
|
+
Find out where the Git directory is by running `bw info`. This can be done even if `init` has not
|
|
78
|
+
been run.
|
|
70
79
|
|
|
71
80
|
### Automation
|
|
72
81
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
baldwin/__init__.py,sha256=zRCtDd8b2My-634tBj2VBVvjruhFu212tMF5HMQ3T8s,62
|
|
2
|
+
baldwin/lib.py,sha256=O880lZ-cJGPMDF2ypg5iOyZy9tgBWO28yMJ7pL7wN0k,7369
|
|
3
|
+
baldwin/main.py,sha256=08a70OZLyRBamntbCdhhBNKSk9mywu_2M085I_mDa-s,2131
|
|
4
|
+
baldwin/resources/default_gitattributes.txt,sha256=uGoWTSVgPmdGB2EUIROkTz3FikGpNGhdS95SuuvoCRo,984
|
|
5
|
+
baldwin/resources/default_gitignore.txt,sha256=oyxukNyK6F778C2jc7oIwosP7ou1WTdbuWwkpgGZtJA,3022
|
|
6
|
+
baldwin/resources/prettier.config.json,sha256=-Hher3B02YflULYn0IYOG_a-rDxpaaaQ0QXD30-5IgQ,387
|
|
7
|
+
baldwin-0.0.5.dist-info/LICENSE.txt,sha256=TDfksi5bdmmL5cu6tAiN1iL7k38hWR2KbUg0JkASPO4,1082
|
|
8
|
+
baldwin-0.0.5.dist-info/METADATA,sha256=CRhbusv0AF5culT23DmwDS7qTsl2v1P7tXK4blRWaIY,4579
|
|
9
|
+
baldwin-0.0.5.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
10
|
+
baldwin-0.0.5.dist-info/entry_points.txt,sha256=Whfij6CPUG0wuXRYWf3VGkluV1jV32ysrGFdlWjFy9o,70
|
|
11
|
+
baldwin-0.0.5.dist-info/RECORD,,
|
baldwin/utils.py
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
from collections.abc import Iterable
|
|
2
|
-
from importlib import resources
|
|
3
|
-
from itertools import chain
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from shlex import quote
|
|
6
|
-
from shutil import which
|
|
7
|
-
import logging
|
|
8
|
-
import subprocess as sp
|
|
9
|
-
|
|
10
|
-
from git import Repo
|
|
11
|
-
import platformdirs
|
|
12
|
-
|
|
13
|
-
__all__ = ('format_', 'get_git_path', 'get_repo')
|
|
14
|
-
|
|
15
|
-
log = logging.getLogger(__name__)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def get_git_path() -> Path:
|
|
19
|
-
"""
|
|
20
|
-
Get the bare Git directory (``GIT_DIR``).
|
|
21
|
-
|
|
22
|
-
This path is platform-specific. On Windows, the Roaming AppData directory will be used.
|
|
23
|
-
"""
|
|
24
|
-
return platformdirs.user_data_path('home-git', roaming=True)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def get_repo() -> Repo:
|
|
28
|
-
"""
|
|
29
|
-
Get a :py:class:`git.Repo` object.
|
|
30
|
-
|
|
31
|
-
Also disables GPG signing for the repository.
|
|
32
|
-
"""
|
|
33
|
-
repo = Repo(get_git_path(), expand_vars=False)
|
|
34
|
-
repo.git.execute(('git', 'config', 'commit.gpgsign', 'false'))
|
|
35
|
-
return repo
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def format_(filenames: Iterable[Path | str], log_level: str = 'error') -> None:
|
|
39
|
-
"""
|
|
40
|
-
Format untracked and modified files in the repository.
|
|
41
|
-
|
|
42
|
-
Does nothing if Prettier is not in ``PATH``.
|
|
43
|
-
|
|
44
|
-
The following plugins will be detected and enabled if found:
|
|
45
|
-
|
|
46
|
-
* @prettier/plugin-xml
|
|
47
|
-
* prettier-plugin-ini
|
|
48
|
-
* prettier-plugin-sort-json
|
|
49
|
-
* prettier-plugin-toml
|
|
50
|
-
"""
|
|
51
|
-
if not (filenames := list(filenames)):
|
|
52
|
-
return
|
|
53
|
-
with resources.path('baldwin.resources', 'prettier.config.json') as config_file:
|
|
54
|
-
if not (prettier := which('prettier')):
|
|
55
|
-
return
|
|
56
|
-
# Detect plugins
|
|
57
|
-
node_modules_path = (Path(prettier).resolve(strict=True).parent / '..' /
|
|
58
|
-
'..').resolve(strict=True)
|
|
59
|
-
cmd = ('prettier', '--config', str(config_file), '--write',
|
|
60
|
-
'--no-error-on-unmatched-pattern', '--ignore-unknown', '--log-level', log_level,
|
|
61
|
-
*chain(*(('--plugin', str(fp)) for module in (
|
|
62
|
-
'@prettier/plugin-xml/src/plugin.js', 'prettier-plugin-ini/src/plugin.js',
|
|
63
|
-
'prettier-plugin-sort-json/dist/index.js', 'prettier-plugin-toml/lib/index.cjs')
|
|
64
|
-
if (fp := (node_modules_path / module)).exists())), *(str(x)
|
|
65
|
-
for x in filenames))
|
|
66
|
-
log.debug('Running: %s', ' '.join(quote(x) for x in cmd))
|
|
67
|
-
sp.run(cmd, check=True)
|
baldwin-0.0.3.dist-info/RECORD
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
baldwin/__init__.py,sha256=3dgZd5iHZ-JqICxPLaJt0GhIkmxPNpiRkebG6wafnXM,62
|
|
2
|
-
baldwin/main.py,sha256=kWnkz91_tTZWbQdWKzmlvdrzg5SY7b9Mu9XKsgQKDOE,5718
|
|
3
|
-
baldwin/resources/default_gitattributes.txt,sha256=uGoWTSVgPmdGB2EUIROkTz3FikGpNGhdS95SuuvoCRo,984
|
|
4
|
-
baldwin/resources/default_gitignore.txt,sha256=oyxukNyK6F778C2jc7oIwosP7ou1WTdbuWwkpgGZtJA,3022
|
|
5
|
-
baldwin/resources/prettier.config.json,sha256=-Hher3B02YflULYn0IYOG_a-rDxpaaaQ0QXD30-5IgQ,387
|
|
6
|
-
baldwin/utils.py,sha256=gOtDvylunSQoZ8QN8RvEeafPCw8Xn42vOflTMxciHtg,2330
|
|
7
|
-
baldwin-0.0.3.dist-info/METADATA,sha256=1SiNS_zOqSKb8H2HKXi39MhCT_l_eAAW4fnnww4mLaw,3659
|
|
8
|
-
baldwin-0.0.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
9
|
-
baldwin-0.0.3.dist-info/entry_points.txt,sha256=Whfij6CPUG0wuXRYWf3VGkluV1jV32ysrGFdlWjFy9o,70
|
|
10
|
-
baldwin-0.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|