add automatic tap detection
This commit is contained in:
@@ -51,7 +51,7 @@ 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
|
reef,manual,,no,personalization,"Shortcuts based app switcher
|
||||||
|
|||||||
|
+66
-13
@@ -1,3 +1,10 @@
|
|||||||
|
import csv
|
||||||
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
import datetime
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
# ====== Config ======
|
# ====== Config ======
|
||||||
CSV_FILE = './apps.csv'
|
CSV_FILE = './apps.csv'
|
||||||
BREWFILE = './Brewfile'
|
BREWFILE = './Brewfile'
|
||||||
@@ -11,14 +18,9 @@ MANUAL_TYPE = 'manual'
|
|||||||
|
|
||||||
support_types = list(SUPPORT_CONFIG.keys())
|
support_types = list(SUPPORT_CONFIG.keys())
|
||||||
|
|
||||||
|
def clear():
|
||||||
|
subprocess.run(['clear'])
|
||||||
|
|
||||||
import csv
|
|
||||||
import subprocess
|
|
||||||
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)
|
||||||
@@ -35,6 +37,12 @@ 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:
|
||||||
@@ -47,11 +55,15 @@ def create_brewfile():
|
|||||||
|
|
||||||
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':
|
||||||
|
tap = extract_tap(row['name'])
|
||||||
|
if tap:
|
||||||
|
taps.add(tap)
|
||||||
content = f'# {row["description"]}\n{SUPPORT_CONFIG[pkg_type]["structure"](row)}\n'
|
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:
|
||||||
@@ -59,12 +71,50 @@ def create_brewfile():
|
|||||||
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 create Brewfile')
|
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)
|
||||||
|
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
|
||||||
|
|
||||||
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}
|
||||||
@@ -105,6 +155,9 @@ def install_dependencies():
|
|||||||
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
|
||||||
@@ -125,7 +178,7 @@ def bundle_check():
|
|||||||
['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)')
|
||||||
@@ -139,7 +192,7 @@ def bundle_check():
|
|||||||
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(['brew', 'bundle', 'cleanup', f'--file={BREWFILE}', '--force'], check=True)
|
||||||
print('✅ Successfully cleanup')
|
print('✅ Successfully cleanup')
|
||||||
else:
|
else:
|
||||||
@@ -171,9 +224,9 @@ def select_option():
|
|||||||
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():
|
||||||
|
|||||||
Reference in New Issue
Block a user