12 Commits
Author SHA1 Message Date
Seungjun Lee a959fdfead add tmux 2026-07-25 22:50:35 +09:00
Seungjun Lee e5ba30d4d1 format code & add todo 2026-07-25 22:50:05 +09:00
Seungjun Lee ab4b05b514 add mise 2026-07-20 10:15:31 +09:00
Seungjun Lee 2a3ea43e36 add vscode extension dependencies 2026-07-19 09:17:53 +09:00
Seungjun Lee d08a47d63c remove busycontacts 2026-07-19 08:59:06 +09:00
Seungjun Lee cd93fdc242 add wget 2026-07-18 13:00:04 +09:00
Seungjun Lee 7c75ee9640 add microsoft things 2026-07-18 11:17:11 +09:00
Seungjun Lee 04fef5ab44 add rcmd, droppy 2026-07-16 20:16:00 +09:00
Seungjun Lee 9acc794a6f remove alcove & edit runcat in apps.csv 2026-07-16 11:20:00 +09:00
seung6lee fc398f7a2a add auto trust operation 2026-07-15 22:04:08 +09:00
seung6lee f9b31593c2 add automatic tap detection 2026-07-15 21:58:52 +09:00
seung6lee 585ecab616 add MIT license 2026-07-15 08:30:25 +09:00
4 changed files with 285 additions and 167 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) [year] [fullname]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+1
View File
@@ -2,3 +2,4 @@
Todo: Todo:
☐ Make dependency not hardcoded ☐ Make dependency not hardcoded
☐ Pass depencency detect if package is in list ☐ Pass depencency detect if package is in list
☐ add type in brewfile_tool.py
+17 -8
View File
@@ -1,4 +1,5 @@
name,type,mas_id,install_on_setup,category,description,price name,type,mas_id,install_on_setup,category,description,price
rcmd,cask,,yes,personalization,Keyboard based app switcher,paid
ente-auth,cask,,yes,security,Free secure two-factor auth service,free ente-auth,cask,,yes,security,Free secure two-factor auth service,free
android-platform-tools,cask,,no,utilities,ADB tools,free android-platform-tools,cask,,no,utilities,ADB tools,free
sozercan/repo/kaset,cask,,yes,media,MacOS YTM client,free sozercan/repo/kaset,cask,,yes,media,MacOS YTM client,free
@@ -27,7 +28,6 @@ rectangle,cask,,yes,personalization,Window management tool,free
karabiner-elements,cask,,yes,personalization,Keyboard customization tool,free karabiner-elements,cask,,yes,personalization,Keyboard customization tool,free
zotero,cask,,no,knowledge,Reference organize tool,free zotero,cask,,no,knowledge,Reference organize tool,free
affine,cask,,yes,knowledge,Opensource notion alternative,free affine,cask,,yes,knowledge,Opensource notion alternative,free
busycontacts,cask,,yes,productivity,Contact management tool with CalDAV support,paid
affinity,cask,,yes,creativity,Photoshop alternative by canva,free affinity,cask,,yes,creativity,Photoshop alternative by canva,free
discord,cask,,yes,social,Discord desktop client,free discord,cask,,yes,social,Discord desktop client,free
shifty,cask,,yes,personalization,Night shift adjust tool,free shifty,cask,,yes,personalization,Night shift adjust tool,free
@@ -35,7 +35,6 @@ keka,cask,,yes,utilities,File extraction enhancer,free
keyboardcleantool,cask,,yes,utilities,Lock keyboard input during cleaning,free keyboardcleantool,cask,,yes,utilities,Lock keyboard input during cleaning,free
appcleaner,cask,,yes,utilities,Remove app without residue,free appcleaner,cask,,yes,utilities,Remove app without residue,free
monitorcontrol,cask,,yes,personalization,Control external monitor brightness,free monitorcontrol,cask,,yes,personalization,Control external monitor brightness,free
alcove,cask,,yes,personalization,Notch app,paid
tunnelbear,cask,,yes,network,VPN,free tunnelbear,cask,,yes,network,VPN,free
arduino-ide,cask,,no,development,Arduino IDE,free arduino-ide,cask,,no,development,Arduino IDE,free
clop,cask,,yes,personalization,File compressor,free clop,cask,,yes,personalization,File compressor,free
@@ -45,17 +44,15 @@ openmtp,cask,,yes,utilities,Android device connector,free
responsively,cask,,no,development,Browser for responsible website development,free responsively,cask,,no,development,Browser for responsible website development,free
telegram,cask,,yes,social,Telegram desktop client,free telegram,cask,,yes,social,Telegram desktop client,free
wireshark-app,cask,,no,network,Network packets capturer,free wireshark-app,cask,,no,network,Network packets capturer,free
git,formula,,yes,development,Version management tool,free git,formula,,yes,development,File version manager,free
mole,formula,,yes,utilities,System optimizer,free mole,formula,,yes,utilities,System optimizer,free
fastfetch,formula,,yes,utilities,Neofetch alternative,free fastfetch,formula,,yes,utilities,Neofetch alternative,free
mas,formula,,yes,utilities,CLI appstore,free mas,formula,,yes,utilities,CLI appstore,free
tree,formula,,yes,utilities,File structure tree,free tree,formula,,yes,utilities,File structure tree,free
scrcpy,formula,,no,utilities,Android screen mirroring,free scrcpy,formula,,no,utilities,Android screen mirroring,free
thaw,formula,,yes,personalization,Menubar hidder,free thaw,cask,,yes,personalization,Menubar hidder,free
nmap,formula,,no,network,Network scanner,free nmap,formula,,no,network,Network scanner,free
davinci resolve ,manual,,no,creativity,Video editor,free davinci resolve ,manual,,no,creativity,Video editor,free
reef,manual,,no,personalization,"Shortcuts based app switcher
https://github.com/gouwsxander/Reef",free
tageditor,mas,984278082,no,utilities,Audio file metadata editor,free tageditor,mas,984278082,no,utilities,Audio file metadata editor,free
Allkdic,mas,1033453958,yes,productivity,Menubar dictionary,free Allkdic,mas,1033453958,yes,productivity,Menubar dictionary,free
Bitwarden,mas,1352778147,yes,security,Password manager,free Bitwarden,mas,1352778147,yes,security,Password manager,free
@@ -64,7 +61,7 @@ KakaoTalk,mas,869223134,yes,social,KakaoTalk,free
Linearity Curve,mas,1219074514,no,creativity,Vector based design tool,free Linearity Curve,mas,1219074514,no,creativity,Vector based design tool,free
Poolsuite FM,mas,1514817810,no,media,Internet music radio,free Poolsuite FM,mas,1514817810,no,media,Internet music radio,free
Print to PDF,mas,1639234272,yes,utilities,Save pdf to file,free Print to PDF,mas,1639234272,yes,utilities,Save pdf to file,free
RunCat,mas,1429033973,yes,personalization,Menubar system usage visualizer,free RunCat Neo,mas,6757801838,yes,personalization,Menubar system usage visualizer,free
Texty,mas,1538996043,yes,social,Third-party google chat desktop client,free Texty,mas,1538996043,yes,social,Third-party google chat desktop client,free
Windows App,mas,1295203466,yes,productivity,Windows RDP client,free Windows App,mas,1295203466,yes,productivity,Windows RDP client,free
WireGuard,mas,1451685025,yes,network,Wireguard client,free WireGuard,mas,1451685025,yes,network,Wireguard client,free
@@ -80,9 +77,13 @@ marp-team.marp-vscode,vscode,,no,integration,Support marp(MD based presentation)
matt-meyers.vscode-dbml,vscode,,yes,integration,Support DBML,free matt-meyers.vscode-dbml,vscode,,yes,integration,Support DBML,free
mechatroner.rainbow-csv,vscode,,yes,format,CSV highlighter,free mechatroner.rainbow-csv,vscode,,yes,format,CSV highlighter,free
ms-azuretools.vscode-containers,vscode,,yes,tool,Container tool,free ms-azuretools.vscode-containers,vscode,,yes,tool,Container tool,free
ms-python.black-formatter,vscode,,yes,format,Python formatter,free
ms-python.python,vscode,,yes,language,Python integration,free ms-python.python,vscode,,yes,language,Python integration,free
ms-python.debugpy,vscode,,yes,language,Dependency of ms-python.python,free
ms-python.vscode-pylance,vscode,,yes,language,Dependency of ms-python.python,free
ms-python.vscode-python-envs,vscode,,yes,language,Dependency of ms-python.python,free
ms-vscode-remote.remote-ssh,vscode,,yes,tool,SSH conntection,free ms-vscode-remote.remote-ssh,vscode,,yes,tool,SSH conntection,free
ms-vscode-remote.remote-ssh-edit,vscode,,yes,tool,Dependency of ms-vscode-remote.remote-ssh,free
ms-vscode.remote-explorer,vscode,,yes,tool,Dependency of ms-vscode-remote.remote-ssh,free
pkief.material-icon-theme,vscode,,yes,theme,Best icon,free pkief.material-icon-theme,vscode,,yes,theme,Best icon,free
pkief.material-product-icons,vscode,,yes,theme,Best product icon,free pkief.material-product-icons,vscode,,yes,theme,Best product icon,free
pomdtr.excalidraw-editor,vscode,,no,integration,Excalidraw integration,free pomdtr.excalidraw-editor,vscode,,no,integration,Excalidraw integration,free
@@ -92,3 +93,11 @@ svelte.svelte-vscode,vscode,,yes,language,Sevelte integration,free
wayou.vscode-todo-highlight,vscode,,yes,tool,Todo file highlighter,free wayou.vscode-todo-highlight,vscode,,yes,tool,Todo file highlighter,free
yzhang.markdown-all-in-one,vscode,,yes,language,Markdown highlighter & formatter,free yzhang.markdown-all-in-one,vscode,,yes,language,Markdown highlighter & formatter,free
zhuangtongfa.material-theme,vscode,,yes,theme,Best darkmode theme (One Dark Pro),free zhuangtongfa.material-theme,vscode,,yes,theme,Best darkmode theme (One Dark Pro),free
charliermarsh.ruff,vscode,,yes,format,Python formatter,free
droppy,manual,,no,personalization,Notch customization,paid
Microsoft word,manual,,no,productivity,Microsoft word,paid
Microsoft excel,manual,,no,productivity,Microsoft excel,paid
Microsoft powerpoint,manual,,no,productivity,Microsoft powerpoint,paid
wget,formula,,yes,utilities,File downloader,free
mise,formula,,yes,development,Package version manager,free
tmux,formula,,yes,development,Terminal multiplexer,free
1 name type mas_id install_on_setup category description price
2 rcmd cask yes personalization Keyboard based app switcher paid
3 ente-auth cask yes security Free secure two-factor auth service free
4 android-platform-tools cask no utilities ADB tools free
5 sozercan/repo/kaset cask yes media MacOS YTM client free
28 karabiner-elements cask yes personalization Keyboard customization tool free
29 zotero cask no knowledge Reference organize tool free
30 affine cask yes knowledge Opensource notion alternative free
busycontacts cask yes productivity Contact management tool with CalDAV support paid
31 affinity cask yes creativity Photoshop alternative by canva free
32 discord cask yes social Discord desktop client free
33 shifty cask yes personalization Night shift adjust tool free
35 keyboardcleantool cask yes utilities Lock keyboard input during cleaning free
36 appcleaner cask yes utilities Remove app without residue free
37 monitorcontrol cask yes personalization Control external monitor brightness free
alcove cask yes personalization Notch app paid
38 tunnelbear cask yes network VPN free
39 arduino-ide cask no development Arduino IDE free
40 clop cask yes personalization File compressor free
44 responsively cask no development Browser for responsible website development free
45 telegram cask yes social Telegram desktop client free
46 wireshark-app cask no network Network packets capturer free
47 git formula yes development Version management tool File version manager free
48 mole formula yes utilities System optimizer free
49 fastfetch formula yes utilities Neofetch alternative free
50 mas formula yes utilities CLI appstore free
51 tree formula yes utilities File structure tree free
52 scrcpy formula no utilities Android screen mirroring free
53 thaw formula cask yes personalization Menubar hidder free
54 nmap formula no network Network scanner free
55 davinci resolve manual no creativity Video editor free
reef manual no personalization Shortcuts based app switcher https://github.com/gouwsxander/Reef free
tageditor mas 984278082 no utilities Audio file metadata editor free
56 Allkdic tageditor mas 1033453958 984278082 yes no productivity utilities Menubar dictionary Audio file metadata editor free
57 Bitwarden Allkdic mas 1352778147 1033453958 yes security productivity Password manager Menubar dictionary free
58 Hancom Office HWP Viewer Bitwarden mas 416746898 1352778147 yes productivity security Hancom Office HWP Viewer Password manager free
61 Poolsuite FM Linearity Curve mas 1514817810 1219074514 no media creativity Internet music radio Vector based design tool free
62 Print to PDF Poolsuite FM mas 1639234272 1514817810 yes no utilities media Save pdf to file Internet music radio free
63 RunCat Print to PDF mas 1429033973 1639234272 yes personalization utilities Menubar system usage visualizer Save pdf to file free
64 Texty RunCat Neo mas 1538996043 6757801838 yes social personalization Third-party google chat desktop client Menubar system usage visualizer free
65 Windows App Texty mas 1295203466 1538996043 yes productivity social Windows RDP client Third-party google chat desktop client free
66 WireGuard Windows App mas 1451685025 1295203466 yes network productivity Wireguard client Windows RDP client free
67 Xcode WireGuard mas 497799835 1451685025 no yes development network Xcode Wireguard client free
77 mechatroner.rainbow-csv matt-meyers.vscode-dbml vscode yes format integration CSV highlighter Support DBML free
78 ms-azuretools.vscode-containers mechatroner.rainbow-csv vscode yes tool format Container tool CSV highlighter free
79 ms-python.black-formatter ms-azuretools.vscode-containers vscode yes format tool Python formatter Container tool free
ms-python.python vscode yes language Python integration free
80 ms-vscode-remote.remote-ssh ms-python.python vscode yes tool language SSH conntection Python integration free
81 ms-python.debugpy vscode yes language Dependency of ms-python.python free
82 ms-python.vscode-pylance vscode yes language Dependency of ms-python.python free
83 ms-python.vscode-python-envs vscode yes language Dependency of ms-python.python free
84 pkief.material-icon-theme ms-vscode-remote.remote-ssh vscode yes theme tool Best icon SSH conntection free
85 ms-vscode-remote.remote-ssh-edit vscode yes tool Dependency of ms-vscode-remote.remote-ssh free
86 ms-vscode.remote-explorer vscode yes tool Dependency of ms-vscode-remote.remote-ssh free
87 pkief.material-product-icons pkief.material-icon-theme vscode yes theme Best product icon Best icon free
88 pomdtr.excalidraw-editor pkief.material-product-icons vscode no yes integration theme Excalidraw integration Best product icon free
89 rickaym.manim-sideview pomdtr.excalidraw-editor vscode no integration Manim integration Excalidraw integration free
93 yzhang.markdown-all-in-one wayou.vscode-todo-highlight vscode yes language tool Markdown highlighter & formatter Todo file highlighter free
94 zhuangtongfa.material-theme yzhang.markdown-all-in-one vscode yes theme language Best darkmode theme (One Dark Pro) Markdown highlighter & formatter free
95 zhuangtongfa.material-theme vscode yes theme Best darkmode theme (One Dark Pro) free
96 charliermarsh.ruff vscode yes format Python formatter free
97 droppy manual no personalization Notch customization paid
98 Microsoft word manual no productivity Microsoft word paid
99 Microsoft excel manual no productivity Microsoft excel paid
100 Microsoft powerpoint manual no productivity Microsoft powerpoint paid
101 wget formula yes utilities File downloader free
102 mise formula yes development Package version manager free
103 tmux formula yes development Terminal multiplexer free
+155 -68
View File
@@ -1,24 +1,48 @@
import csv
import datetime
import re
import shutil
import subprocess
import sys
# ====== Config ====== # ====== Config ======
CSV_FILE = './apps.csv' CSV_FILE = "./apps.csv"
BREWFILE = './Brewfile' BREWFILE = "./Brewfile"
SUPPORT_CONFIG = { SUPPORT_CONFIG = {
'formula': {'token': 'brew', 'structure': lambda data: f'brew "{data["name"]}"', 'dependency': [] }, "formula": {
'cask' : {'token': 'cask', 'structure': lambda data: f'cask "{data["name"]}"', 'dependency': [] }, "token": "brew",
'mas': {'token': 'mas', 'structure': lambda data: f'mas "{data["name"]}", id: {data["mas_id"]}', 'dependency': [{'name': 'mas', 'script': ['brew', 'install', 'mas']}] }, "structure": lambda data: f'brew "{data["name"]}"',
'vscode': {'token': 'vscode', 'structure': lambda data: f'vscode "{data["name"]}"', 'dependency': [{'name': 'code', 'script': ['brew', 'install', '--cask', 'visual-studio-code']}] } "dependency": [],
},
"cask": {
"token": "cask",
"structure": lambda data: f'cask "{data["name"]}"',
"dependency": [],
},
"mas": {
"token": "mas",
"structure": lambda data: f'mas "{data["name"]}", id: {data["mas_id"]}',
"dependency": [{"name": "mas", "script": ["brew", "install", "mas"]}],
},
"vscode": {
"token": "vscode",
"structure": lambda data: f'vscode "{data["name"]}"',
"dependency": [
{
"name": "code",
"script": ["brew", "install", "--cask", "visual-studio-code"],
} }
MANUAL_TYPE = 'manual' ],
},
}
MANUAL_TYPE = "manual"
support_types = list(SUPPORT_CONFIG.keys()) support_types = list(SUPPORT_CONFIG.keys())
import csv def clear():
import subprocess subprocess.run(["clear"])
import shutil
import datetime
import sys
clear = lambda: subprocess.run(['clear'])
def check_package(name): def check_package(name):
path = shutil.which(name) path = shutil.which(name)
@@ -26,75 +50,131 @@ def check_package(name):
return False return False
return True return True
def check_brew(): def check_brew():
if not check_package('brew'): if not check_package("brew"):
print('❌ Unable to find brew') print("❌ Unable to find brew")
sys.exit() sys.exit()
def get_csv(): def get_csv():
with open(CSV_FILE, 'r', encoding='utf-8-sig') as f: with open(CSV_FILE, "r", encoding="utf-8-sig") as f:
return list(csv.DictReader(f)) return list(csv.DictReader(f))
def extract_tap(name):
parts = name.split("/")
if len(parts) == 3:
return f"{parts[0]}/{parts[1]}"
return None
def create_brewfile(): def create_brewfile():
try: try:
with open(BREWFILE, 'r') as old: with open(BREWFILE, "r") as old:
stamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S') stamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
with open(f'./Brewfile_{stamp}.backup', 'w') as new: with open(f"./Brewfile_{stamp}.backup", "w") as new:
new.writelines(old.readlines()) new.writelines(old.readlines())
print(f'📢 Backup old Brewfile (Brewfile_{stamp}.backup)') print(f"📢 Backup old Brewfile (Brewfile_{stamp}.backup)")
except FileNotFoundError: except FileNotFoundError:
pass pass
raw_list = get_csv() raw_list = get_csv()
temp = {pkg_type: [] for pkg_type in support_types} temp = {pkg_type: [] for pkg_type in support_types}
taps = set()
for row in raw_list: for row in raw_list:
pkg_type = row['type'] pkg_type = row["type"]
if pkg_type in temp.keys(): if pkg_type in temp.keys():
if row['install_on_setup'] == 'yes': if row["install_on_setup"] == "yes":
content = f'# {row["description"]}\n{SUPPORT_CONFIG[pkg_type]["structure"](row)}\n' tap = extract_tap(row["name"])
if tap:
taps.add(tap)
content = f"# {row['description']}\n{SUPPORT_CONFIG[pkg_type]['structure'](row)}\n"
temp[pkg_type].append(content) temp[pkg_type].append(content)
elif pkg_type != MANUAL_TYPE: elif pkg_type != MANUAL_TYPE:
print(f'Error: {row["name"]} {pkg_type}') print(f"Error: {row['name']} {pkg_type}")
sys.exit() sys.exit()
with open(BREWFILE, 'w') as f: with open(BREWFILE, "w") as f:
if taps:
f.write(f"# {'=' * 15} tap {'=' * 15}\n")
for tap in sorted(taps):
f.write(f'tap "{tap}"\n')
f.write("\n")
for pkg_type in support_types: for pkg_type in support_types:
f.write(f'# {"=" * 15} {pkg_type} {"=" * 15}\n') f.write(f"# {'=' * 15} {pkg_type} {'=' * 15}\n")
f.writelines(temp[pkg_type]) f.writelines(temp[pkg_type])
f.write('\n') f.write("\n")
print("✅ Successfully created Brewfile")
def handle_untrusted_taps():
taps = set()
try:
with open(BREWFILE, "r") as f:
for line in f:
m = re.fullmatch(r'tap "([^/]+/[^/]+)"', line.strip())
if m:
taps.add(m.group(1))
except FileNotFoundError:
print("❌ Unable to find Brewfile (create it first)")
return False
if taps:
print("⚠️ These third-party taps are needed")
for tap in sorted(taps):
print(f" - {tap}")
print(" These taps is not official and my execute certain script.\n")
if input("Trust these taps? (y/N): ").strip().lower() != "y":
print("📢 Operation is canceled as these taps are not allowed.")
return False
for tap in sorted(taps):
try:
subprocess.run(["brew", "tap", tap], check=True)
subprocess.run(["brew", "trust", tap], check=True)
print(f'✅ Successfully installed tap "{tap}"')
except subprocess.CalledProcessError as e:
print(f'❌ Failed to install tap "{tap}" ({e.returncode})')
return False
except FileNotFoundError:
print("❌ Unable to find brew")
return False
return True
print('✅ Successfully create Brewfile')
def get_brewfile_types(): def get_brewfile_types():
token_to_type = {SUPPORT_CONFIG[t]['token']: t for t in support_types} token_to_type = {SUPPORT_CONFIG[t]["token"]: t for t in support_types}
types = set() types = set()
try: try:
with open(BREWFILE, 'r') as f: with open(BREWFILE, "r") as f:
for line in f: for line in f:
token = line.strip().split(' ', 1)[0] token = line.strip().split(" ", 1)[0]
if token in token_to_type: if token in token_to_type:
types.add(token_to_type[token]) types.add(token_to_type[token])
except FileNotFoundError: except FileNotFoundError:
print('❌ Unable to find Brewfile (create it first)') print("❌ Unable to find Brewfile (create it first)")
return types return types
def install_dependencies(): def install_dependencies():
dependencies = [] dependencies = []
seen = set() seen = set()
for pkg_type in get_brewfile_types(): for pkg_type in get_brewfile_types():
for dep in SUPPORT_CONFIG[pkg_type]['dependency']: for dep in SUPPORT_CONFIG[pkg_type]["dependency"]:
if dep['name'] not in seen: if dep["name"] not in seen:
seen.add(dep['name']) seen.add(dep["name"])
dependencies.append(dep) dependencies.append(dep)
for dep in dependencies: for dep in dependencies:
if check_package(dep['name']): if check_package(dep["name"]):
print(f'✅ Dependency "{dep["name"]}" already installed') print(f'✅ Dependency "{dep["name"]}" already installed')
continue continue
print(f'📢 Installing missing dependency "{dep["name"]}"...') print(f'📢 Installing missing dependency "{dep["name"]}"...')
try: try:
subprocess.run(dep['script'], check=True) subprocess.run(dep["script"], check=True)
print(f'✅ Successfully installed dependency "{dep["name"]}"') print(f'✅ Successfully installed dependency "{dep["name"]}"')
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
print(f'❌ Failed to install dependency "{dep["name"]}" ({e.returncode})') print(f'❌ Failed to install dependency "{dep["name"]}" ({e.returncode})')
@@ -104,76 +184,82 @@ def install_dependencies():
return False return False
return True return True
def bundle_install(): def bundle_install():
if not handle_untrusted_taps():
return
if not install_dependencies(): if not install_dependencies():
print('❌ Aborting install due to missing dependency') print("❌ Aborting install due to missing dependency")
return return
try: try:
subprocess.run(['brew', 'bundle', 'install', f'--file={BREWFILE}'], check=True) subprocess.run(["brew", "bundle", "install", f"--file={BREWFILE}"], check=True)
print('✅ Successfully install all packages') print("✅ Successfully install all packages")
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
print(f'❌ Failed to install some packages ({e.returncode})') print(f"❌ Failed to install some packages ({e.returncode})")
except FileNotFoundError: except FileNotFoundError:
print('❌ Unable to find brew') print("❌ Unable to find brew")
def bundle_check(): def bundle_check():
try: try:
print('📢 Check script running') print("📢 Check script running")
result = subprocess.run( result = subprocess.run(
['brew', 'bundle', 'check', f'--file={BREWFILE}', '--verbose'] ["brew", "bundle", "check", f"--file={BREWFILE}", "--verbose"]
) )
if result.returncode == 0: if result.returncode == 0:
print('✅ Every packages are installed') print("✅ All packages are installed")
return True return True
else: else:
print('⚠️ There are uninstalled package(s)') print("⚠️ There are uninstalled package(s)")
return False return False
except FileNotFoundError: except FileNotFoundError:
print('❌ Unable to find brew') print("❌ Unable to find brew")
return False return False
def bundle_cleanup(): def bundle_cleanup():
try: try:
subprocess.run(['brew', 'bundle', 'cleanup', f'--file={BREWFILE}']) subprocess.run(["brew", "bundle", "cleanup", f"--file={BREWFILE}"])
if input('⚠️ Are sure want to remove? (y/N): ').strip().lower() == 'y': if input("⚠️ Are sure to remove? (y/N): ").strip().lower() == "y":
subprocess.run(['brew', 'bundle', 'cleanup', f'--file={BREWFILE}', '--force'], check=True) subprocess.run(
print('✅ Successfully cleanup') ["brew", "bundle", "cleanup", f"--file={BREWFILE}", "--force"],
check=True,
)
print("✅ Successfully cleanup")
else: else:
print('📢 Canceled') print("📢 Canceled")
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
print(f'❌ Failed to cleanup ({e.returncode})') print(f"❌ Failed to cleanup ({e.returncode})")
except FileNotFoundError: except FileNotFoundError:
print('❌ Unable to find brew') print("❌ Unable to find brew")
def select_option(): def select_option():
options = [ options = [
{'text': 'Create Brewfile', 'func': create_brewfile}, {"text": "Create Brewfile", "func": create_brewfile},
{'text': 'Install packages', 'func': bundle_install}, {"text": "Install packages", "func": bundle_install},
{'text': 'Check packages', 'func': bundle_check}, {"text": "Check packages", "func": bundle_check},
{'text': 'Cleanup packages', 'func': bundle_cleanup}, {"text": "Cleanup packages", "func": bundle_cleanup},
{'text': 'Exit', 'func': sys.exit} {"text": "Exit", "func": sys.exit},
] ]
while True: while True:
print('Select option') print("Select option")
for idx, row in enumerate(options, 1): for idx, row in enumerate(options, 1):
print(f' {idx}) {row["text"]}') print(f" {idx}) {row['text']}")
raw = input('option: ').strip() raw = input("option: ").strip()
try: try:
clear() clear()
idx = int(raw) - 1 idx = int(raw) - 1
if 0 <= idx < len(options): if 0 <= idx < len(options):
options[idx]['func']() options[idx]["func"]()
print() print()
return return
else: else:
print(f'⚠️ Write valid number\n') print("⚠️ Write valid number\n")
except ValueError as e: except ValueError:
print(f'⚠️ Write valid number\n') print("⚠️ Write valid number\n")
def main(): def main():
@@ -181,5 +267,6 @@ def main():
while True: while True:
select_option() select_option()
if __name__ == '__main__':
if __name__ == "__main__":
main() main()