Skip to content

Commit

Permalink
fix: check no URL formula and remove to get all formula information (…
Browse files Browse the repository at this point in the history
…currently only for casklist) (resolve #293)
  • Loading branch information
rcmdnk committed Oct 21, 2024
1 parent 7ddd6e3 commit 2410d06
Show file tree
Hide file tree
Showing 3 changed files with 234 additions and 78 deletions.
156 changes: 117 additions & 39 deletions bin/brew-file
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,12 @@ class BrewHelper:
def __post_init__(self) -> None:
self.log = logging.getLogger(__name__)

self.all_info: dict[str, dict[str, Any]] | None = None
self.info: dict[str, dict[str, Any]] | None = None
self.all_formulae: dict[str, Any] | None = None

self.formulae: list[str] | None = None
self.casks: list[str] | None = None

self.formula_aliases: dict[str, dict[str, str]] | None = None
self.cask_aliases: dict[str, dict[str, str]] | None = None
self.taps: dict[str, Any] | None = None
Expand Down Expand Up @@ -289,38 +293,118 @@ class BrewHelper:
self.opt[name] = lines[0]
return self.opt[name]

def get_info(self) -> dict[str, Any]:
"""Get info of installed brew package."""
if self.info is None:
def get_formulae(self) -> list[str]:
if self.formulae is None:
_, lines = self.proc(
cmd="brew info --json=v2 --installed",
cmd="brew formulae",
print_cmd=False,
print_out=False,
exit_on_err=True,
separate_err=True,
)
# test formulae in a deep direcotyr was found for hashicorp/tap
self.formulae = [
x for x in lines if len(x.split("/")[-1]) in (1, 3)
]
return self.formulae

def get_casks(self) -> list[str]:
if self.casks is None:
_, lines = self.proc(
cmd="brew casks",
print_cmd=False,
print_out=False,
exit_on_err=True,
separate_err=True,
)
self.casks = lines
return self.casks

def get_packages(self) -> list[str]:
formulae = self.get_formulae()
casks = self.get_casks()
return formulae + casks

def get_all_info(self) -> dict[str, Any]:
"""Get info of all available brew package."""
if self.all_info is None:
ret, lines = self.proc(
cmd="brew info --json=v2 --eval-all",
print_cmd=False,
print_out=False,
exit_on_err=False,
separate_err=False,
)
if ret != 0:
formulae = self.get_formulae()
casks = self.get_casks()

_, lines = self.proc(
cmd=f"brew info --json=v2 --cask {' '.join(casks)}",
print_cmd=False,
print_out=False,
exit_on_err=True,
separate_err=True,
)
lines = lines[lines.index("{") :]
data = json.loads("".join(lines))
self.info = {
"formulae": {x["name"]: x for x in data["formulae"]},
self.all_info = {
"formulae": {},
"casks": {x["token"]: x for x in data["casks"]},
}
return self.info
while ret != 0:
ret, lines = self.proc(
cmd=f"brew info --json=v2 --formula {' '.join(formulae)}",
print_cmd=False,
print_out=False,
exit_on_err=False,
separate_err=False,
)
if ret == 0:
break
formulae_updated = 0
for line in lines:
# Remove package from list if it has no URL
# https://github.com/hashicorp/homebrew-tap/issues/258
if "formula requires at least a URL" in line:
formula = line.split()[1]
if formula in formulae:
formulae.remove(formula)
formulae_updated = 1
if formula.split("/")[-1] in formulae:
formulae.remove(formula.split("/")[-1])
formulae_updated = 1
continue
if formulae_updated:
continue
msg = "Failed to get info of all packages.\n\n"
msg += "\n".join(lines)
raise RuntimeError(msg)

def get_all_formulae(self) -> dict[str, Any]:
"""Get info of all formulae."""
if self.all_formulae is None:
lines = lines[lines.index("{") :]
data = json.loads("".join(lines))
self.all_info["formulae"] = {
x["name"]: x for x in data["formulae"]
}
return self.all_info

def get_info(self) -> dict[str, Any]:
"""Get info of installed brew package."""
if self.info is None:
_, lines = self.proc(
cmd="brew info --json=v1 --eval-all",
cmd="brew info --json=v2 --installed",
print_cmd=False,
print_out=False,
exit_on_err=True,
separate_err=True,
)
lines = lines[lines.index("[") :]
lines = lines[lines.index("{") :]
data = json.loads("".join(lines))
self.all_formulae = {x["name"]: x for x in data}
return self.all_formulae
self.info = {
"formulae": {x["name"]: x for x in data["formulae"]},
"casks": {x["token"]: x for x in data["casks"]},
}
return self.info

def get_formula_list(self) -> list[str]:
info = self.get_info()
Expand Down Expand Up @@ -2869,30 +2953,25 @@ class BrewFile:
# First, get App Store applications
appstore_list = self.get_appstore_dict()

# Check installed casks untill brew info --eval-all contains core/cask for AMI
# once fixed, compare info['token']['version'] and installed to check latest
cask_list = self.helper.get_cask_list()
# Get all available formulae/casks information
all_info = self.helper.get_all_info()

# Get cask information
info = self.helper.get_info()["casks"]
casks: dict[str, dict[str, str | bool]] = {}
apps: dict[str, str] = {}
installed_casks: dict[str, list[str]] = {self.opt["cask_repo"]: []}
for cask in info:
apps_in_cask = []
installed = cask in cask_list
for cask, info in all_info["casks"].items():
installed = False
latest = False
if installed:
if info[cask]["installed"] is None:
latest = True
else:
latest = info[cask]["installed"] == info[cask]["version"]
installed_casks[info[cask]["tap"]] = installed_casks.get(
info[cask]["tap"], []
apps_in_cask = []
if "installed" in info and info["installed"]:
installed = True
latest = info["installed"] == info["version"]
installed_casks[info["tap"]] = installed_casks.get(
info["tap"], []
) + [cask]

if "artifacts" in info[cask]:
for artifact in info[cask]["artifacts"]:
if "artifacts" in info:
for artifact in info["artifacts"]:
if "app" in artifact:
for a in artifact["app"]:
if isinstance(a, str):
Expand All @@ -2906,17 +2985,14 @@ class BrewFile:
):
apps_in_cask.append(a)
casks[cask] = {
"tap": info[cask]["tap"],
"tap": info["tap"],
"installed": installed,
"latest": latest,
}
apps_in_cask = list(set(apps_in_cask))
for a in apps_in_cask:
if a not in apps or installed:
apps[a] = cask
# brew
formulae = self.helper.get_formula_list()
formulae_all = self.helper.get_all_formulae()

# Set applications directories
app_dirs = self.opt["appdirlist"]
Expand Down Expand Up @@ -2996,9 +3072,11 @@ class BrewFile:
has_cask_apps[cask_tap] = has_cask_apps.get(
cask_tap, []
) + [(app_path, token)]
elif token in formulae_all:
brew_tap = cast(str, formulae_all[token]["tap"])
if token in formulae:
elif token in all_info["formulae"]:
brew_tap = cast(
str, all_info["formulae"][token]["tap"]
)
if all_info["formulae"][token]["installed"]:
check = "brew"
brew_apps[brew_tap] = brew_apps.get(
brew_tap, []
Expand Down
42 changes: 18 additions & 24 deletions src/brew_file/brew_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -1854,30 +1854,25 @@ def check_cask(self) -> None:
# First, get App Store applications
appstore_list = self.get_appstore_dict()

# Check installed casks untill brew info --eval-all contains core/cask for AMI
# once fixed, compare info['token']['version'] and installed to check latest
cask_list = self.helper.get_cask_list()
# Get all available formulae/casks information
all_info = self.helper.get_all_info()

# Get cask information
info = self.helper.get_info()["casks"]
casks: dict[str, dict[str, str | bool]] = {}
apps: dict[str, str] = {}
installed_casks: dict[str, list[str]] = {self.opt["cask_repo"]: []}
for cask in info:
apps_in_cask = []
installed = cask in cask_list
for cask, info in all_info["casks"].items():
installed = False
latest = False
if installed:
if info[cask]["installed"] is None:
latest = True
else:
latest = info[cask]["installed"] == info[cask]["version"]
installed_casks[info[cask]["tap"]] = installed_casks.get(
info[cask]["tap"], []
apps_in_cask = []
if "installed" in info and info["installed"]:
installed = True
latest = info["installed"] == info["version"]
installed_casks[info["tap"]] = installed_casks.get(
info["tap"], []
) + [cask]

if "artifacts" in info[cask]:
for artifact in info[cask]["artifacts"]:
if "artifacts" in info:
for artifact in info["artifacts"]:
if "app" in artifact:
for a in artifact["app"]:
if isinstance(a, str):
Expand All @@ -1891,17 +1886,14 @@ def check_cask(self) -> None:
):
apps_in_cask.append(a)
casks[cask] = {
"tap": info[cask]["tap"],
"tap": info["tap"],
"installed": installed,
"latest": latest,
}
apps_in_cask = list(set(apps_in_cask))
for a in apps_in_cask:
if a not in apps or installed:
apps[a] = cask
# brew
formulae = self.helper.get_formula_list()
formulae_all = self.helper.get_all_formulae()

# Set applications directories
app_dirs = self.opt["appdirlist"]
Expand Down Expand Up @@ -1981,9 +1973,11 @@ def check_cask(self) -> None:
has_cask_apps[cask_tap] = has_cask_apps.get(
cask_tap, []
) + [(app_path, token)]
elif token in formulae_all:
brew_tap = cast(str, formulae_all[token]["tap"])
if token in formulae:
elif token in all_info["formulae"]:
brew_tap = cast(
str, all_info["formulae"][token]["tap"]
)
if all_info["formulae"][token]["installed"]:
check = "brew"
brew_apps[brew_tap] = brew_apps.get(
brew_tap, []
Expand Down
Loading

0 comments on commit 2410d06

Please sign in to comment.