install_extras.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #!/usr/bin/env python3
  2. from __future__ import annotations
  3. import os
  4. import pathlib
  5. import platform
  6. import shutil
  7. import subprocess
  8. import tarfile
  9. import httpx
  10. CURRENT_DIR = pathlib.Path(__file__).parent
  11. def main():
  12. bat()
  13. delta()
  14. dua()
  15. dust()
  16. eza()
  17. git_whence()
  18. lazygit()
  19. oh_my_posh()
  20. starship()
  21. def bat():
  22. if platform.system() == 'Darwin':
  23. print('$ brew install git-delta')
  24. subprocess.run(['brew', 'install', 'bat'], check=True)
  25. return
  26. else:
  27. assert platform.system() == 'Linux'
  28. if subprocess.run(['dpkg', '-l', 'bat'], stdout=subprocess.DEVNULL).returncode == 0:
  29. print('bat package already installed')
  30. return
  31. subprocess.run(['sudo', 'apt', 'install', 'bat', '--yes'], check=True)
  32. def delta():
  33. if platform.system() == 'Darwin':
  34. print('$ brew install git-delta')
  35. subprocess.run(['brew', 'install', 'git-delta'], check=True)
  36. return
  37. else:
  38. assert platform.system() == 'Linux'
  39. if subprocess.run(['dpkg', '-l', 'git-delta'], stdout=subprocess.DEVNULL).returncode == 0:
  40. print('git-delta package already installed')
  41. return
  42. client = httpx.Client()
  43. latest = gh_latest_version(client, 'dandavison', 'delta')
  44. version = latest['name']
  45. arch = get_output(['dpkg', '--print-architecture'])
  46. filename = f'git-delta_{version}_{arch}.deb'
  47. (asset,) = (asset for asset in latest['assets'] if asset['name'] == filename)
  48. deb_path = CURRENT_DIR / 'git-delta.deb'
  49. download(client, asset['browser_download_url'], deb_path)
  50. try:
  51. subprocess.run(['sudo', 'dpkg', '-i', deb_path], check=True)
  52. finally:
  53. os.unlink(deb_path)
  54. def dua():
  55. if platform.system() == 'Darwin':
  56. print('$ brew install dua-cli')
  57. subprocess.run(['brew', 'install', 'dua-cli'], check=True)
  58. return
  59. else:
  60. assert platform.system() == 'Linux'
  61. dua_path = CURRENT_DIR / 'dua'
  62. if dua_path.exists():
  63. print('dua already downloaded')
  64. return
  65. client = httpx.Client()
  66. latest = gh_latest_version(client, 'Byron', 'dua-cli')
  67. version = latest['name']
  68. dirname = f'dua-{version}-{platform.machine()}-unknown-linux-musl'
  69. filename = dirname + '.tar.gz'
  70. (asset,) = (asset for asset in latest['assets'] if asset['name'] == filename)
  71. tarball_path = CURRENT_DIR / 'dua.tar.gz'
  72. download(client, asset['browser_download_url'], tarball_path)
  73. with tarfile.open(tarball_path) as tar:
  74. with tar.extractfile(dirname + '/dua') as binary, dua_path.open('wb') as f: # pyright: ignore[reportOptionalContextManager]
  75. shutil.copyfileobj(binary, f)
  76. os.unlink(tarball_path)
  77. dua_path.chmod(0o755)
  78. def dust():
  79. if platform.system() == 'Darwin':
  80. print('$ brew install dust')
  81. subprocess.run(['brew', 'install', 'dust'], check=True)
  82. return
  83. else:
  84. assert platform.system() == 'Linux'
  85. dust_path = CURRENT_DIR / 'dust'
  86. if dust_path.exists():
  87. print('dust already downloaded')
  88. return
  89. client = httpx.Client()
  90. latest = gh_latest_version(client, 'bootandy', 'dust')
  91. version = latest['name']
  92. dirname = f'dust-{version}-{platform.machine()}-unknown-linux-musl'
  93. filename = dirname + '.tar.gz'
  94. (asset,) = (asset for asset in latest['assets'] if asset['name'] == filename)
  95. tarball_path = CURRENT_DIR / 'dust.tar.gz'
  96. download(client, asset['browser_download_url'], tarball_path)
  97. with tarfile.open(tarball_path) as tar:
  98. with tar.extractfile(dirname + '/dust') as binary, dust_path.open('wb') as f: # pyright: ignore[reportOptionalContextManager]
  99. shutil.copyfileobj(binary, f)
  100. os.unlink(tarball_path)
  101. dust_path.chmod(0o755)
  102. def eza():
  103. if platform.system() == 'Darwin':
  104. print('$ brew install eza')
  105. subprocess.run(['brew', 'install', 'eza'], check=True)
  106. return
  107. else:
  108. assert platform.system() == 'Linux'
  109. if (CURRENT_DIR / 'eza').exists():
  110. print('eza already downloaded')
  111. return
  112. client = httpx.Client()
  113. url = f'https://github.com/eza-community/eza/releases/latest/download/eza_{platform.machine()}-unknown-linux-gnu.tar.gz'
  114. tarball_path = CURRENT_DIR / 'eza.tar.gz'
  115. download(client, url, tarball_path)
  116. with tarfile.open(tarball_path) as tar:
  117. tar.extract('./eza', CURRENT_DIR)
  118. tarball_path.unlink()
  119. def git_whence():
  120. if platform.system() == 'Darwin':
  121. print('$ brew install raylu/formulae/git-whence')
  122. subprocess.run(['brew', 'install', 'raylu/formulae/git-whence'], check=True)
  123. return
  124. else:
  125. assert platform.system() == 'Linux'
  126. if (CURRENT_DIR / 'git-whence').exists():
  127. print('git-whence already downloaded')
  128. return
  129. client = httpx.Client()
  130. url = f'https://github.com/raylu/git-whence/releases/latest/download/git-whence-{platform.machine()}-unknown-linux-gnu'
  131. download(client, url, CURRENT_DIR / 'git-whence')
  132. os.chmod(CURRENT_DIR / 'git-whence', 0o755)
  133. def lazygit():
  134. if (CURRENT_DIR / 'lazygit').exists():
  135. print('lazygit package already installed')
  136. return
  137. client = httpx.Client()
  138. latest = gh_latest_version(client, 'jesseduffield', 'lazygit')
  139. version = latest['name']
  140. arch = platform.machine()
  141. if arch == 'aarch64':
  142. arch = 'arm64'
  143. url = f'https://github.com/jesseduffield/lazygit/releases/download/{version}/lazygit_{version.lstrip("v")}_{platform.system()}_{arch}.tar.gz'
  144. download(client, url, CURRENT_DIR / 'lazygit.tgz')
  145. with tarfile.open(CURRENT_DIR / 'lazygit.tgz', 'r:gz') as tar:
  146. tar.extract('lazygit', CURRENT_DIR)
  147. os.unlink(CURRENT_DIR / 'lazygit.tgz')
  148. def oh_my_posh():
  149. if platform.system() == 'Darwin':
  150. print('$ brew install oh-my-posh')
  151. subprocess.run(['brew', 'install', 'oh-my-posh'], check=True)
  152. return
  153. else:
  154. assert platform.system() == 'Linux'
  155. if (CURRENT_DIR / 'oh-my-posh').exists():
  156. print('oh-my-posh already downloaded')
  157. return
  158. client = httpx.Client()
  159. arch = platform.machine()
  160. if arch == 'aarch64':
  161. arch = 'arm64'
  162. url = f'https://github.com/JanDeDobbeleer/oh-my-posh/releases/latest/download/posh-linux-{arch}'
  163. download(client, url, CURRENT_DIR / 'oh-my-posh')
  164. os.chmod(CURRENT_DIR / 'oh-my-posh', 0o755)
  165. def starship():
  166. if platform.system() == 'Darwin':
  167. print('$ brew install starship')
  168. subprocess.run(['brew', 'install', 'starship'], check=True)
  169. return
  170. else:
  171. assert platform.system() == 'Linux'
  172. if (CURRENT_DIR / 'starship').exists():
  173. print('starship already downloaded')
  174. return
  175. client = httpx.Client()
  176. arch = platform.machine()
  177. if arch == 'x86_64':
  178. libc = 'gnu'
  179. else:
  180. libc = 'musl'
  181. url = f'https://github.com/starship/starship/releases/latest/download/starship-{arch}-unknown-linux-{libc}.tar.gz'
  182. tarball_path = CURRENT_DIR / 'starship.tar.gz'
  183. download(client, url, tarball_path)
  184. with tarfile.open(tarball_path, 'r:gz') as tar:
  185. tar.extract('starship', CURRENT_DIR)
  186. tarball_path.unlink()
  187. def get_output(argv: list[str]) -> str:
  188. proc = subprocess.run(argv, check=True, capture_output=True, encoding='ascii')
  189. return proc.stdout.rstrip('\n')
  190. def gh_latest_version(client: httpx.Client, org: str, repo: str) -> dict:
  191. r = client.get(f'https://api.github.com/repos/{org}/{repo}/releases/latest',
  192. headers={'Accept': 'application/vnd.github+json', 'X-GitHub-Api-Version': '2022-11-28'})
  193. r.raise_for_status()
  194. return r.json()
  195. def download(client: httpx.Client, url: str, path: pathlib.Path) -> None:
  196. print('downloading', url, 'to', path)
  197. with client.stream('GET', url, follow_redirects=True) as r:
  198. r.raise_for_status()
  199. with path.open('wb') as f:
  200. for chunk in r.iter_bytes():
  201. f.write(chunk)
  202. if __name__ == '__main__':
  203. main()