machineconfig 1.9__py3-none-any.whl → 1.91__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 machineconfig might be problematic. Click here for more details.
- machineconfig/__init__.py +1 -1
- machineconfig/jobs/python/check_installations.py +7 -5
- machineconfig/jobs/python/checkout_version.py +27 -32
- machineconfig/jobs/python/create_bootable_media.py +1 -1
- machineconfig/jobs/python/python_cargo_build_share.py +2 -2
- machineconfig/jobs/python/tasks.py +2 -2
- machineconfig/jobs/python_custom_installers/{helix.py → hx.py} +17 -5
- machineconfig/profile/create.py +23 -21
- machineconfig/profile/create_hardlinks.py +101 -0
- machineconfig/profile/shell.py +5 -5
- machineconfig/scripts/python/cloud_copy.py +19 -16
- machineconfig/scripts/python/cloud_repo_sync.py +92 -47
- machineconfig/scripts/python/cloud_sync.py +70 -63
- machineconfig/scripts/python/croshell.py +6 -6
- machineconfig/scripts/python/devops.py +19 -20
- machineconfig/scripts/python/devops_backup_retrieve.py +19 -10
- machineconfig/scripts/python/devops_devapps_install.py +80 -62
- machineconfig/scripts/python/devops_update_repos.py +5 -5
- machineconfig/scripts/python/dotfile.py +4 -4
- machineconfig/scripts/python/fire_jobs.py +57 -23
- machineconfig/scripts/python/gh_models.py +53 -0
- machineconfig/scripts/python/mount_nfs.py +1 -1
- machineconfig/scripts/python/mount_nw_drive.py +3 -3
- machineconfig/scripts/python/mount_ssh.py +2 -3
- machineconfig/scripts/python/pomodoro.py +1 -1
- machineconfig/scripts/python/repos.py +21 -22
- machineconfig/scripts/python/scheduler.py +1 -1
- machineconfig/scripts/python/start_slidev.py +10 -4
- machineconfig/scripts/python/start_terminals.py +5 -4
- machineconfig/scripts/python/wifi_conn.py +34 -42
- machineconfig/scripts/python/wsl_windows_transfer.py +1 -1
- machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +1 -1
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +3 -2
- machineconfig/utils/installer.py +78 -39
- machineconfig/utils/procs.py +2 -2
- machineconfig/utils/scheduling.py +3 -3
- machineconfig/utils/utils.py +131 -52
- machineconfig/utils/ve.py +145 -95
- {machineconfig-1.9.dist-info → machineconfig-1.91.dist-info}/METADATA +160 -155
- machineconfig-1.91.dist-info/RECORD +69 -0
- machineconfig/jobs/python_custom_installers/azuredatastudio.py +0 -36
- machineconfig/jobs/python_custom_installers/bypass_paywall.py +0 -30
- machineconfig/jobs/python_custom_installers/docker_desktop.py +0 -52
- machineconfig/jobs/python_custom_installers/goes.py +0 -35
- machineconfig/jobs/python_custom_installers/lvim.py +0 -48
- machineconfig/jobs/python_custom_installers/ngrok.py +0 -39
- machineconfig/jobs/python_custom_installers/nvim.py +0 -48
- machineconfig/jobs/python_custom_installers/vscode.py +0 -45
- machineconfig/jobs/python_custom_installers/wezterm.py +0 -41
- machineconfig-1.9.dist-info/RECORD +0 -76
- {machineconfig-1.9.dist-info → machineconfig-1.91.dist-info}/LICENSE +0 -0
- {machineconfig-1.9.dist-info → machineconfig-1.91.dist-info}/WHEEL +0 -0
- {machineconfig-1.9.dist-info → machineconfig-1.91.dist-info}/top_level.txt +0 -0
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
|
|
2
2
|
"""utils"""
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
from
|
|
6
|
-
from crocodile.file_management import P, Read, install_n_import
|
|
4
|
+
import git
|
|
5
|
+
from crocodile.file_management import P, Read
|
|
7
6
|
from crocodile.core import randstr
|
|
8
7
|
from crocodile.meta import Terminal
|
|
8
|
+
|
|
9
|
+
from machineconfig.utils.utils import CONFIG_PATH, DEFAULTS_PATH, PROGRAM_PATH, write_shell_script, get_shell_file_executing_python_script, get_shell_script, choose_one_option
|
|
9
10
|
import argparse
|
|
10
11
|
import platform
|
|
11
|
-
from typing import Optional
|
|
12
|
+
from typing import Optional, Literal
|
|
12
13
|
# import sys
|
|
13
14
|
# import subprocess
|
|
14
15
|
|
|
@@ -22,13 +23,14 @@ def get_wt_cmd(wd1: P, wd2: P) -> str:
|
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
def get_zellij_cmd(wd1: P, wd2: P) -> str:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
_ = wd1, wd2
|
|
27
|
+
lines = [""" zellij action new-tab --name gitdiff""",
|
|
28
|
+
"""zellij action new-pane --direction down --name local --cwd ./data """,
|
|
29
|
+
"""zellij action write-chars "cd '{wd1}'; git status" """,
|
|
30
|
+
"""zellij action move-focus up; zellij action close-pane """,
|
|
31
|
+
"""zellij action new-pane --direction down --name remote --cwd code """,
|
|
32
|
+
"""zellij action write-chars "cd '{wd2}' """,
|
|
33
|
+
"""git status" """
|
|
32
34
|
]
|
|
33
35
|
return "; ".join(lines)
|
|
34
36
|
|
|
@@ -43,20 +45,23 @@ def args_parser():
|
|
|
43
45
|
|
|
44
46
|
parser.add_argument("--cloud", "-c", help="rclone cloud profile name.", default=None)
|
|
45
47
|
parser.add_argument("--message", "-m", help="Commit Message", default=f"new message {randstr()}")
|
|
46
|
-
parser.add_argument("--skip_confirmation", "-s", help="Skip confirmation.", action="store_true", default=False)
|
|
48
|
+
# parser.add_argument("--skip_confirmation", "-s", help="Skip confirmation.", action="store_true", default=False)
|
|
47
49
|
# parser.add_argument("--key", "-k", help="Key for encryption", default=None)
|
|
48
50
|
parser.add_argument("--pwd", "-p", help="Password for encryption", default=None)
|
|
49
|
-
parser.add_argument("--no_push", "-u", help="push to reomte.", action="store_true") # default is False
|
|
51
|
+
# parser.add_argument("--no_push", "-u", help="push to reomte.", action="store_true") # default is False
|
|
52
|
+
parser.add_argument("--action", "-a", help="Action to take if merge fails.", choices=["ask", "pushLocalMerge", "overwriteLocal", "InspectRepos", "RemoveLocalRclone"], default="ask")
|
|
50
53
|
args = parser.parse_args()
|
|
51
54
|
|
|
52
55
|
# if args.share:
|
|
53
56
|
# from machineconfig.scripts.cloud.dotfiles import put
|
|
54
57
|
# put()
|
|
55
58
|
# return None
|
|
56
|
-
main(cloud=args.cloud, path=args.path, message=args.message,
|
|
59
|
+
main(cloud=args.cloud, path=args.path, message=args.message, action=args.action)
|
|
57
60
|
|
|
58
61
|
|
|
59
|
-
def main(cloud: Optional[str] = None, path: Optional[str] = None, message: Optional[str] = None,
|
|
62
|
+
def main(cloud: Optional[str] = None, path: Optional[str] = None, message: Optional[str] = None,
|
|
63
|
+
action: Literal["ask", "pushLocalMerge", "overwriteLocal", "InspectRepos", "RemoveLocalRclone"] = "ask",
|
|
64
|
+
pwd: Optional[str] = None):
|
|
60
65
|
if cloud is None:
|
|
61
66
|
try:
|
|
62
67
|
cloud_resolved = Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
|
|
@@ -67,7 +72,7 @@ def main(cloud: Optional[str] = None, path: Optional[str] = None, message: Optio
|
|
|
67
72
|
else: cloud_resolved = cloud
|
|
68
73
|
# repo_root = P(args.repo).expanduser().absolute()
|
|
69
74
|
repo_local_root = P.cwd() if path is None else P(path).expanduser().absolute()
|
|
70
|
-
repo_local_obj =
|
|
75
|
+
repo_local_obj = git.Repo(repo_local_root, search_parent_directories=True)
|
|
71
76
|
repo_local_root = P(repo_local_obj.working_dir) # cwd might have been in a sub directory of repo_root, so its better to redefine it.
|
|
72
77
|
CONFIG_PATH.joinpath("remote").create()
|
|
73
78
|
repo_remote_root = CONFIG_PATH.joinpath("remote", repo_local_root.rel2home()) # .delete(sure=True)
|
|
@@ -79,7 +84,7 @@ def main(cloud: Optional[str] = None, path: Optional[str] = None, message: Optio
|
|
|
79
84
|
print("Remote does not exist, creating it and exiting ... ")
|
|
80
85
|
repo_local_root.to_cloud(cloud=cloud_resolved, zip=True, encrypt=True, rel2home=True, pwd=pwd, os_specific=False)
|
|
81
86
|
return ""
|
|
82
|
-
repo_remote_obj =
|
|
87
|
+
repo_remote_obj = git.Repo(repo_remote_root)
|
|
83
88
|
if repo_remote_obj.is_dirty():
|
|
84
89
|
print("=" * 50, '\n', f"WRANING: the remote `{repo_remote_root}` is dirty, please commit or stash changes before proceeding.", '\n', "=" * 50)
|
|
85
90
|
|
|
@@ -102,49 +107,76 @@ echo '-> Fetching originEnc remote.'
|
|
|
102
107
|
git pull originEnc master
|
|
103
108
|
|
|
104
109
|
"""
|
|
105
|
-
|
|
106
|
-
|
|
110
|
+
|
|
111
|
+
shell_path = get_shell_script(shell_script=script)
|
|
112
|
+
res = Terminal().run(f". {shell_path}", shell="powershell").capture().print()
|
|
107
113
|
|
|
108
114
|
if res.is_successful(strict_err=True, strict_returcode=True):
|
|
109
115
|
print("\n", "Pull succeeded, removing originEnc, the local copy of remote & pushing merged repo_root to remote ... ")
|
|
110
116
|
repo_remote_root.delete(sure=True)
|
|
111
117
|
from git.remote import Remote
|
|
112
118
|
Remote.remove(repo_local_obj, "originEnc")
|
|
113
|
-
|
|
114
|
-
repo_local_root.to_cloud(cloud=cloud_resolved, zip=True, encrypt=True, rel2home=True, pwd=pwd, os_specific=False)
|
|
119
|
+
repo_local_root.to_cloud(cloud=cloud_resolved, zip=True, encrypt=True, rel2home=True, pwd=pwd, os_specific=False)
|
|
115
120
|
else:
|
|
116
|
-
print(f"Failed to
|
|
121
|
+
print(f"Failed to merge with no errors, keeping local copy of remote at {repo_remote_root} ... ")
|
|
117
122
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
else: resp = "n"
|
|
122
|
-
|
|
123
|
-
if resp.lower() == "y":
|
|
124
|
-
delete_remote_repo_copy_and_push_local(remote_repo=repo_remote_root.str, local_repo=repo_local_root.str, cloud=cloud_resolved)
|
|
125
|
-
else:
|
|
126
|
-
program = f"""
|
|
123
|
+
# ================================================================================
|
|
124
|
+
option1 = 'Delete remote copy and push local:'
|
|
125
|
+
program_1_py = f"""
|
|
127
126
|
from machineconfig.scripts.python.cloud_repo_sync import delete_remote_repo_copy_and_push_local as func
|
|
128
|
-
func(remote_repo=r'{repo_remote_root.
|
|
127
|
+
func(remote_repo=r'{repo_remote_root.to_str()}', local_repo=r'{repo_local_root.to_str()}', cloud=r'{cloud_resolved}')
|
|
129
128
|
"""
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
129
|
+
shell_file_1 = get_shell_file_executing_python_script(python_script=program_1_py, ve_name="ve")
|
|
130
|
+
# ================================================================================
|
|
131
|
+
|
|
132
|
+
option2 = 'Delete local repo and replace it with remote copy:'
|
|
133
|
+
program_2 = f"""
|
|
135
134
|
rm -rfd {repo_local_root}
|
|
136
135
|
mv {repo_remote_root} {repo_local_root}
|
|
136
|
+
sudo chmod 600 ~/.ssh/*
|
|
137
|
+
sudo chmod 700 ~/.ssh
|
|
138
|
+
"""
|
|
137
139
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
140
|
+
shell_file_2 = get_shell_script(shell_script=program_2)
|
|
141
|
+
|
|
142
|
+
# ================================================================================
|
|
143
|
+
option3 = 'Inspect repos:'
|
|
144
|
+
program_3_py = f"""
|
|
145
|
+
from machineconfig.scripts.python.cloud_repo_sync import inspect_repos as func
|
|
146
|
+
func(repo_local_root=r'{repo_local_root.to_str()}', repo_remote_root=r'{repo_remote_root.to_str()}')
|
|
147
|
+
"""
|
|
148
|
+
shell_file_3 = get_shell_file_executing_python_script(python_script=program_3_py, ve_name="ve")
|
|
149
|
+
# ================================================================================
|
|
150
|
+
|
|
151
|
+
option4 = 'Remove problematic rclone file from repo and replace with remote:'
|
|
152
|
+
program_4 = """
|
|
153
|
+
rm ~/dotfiles/creds/rclone/rclone.conf
|
|
154
|
+
cp ~/.config/machineconfig/remote/dotfiles/creds/rclone/rclone.conf ~/dotfiles/creds/rclone
|
|
155
|
+
"""
|
|
156
|
+
shell_file_4 = get_shell_script(shell_script=program_4)
|
|
157
|
+
# ================================================================================
|
|
158
|
+
|
|
159
|
+
print(f"• {option1:75} 👉 {shell_file_1}")
|
|
160
|
+
print(f"• {option2:75} 👉 {shell_file_2}")
|
|
161
|
+
print(f"• {option3:75} 👉 {shell_file_3}")
|
|
162
|
+
print(f"• {option4:75} 👉 {shell_file_4}")
|
|
163
|
+
|
|
164
|
+
match action:
|
|
165
|
+
case "ask":
|
|
166
|
+
choice = choose_one_option(options=[option1, option2, option3, option4])
|
|
167
|
+
if choice == option1: PROGRAM_PATH.write_text(shell_file_1.read_text())
|
|
168
|
+
elif choice == option2: PROGRAM_PATH.write_text(program_2)
|
|
169
|
+
elif choice == option3: PROGRAM_PATH.write_text(shell_file_3.read_text())
|
|
170
|
+
elif choice == option4: PROGRAM_PATH.write_text(program_4)
|
|
171
|
+
else: raise NotImplementedError(f"Choice {choice} not implemented.")
|
|
172
|
+
case "pushLocalMerge":
|
|
173
|
+
PROGRAM_PATH.write_text(shell_file_1.read_text())
|
|
174
|
+
case "overwriteLocal":
|
|
175
|
+
PROGRAM_PATH.write_text(program_2)
|
|
176
|
+
case "InspectRepos":
|
|
177
|
+
PROGRAM_PATH.write_text(shell_file_3.read_text())
|
|
178
|
+
case "RemoveLocalRclone":
|
|
179
|
+
PROGRAM_PATH.write_text(program_4)
|
|
148
180
|
|
|
149
181
|
|
|
150
182
|
def delete_remote_repo_copy_and_push_local(remote_repo: str, local_repo: str, cloud: str):
|
|
@@ -158,5 +190,18 @@ def delete_remote_repo_copy_and_push_local(remote_repo: str, local_repo: str, cl
|
|
|
158
190
|
repo_root_path.to_cloud(cloud=cloud, zip=True, encrypt=True, rel2home=True, os_specific=False)
|
|
159
191
|
|
|
160
192
|
|
|
193
|
+
def inspect_repos(repo_local_root: str, repo_remote_root: str):
|
|
194
|
+
if platform.system() == "Windows":
|
|
195
|
+
program = get_wt_cmd(wd1=P(repo_local_root), wd2=P(repo_local_root))
|
|
196
|
+
write_shell_script(program=program, execute=True)
|
|
197
|
+
return None
|
|
198
|
+
elif platform.system() == "Linux":
|
|
199
|
+
program = get_zellij_cmd(wd1=P(repo_local_root), wd2=P(repo_remote_root))
|
|
200
|
+
write_shell_script(program=program, execute=True)
|
|
201
|
+
return None
|
|
202
|
+
else: raise NotImplementedError(f"Platform {platform.system()} not implemented.")
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
161
206
|
if __name__ == "__main__":
|
|
162
207
|
args_parser()
|
|
@@ -4,8 +4,8 @@ TODO: use tap typed-argument-parser to parse args
|
|
|
4
4
|
TODO: use typer to make clis
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from crocodile.file_management import P, Read
|
|
8
|
-
|
|
7
|
+
from crocodile.file_management import P, Read
|
|
8
|
+
from crocodile.core import Struct
|
|
9
9
|
from machineconfig.utils.utils import PROGRAM_PATH, DEFAULTS_PATH
|
|
10
10
|
from machineconfig.scripts.python.cloud_mount import get_mprocs_mount_txt
|
|
11
11
|
import argparse
|
|
@@ -22,12 +22,12 @@ ES = "^" # chosen carefully to not mean anything on any shell. `$` was a bad ch
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class ArgsDefaults:
|
|
25
|
-
# source: str
|
|
26
|
-
# target: str
|
|
27
|
-
encrypt: bool
|
|
28
|
-
zip_: bool
|
|
29
|
-
overwrite: bool
|
|
30
|
-
share: bool
|
|
25
|
+
# source: str=None
|
|
26
|
+
# target: str=None
|
|
27
|
+
encrypt: bool=False
|
|
28
|
+
zip_: bool=False
|
|
29
|
+
overwrite: bool=False
|
|
30
|
+
share: bool=False
|
|
31
31
|
rel2home = False
|
|
32
32
|
root = None
|
|
33
33
|
os_specific = False
|
|
@@ -35,19 +35,19 @@ class ArgsDefaults:
|
|
|
35
35
|
pwd = None
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
@dataclass(config=ConfigDict(extra="forbid", frozen=
|
|
38
|
+
@dataclass(config=ConfigDict(extra="forbid", frozen=False))
|
|
39
39
|
class Args():
|
|
40
40
|
cloud: Optional[str] = None
|
|
41
41
|
|
|
42
|
-
zip: bool
|
|
43
|
-
overwrite: bool
|
|
44
|
-
share: bool
|
|
42
|
+
zip: bool=ArgsDefaults.zip_
|
|
43
|
+
overwrite: bool=ArgsDefaults.overwrite
|
|
44
|
+
share: bool=ArgsDefaults.share
|
|
45
45
|
|
|
46
46
|
root: Optional[str] = ArgsDefaults.root
|
|
47
|
-
os_specific: bool
|
|
48
|
-
rel2home: bool
|
|
47
|
+
os_specific: bool=ArgsDefaults.os_specific
|
|
48
|
+
rel2home: bool=ArgsDefaults.rel2home
|
|
49
49
|
|
|
50
|
-
encrypt: bool
|
|
50
|
+
encrypt: bool=ArgsDefaults.encrypt
|
|
51
51
|
key: Optional[str] = ArgsDefaults.key
|
|
52
52
|
pwd: Optional[str] = ArgsDefaults.pwd
|
|
53
53
|
|
|
@@ -70,7 +70,7 @@ def absolute(path: str) -> P:
|
|
|
70
70
|
return obj.absolute()
|
|
71
71
|
|
|
72
72
|
|
|
73
|
-
def get_secure_share_cloud_config(interactive: bool
|
|
73
|
+
def get_secure_share_cloud_config(interactive: bool=True) -> Args:
|
|
74
74
|
if os.environ.get("CLOUD_CONFIG_NAME") is not None:
|
|
75
75
|
default_cloud = os.environ.get("CLOUD_CONFIG_NAME")
|
|
76
76
|
assert default_cloud is not None
|
|
@@ -98,7 +98,7 @@ def get_secure_share_cloud_config(interactive: bool = True) -> Args:
|
|
|
98
98
|
pwd=pwd, encrypt=True,
|
|
99
99
|
zip=True, overwrite=True, share=True,
|
|
100
100
|
rel2home=True, root="myshare", os_specific=False,)
|
|
101
|
-
Struct(res.__dict__).print(as_config=True, title=
|
|
101
|
+
Struct(res.__dict__).print(as_config=True, title="⚠️ Using SecureShare cloud config")
|
|
102
102
|
return res
|
|
103
103
|
|
|
104
104
|
|
|
@@ -113,55 +113,62 @@ def find_cloud_config(path: P):
|
|
|
113
113
|
|
|
114
114
|
|
|
115
115
|
def parse_cloud_source_target(args: Args, source: str, target: str) -> tuple[str, str, str]:
|
|
116
|
+
config = args.config
|
|
117
|
+
root = args.root
|
|
118
|
+
rel2home = args.rel2home
|
|
119
|
+
pwd = args.pwd
|
|
120
|
+
encrypt = args.encrypt
|
|
121
|
+
zip_arg = args.zip
|
|
122
|
+
share = args.share
|
|
123
|
+
os_specific = args.os_specific
|
|
124
|
+
|
|
125
|
+
if config == "ss":
|
|
126
|
+
maybe_config = get_secure_share_cloud_config()
|
|
127
|
+
elif config is not None:
|
|
128
|
+
maybe_config = Args.from_config(absolute(config))
|
|
129
|
+
else:
|
|
130
|
+
maybe_config = None
|
|
131
|
+
|
|
116
132
|
if source.startswith(":"): # default cloud name is omitted cloud_name: # or ES in source
|
|
117
133
|
# At the moment, this cloud.json defaults overrides the args and is activated only when source or target are just ":"
|
|
118
134
|
# consider activating it by a flag, and also not not overriding explicitly passed args options.
|
|
119
|
-
assert ES not in target,
|
|
135
|
+
assert ES not in target, "Not Implemented here yet."
|
|
120
136
|
path = absolute(target)
|
|
121
|
-
if
|
|
122
|
-
maybe_config: Optional[Args] = find_cloud_config(path=path)
|
|
123
|
-
else:
|
|
124
|
-
if args.config == "ss": maybe_config = get_secure_share_cloud_config()
|
|
125
|
-
else: maybe_config = Args.from_config(absolute(args.config))
|
|
137
|
+
if maybe_config is None: maybe_config: Optional[Args] = find_cloud_config(path=path)
|
|
126
138
|
|
|
127
139
|
if maybe_config is None:
|
|
128
|
-
default_cloud: str
|
|
140
|
+
default_cloud: str=Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
|
|
129
141
|
print(f"⚠️ Using default cloud: {default_cloud}")
|
|
130
142
|
source = default_cloud + ":" + source[1:]
|
|
131
143
|
else:
|
|
132
144
|
tmp = maybe_config
|
|
133
145
|
source = f"{tmp.cloud}:" + source[1:]
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
# args.jh = 22
|
|
146
|
+
root = tmp.root
|
|
147
|
+
rel2home = tmp.rel2home
|
|
148
|
+
pwd = tmp.pwd
|
|
149
|
+
encrypt = tmp.encrypt
|
|
150
|
+
zip_arg = tmp.zip
|
|
151
|
+
share = tmp.share
|
|
141
152
|
|
|
142
153
|
if target.startswith(":"): # default cloud name is omitted cloud_name: # or ES in target
|
|
143
|
-
assert ES not in source,
|
|
154
|
+
assert ES not in source, "Not Implemented here yet."
|
|
144
155
|
path = absolute(source)
|
|
145
|
-
if
|
|
146
|
-
maybe_config = find_cloud_config(path)
|
|
147
|
-
else:
|
|
148
|
-
if args.config == "ss": maybe_config = get_secure_share_cloud_config()
|
|
149
|
-
else: maybe_config = Args.from_config(absolute(args.config))
|
|
150
|
-
|
|
151
|
-
if maybe_config is not None:
|
|
152
|
-
tmp = maybe_config
|
|
153
|
-
target = f"{tmp.cloud}:" + target[1:]
|
|
154
|
-
args.root = tmp.root
|
|
155
|
-
args.rel2home = tmp.rel2home
|
|
156
|
-
args.pwd = tmp.pwd
|
|
157
|
-
args.encrypt = tmp.encrypt
|
|
158
|
-
args.zip = tmp.zip
|
|
159
|
-
args.share = tmp.share
|
|
156
|
+
if maybe_config is None: maybe_config = find_cloud_config(path)
|
|
160
157
|
|
|
161
|
-
|
|
158
|
+
if maybe_config is None:
|
|
162
159
|
default_cloud = Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
|
|
163
160
|
print(f"⚠️ Using default cloud: {default_cloud}")
|
|
164
161
|
target = default_cloud + ":" + target[1:]
|
|
162
|
+
else:
|
|
163
|
+
tmp = maybe_config
|
|
164
|
+
target = f"{tmp.cloud}:" + target[1:]
|
|
165
|
+
root = tmp.root
|
|
166
|
+
rel2home = tmp.rel2home
|
|
167
|
+
pwd = tmp.pwd
|
|
168
|
+
encrypt = tmp.encrypt
|
|
169
|
+
zip_arg = tmp.zip
|
|
170
|
+
share = tmp.share
|
|
171
|
+
|
|
165
172
|
|
|
166
173
|
if ":" in source and (source[1] != ":" if len(source) > 1 else True): # avoid the deceptive case of "C:/"
|
|
167
174
|
source_parts: list[str] = source.split(":")
|
|
@@ -170,37 +177,37 @@ def parse_cloud_source_target(args: Args, source: str, target: str) -> tuple[str
|
|
|
170
177
|
if len(source_parts) > 1 and source_parts[1] == ES: # the source path is to be inferred from target.
|
|
171
178
|
assert ES not in target, f"You can't use expand symbol `{ES}` in both source and target. Cyclical inference dependency arised."
|
|
172
179
|
target_obj = absolute(target)
|
|
173
|
-
remote_path = target_obj.get_remote_path(os_specific=
|
|
180
|
+
remote_path = target_obj.get_remote_path(os_specific=os_specific, root=root, rel2home=rel2home, strict=False)
|
|
174
181
|
source = f"{cloud}:{remote_path.as_posix()}"
|
|
175
|
-
|
|
176
182
|
else: # source path is mentioned, target? maybe.
|
|
177
183
|
if target == ES: # target path is to be inferred from source.
|
|
178
|
-
raise NotImplementedError(
|
|
184
|
+
raise NotImplementedError("There is no .get_local_path method yet")
|
|
179
185
|
else:
|
|
180
186
|
target_obj = absolute(target)
|
|
181
|
-
if
|
|
182
|
-
if
|
|
187
|
+
if zip_arg and ".zip" not in source: source += ".zip"
|
|
188
|
+
if encrypt and ".enc" not in source: source += ".enc"
|
|
183
189
|
|
|
184
190
|
elif ":" in target and (target[1] != ":" if len(target) > 1 else True): # avoid the case of "C:/"
|
|
185
191
|
target_parts: list[str] = target.split(":")
|
|
186
192
|
cloud = target.split(":")[0]
|
|
187
193
|
|
|
188
194
|
if len(target_parts) > 1 and target_parts[1] == ES: # the target path is to be inferred from source.
|
|
189
|
-
assert ES not in source,
|
|
195
|
+
assert ES not in source, "You can't use $ in both source and target. Cyclical inference dependency arised."
|
|
190
196
|
source_obj = absolute(source)
|
|
191
|
-
remote_path = source_obj.get_remote_path(os_specific=
|
|
197
|
+
remote_path = source_obj.get_remote_path(os_specific=os_specific, root=root, rel2home=rel2home, strict=False)
|
|
192
198
|
target = f"{cloud}:{remote_path.as_posix()}"
|
|
193
199
|
else: # target path is mentioned, source? maybe.
|
|
194
200
|
target = str(target)
|
|
195
201
|
if source == ES:
|
|
196
|
-
raise NotImplementedError(
|
|
202
|
+
raise NotImplementedError("There is no .get_local_path method yet")
|
|
197
203
|
else:
|
|
198
204
|
source_obj = absolute(source)
|
|
199
|
-
if
|
|
200
|
-
if
|
|
205
|
+
if zip_arg and ".zip" not in target: target += ".zip"
|
|
206
|
+
if encrypt and ".enc" not in target: target += ".enc"
|
|
201
207
|
else:
|
|
202
208
|
raise ValueError("Either source or target must be a remote path (i.e. machine:path)")
|
|
203
209
|
Struct({"cloud": cloud, "source": str(source), "target": str(target)}).print(as_config=True, title="CLI Resolution")
|
|
210
|
+
_ = pwd, encrypt, zip_arg, share
|
|
204
211
|
return cloud, str(source), str(target)
|
|
205
212
|
|
|
206
213
|
|
|
@@ -224,11 +231,11 @@ def args_parser():
|
|
|
224
231
|
|
|
225
232
|
args = parser.parse_args()
|
|
226
233
|
args_dict = vars(args)
|
|
227
|
-
source: str
|
|
228
|
-
target: str
|
|
229
|
-
verbose: bool
|
|
230
|
-
delete: bool
|
|
231
|
-
bisync: bool
|
|
234
|
+
source: str=args_dict.pop("source")
|
|
235
|
+
target: str=args_dict.pop("target")
|
|
236
|
+
verbose: bool=args_dict.pop("verbose")
|
|
237
|
+
delete: bool=args_dict.pop("delete")
|
|
238
|
+
bisync: bool=args_dict.pop("bisync")
|
|
232
239
|
transfers: int = args_dict.pop("transfers")
|
|
233
240
|
args_obj = Args(**args_dict)
|
|
234
241
|
|
|
@@ -43,7 +43,7 @@ except Exception as e:
|
|
|
43
43
|
return pycode
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
def get_read_pyfile_pycode(path: P, as_module: bool, cmd: str
|
|
46
|
+
def get_read_pyfile_pycode(path: P, as_module: bool, cmd: str=""):
|
|
47
47
|
if as_module: pycode = fr"""
|
|
48
48
|
import sys
|
|
49
49
|
sys.path.append(r'{path.parent}')
|
|
@@ -72,8 +72,8 @@ def build_parser():
|
|
|
72
72
|
parser.add_argument("--read", "-r", dest="read", help="read a binary file.", default="")
|
|
73
73
|
parser.add_argument("--file", "-f", dest="file", help="python file path to interpret", default="")
|
|
74
74
|
parser.add_argument("--cmd", "-c", dest="cmd", help="python command to interpret", default="")
|
|
75
|
-
parser.add_argument("--terminal", "-t", dest="terminal", help=
|
|
76
|
-
parser.add_argument("--shell", "-S", dest="shell", help=
|
|
75
|
+
parser.add_argument("--terminal", "-t", dest="terminal", help="specify which terminal to be used. Default console host.", default="") # can choose `wt`
|
|
76
|
+
parser.add_argument("--shell", "-S", dest="shell", help="specify which shell to be used. Defaults to CMD.", default="")
|
|
77
77
|
|
|
78
78
|
args = parser.parse_args()
|
|
79
79
|
# print(f"Crocodile.run: args of the firing command = {args.__dict__}")
|
|
@@ -142,10 +142,10 @@ print_logo(logo="crocodile")
|
|
|
142
142
|
ve = get_ve_profile(P(file)) if args.ve is None else str(args.ve)
|
|
143
143
|
|
|
144
144
|
final_program = f"""
|
|
145
|
-
|
|
146
|
-
. activate_ve {ve}
|
|
145
|
+
. $HOME/scripts/activate_ve '{ve}'
|
|
147
146
|
{interpreter} """
|
|
148
|
-
if interpreter == "ipython":
|
|
147
|
+
if interpreter == "ipython":
|
|
148
|
+
final_program += f"{interactivity} --profile {profile} --no-banner"
|
|
149
149
|
final_program += f" {str(pyfile)}"
|
|
150
150
|
print(f"🔥 sourcing ... {pyfile}")
|
|
151
151
|
# print(f"Running ... {final_program}")
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
"""devops
|
|
5
4
|
"""
|
|
6
|
-
|
|
5
|
+
|
|
7
6
|
from machineconfig.utils.utils import display_options, PROGRAM_PATH, write_shell_script
|
|
8
7
|
from platform import system
|
|
9
8
|
from enum import Enum
|
|
@@ -49,19 +48,19 @@ def main(which: Optional[str] = None):
|
|
|
49
48
|
|
|
50
49
|
elif choice_key == Options.ve.value:
|
|
51
50
|
program = ""
|
|
52
|
-
reply: bool
|
|
53
|
-
if P.cwd().joinpath(".ve.ini").exists():
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
51
|
+
reply: bool=False
|
|
52
|
+
# if P.cwd().joinpath(".ve.ini").exists():
|
|
53
|
+
# reply = input("Detected .ve.ini file. Do you want to use it to build ve? (y/[n]): ") == "y"
|
|
54
|
+
# if reply:
|
|
55
|
+
# from machineconfig.utils.ve import get_ve_install_script_from_specs
|
|
56
|
+
# program_win = get_ve_install_script_from_specs(repo_root=P.cwd().to_str(), system="Windows")
|
|
57
|
+
# program_lin = get_ve_install_script_from_specs(repo_root=P.cwd().to_str(), system="Linux")
|
|
58
|
+
# install_reply = input("Proceed with installation? (y/[n]): ") == "y"
|
|
59
|
+
# if not install_reply: program = ""
|
|
60
|
+
# else:
|
|
61
|
+
# if system() == "Windows": program = program_win
|
|
62
|
+
# elif system() == "Linux": program = program_lin
|
|
63
|
+
# else: raise ValueError(f"Unknown system: {system()}")
|
|
65
64
|
|
|
66
65
|
if not reply:
|
|
67
66
|
from machineconfig.utils.ve import get_ve_install_script
|
|
@@ -92,18 +91,18 @@ def main(which: Optional[str] = None):
|
|
|
92
91
|
program = helper.main()
|
|
93
92
|
|
|
94
93
|
elif choice_key == Options.ssh_setup.value:
|
|
95
|
-
program_windows =
|
|
96
|
-
program_linux =
|
|
94
|
+
program_windows = """Invoke-WebRequest https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_windows/openssh_all.ps1 | Invoke-Expression # https://github.com/thisismygitrepo.keys"""
|
|
95
|
+
program_linux = """curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/openssh_all.sh | sudo bash # https://github.com/thisismygitrepo.keys"""
|
|
97
96
|
program = program_linux if system() == "Linux" else program_windows
|
|
98
97
|
|
|
99
98
|
elif choice_key == Options.ssh_setup_wsl.value:
|
|
100
|
-
program =
|
|
99
|
+
program = """curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/openssh_wsl.sh | sudo bash"""
|
|
101
100
|
|
|
102
101
|
elif choice_key == Options.backup.value:
|
|
103
|
-
from machineconfig.scripts.python.devops_backup_retrieve import
|
|
102
|
+
from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve as helper
|
|
104
103
|
program = helper(direction="BACKUP")
|
|
105
104
|
elif choice_key == Options.retreive.value:
|
|
106
|
-
from machineconfig.scripts.python.devops_backup_retrieve import
|
|
105
|
+
from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve as helper
|
|
107
106
|
program = helper(direction="RETRIEVE")
|
|
108
107
|
|
|
109
108
|
elif choice_key == Options.scheduler.value:
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
# import subprocess
|
|
6
6
|
from crocodile.file_management import Read, P
|
|
7
|
-
from machineconfig.utils.utils import LIBRARY_ROOT, DEFAULTS_PATH, print_code, choose_cloud_interactively,
|
|
7
|
+
from machineconfig.utils.utils import LIBRARY_ROOT, DEFAULTS_PATH, print_code, choose_cloud_interactively, choose_multiple_options
|
|
8
8
|
from machineconfig.scripts.python.cloud_sync import ES
|
|
9
9
|
from platform import system
|
|
10
10
|
from typing import Any, Literal, Optional
|
|
@@ -13,23 +13,25 @@ from typing import Any, Literal, Optional
|
|
|
13
13
|
OPTIONS = Literal["BACKUP", "RETRIEVE"]
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def
|
|
16
|
+
def main_backup_retrieve(direction: OPTIONS, which: Optional[str] = None):
|
|
17
17
|
try:
|
|
18
18
|
cloud: str = Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
|
|
19
19
|
print(f"\n{'--' * 50}\n ⚠️ Using default cloud: `{cloud}` ⚠️\n{'--' * 50}\n")
|
|
20
20
|
except (FileNotFoundError, KeyError, IndexError): cloud = choose_cloud_interactively()
|
|
21
21
|
|
|
22
|
-
bu_file: dict[str, Any] = LIBRARY_ROOT.joinpath("profile/backup.toml")
|
|
22
|
+
bu_file: dict[str, Any] = Read.toml(LIBRARY_ROOT.joinpath("profile/backup.toml"))
|
|
23
23
|
if system() == "Linux": bu_file = {key: val for key, val in bu_file.items() if "windows" not in key}
|
|
24
24
|
elif system() == "Windows": bu_file = {key: val for key, val in bu_file.items() if "linux" not in key}
|
|
25
25
|
|
|
26
26
|
if which is None:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
choices = choose_multiple_options(msg=f"WHICH FILE of the following do you want to {direction}?", options=['all'] + list(bu_file.keys()))
|
|
28
|
+
else:
|
|
29
|
+
choices = which.split(",") if isinstance(which, str) else which
|
|
30
30
|
|
|
31
|
-
if
|
|
32
|
-
else:
|
|
31
|
+
if "all" in choices: items = bu_file
|
|
32
|
+
else:
|
|
33
|
+
# items = {choices: bu_file[choices]}
|
|
34
|
+
items = {key: val for key, val in bu_file.items() if key in choices}
|
|
33
35
|
|
|
34
36
|
program = f"""$cloud = "{cloud}:{ES}" \n """ if system() == "Windows" else f"""cloud="{cloud}:{ES}" \n """
|
|
35
37
|
for item_name, item in items.items():
|
|
@@ -42,11 +44,18 @@ def main(direction: OPTIONS, which: Optional[str] = None):
|
|
|
42
44
|
if flags: flags = "-" + flags
|
|
43
45
|
if direction == "BACKUP": program += f"""\ncloud_copy "{P(item['path']).as_posix()}" $cloud {flags}\n"""
|
|
44
46
|
elif direction == "RETRIEVE": program += f"""\ncloud_copy $cloud "{P(item['path']).as_posix()}" {flags}\n"""
|
|
45
|
-
else:
|
|
46
|
-
|
|
47
|
+
else:
|
|
48
|
+
raise RuntimeError(f"Unknown direction: {direction}")
|
|
49
|
+
if item_name == "dotfiles" and system() == "Linux": program += """\nchmod 700 ~/.ssh/*\n"""
|
|
47
50
|
print_code(program, lexer="shell", desc=f"{direction} script")
|
|
48
51
|
return program
|
|
49
52
|
|
|
50
53
|
|
|
54
|
+
def main(direction: OPTIONS, which: Optional[str] = None):
|
|
55
|
+
code = main_backup_retrieve(direction=direction, which=which)
|
|
56
|
+
from machineconfig.utils.utils import write_shell_script
|
|
57
|
+
write_shell_script(program=code, desc="backup_retrieve.sh")
|
|
58
|
+
|
|
59
|
+
|
|
51
60
|
if __name__ == "__main__":
|
|
52
61
|
pass
|