bake 0.1.0__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.
- bake/__init__.py +1 -0
- bake/cli.py +40 -0
- bake/commands/__init__.py +1 -0
- bake/commands/dpkg/__init__.py +1 -0
- bake/commands/dpkg/bake_dpkg_command.py +45 -0
- bake/commands/init/__init__.py +1 -0
- bake/commands/init/bake_downloader.py +52 -0
- bake/commands/init/bake_init_command.py +217 -0
- bake/commands/init/bake_installer.py +234 -0
- bake/commands/init/bake_path.py +58 -0
- bake/dpkg.py +32 -0
- bake/exceptions.py +56 -0
- bake/install.py +10 -0
- bake/output_style.py +24 -0
- bake/system/__init__.py +1 -0
- bake/system/copy_subprocess.py +21 -0
- bake/system/git_subprocess.py +29 -0
- bake/utils/__init__.py +1 -0
- bake/utils/bake_setup.py +82 -0
- bake-0.1.0.dist-info/METADATA +87 -0
- bake-0.1.0.dist-info/RECORD +23 -0
- bake-0.1.0.dist-info/WHEEL +4 -0
- bake-0.1.0.dist-info/entry_points.txt +2 -0
bake/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Bake package."""
|
bake/cli.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
|
|
5
|
+
from bake import dpkg, install
|
|
6
|
+
|
|
7
|
+
load_dotenv()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main():
|
|
11
|
+
if len(sys.argv) < 2:
|
|
12
|
+
print("Error: No command provided")
|
|
13
|
+
print("Usage: bake <command> [args...]")
|
|
14
|
+
print("")
|
|
15
|
+
print("Available commands:")
|
|
16
|
+
print("")
|
|
17
|
+
print(" install Initialize Bake")
|
|
18
|
+
print(" dpkg Bake package manager")
|
|
19
|
+
print("")
|
|
20
|
+
sys.exit(1)
|
|
21
|
+
|
|
22
|
+
command = sys.argv[1]
|
|
23
|
+
command_args = sys.argv[2:]
|
|
24
|
+
original_argv = sys.argv
|
|
25
|
+
sys.argv = ["bake " + command] + command_args
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
if command == "install":
|
|
29
|
+
install.main()
|
|
30
|
+
elif command == "dpkg":
|
|
31
|
+
dpkg.main()
|
|
32
|
+
else:
|
|
33
|
+
print(f"Error: Unknown command '{command}'")
|
|
34
|
+
sys.exit(1)
|
|
35
|
+
finally:
|
|
36
|
+
sys.argv = original_argv
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Bake command modules."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Package management command modules for Bake."""
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from bake.exceptions import BakePathNotConfiguredException, ErrorCopyingException
|
|
4
|
+
from bake.output_style import OutputStyle
|
|
5
|
+
from bake.system.copy_subprocess import CopySubprocess
|
|
6
|
+
from bake.utils.bake_setup import BakeSetup
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BakeDpkgCommand:
|
|
10
|
+
def __init__(self, output_style: OutputStyle, bake_setup: BakeSetup):
|
|
11
|
+
self.output_style = output_style
|
|
12
|
+
self.bake_setup = bake_setup
|
|
13
|
+
|
|
14
|
+
def sync_configurations(self):
|
|
15
|
+
"""Synchronize default bake definitions into BAKE_PATH."""
|
|
16
|
+
try:
|
|
17
|
+
bake_path = self.bake_setup.bake_path()
|
|
18
|
+
except BakePathNotConfiguredException:
|
|
19
|
+
self.output_style.writeln("No Bake path set", "error")
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
built_in_tools_dir = self._built_in_tools_dir()
|
|
23
|
+
try:
|
|
24
|
+
CopySubprocess().copy(
|
|
25
|
+
str(built_in_tools_dir), bake_path + "/", ["-Rf"]
|
|
26
|
+
)
|
|
27
|
+
except ErrorCopyingException as exc:
|
|
28
|
+
self.output_style.writeln(
|
|
29
|
+
"Error copying default configuration files: " + str(exc), "error"
|
|
30
|
+
)
|
|
31
|
+
return
|
|
32
|
+
|
|
33
|
+
self.output_style.writeln(
|
|
34
|
+
"Built-in tools directory copied successfully.", "success"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def _built_in_tools_dir(self) -> Path:
|
|
38
|
+
built_in_tools_dir = Path(__file__).resolve().parents[3] / "tools" / "config"
|
|
39
|
+
if not built_in_tools_dir.exists():
|
|
40
|
+
raise MissingBuiltInToolsDirException(
|
|
41
|
+
"No built-in tools directory found at "
|
|
42
|
+
+ str(built_in_tools_dir.absolute())
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
return built_in_tools_dir
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Initialization command modules for Bake."""
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from bake.exceptions import (
|
|
4
|
+
BakeAlreadyExistsException,
|
|
5
|
+
ErrorReadingBakeConfigException,
|
|
6
|
+
MissingConfigurationKeysException,
|
|
7
|
+
)
|
|
8
|
+
from bake.output_style import OutputStyle
|
|
9
|
+
from bake.system.git_subprocess import GitSubprocess
|
|
10
|
+
from bake.utils.bake_setup import BakeSetup
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BakeDownloader:
|
|
14
|
+
"""Download Bake-managed repositories from config definitions."""
|
|
15
|
+
|
|
16
|
+
def __init__(self):
|
|
17
|
+
self.output = OutputStyle()
|
|
18
|
+
self.git_subprocess = GitSubprocess()
|
|
19
|
+
self.bake_setup = BakeSetup()
|
|
20
|
+
|
|
21
|
+
def list_available_bakes(self):
|
|
22
|
+
bake_list = []
|
|
23
|
+
for config_file in self.bake_setup.config_path().glob("*.json"):
|
|
24
|
+
try:
|
|
25
|
+
with open(config_file, "r") as config_stream:
|
|
26
|
+
config = json.load(config_stream)
|
|
27
|
+
bake_list.append(config)
|
|
28
|
+
except Exception as exc:
|
|
29
|
+
raise ErrorReadingBakeConfigException(
|
|
30
|
+
"Error reading bake configuration "
|
|
31
|
+
+ str(config_file.absolute())
|
|
32
|
+
+ ": "
|
|
33
|
+
+ str(exc)
|
|
34
|
+
) from exc
|
|
35
|
+
return bake_list
|
|
36
|
+
|
|
37
|
+
def download_bake(self, config):
|
|
38
|
+
name = config.get("name")
|
|
39
|
+
repo_url = config.get("repo_url")
|
|
40
|
+
|
|
41
|
+
if not name or not repo_url:
|
|
42
|
+
raise MissingConfigurationKeysException(
|
|
43
|
+
"Invalid configuration: missing name or repo_url"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
target_path = self.bake_setup.repositories_path() / name
|
|
47
|
+
if target_path.exists():
|
|
48
|
+
raise BakeAlreadyExistsException(
|
|
49
|
+
"Bake " + name + " already exists at " + str(target_path.absolute())
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
return self.git_subprocess.clone(repo_url, target_path)
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from bake.commands.init.bake_downloader import BakeDownloader
|
|
4
|
+
from bake.commands.init.bake_installer import BakeInstaller
|
|
5
|
+
from bake.commands.init.bake_path import BakePath
|
|
6
|
+
from bake.exceptions import (
|
|
7
|
+
BakeAlreadyExistsException,
|
|
8
|
+
BakePathNotConfiguredException,
|
|
9
|
+
ErrorCopyingException,
|
|
10
|
+
ErrorReadingBakeConfigException,
|
|
11
|
+
MissingConfigurationKeysException,
|
|
12
|
+
NoInstallableBakesException,
|
|
13
|
+
)
|
|
14
|
+
from bake.output_style import OutputStyle
|
|
15
|
+
from bake.system.copy_subprocess import CopySubprocess
|
|
16
|
+
from bake.utils.bake_setup import BakeSetup
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BakeInitCommand:
|
|
20
|
+
def __init__(self, bake_path: BakePath):
|
|
21
|
+
self.bake_path = bake_path
|
|
22
|
+
self.output = OutputStyle()
|
|
23
|
+
self.bake_setup = BakeSetup()
|
|
24
|
+
|
|
25
|
+
def execute(self):
|
|
26
|
+
self.set_bake_path()
|
|
27
|
+
self.setup_bake_directories()
|
|
28
|
+
self.download_bakes()
|
|
29
|
+
self.install_bakes()
|
|
30
|
+
|
|
31
|
+
def set_bake_path(self):
|
|
32
|
+
self.output.writeln("Initializing Bake...", "success")
|
|
33
|
+
self.output.writeln()
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
current_path = self.bake_setup.bake_path()
|
|
37
|
+
except BakePathNotConfiguredException:
|
|
38
|
+
current_path = None
|
|
39
|
+
|
|
40
|
+
if current_path:
|
|
41
|
+
self.output.writeln(f"Current Bake path: {current_path}", "info")
|
|
42
|
+
else:
|
|
43
|
+
self.output.writeln("No Bake path configured yet.", "warning")
|
|
44
|
+
self.output.writeln("Suggested paths:")
|
|
45
|
+
for idx, path in enumerate(self.bake_path.get_suggested_paths(), 1):
|
|
46
|
+
self.output.writeln(f" {idx}. {path}", "info")
|
|
47
|
+
|
|
48
|
+
while True:
|
|
49
|
+
if current_path:
|
|
50
|
+
self.output.writeln("Press Enter to keep this path or enter a new one:")
|
|
51
|
+
else:
|
|
52
|
+
self.output.writeln("Enter the path where Bake repositories will live:")
|
|
53
|
+
|
|
54
|
+
new_path = input().strip()
|
|
55
|
+
final_path = new_path if new_path else current_path
|
|
56
|
+
if final_path:
|
|
57
|
+
break
|
|
58
|
+
|
|
59
|
+
self.output.writeln("Invalid path. Please try again.", "error")
|
|
60
|
+
|
|
61
|
+
if self.bake_path.path_exists(final_path):
|
|
62
|
+
self.output.writeln(f"Directory already exists: {final_path}", "success")
|
|
63
|
+
else:
|
|
64
|
+
success, message = self.bake_path.create_directory(final_path)
|
|
65
|
+
self.output.writeln(message, "success" if success else "error")
|
|
66
|
+
if not success:
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
self.bake_path.save_env_file("BAKE_PATH", final_path)
|
|
70
|
+
self.output.writeln(f"Bake path configured: {final_path}", "success")
|
|
71
|
+
|
|
72
|
+
def setup_bake_directories(self):
|
|
73
|
+
try:
|
|
74
|
+
bake_path = self.bake_setup.bake_path()
|
|
75
|
+
except BakePathNotConfiguredException:
|
|
76
|
+
self.output.writeln("Bake path not configured", "error")
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
self.output.writeln()
|
|
80
|
+
self.output.writeln("Setting up Bake directories...", "info")
|
|
81
|
+
|
|
82
|
+
if not self.bake_setup.config_dir_exists() or self.bake_setup.is_config_dir_empty():
|
|
83
|
+
self.bake_setup.setup_config_dir()
|
|
84
|
+
self.output.writeln("Config directory created", "success")
|
|
85
|
+
|
|
86
|
+
built_in_tools_dir = self._built_in_tools_dir()
|
|
87
|
+
try:
|
|
88
|
+
CopySubprocess().copy(
|
|
89
|
+
str(built_in_tools_dir), bake_path + "/", ["-R"]
|
|
90
|
+
)
|
|
91
|
+
except ErrorCopyingException as exc:
|
|
92
|
+
self.output.writeln(
|
|
93
|
+
"Error copying built-in tools: " + str(exc), "error"
|
|
94
|
+
)
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
self.output.writeln("Built-in tools directory copied", "success")
|
|
98
|
+
|
|
99
|
+
if not self.bake_setup.repositories_dir_exists():
|
|
100
|
+
self.bake_setup.setup_repositories_dir()
|
|
101
|
+
self.output.writeln("Repositories directory created", "success")
|
|
102
|
+
|
|
103
|
+
if not self.bake_setup.bin_dir_exists():
|
|
104
|
+
self.bake_setup.setup_bin_dir()
|
|
105
|
+
self.output.writeln("Bin directory created", "success")
|
|
106
|
+
|
|
107
|
+
def download_bakes(self):
|
|
108
|
+
try:
|
|
109
|
+
self.bake_setup.bake_path()
|
|
110
|
+
except BakePathNotConfiguredException:
|
|
111
|
+
self.output.writeln("Bake path not configured", "error")
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
downloader = BakeDownloader()
|
|
115
|
+
try:
|
|
116
|
+
bakes = downloader.list_available_bakes()
|
|
117
|
+
self.output.writeln()
|
|
118
|
+
self.output.writeln(f"Available bakes ({len(bakes)}):", "info")
|
|
119
|
+
for idx, config in enumerate(bakes, 1):
|
|
120
|
+
self.output.writeln(f" {idx}. {config.get('name', 'Unknown')}", "info")
|
|
121
|
+
self.output.writeln(
|
|
122
|
+
f" Description: {config.get('description', 'No description')}",
|
|
123
|
+
"info",
|
|
124
|
+
)
|
|
125
|
+
self.output.writeln(
|
|
126
|
+
f" Repository: {config.get('repo_url', 'No URL')}", "info"
|
|
127
|
+
)
|
|
128
|
+
except ErrorReadingBakeConfigException as exc:
|
|
129
|
+
self.output.writeln("Error listing available bakes: " + str(exc), "error")
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
self.output.writeln()
|
|
133
|
+
self.output.writeln("Download available bakes? (y/n):", "info")
|
|
134
|
+
if input().strip().lower() not in ["y", "yes"]:
|
|
135
|
+
return
|
|
136
|
+
|
|
137
|
+
self.output.writeln()
|
|
138
|
+
success_count = 0
|
|
139
|
+
for config in bakes:
|
|
140
|
+
name = config.get("name", "Unknown")
|
|
141
|
+
self.output.writeln(f"Processing: {name}", "info")
|
|
142
|
+
try:
|
|
143
|
+
downloader.download_bake(config)
|
|
144
|
+
success_count += 1
|
|
145
|
+
except BakeAlreadyExistsException:
|
|
146
|
+
self.output.writeln(f"{name} already exists", "info")
|
|
147
|
+
except MissingConfigurationKeysException as exc:
|
|
148
|
+
self.output.writeln(f"Error downloading {name}: {exc}", "error")
|
|
149
|
+
|
|
150
|
+
self.output.writeln()
|
|
151
|
+
self.output.writeln(
|
|
152
|
+
f"Successfully downloaded {success_count}/{len(bakes)} bakes", "success"
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
def install_bakes(self):
|
|
156
|
+
try:
|
|
157
|
+
self.bake_setup.bake_path()
|
|
158
|
+
except BakePathNotConfiguredException:
|
|
159
|
+
self.output.writeln("Bake path not configured", "error")
|
|
160
|
+
return
|
|
161
|
+
|
|
162
|
+
installer = BakeInstaller()
|
|
163
|
+
try:
|
|
164
|
+
installable_bakes = installer.list_installable_bakes()
|
|
165
|
+
self.output.writeln()
|
|
166
|
+
self.output.writeln(
|
|
167
|
+
f"Installable bakes ({len(installable_bakes)}):", "info"
|
|
168
|
+
)
|
|
169
|
+
for idx, bake_name in enumerate(installable_bakes, 1):
|
|
170
|
+
self.output.writeln(f" {idx}. {bake_name}", "info")
|
|
171
|
+
except NoInstallableBakesException as exc:
|
|
172
|
+
self.output.writeln(str(exc), "error")
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
self.output.writeln()
|
|
176
|
+
self.output.writeln("Install available bakes? (y/n):", "info")
|
|
177
|
+
if input().strip().lower() not in ["y", "yes"]:
|
|
178
|
+
return
|
|
179
|
+
|
|
180
|
+
self.output.writeln()
|
|
181
|
+
self.output.writeln("Installing bakes...", "info")
|
|
182
|
+
results = installer.install_all_bakes()
|
|
183
|
+
success_count = 0
|
|
184
|
+
failed_count = 0
|
|
185
|
+
|
|
186
|
+
for bake_name, result in results.items():
|
|
187
|
+
if result["success"]:
|
|
188
|
+
success_count += 1
|
|
189
|
+
self.output.writeln(f"{bake_name}: installed", "success")
|
|
190
|
+
else:
|
|
191
|
+
failed_count += 1
|
|
192
|
+
self.output.writeln(f"{bake_name}: failed", "error")
|
|
193
|
+
self.output.writeln(f" Error: {result.get('error', 'Unknown')}", "error")
|
|
194
|
+
|
|
195
|
+
self.output.writeln()
|
|
196
|
+
if failed_count == 0:
|
|
197
|
+
self.output.writeln("Bake initialization completed successfully!", "success")
|
|
198
|
+
self.output.writeln("Add this to your shell profile:", "info")
|
|
199
|
+
self.output.writeln(
|
|
200
|
+
f' export PATH="$PATH:{self.bake_setup.bin_path()}"', "warning"
|
|
201
|
+
)
|
|
202
|
+
else:
|
|
203
|
+
self.output.writeln(
|
|
204
|
+
f"{success_count} bakes installed successfully, {failed_count} failed.",
|
|
205
|
+
"warning",
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
def _built_in_tools_dir(self) -> Path:
|
|
209
|
+
# First look for packaged configs (works from wheel/sdist installs).
|
|
210
|
+
built_in_tools_dir = Path(__file__).resolve().parents[3] / "tools" / "config"
|
|
211
|
+
if not built_in_tools_dir.exists():
|
|
212
|
+
raise MissingBuiltInToolsDirException(
|
|
213
|
+
"No built-in tools directory found at "
|
|
214
|
+
+ str(built_in_tools_dir.absolute())
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
return built_in_tools_dir
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
from bake.exceptions import (
|
|
6
|
+
BakeNotFoundException,
|
|
7
|
+
ErrorCreatingSymlinkException,
|
|
8
|
+
ErrorReadingBakeConfigException,
|
|
9
|
+
NoInstallableBakesException,
|
|
10
|
+
SetupCommandFailedException,
|
|
11
|
+
)
|
|
12
|
+
from bake.utils.bake_setup import BakeSetup
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BakeInstaller:
|
|
16
|
+
"""Install Bake-managed repositories and expose runnable binaries."""
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
self.bake_setup = BakeSetup()
|
|
20
|
+
|
|
21
|
+
def get_installed_bakes(self):
|
|
22
|
+
if not self.bake_setup.repositories_dir_exists():
|
|
23
|
+
return []
|
|
24
|
+
return [
|
|
25
|
+
d.name
|
|
26
|
+
for d in self.bake_setup.repositories_path().iterdir()
|
|
27
|
+
if d.is_dir()
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
def load_bake_config(self, bake_name):
|
|
31
|
+
config_file = self.bake_setup.config_path() / f"{bake_name}.json"
|
|
32
|
+
if not config_file.exists():
|
|
33
|
+
raise ErrorReadingBakeConfigException(
|
|
34
|
+
f"Configuration file not found: {config_file}"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
with open(config_file, "r") as config_stream:
|
|
39
|
+
return json.load(config_stream)
|
|
40
|
+
except json.JSONDecodeError as exc:
|
|
41
|
+
raise ErrorReadingBakeConfigException(
|
|
42
|
+
f"Invalid JSON in {config_file}: {exc}"
|
|
43
|
+
) from exc
|
|
44
|
+
except Exception as exc:
|
|
45
|
+
raise ErrorReadingBakeConfigException(
|
|
46
|
+
f"Error reading {config_file}: {exc}"
|
|
47
|
+
) from exc
|
|
48
|
+
|
|
49
|
+
def run_setup_script(self, bake_name, script_commands):
|
|
50
|
+
bake_path = self.bake_setup.repositories_path() / bake_name
|
|
51
|
+
if not bake_path.exists():
|
|
52
|
+
raise BakeNotFoundException(f"Bake {bake_name} not found at {bake_path}")
|
|
53
|
+
|
|
54
|
+
original_dir = os.getcwd()
|
|
55
|
+
os.chdir(bake_path)
|
|
56
|
+
try:
|
|
57
|
+
results = []
|
|
58
|
+
for command in script_commands:
|
|
59
|
+
if command.startswith("source"):
|
|
60
|
+
result = subprocess.run(
|
|
61
|
+
["bash", "-c", command], capture_output=True, text=True
|
|
62
|
+
)
|
|
63
|
+
else:
|
|
64
|
+
result = subprocess.run(
|
|
65
|
+
command.split(), capture_output=True, text=True
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
output = result.stdout or result.stderr or ""
|
|
69
|
+
results.append(
|
|
70
|
+
{"command": command, "code": result.returncode, "output": output}
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
if result.returncode != 0:
|
|
74
|
+
raise SetupCommandFailedException(
|
|
75
|
+
f"Command failed: {command}. Error: {result.stderr}"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return results
|
|
79
|
+
except SetupCommandFailedException:
|
|
80
|
+
raise
|
|
81
|
+
except Exception as exc:
|
|
82
|
+
raise SetupCommandFailedException(
|
|
83
|
+
f"Error running setup script for {bake_name}: {exc}"
|
|
84
|
+
) from exc
|
|
85
|
+
finally:
|
|
86
|
+
os.chdir(original_dir)
|
|
87
|
+
|
|
88
|
+
def create_binary_symlinks(self, bake_name, binaries):
|
|
89
|
+
if not binaries:
|
|
90
|
+
return []
|
|
91
|
+
|
|
92
|
+
bake_path = self.bake_setup.repositories_path() / bake_name
|
|
93
|
+
bin_path = self.bake_setup.bin_path()
|
|
94
|
+
|
|
95
|
+
if not bake_path.exists():
|
|
96
|
+
raise BakeNotFoundException(f"Bake {bake_name} not found at {bake_path}")
|
|
97
|
+
if not bin_path.exists():
|
|
98
|
+
raise ErrorCreatingSymlinkException(f"Bin directory not found at {bin_path}")
|
|
99
|
+
|
|
100
|
+
created_links = []
|
|
101
|
+
for binary_config in binaries:
|
|
102
|
+
if isinstance(binary_config, str):
|
|
103
|
+
binary_path = binary_config
|
|
104
|
+
alias = (
|
|
105
|
+
binary_path.replace(".py", "")
|
|
106
|
+
if binary_path.endswith(".py")
|
|
107
|
+
else binary_path
|
|
108
|
+
)
|
|
109
|
+
chdir = False
|
|
110
|
+
executor = self._get_default_executor(binary_path)
|
|
111
|
+
elif isinstance(binary_config, dict):
|
|
112
|
+
binary_path = binary_config.get("path")
|
|
113
|
+
alias = binary_config.get("alias")
|
|
114
|
+
chdir = binary_config.get("chdir", False)
|
|
115
|
+
executor = binary_config.get(
|
|
116
|
+
"executor", self._get_default_executor(binary_path)
|
|
117
|
+
)
|
|
118
|
+
if not binary_path:
|
|
119
|
+
raise ErrorCreatingSymlinkException(
|
|
120
|
+
f"Binary configuration missing 'path': {binary_config}"
|
|
121
|
+
)
|
|
122
|
+
if not alias:
|
|
123
|
+
alias = (
|
|
124
|
+
binary_path.replace(".py", "")
|
|
125
|
+
if binary_path.endswith(".py")
|
|
126
|
+
else binary_path
|
|
127
|
+
)
|
|
128
|
+
else:
|
|
129
|
+
raise ErrorCreatingSymlinkException(
|
|
130
|
+
f"Invalid binary configuration format: {binary_config}"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
source_path = bake_path / binary_path
|
|
134
|
+
if not source_path.exists():
|
|
135
|
+
raise ErrorCreatingSymlinkException(
|
|
136
|
+
f"Binary {binary_path} not found in {bake_name} at {source_path}"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
link_path = bin_path / alias
|
|
140
|
+
try:
|
|
141
|
+
if link_path.exists() or link_path.is_symlink():
|
|
142
|
+
link_path.unlink()
|
|
143
|
+
|
|
144
|
+
if chdir:
|
|
145
|
+
self._create_chdir_wrapper(bake_path, source_path, link_path, executor)
|
|
146
|
+
else:
|
|
147
|
+
link_path.symlink_to(source_path)
|
|
148
|
+
created_links.append(alias)
|
|
149
|
+
except Exception as exc:
|
|
150
|
+
raise ErrorCreatingSymlinkException(
|
|
151
|
+
f"Error creating symbolic link for {binary_path} as {alias}: {exc}"
|
|
152
|
+
) from exc
|
|
153
|
+
|
|
154
|
+
return created_links
|
|
155
|
+
|
|
156
|
+
def _create_chdir_wrapper(self, bake_path, source_path, link_path, executor):
|
|
157
|
+
if executor == "uv run":
|
|
158
|
+
exec_command = f'exec uv run "{source_path}" "$@"'
|
|
159
|
+
elif executor == "source":
|
|
160
|
+
exec_command = f'. "{source_path}" "$@"'
|
|
161
|
+
elif executor == "direct":
|
|
162
|
+
exec_command = f'exec "{source_path}" "$@"'
|
|
163
|
+
else:
|
|
164
|
+
exec_command = f'exec uv run "{source_path}" "$@"'
|
|
165
|
+
|
|
166
|
+
wrapper_content = f"""#!/usr/bin/env bash
|
|
167
|
+
# Wrapper script for {source_path.name}
|
|
168
|
+
# Ensures execution in repository directory.
|
|
169
|
+
|
|
170
|
+
cd "{bake_path}"
|
|
171
|
+
{exec_command}
|
|
172
|
+
"""
|
|
173
|
+
with open(link_path, "w") as wrapper:
|
|
174
|
+
wrapper.write(wrapper_content)
|
|
175
|
+
link_path.chmod(0o755)
|
|
176
|
+
|
|
177
|
+
def _get_default_executor(self, binary_path):
|
|
178
|
+
if binary_path.endswith(".py"):
|
|
179
|
+
return "uv run"
|
|
180
|
+
if binary_path.endswith(".sh"):
|
|
181
|
+
return "source"
|
|
182
|
+
return "direct"
|
|
183
|
+
|
|
184
|
+
def install_bake(self, bake_name):
|
|
185
|
+
try:
|
|
186
|
+
config = self.load_bake_config(bake_name)
|
|
187
|
+
scripts = config.get("scripts", {})
|
|
188
|
+
install_scripts = scripts.get("install", [])
|
|
189
|
+
if not install_scripts:
|
|
190
|
+
install_scripts = config.get(
|
|
191
|
+
"installation_scripts", config.get("setup_scripts", [])
|
|
192
|
+
)
|
|
193
|
+
binaries = config.get("binaries", [])
|
|
194
|
+
|
|
195
|
+
results = {"setup": None, "symlinks": []}
|
|
196
|
+
|
|
197
|
+
if install_scripts:
|
|
198
|
+
results["setup"] = self.run_setup_script(bake_name, install_scripts)
|
|
199
|
+
elif not binaries:
|
|
200
|
+
raise SetupCommandFailedException(
|
|
201
|
+
f"No installation scripts or binaries defined for {bake_name}"
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
if binaries:
|
|
205
|
+
results["symlinks"] = self.create_binary_symlinks(bake_name, binaries)
|
|
206
|
+
return results
|
|
207
|
+
except ErrorReadingBakeConfigException as exc:
|
|
208
|
+
raise SetupCommandFailedException(
|
|
209
|
+
f"Error loading configuration for {bake_name}: {exc}"
|
|
210
|
+
) from exc
|
|
211
|
+
|
|
212
|
+
def install_all_bakes(self):
|
|
213
|
+
installed_bakes = self.get_installed_bakes()
|
|
214
|
+
if not installed_bakes:
|
|
215
|
+
raise NoInstallableBakesException("No bakes found to install")
|
|
216
|
+
|
|
217
|
+
results = {}
|
|
218
|
+
for bake_name in installed_bakes:
|
|
219
|
+
try:
|
|
220
|
+
result = self.install_bake(bake_name)
|
|
221
|
+
results[bake_name] = {"success": True, "result": result}
|
|
222
|
+
except (
|
|
223
|
+
BakeNotFoundException,
|
|
224
|
+
SetupCommandFailedException,
|
|
225
|
+
ErrorReadingBakeConfigException,
|
|
226
|
+
) as exc:
|
|
227
|
+
results[bake_name] = {"success": False, "error": str(exc)}
|
|
228
|
+
return results
|
|
229
|
+
|
|
230
|
+
def list_installable_bakes(self):
|
|
231
|
+
installed_bakes = self.get_installed_bakes()
|
|
232
|
+
if not installed_bakes:
|
|
233
|
+
raise NoInstallableBakesException("No bakes found to install")
|
|
234
|
+
return installed_bakes
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import platform
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BakePath:
|
|
7
|
+
"""Path helpers for Bake home directory configuration."""
|
|
8
|
+
|
|
9
|
+
def get_default_path(self):
|
|
10
|
+
return os.getenv("BAKE_PATH", "")
|
|
11
|
+
|
|
12
|
+
def get_suggested_paths(self):
|
|
13
|
+
home = Path.home()
|
|
14
|
+
common_paths = [
|
|
15
|
+
str(home / "bake"),
|
|
16
|
+
str(home / ".bake"),
|
|
17
|
+
str(home / "Documents" / "bake"),
|
|
18
|
+
str(home / "Desktop" / "bake"),
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
if platform.system().lower() == "linux":
|
|
22
|
+
return common_paths + [
|
|
23
|
+
str(home / ".local" / "share" / "bake"),
|
|
24
|
+
str(home / ".config" / "bake"),
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
return common_paths
|
|
28
|
+
|
|
29
|
+
def path_exists(self, path_str):
|
|
30
|
+
return Path(path_str).exists()
|
|
31
|
+
|
|
32
|
+
def create_directory(self, path_str):
|
|
33
|
+
path_obj = Path(path_str)
|
|
34
|
+
try:
|
|
35
|
+
path_obj.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
return True, f"Created directory: {path_str}"
|
|
37
|
+
except PermissionError:
|
|
38
|
+
return False, f"Permission denied creating directory: {path_str}"
|
|
39
|
+
except OSError as exc:
|
|
40
|
+
return False, f"Error creating directory: {exc}"
|
|
41
|
+
|
|
42
|
+
def save_env_file(self, key, value):
|
|
43
|
+
env_file = Path(".env")
|
|
44
|
+
existing_vars = {}
|
|
45
|
+
|
|
46
|
+
if env_file.exists():
|
|
47
|
+
with open(env_file, "r") as env:
|
|
48
|
+
for line in env:
|
|
49
|
+
line = line.strip()
|
|
50
|
+
if line and not line.startswith("#") and "=" in line:
|
|
51
|
+
k, v = line.split("=", 1)
|
|
52
|
+
existing_vars[k] = v
|
|
53
|
+
|
|
54
|
+
existing_vars[key] = value
|
|
55
|
+
|
|
56
|
+
with open(env_file, "w") as env:
|
|
57
|
+
for k, v in existing_vars.items():
|
|
58
|
+
env.write(f"{k}={v}\n")
|
bake/dpkg.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
from bake.commands.dpkg.bake_dpkg_command import BakeDpkgCommand
|
|
5
|
+
from bake.output_style import OutputStyle
|
|
6
|
+
from bake.utils.bake_setup import BakeSetup
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main():
|
|
10
|
+
parser = argparse.ArgumentParser(
|
|
11
|
+
description="Bake package manager commands",
|
|
12
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
13
|
+
)
|
|
14
|
+
parser.add_argument("command", help="Command to execute")
|
|
15
|
+
args = parser.parse_args()
|
|
16
|
+
|
|
17
|
+
if args.command == "sync-config":
|
|
18
|
+
BakeDpkgCommand(OutputStyle(), BakeSetup()).sync_configurations()
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
print("Error: Invalid command provided")
|
|
22
|
+
print("Usage: bake dpkg <command>")
|
|
23
|
+
print("")
|
|
24
|
+
print("Available commands:")
|
|
25
|
+
print("")
|
|
26
|
+
print(" sync-config Synchronize bake definitions")
|
|
27
|
+
print("")
|
|
28
|
+
sys.exit(1)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
if __name__ == "__main__":
|
|
32
|
+
main()
|
bake/exceptions.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
class BakePathNotConfiguredException(Exception):
|
|
2
|
+
pass
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class BakeAlreadyExistsException(Exception):
|
|
6
|
+
pass
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BakeNotFoundException(Exception):
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MissingConfigurationKeysException(Exception):
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ErrorReadingBakeConfigException(Exception):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class SetupCommandFailedException(Exception):
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class NoInstallableBakesException(Exception):
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ErrorCreatingSymlinkException(Exception):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ErrorCopyingException(Exception):
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
class MissingBuiltInToolsDirException(Exception):
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
class ErrorCreatingConfigFolderException(Exception):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ErrorCreatingRepoFolderException(Exception):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class NoConfigurationsFolderException(Exception):
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class MissingPackageException(Exception):
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ErrorCloningRepositoryException(Exception):
|
|
56
|
+
pass
|
bake/install.py
ADDED
bake/output_style.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from rich.console import Console
|
|
2
|
+
from rich.theme import Theme
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class OutputStyle:
|
|
6
|
+
"""Styled terminal output for Bake."""
|
|
7
|
+
|
|
8
|
+
def __init__(self):
|
|
9
|
+
self.console = Console(
|
|
10
|
+
theme=Theme(
|
|
11
|
+
{
|
|
12
|
+
"info": "cyan",
|
|
13
|
+
"warning": "yellow",
|
|
14
|
+
"error": "red bold",
|
|
15
|
+
"success": "green",
|
|
16
|
+
}
|
|
17
|
+
)
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
def write(self, message: str, style: str = "") -> None:
|
|
21
|
+
self.console.print(message, end="", style=style, soft_wrap=True)
|
|
22
|
+
|
|
23
|
+
def writeln(self, message: str = "", style: str = "") -> None:
|
|
24
|
+
self.console.print(message, style=style, soft_wrap=True)
|
bake/system/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""System subprocess wrappers for Bake."""
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
|
|
3
|
+
from bake.exceptions import ErrorCopyingException
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CopySubprocess:
|
|
7
|
+
"""Copy files and directories via subprocess."""
|
|
8
|
+
|
|
9
|
+
def copy(self, source, destination, options=None):
|
|
10
|
+
if options is None:
|
|
11
|
+
options = []
|
|
12
|
+
|
|
13
|
+
command = ["cp"] + options + [source, destination]
|
|
14
|
+
result = subprocess.run(command, capture_output=True, text=True)
|
|
15
|
+
|
|
16
|
+
if result.returncode != 0:
|
|
17
|
+
raise ErrorCopyingException(
|
|
18
|
+
"Error copying default configuration files: " + str(result.stderr)
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
return result
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
|
|
3
|
+
from bake.exceptions import ErrorCloningRepositoryException, MissingPackageException
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class GitSubprocess:
|
|
7
|
+
def clone(self, repo_url, target_path):
|
|
8
|
+
"""Clone a git repository to the target path."""
|
|
9
|
+
try:
|
|
10
|
+
version_check = subprocess.run(
|
|
11
|
+
["git", "--version"], capture_output=True, text=True
|
|
12
|
+
)
|
|
13
|
+
if version_check.returncode != 0:
|
|
14
|
+
raise MissingPackageException("git is not installed or not available in PATH")
|
|
15
|
+
|
|
16
|
+
result = subprocess.run(
|
|
17
|
+
["git", "clone", repo_url, str(target_path)],
|
|
18
|
+
capture_output=True,
|
|
19
|
+
text=True,
|
|
20
|
+
)
|
|
21
|
+
if result.returncode != 0:
|
|
22
|
+
raise ErrorCloningRepositoryException(
|
|
23
|
+
f"Failed to clone {repo_url}: {result.stderr}"
|
|
24
|
+
)
|
|
25
|
+
return result.stdout
|
|
26
|
+
except Exception as exc:
|
|
27
|
+
raise ErrorCloningRepositoryException(
|
|
28
|
+
f"Failed to clone {repo_url}: {exc}"
|
|
29
|
+
) from exc
|
bake/utils/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Utility modules for Bake."""
|
bake/utils/bake_setup.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from bake.exceptions import (
|
|
5
|
+
BakePathNotConfiguredException,
|
|
6
|
+
ErrorCreatingConfigFolderException,
|
|
7
|
+
ErrorCreatingRepoFolderException,
|
|
8
|
+
NoConfigurationsFolderException,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BakeSetup:
|
|
13
|
+
def bake_path(self):
|
|
14
|
+
bake_path = self.__get_env_path()
|
|
15
|
+
if not bake_path:
|
|
16
|
+
raise BakePathNotConfiguredException()
|
|
17
|
+
return bake_path
|
|
18
|
+
|
|
19
|
+
def config_path(self):
|
|
20
|
+
return Path(self.bake_path()) / "config"
|
|
21
|
+
|
|
22
|
+
def repositories_path(self):
|
|
23
|
+
return Path(self.bake_path()) / "repositories"
|
|
24
|
+
|
|
25
|
+
def bin_path(self):
|
|
26
|
+
return Path(self.bake_path()) / "bin"
|
|
27
|
+
|
|
28
|
+
def config_dir_exists(self):
|
|
29
|
+
return self.config_path().exists()
|
|
30
|
+
|
|
31
|
+
def repositories_dir_exists(self):
|
|
32
|
+
return self.repositories_path().exists()
|
|
33
|
+
|
|
34
|
+
def bin_dir_exists(self):
|
|
35
|
+
return self.bin_path().exists()
|
|
36
|
+
|
|
37
|
+
def is_config_dir_empty(self):
|
|
38
|
+
if not self.config_dir_exists():
|
|
39
|
+
raise NoConfigurationsFolderException(
|
|
40
|
+
"No bake configuration path found at "
|
|
41
|
+
+ str(self.config_path().absolute())
|
|
42
|
+
)
|
|
43
|
+
return not os.listdir(self.config_path())
|
|
44
|
+
|
|
45
|
+
def setup_config_dir(self):
|
|
46
|
+
try:
|
|
47
|
+
if not self.config_dir_exists():
|
|
48
|
+
self.config_path().mkdir(parents=True, exist_ok=True)
|
|
49
|
+
except Exception as exc:
|
|
50
|
+
raise ErrorCreatingConfigFolderException(
|
|
51
|
+
"Error creating configuration folder "
|
|
52
|
+
+ str(self.config_path().absolute())
|
|
53
|
+
+ ": "
|
|
54
|
+
+ str(exc)
|
|
55
|
+
) from exc
|
|
56
|
+
|
|
57
|
+
def setup_repositories_dir(self):
|
|
58
|
+
try:
|
|
59
|
+
if not self.repositories_dir_exists():
|
|
60
|
+
self.repositories_path().mkdir(parents=True, exist_ok=True)
|
|
61
|
+
except Exception as exc:
|
|
62
|
+
raise ErrorCreatingRepoFolderException(
|
|
63
|
+
"Error creating repositories folder "
|
|
64
|
+
+ str(self.repositories_path().absolute())
|
|
65
|
+
+ ": "
|
|
66
|
+
+ str(exc)
|
|
67
|
+
) from exc
|
|
68
|
+
|
|
69
|
+
def setup_bin_dir(self):
|
|
70
|
+
try:
|
|
71
|
+
if not self.bin_dir_exists():
|
|
72
|
+
self.bin_path().mkdir(parents=True, exist_ok=True)
|
|
73
|
+
except Exception as exc:
|
|
74
|
+
raise ErrorCreatingRepoFolderException(
|
|
75
|
+
"Error creating bin folder "
|
|
76
|
+
+ str(self.bin_path().absolute())
|
|
77
|
+
+ ": "
|
|
78
|
+
+ str(exc)
|
|
79
|
+
) from exc
|
|
80
|
+
|
|
81
|
+
def __get_env_path(self):
|
|
82
|
+
return os.getenv("BAKE_PATH", "")
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bake
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Bake orchestrates internal CLI tools, setup scripts, and repeatable automation workflows.
|
|
5
|
+
Keywords: automation,cli,developer-tools,scripts,workflow
|
|
6
|
+
Classifier: Development Status :: 3 - Alpha
|
|
7
|
+
Classifier: Environment :: Console
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
15
|
+
Classifier: Topic :: Utilities
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Requires-Dist: python-dotenv>=1.1.1
|
|
18
|
+
Requires-Dist: rich>=14.1.0
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Bake
|
|
22
|
+
|
|
23
|
+
Bake is a CLI automation orchestrator for managing internal tool repositories,
|
|
24
|
+
setup scripts, and reusable command workflows.
|
|
25
|
+
|
|
26
|
+
## Why Bake
|
|
27
|
+
|
|
28
|
+
- Organize automation in one place instead of scattered shell scripts.
|
|
29
|
+
- Bootstrap and install tool repositories from JSON definitions.
|
|
30
|
+
- Expose runnable binaries in a shared `bin` directory.
|
|
31
|
+
- Keep local setup repeatable across developers.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uv venv
|
|
37
|
+
source .venv/bin/activate
|
|
38
|
+
uv pip install -e .
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
After installation, the main command is:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
bake
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Commands
|
|
48
|
+
|
|
49
|
+
### `bake install`
|
|
50
|
+
|
|
51
|
+
Interactive initialization flow that:
|
|
52
|
+
|
|
53
|
+
- Configures `BAKE_PATH` in `.env`.
|
|
54
|
+
- Creates `config`, `repositories`, and `bin` folders.
|
|
55
|
+
- Copies default configuration templates from `tools/config`.
|
|
56
|
+
- Optionally downloads and installs configured repositories.
|
|
57
|
+
|
|
58
|
+
### `bake dpkg sync-config`
|
|
59
|
+
|
|
60
|
+
Synchronizes default configuration definitions from `tools/config` into
|
|
61
|
+
`$BAKE_PATH/config`.
|
|
62
|
+
|
|
63
|
+
## Configuration Model
|
|
64
|
+
|
|
65
|
+
Bake uses JSON files in `tools/config`, for example:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"name": "aws-cli-toolkit",
|
|
70
|
+
"repo_url": "https://github.com/darioriverat/aws-cli-toolkit",
|
|
71
|
+
"description": "A comprehensive command-line toolkit for managing AWS services",
|
|
72
|
+
"scripts": {
|
|
73
|
+
"install": [
|
|
74
|
+
"uv venv",
|
|
75
|
+
"source .venv/bin/activate",
|
|
76
|
+
"uv pip install -e ."
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Optional `binaries` entries can create symlinks/wrappers in `$BAKE_PATH/bin`.
|
|
83
|
+
|
|
84
|
+
## Notes
|
|
85
|
+
|
|
86
|
+
- `BAKE_PATH` is the environment variable used by Bake.
|
|
87
|
+
- `bake` is the canonical command.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
bake/__init__.py,sha256=C2nrEhouHcXSnMN-0auN78UG3TiKuHO5gyWQ7KQ2HHU,20
|
|
2
|
+
bake/cli.py,sha256=KPf2SC1NQRvqzWOHftS6B8h2b1XG_b87TyxGbqt_lD8,882
|
|
3
|
+
bake/dpkg.py,sha256=1--Jb-SOOds1OTOx3A-TebA3P1Yr7B4N34MlfEjh334,849
|
|
4
|
+
bake/exceptions.py,sha256=XC3fnWPO0RC2gj2p2uvc1Goqdg-ABfMO_lcninffRHE,873
|
|
5
|
+
bake/install.py,sha256=eYjPlqi8-AYKq0qPUTMKcqYeDPf68B6IIg5kgSC3PIM,211
|
|
6
|
+
bake/output_style.py,sha256=ngXYLgiBIW0bd1_2bjALt5c0xVNI2ddt4IfxamcpJHs,693
|
|
7
|
+
bake/commands/__init__.py,sha256=i3puFYleYrC9wrXzAgXeRtsHaooBuMR25FKps4_k08c,28
|
|
8
|
+
bake/commands/dpkg/__init__.py,sha256=K-J8KlEr6xHMMX46PoPT9xrqIUnl5hQG3fnuzVanqe0,51
|
|
9
|
+
bake/commands/dpkg/bake_dpkg_command.py,sha256=QefP45ZemarzVS9dGbHwfameeth1NWeVc9GF-7KZhWo,1611
|
|
10
|
+
bake/commands/init/__init__.py,sha256=5zqy0RkAbIKvllKF3zM7cAMS3izJxjz08ZxNcnbMTks,47
|
|
11
|
+
bake/commands/init/bake_downloader.py,sha256=Nuqv4AjzTOYLwPjNeVU3DoKNli_Y2XJR90174pPkVHQ,1740
|
|
12
|
+
bake/commands/init/bake_init_command.py,sha256=l0X96TtgLJexbKBwk5nwEzAhyWrgnRBYNPJxbhD5_2M,8368
|
|
13
|
+
bake/commands/init/bake_installer.py,sha256=hk1DLR3rZEO2Mw2n4nMy63TxHazCIKbOjyF8Mfq2BKQ,8609
|
|
14
|
+
bake/commands/init/bake_path.py,sha256=MdwJ5Fyl3qo8kh1TnhJqYliaYVGhF5-ajgGEhuibFyA,1760
|
|
15
|
+
bake/system/__init__.py,sha256=E3Uyp47qDRFGTmUa6rV-87k2vaV5j0Fd3RqiVOm0ul0,43
|
|
16
|
+
bake/system/copy_subprocess.py,sha256=QxJX92XC3bzMJSmjBtwF0fdiPJTzE9Luk5Lhv4gIb6s,585
|
|
17
|
+
bake/system/git_subprocess.py,sha256=GBBF_-Qyle4-Ae2ERvdDU5KhWN8ARmkfQ1pMB_3BOho,1059
|
|
18
|
+
bake/utils/__init__.py,sha256=VhOkMFl6hqC5ezszTwSdb1hKjktf6Npjezn7-aDEe8c,32
|
|
19
|
+
bake/utils/bake_setup.py,sha256=96Xi77YMx_93DjbzTt_F4Kat0-MBzbsfG19YB2y0fxY,2538
|
|
20
|
+
bake-0.1.0.dist-info/METADATA,sha256=JfqyQ8veefEUQJkl3wcx6ojpf6obrIbVX0G751J0pak,2306
|
|
21
|
+
bake-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
22
|
+
bake-0.1.0.dist-info/entry_points.txt,sha256=L7IwlY_HKD-yw5GyQyBYeYdN5oium1yWGmsNiMktjRI,39
|
|
23
|
+
bake-0.1.0.dist-info/RECORD,,
|