machineconfig 1.7__py3-none-any.whl → 1.9__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.

Files changed (72) hide show
  1. machineconfig/__init__.py +4 -2
  2. machineconfig/jobs/python/check_installations.py +38 -32
  3. machineconfig/jobs/python/create_bootable_media.py +4 -4
  4. machineconfig/jobs/python/create_zellij_template.py +3 -2
  5. machineconfig/jobs/python/python_cargo_build_share.py +14 -9
  6. machineconfig/jobs/python/python_ve_symlink.py +6 -6
  7. machineconfig/jobs/python_custom_installers/azuredatastudio.py +36 -0
  8. machineconfig/jobs/python_custom_installers/bypass_paywall.py +30 -0
  9. machineconfig/jobs/{python_linux_installers/dev → python_custom_installers}/docker_desktop.py +15 -4
  10. machineconfig/jobs/python_custom_installers/gh.py +53 -0
  11. machineconfig/jobs/python_custom_installers/goes.py +35 -0
  12. machineconfig/jobs/python_custom_installers/helix.py +43 -0
  13. machineconfig/jobs/python_custom_installers/lvim.py +48 -0
  14. machineconfig/jobs/python_custom_installers/ngrok.py +39 -0
  15. machineconfig/jobs/python_custom_installers/nvim.py +48 -0
  16. machineconfig/jobs/python_custom_installers/vscode.py +45 -0
  17. machineconfig/jobs/python_custom_installers/wezterm.py +41 -0
  18. machineconfig/profile/create.py +12 -7
  19. machineconfig/profile/shell.py +15 -13
  20. machineconfig/scripts/python/choose_wezterm_theme.py +96 -0
  21. machineconfig/scripts/python/cloud_copy.py +18 -13
  22. machineconfig/scripts/python/cloud_mount.py +41 -15
  23. machineconfig/scripts/python/cloud_repo_sync.py +57 -31
  24. machineconfig/scripts/python/cloud_sync.py +13 -15
  25. machineconfig/scripts/python/croshell.py +19 -10
  26. machineconfig/scripts/python/devops.py +22 -6
  27. machineconfig/scripts/python/devops_add_identity.py +7 -6
  28. machineconfig/scripts/python/devops_add_ssh_key.py +10 -9
  29. machineconfig/scripts/python/devops_backup_retrieve.py +5 -5
  30. machineconfig/scripts/python/devops_devapps_install.py +24 -19
  31. machineconfig/scripts/python/devops_update_repos.py +5 -4
  32. machineconfig/scripts/python/dotfile.py +8 -4
  33. machineconfig/scripts/python/fire_jobs.py +165 -55
  34. machineconfig/scripts/python/ftpx.py +18 -8
  35. machineconfig/scripts/python/mount_nfs.py +13 -10
  36. machineconfig/scripts/python/mount_nw_drive.py +4 -3
  37. machineconfig/scripts/python/mount_ssh.py +8 -5
  38. machineconfig/scripts/python/repos.py +26 -21
  39. machineconfig/scripts/python/snapshot.py +2 -2
  40. machineconfig/scripts/python/start_slidev.py +104 -0
  41. machineconfig/scripts/python/start_terminals.py +1 -1
  42. machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +20 -34
  43. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +11 -12
  44. machineconfig/utils/installer.py +177 -217
  45. machineconfig/utils/scheduling.py +1 -1
  46. machineconfig/utils/utils.py +107 -54
  47. machineconfig/utils/ve.py +120 -16
  48. machineconfig-1.9.dist-info/LICENSE +201 -0
  49. {machineconfig-1.7.dist-info → machineconfig-1.9.dist-info}/METADATA +155 -140
  50. machineconfig-1.9.dist-info/RECORD +76 -0
  51. {machineconfig-1.7.dist-info → machineconfig-1.9.dist-info}/WHEEL +1 -1
  52. machineconfig/jobs/python_generic_installers/archive/gopass.py +0 -18
  53. machineconfig/jobs/python_generic_installers/archive/nvim.py +0 -20
  54. machineconfig/jobs/python_generic_installers/archive/opencommit.py +0 -25
  55. machineconfig/jobs/python_generic_installers/archive/strongbox.py +0 -33
  56. machineconfig/jobs/python_generic_installers/dev/__init__.py +0 -0
  57. machineconfig/jobs/python_linux_installers/archive/__init__.py +0 -0
  58. machineconfig/jobs/python_linux_installers/archive/bandwhich.py +0 -14
  59. machineconfig/jobs/python_linux_installers/archive/ranger.py +0 -19
  60. machineconfig/jobs/python_linux_installers/dev/azure_data_studio.py +0 -21
  61. machineconfig/jobs/python_linux_installers/dev/bytehound.py +0 -20
  62. machineconfig/jobs/python_linux_installers/dev/nnn.py +0 -22
  63. machineconfig/jobs/python_windows_installers/archive/ntop.py +0 -21
  64. machineconfig/jobs/python_windows_installers/dev/bypass_paywall.py +0 -22
  65. machineconfig/jobs/python_windows_installers/dev/obs_background_removal_plugin.py +0 -22
  66. machineconfig/scripts/python/choose_ohmybash_theme.py +0 -31
  67. machineconfig/scripts/python/choose_ohmyposh_theme.py +0 -57
  68. machineconfig/utils/pandas_type.py +0 -37
  69. machineconfig/utils/to_exe.py +0 -7
  70. machineconfig-1.7.dist-info/RECORD +0 -81
  71. /machineconfig/jobs/{python_generic_installers/archive → python_custom_installers}/__init__.py +0 -0
  72. {machineconfig-1.7.dist-info → machineconfig-1.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,45 @@
1
+
2
+ """vs code installer as per https://code.visualstudio.com/docs/setup/linux
3
+ """
4
+
5
+ from typing import Optional
6
+ import platform
7
+
8
+
9
+ config_dict = {
10
+ "repo_url": "CUSTOM",
11
+ "doc": "Visual Studio Code",
12
+ "filename_template_windows_amd_64": "VSCodeSetup-{}.exe",
13
+ "filename_template_linux_amd_64": "code_{}.deb",
14
+ "strip_v": True,
15
+ "exe_name": "code"
16
+ }
17
+
18
+
19
+ def main(version: Optional[str] = None):
20
+
21
+ if platform.system() == 'Linux':
22
+ code = """
23
+
24
+ sudo apt-get install wget gpg
25
+ wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
26
+ sudo install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg
27
+ sudo sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list'
28
+ rm -f packages.microsoft.gpg
29
+
30
+ sudo apt install apt-transport-https -y
31
+ sudo apt update
32
+ sudo apt install code -y # or code-insiders
33
+
34
+ """
35
+
36
+ elif platform.system() == 'Windows':
37
+ code = "winget install -e --id Microsoft.VisualStudioCode"
38
+ else:
39
+ raise NotImplementedError(f"Unsupported platform: {platform.system()}")
40
+ _ = version
41
+ return code
42
+
43
+
44
+ if __name__ == '__main__':
45
+ pass
@@ -0,0 +1,41 @@
1
+
2
+ """wezterm installer
3
+ """
4
+
5
+ from machineconfig.utils.installer import Installer
6
+ from typing import Optional
7
+ import platform
8
+
9
+
10
+ config_dict = {
11
+ "repo_url": "https://github.com/wez/wezterm",
12
+ "doc": "cross-platform terminal emulator",
13
+ "filename_template_windows_amd_64": "WezTerm-windows-{}.zip",
14
+ "filename_template_linux_amd_64": "wezterm-{}.Ubuntu22.04.deb",
15
+ "strip_v": False,
16
+ "exe_name": "wezterm"
17
+ }
18
+
19
+
20
+ def main(version: Optional[str]):
21
+ if platform.system() == "Windows":
22
+ program = "winget install --Id wez.wezterm --source winget --accept-package-agreements --accept-source-agreements"
23
+ elif platform.system() == "Linux":
24
+ inst = Installer.from_dict(d=config_dict, name="wezterm")
25
+ program = ""
26
+ # as per https://wezfurlong.org/wezterm/install/linux.html#installing-on-ubuntu-and-debian-based-systems
27
+ downloaded, version_to_be_installed = inst.download(version=version)
28
+ _= version_to_be_installed
29
+
30
+ program = f"""
31
+ sudo apt install -y {downloaded}
32
+ rm {downloaded}
33
+ """
34
+ else:
35
+ raise NotImplementedError("unsupported platform")
36
+ return program
37
+
38
+
39
+ if __name__ == "__main__":
40
+ # main(version=None)
41
+ pass
@@ -5,8 +5,10 @@ This script Takes away all config files from the computer, place them in one dir
5
5
 
6
6
  """
7
7
 
8
- import crocodile.toolbox as tb
8
+
9
9
  from crocodile.environment import system, UserName # ProgramFiles, WindowsApps # , exe
10
+ from crocodile.meta import Terminal
11
+ from crocodile.file_management import P
10
12
  from machineconfig.utils.utils import symlink, LIBRARY_ROOT, REPO_ROOT, display_options
11
13
  from machineconfig.profile.shell import create_default_shell_profile
12
14
  # import os
@@ -24,7 +26,7 @@ SYSTEM = system.lower()
24
26
  # =================== SYMLINKS ====================================
25
27
 
26
28
 
27
- def symlink_contents(source_dir: tb.P, target_dir: tb.P, overwrite: bool = True):
29
+ def symlink_contents(source_dir: P, target_dir: P, overwrite: bool = True):
28
30
  for a_target in target_dir.expanduser().search("*"):
29
31
  symlink(this=source_dir.joinpath(a_target.name), to_this=a_target, prioritize_to_this=overwrite)
30
32
 
@@ -58,7 +60,7 @@ def main_symlinks(choice: Optional[str] = None):
58
60
  else: choice_selected = choice
59
61
 
60
62
  if isinstance(choice_selected, str):
61
- if str(choice_selected) == "all" and system == "Windows" and not tb.Terminal.is_user_admin():
63
+ if str(choice_selected) == "all" and system == "Windows" and not Terminal.is_user_admin():
62
64
  print("*" * 200)
63
65
  raise RuntimeError(f"Run terminal as admin and try again, otherwise, there will be too many popups for admin requests and no chance to terminate the program.")
64
66
  elif choice_selected == "all":
@@ -69,8 +71,8 @@ def main_symlinks(choice: Optional[str] = None):
69
71
 
70
72
  for program_key in program_keys:
71
73
  for file_key, file_map in symlink_mapper[program_key].items():
72
- this = tb.P(file_map['this'])
73
- to_this = tb.P(file_map['to_this'].replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix()))
74
+ this = P(file_map['this'])
75
+ to_this = P(file_map['to_this'].replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix()))
74
76
  if "contents" in file_map:
75
77
  try: symlink_contents(source_dir=this, target_dir=to_this, overwrite=overwrite)
76
78
  except Exception as ex: print("Config error: ", program_key, file_key, "missing keys 'this ==> to_this'.", ex)
@@ -82,12 +84,15 @@ def main_symlinks(choice: Optional[str] = None):
82
84
  try:
83
85
  subprocess.run(f"chmod 700 ~/.ssh/", check=True)
84
86
  subprocess.run(f"chmod 700 ~/dotfiles/creds/.ssh/", check=True) # may require sudo
85
- subprocess.run(f"chmod 600 ~/dotfiles/creds/.ssh//*", check=True)
87
+ subprocess.run(f"chmod 600 ~/dotfiles/creds/.ssh/*", check=True)
86
88
  except Exception as e:
87
89
  ERROR_LIST.append(e)
88
90
  print("Caught error", e)
89
91
 
90
- if system == "Linux": tb.Terminal().run(f'chmod +x {LIBRARY_ROOT.joinpath(f"scripts/{system.lower()}")} -R')
92
+ if system == "Linux": Terminal().run(f'chmod +x {LIBRARY_ROOT.joinpath(f"scripts/{system.lower()}")} -R')
93
+ print("\n\n", "*" * 200)
94
+ if len(ERROR_LIST) > 0:
95
+ print("Errors caught: ", ERROR_LIST)
91
96
 
92
97
 
93
98
  def main(choice: Optional[str] = None):
@@ -3,7 +3,9 @@
3
3
  """
4
4
 
5
5
  from crocodile.environment import PathVar
6
- import crocodile.toolbox as tb
6
+ from crocodile.core import randstr
7
+ from crocodile.file_management import P
8
+ from crocodile.meta import Terminal
7
9
  from machineconfig.utils.utils import LIBRARY_ROOT, REPO_ROOT, display_options
8
10
  import platform
9
11
  from typing import Optional
@@ -27,7 +29,7 @@ def create_default_shell_profile():
27
29
  else:
28
30
  profile += "\n" + source + "\n"
29
31
  if system == "Linux":
30
- res = tb.Terminal().run("cat /proc/version").op
32
+ res = Terminal().run("cat /proc/version").op
31
33
  if "microsoft" in res.lower() or "wsl" in res.lower():
32
34
  profile += "\ncd ~" # this is to make sure that the current dir is not in the windows file system, which is terribly slow and its a bad idea to be there anyway.
33
35
  profile_path.create(parents_only=True).write_text(profile)
@@ -35,10 +37,10 @@ def create_default_shell_profile():
35
37
 
36
38
  def get_shell_profile_path():
37
39
  if system == "Windows":
38
- res = tb.Terminal().run("$profile", shell="pwsh").op2path()
39
- if isinstance(res, tb.P): profile_path = res
40
+ res = Terminal().run("$profile", shell="pwsh").op2path()
41
+ if isinstance(res, P): profile_path = res
40
42
  else: raise ValueError(f"Could not get profile path for Windows. Got {res}")
41
- elif system == "Linux": profile_path = tb.P("~/.bashrc").expanduser()
43
+ elif system == "Linux": profile_path = P("~/.bashrc").expanduser()
42
44
  else: raise ValueError(f"Not implemented for this system {system}")
43
45
  print(f"Working on shell profile `{profile_path}`")
44
46
  return profile_path
@@ -49,7 +51,7 @@ def main_env_path(choice: Optional[str] = None, profile_path: Optional[str] = No
49
51
  dirs = env_path[f'path_{system.lower()}']['extension']
50
52
 
51
53
  print(f"Current PATH: ", "\n============")
52
- tb.P.get_env().PATH.print()
54
+ P.get_env().PATH.print()
53
55
 
54
56
  if choice is None:
55
57
  tmp = display_options(msg="Which directory to add?", options=dirs + ["all", "none(EXIT)"], default="none(EXIT)")
@@ -59,8 +61,8 @@ def main_env_path(choice: Optional[str] = None, profile_path: Optional[str] = No
59
61
  if choice == "none(EXIT)": return
60
62
 
61
63
  addition = PathVar.append_temporarily(dirs=dirs)
62
- profile_path_obj = tb.P(profile_path) if isinstance(profile_path, str) else get_shell_profile_path()
63
- profile_path_obj.copy(name=profile_path_obj.name + f".orig_" + tb.randstr())
64
+ profile_path_obj = P(profile_path) if isinstance(profile_path, str) else get_shell_profile_path()
65
+ profile_path_obj.copy(name=profile_path_obj.name + f".orig_" + randstr())
64
66
  profile_path_obj.modify_text(addition, addition, replace_line=False, notfound_append=True)
65
67
 
66
68
 
@@ -78,13 +80,13 @@ def main_add_sources_to_shell_profile(profile_path: Optional[str] = None, choice
78
80
  elif choice == "none(EXIT)": return
79
81
 
80
82
  if isinstance(profile_path, str):
81
- profile_path_obj = tb.P(profile_path)
83
+ profile_path_obj = P(profile_path)
82
84
  else: profile_path_obj = get_shell_profile_path()
83
85
  profile = profile_path_obj.read_text()
84
86
 
85
87
  for a_file in sources:
86
88
  tmp = a_file.replace("REPO_ROOT", REPO_ROOT.as_posix()).replace("LIBRARY_ROOT", LIBRARY_ROOT.as_posix())
87
- file = tb.P(tmp).collapseuser() # this makes the shell profile interuseable across machines.
89
+ file = P(tmp).collapseuser() # this makes the shell profile interuseable across machines.
88
90
  file = file.as_posix() if system == "Linux" else str(file)
89
91
  if file not in profile:
90
92
  if system == "Windows": profile += f"\n. {file}"
@@ -104,17 +106,17 @@ def main_add_patches_to_shell_profile(profile_path: Optional[str] = None, choice
104
106
  elif str(choice) == "all": pass # i.e. patches = patches
105
107
  else: patches = [choice]
106
108
 
107
- profile_path_obj = tb.P(profile_path) if isinstance(profile_path, str) else get_shell_profile_path()
109
+ profile_path_obj = P(profile_path) if isinstance(profile_path, str) else get_shell_profile_path()
108
110
  profile = profile_path_obj.read_text()
109
111
 
110
112
  for patch_path in patches:
111
- patch_path_obj = tb.P(patch_path)
113
+ patch_path_obj = P(patch_path)
112
114
  patch = patch_path_obj.read_text()
113
115
  if patch in profile: print(f"Skipping `{patch_path_obj.name}`; patch already in profile")
114
116
  else: profile += "\n" + patch
115
117
 
116
118
  if system == "Linux":
117
- res = tb.Terminal().run("cat /proc/version").op
119
+ res = Terminal().run("cat /proc/version").op
118
120
  if "microsoft" in res.lower() or "wsl" in res.lower():
119
121
  profile += "\ncd ~" # this is to make sure that the current dir is not in the windows file system, which is terribly slow and its a bad idea to be there anyway.
120
122
 
@@ -0,0 +1,96 @@
1
+
2
+ """
3
+ Choose a theme for Wezterm
4
+ """
5
+
6
+ from machineconfig.utils.utils import choose_one_option, P
7
+ from typing import Any
8
+ import time
9
+
10
+
11
+ schemes_list = [
12
+ 'Pro',
13
+ 'Spiderman',
14
+ 'shades-of-purple',
15
+ 'synthwave',
16
+ 'Symfonic',
17
+ 'PaulMillr',
18
+ 'Neon',
19
+ 'LiquidCarbonTransparentInverse',
20
+ 'Laser',
21
+ 'IR_Black',
22
+ 'Hurtado',
23
+ 'Homebrew',
24
+ 'Hipster Green',
25
+ 'Firefly Traditional',
26
+ 'Elementary',
27
+ 'deep',
28
+ 'Dark Pastel',
29
+ 'Bright Lights',
30
+ 'Adventure',
31
+ 'Nancy (terminal.sexy)',
32
+ 'Bim (Gogh)',
33
+ 'BlueDolphin',
34
+ 'Borland',
35
+ 'Grass (Gogh)',
36
+ 'Greenscreen (light) (terminal.sexy)',
37
+ 'Grayscale (dark) (terminal.sexy)',
38
+ ]
39
+
40
+
41
+ def main2():
42
+ option = choose_one_option(options=schemes_list, header="Choose a theme for Wezterm", fzf=True)
43
+ set_theme(option)
44
+
45
+
46
+ def set_theme(theme: str):
47
+ txt_lines = P("~/.config/wezterm/wezterm.lua").expanduser().read_text().splitlines()
48
+ res_lines = []
49
+ for line in txt_lines:
50
+ if 'config.color_scheme = ' in line:
51
+ res_lines.append(f"config.color_scheme = '{theme}'")
52
+ else: res_lines.append(line)
53
+ P("~/.config/wezterm/wezterm.lua").expanduser().write_text('\n'.join(res_lines))
54
+ time.sleep(0.1)
55
+
56
+
57
+ def main():
58
+ import curses # not availble on windows: https://docs.python.org/3/howto/curses.html
59
+ # from curses import wrapper
60
+ curses.wrapper(accessory)
61
+
62
+ def accessory(stdscr: Any):
63
+ import curses
64
+ options = schemes_list
65
+ current_option = 0
66
+ page_size = stdscr.getmaxyx()[0] - 1 # curses.LINES - 1 # Number of lines in the terminal, -1 for status line
67
+
68
+ while True:
69
+ stdscr.clear()
70
+
71
+ # Calculate start and end indices for options
72
+ start_index = (current_option // page_size) * page_size
73
+ end_index = start_index + page_size
74
+
75
+ # Display options
76
+ for i, option in enumerate(options[start_index:end_index]):
77
+ if start_index + i == current_option:
78
+ stdscr.addstr(i, 0, option, curses.A_REVERSE) # Highlighted
79
+ else:
80
+ stdscr.addstr(i, 0, option)
81
+
82
+ # Display status line
83
+ status_line = f"Option {current_option+1} of {len(options)}. Use arrow keys to navigate, Enter to select."
84
+ stdscr.addstr(page_size, 0, status_line)
85
+
86
+ # Get key press
87
+ key = stdscr.getch()
88
+
89
+ # Handle key press
90
+ if key == curses.KEY_UP and current_option > 0:
91
+ current_option -= 1
92
+ elif key == curses.KEY_DOWN and current_option < len(options) - 1:
93
+ current_option += 1
94
+ elif key == ord('\n'): # Enter key
95
+ break # Exit the loop
96
+ set_theme(options[current_option])
@@ -14,12 +14,13 @@ from typing import Optional
14
14
 
15
15
 
16
16
  @RepeatUntilNoException()
17
- def get_shared_file(url: Optional[str] = None, folder: Optional[str] = None):
17
+ def get_securely_shared_file(url: Optional[str] = None, folder: Optional[str] = None) -> None:
18
+ folder_obj = P.cwd() if folder is None else P(folder)
18
19
 
19
20
  if os.environ.get("DECRYPTION_PASSWORD") is not None:
20
- pwd = os.environ.get("DECRYPTION_PASSWORD")
21
+ pwd: str = str(os.environ.get("DECRYPTION_PASSWORD"))
21
22
  else:
22
- pwd = getpass.getpass("Enter decryption password: ")
23
+ pwd = getpass.getpass(prompt="Enter decryption password: ")
23
24
 
24
25
  if url is None:
25
26
  if os.environ.get("SHARE_URL") is not None:
@@ -31,10 +32,12 @@ def get_shared_file(url: Optional[str] = None, folder: Optional[str] = None):
31
32
  from rich.progress import Progress
32
33
  with Progress(transient=True) as progress:
33
34
  _task = progress.add_task("Downloading ... ", total=None)
34
- url_obj = P(url).download(folder=folder)
35
+ url_obj = P(url).download(folder=folder_obj)
35
36
  with Progress(transient=True) as progress:
36
37
  _task = progress.add_task("Decrypting ... ", total=None)
37
- res = url_obj.decrypt(pwd=pwd, inplace=True).unzip(inplace=True, merge=True)
38
+ tmp_folder = P.tmpdir(prefix="tmp_unzip")
39
+ res = url_obj.decrypt(pwd=pwd, inplace=True).unzip(inplace=True, folder=tmp_folder)
40
+ res.search("*").apply(lambda x: x.move(folder=folder_obj, overwrite=True))
38
41
  print(f"Decrypted to {res}")
39
42
 
40
43
 
@@ -44,19 +47,17 @@ def arg_parser() -> None:
44
47
  # positional argument
45
48
  parser.add_argument("source", help="file/folder path to be taken from here.")
46
49
  parser.add_argument("target", help="file/folder path to be be sent to here.")
47
- # FLAGS
48
- # parser.add_argument("--recursive", "-r", help="Send recursively.", action="store_true") # default is False
49
- parser.add_argument("--encrypt", "-e", help="Decrypt after receiving.", action="store_true", default=ArgsDefaults.encrypt)
50
- parser.add_argument("--zip", "-z", help="unzip after receiving.", action="store_true", default=ArgsDefaults.zip_)
50
+
51
51
  parser.add_argument("--overwrite", "-w", help="Overwrite existing file.", action="store_true", default=ArgsDefaults.overwrite)
52
52
  parser.add_argument("--share", "-s", help="Share file / directory", action="store_true", default=ArgsDefaults.share)
53
- # optional argument
54
53
  parser.add_argument("--rel2home", "-r", help="Relative to `myhome` folder", action="store_true", default=ArgsDefaults.rel2home)
55
54
  parser.add_argument("--root", "-R", help="Remote root. None is the default, unless rel2home is raied, making the default `myhome`.", default=ArgsDefaults.root)
56
- parser.add_argument("--os_specific", "-o", help="OS specific path (relevant only when relative flag is raised as well.", action="store_true", default=ArgsDefaults.os_specific)
57
55
 
58
56
  parser.add_argument("--key", "-k", help="Key for encryption", type=str, default=ArgsDefaults.key)
59
57
  parser.add_argument("--pwd", "-p", help="Password for encryption", type=str, default=ArgsDefaults.pwd)
58
+ parser.add_argument("--encrypt", "-e", help="Decrypt after receiving.", action="store_true", default=ArgsDefaults.encrypt)
59
+ parser.add_argument("--zip", "-z", help="unzip after receiving.", action="store_true", default=ArgsDefaults.zip_)
60
+ parser.add_argument("--os_specific", "-o", help="choose path specific for this OS.", action="store_true", default=ArgsDefaults.os_specific)
60
61
 
61
62
  parser.add_argument("--config", "-c", help="path to cloud.json file.", default=None)
62
63
 
@@ -67,7 +68,7 @@ def arg_parser() -> None:
67
68
  args_obj = Args(**args_dict)
68
69
  Struct(args_obj.__dict__).print(as_config=True, title=f"CLI config")
69
70
 
70
- if args_obj.config == "ss" and (source.startswith("http") or source.startswith("bit.ly")): return get_shared_file(url=source, folder=target)
71
+ if args_obj.config == "ss" and (source.startswith("http") or source.startswith("bit.ly")): return get_securely_shared_file(url=source, folder=target)
71
72
  if args_obj.rel2home is True and args_obj.root is None: args_obj.root = "myhome"
72
73
 
73
74
  cloud, source, target = parse_cloud_source_target(args=args_obj, source=source, target=target)
@@ -84,7 +85,11 @@ def arg_parser() -> None:
84
85
  zip=args_obj.zip, encrypt=args_obj.encrypt, pwd=args_obj.pwd,
85
86
  rel2home=args_obj.rel2home, root=args_obj.root, os_specific=args_obj.os_specific, strict=False,
86
87
  share=args_obj.share)
87
- if args_obj.share: print(res.as_url_str())
88
+ if args_obj.share:
89
+ print(res.as_url_str())
90
+ if P(source).is_dir(): share_url_path = P(source).joinpath(".share_url")
91
+ else: share_url_path = P(source).with_suffix(".share_url")
92
+ share_url_path.write_text(res.as_url_str())
88
93
  else: raise ValueError(f"Cloud `{cloud}` not found in source or target.")
89
94
 
90
95
 
@@ -2,8 +2,10 @@
2
2
  """Cloud mount script
3
3
  """
4
4
 
5
- import crocodile.toolbox as tb
6
- from machineconfig.utils.utils import PROGRAM_PATH, display_options
5
+
6
+ from machineconfig.utils.utils import PROGRAM_PATH, choose_one_option
7
+ from crocodile.file_management import P, Read
8
+
7
9
  import platform
8
10
  import argparse
9
11
  from typing import Optional
@@ -13,17 +15,17 @@ DEFAULT_MOUNT = "~/data/rclone"
13
15
 
14
16
 
15
17
  def get_rclone_config():
16
- if platform.system() == "Windows": config = tb.Read.ini(tb.P.home().joinpath("AppData/Roaming/rclone/rclone.conf"))
17
- elif platform.system() == "Linux": config = tb.Read.ini(tb.P.home().joinpath(".config/rclone/rclone.conf"))
18
+ if platform.system() == "Windows": config = Read.ini(P.home().joinpath("AppData/Roaming/rclone/rclone.conf"))
19
+ elif platform.system() == "Linux": config = Read.ini(P.home().joinpath(".config/rclone/rclone.conf"))
18
20
  else: raise ValueError("unsupported platform")
19
21
  return config
20
22
 
21
23
 
22
24
  def get_mprocs_mount_txt(cloud: str, rclone_cmd: str, cloud_brand: str): # cloud_brand = config[cloud]["type"]
23
- # config = tb.Read.ini(tb.P.home().joinpath(".config/rclone/rclone.conf"))
25
+ # config = Read.ini(P.home().joinpath(".config/rclone/rclone.conf"))
24
26
  header = f"{' ' + cloud + ' | ' + cloud_brand + ' '}".center(50, "=")
25
27
  if platform.system() == "Windows":
26
- sub_text_path = tb.P.tmpfile(suffix=".ps1").write_text(f"""
28
+ sub_text_path = P.tmpfile(suffix=".ps1").write_text(f"""
27
29
  echo "{header}"
28
30
  iex 'rclone about {cloud}:'
29
31
  echo 'See {DEFAULT_MOUNT}/{cloud} for the mounted cloud'
@@ -40,29 +42,52 @@ mprocs "echo 'see {DEFAULT_MOUNT}/{cloud} for the mounted cloud'; rclone about {
40
42
  return txt
41
43
 
42
44
 
43
- def mount(cloud: Optional[str] = None, network: Optional[str] = None) -> None:
44
-
45
+ def mount(cloud: Optional[str], network: Optional[str], destination: Optional[str]) -> None:
45
46
  config = get_rclone_config()
46
47
  if cloud is None:
47
- res = display_options(msg="which cloud", options=config.sections(), header="CLOUD MOUNT", default=None)
48
+ res = choose_one_option(msg="which cloud", options=config.sections(), header="CLOUD MOUNT", default=None)
48
49
  if type(res) is str: cloud = res
49
50
  else: raise ValueError("no cloud selected")
50
- # assert isinstance(cloud, str)
51
+
51
52
  if network is None:
52
- mount_loc = tb.P(DEFAULT_MOUNT).expanduser().joinpath(cloud)
53
- if platform.system() == "Windows": mount_loc.parent.create()
54
- elif platform.system() == "Linux": mount_loc.create()
53
+ if destination is None:
54
+ mount_loc = P(DEFAULT_MOUNT).expanduser().joinpath(cloud)
55
+ else:
56
+ mount_loc = P(destination)
57
+
58
+ if platform.system() == "Windows":
59
+ mount_loc.parent.create()
60
+ elif platform.system() == "Linux":
61
+ try: mount_loc.create()
62
+ except (FileExistsError, OSError) as err:
63
+ # We need a umount command here.
64
+ print(err)
65
+ pass
55
66
  else: raise ValueError("unsupported platform")
67
+
56
68
  elif network and platform.system() == "Windows": mount_loc = "X: --network-mode"
57
69
  else: raise ValueError("network mount only supported on windows")
58
70
 
59
71
  mount_cmd = f"rclone mount {cloud}: {mount_loc} --vfs-cache-mode full --file-perms=0777"
60
72
 
61
73
  # txt = get_mprocs_mount_txt(cloud, mount_cmd)
62
- if platform.system() == "Windows": txt = f"""
74
+ if platform.system() == "Windows":
75
+
76
+ txt = f"""
63
77
  wt --window 0 --profile "Windows PowerShell" --startingDirectory "$HOME/data/rclone" `; split-pane --horizontal --profile "Command Prompt" --size 0.2 powershell -Command "{mount_cmd}" `; split-pane --vertical --profile "Windows PowerShell" --size 0.2 powershell -NoExit -Command "rclone about {cloud}:" `; move-focus up
64
78
  """
65
79
  elif platform.system() == "Linux": txt = f"""
80
+
81
+ ZJ_SESSIONS=$(zellij list-sessions)
82
+
83
+ if [[ "${{ZJ_SESSIONS}}" != *"(current)"* ]]; then
84
+ echo "Not inside a zellij session ..."
85
+ echo '{mount_cmd} --daemon'
86
+ # exit 1
87
+
88
+ {mount_cmd} --daemon
89
+ fi
90
+
66
91
  zellij run --direction down --name rclone -- {mount_cmd}
67
92
  sleep 1; zellij action resize decrease down
68
93
  sleep 0.2; zellij action resize decrease up
@@ -90,9 +115,10 @@ zellij action move-focus up
90
115
  def main():
91
116
  parser = argparse.ArgumentParser(description='mount cloud')
92
117
  parser.add_argument('cloud', nargs='?', type=str, default=None, help='cloud to mount')
118
+ parser.add_argument('destination', nargs='?', type=str, default=None, help='destination to mount')
93
119
  parser.add_argument('--network', type=str, default=None, help='mount network drive')
94
120
  args = parser.parse_args()
95
- mount(cloud=args.cloud, network=args.network)
121
+ mount(cloud=args.cloud, network=args.network, destination=args.destination)
96
122
 
97
123
 
98
124
  if __name__ == '__main__':