ShadowHunter222 commited on
Commit
dcfa7f7
·
verified ·
1 Parent(s): 655963a

Upload 7 files

Browse files
Files changed (1) hide show
  1. app.py +98 -8
app.py CHANGED
@@ -392,6 +392,22 @@ def detect_type(src: Path) -> str:
392
  has_fw = False
393
  if has_web_entry or has_fw or has_pkg:
394
  return "hybrid-capacitor"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  if (src / "config.xml").exists() and (src / "package.json").exists():
396
  return "hybrid-cordova"
397
  if list(src.rglob("app/build.gradle")) or list(src.rglob("app/build.gradle.kts")):
@@ -1641,6 +1657,59 @@ async def run_build(job_id: str, build_id: str, task: str, signing: dict, app_co
1641
  log(f"WARNING: capacitor dev server.url={server_url} — remove it for production builds, else the app loads your machine instead of the bundled web")
1642
  except Exception as e:
1643
  log(f"capacitor config note: {e} — using webDir={web_dir_name}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1644
  # --- env preflight (versions only) + JDK gate (Cap7+ cannot compile on JDK17) ---
1645
  try:
1646
  res = await _run_cmd(["node", "-v"], timeout=15)
@@ -1782,13 +1851,22 @@ async def run_build(job_id: str, build_id: str, task: str, signing: dict, app_co
1782
  # used as-is (extra files under android/ preserved).
1783
  try:
1784
  andra = work_base / "android"
1785
- baked_man = andra / "app" / "src" / "main" / "AndroidManifest.xml"
 
 
 
1786
  baked_bytes = None
1787
- if baked_man.is_file():
1788
- try:
1789
- baked_bytes = baked_man.read_bytes()
1790
- except Exception:
1791
- baked_bytes = None
 
 
 
 
 
 
1792
  shell_complete = (
1793
  (andra / "app" / "build.gradle").is_file()
1794
  or (andra / "app" / "build.gradle.kts").is_file()
@@ -1809,7 +1887,10 @@ async def run_build(job_id: str, build_id: str, task: str, signing: dict, app_co
1809
  log("cap: local binary missing — using npx @capacitor/cli")
1810
  if not andra.exists() or not shell_complete:
1811
  if baked_bytes is not None:
1812
- log("Partial baked android/ detected (manifest without Gradle shell) — cap add builds the shell first, baked manifest replaces the generated one afterwards")
 
 
 
1813
  else:
1814
  log("android/ missing or incomplete — running cap add android")
1815
  # Move the partial shell aside (never rmtree): on `cap add`
@@ -1826,7 +1907,16 @@ async def run_build(job_id: str, build_id: str, task: str, signing: dict, app_co
1826
  res = await _run_cmd(cap_add, cwd=work_base, timeout=180)
1827
  if res.returncode != 0:
1828
  try:
1829
- if partial_bak.exists() and not andra.exists():
 
 
 
 
 
 
 
 
 
1830
  partial_bak.rename(andra)
1831
  log("Restored partial android/ after cap add failure")
1832
  except Exception:
 
392
  has_fw = False
393
  if has_web_entry or has_fw or has_pkg:
394
  return "hybrid-capacitor"
395
+ # Flat baked manifest: AndroidManifest.xml at project root next to web
396
+ # files (same level as index.html / capacitor config). Same baked-perms
397
+ # intent as the partial-shell path above, minus the scaffolding. Gated on
398
+ # a web entry so stray files alone never hijack routing; native uploads
399
+ # keep their manifests under android/... and never match here.
400
+ if (src / "AndroidManifest.xml").is_file():
401
+ try:
402
+ has_flat_web = (
403
+ (src / "index.html").exists()
404
+ or (src / "www" / "index.html").exists()
405
+ or any(p.suffix == ".html" for p in src.rglob("*.html"))
406
+ )
407
+ except Exception:
408
+ has_flat_web = False
409
+ if has_flat_web:
410
+ return "hybrid-capacitor"
411
  if (src / "config.xml").exists() and (src / "package.json").exists():
412
  return "hybrid-cordova"
413
  if list(src.rglob("app/build.gradle")) or list(src.rglob("app/build.gradle.kts")):
 
1657
  log(f"WARNING: capacitor dev server.url={server_url} — remove it for production builds, else the app loads your machine instead of the bundled web")
1658
  except Exception as e:
1659
  log(f"capacitor config note: {e} — using webDir={web_dir_name}")
1660
+ # --- webDir "." normalization (Capacitor CLI rejects it by design:
1661
+ # checkWebDir invalidFolders = ['', '.', '..', '../', './'] — copying
1662
+ # the project root would swallow android/ itself. Materialize www/
1663
+ # in the disposable work copy (the upload is never touched) and point
1664
+ # the work-copy config at it. Meaning-preserving: identical files,
1665
+ # CLI-accepted directory. Baked-manifest handling below is unchanged.
1666
+ try:
1667
+ if web_dir_name.strip() in (".", "./", ""):
1668
+ www = work_base / "www"
1669
+ www.mkdir(parents=True, exist_ok=True)
1670
+ skip = {"android", "android.partial_bak", "node_modules",
1671
+ "package.json", "package-lock.json",
1672
+ "capacitor.config.json", "capacitor.config.ts",
1673
+ "capacitor.config.js", "AndroidManifest.xml"}
1674
+ copied = 0
1675
+ for child in work_base.iterdir():
1676
+ if child.name in skip or child.name.startswith("."):
1677
+ continue
1678
+ dest = www / child.name
1679
+ if dest.exists():
1680
+ continue
1681
+ try:
1682
+ if child.is_dir() and not child.is_symlink():
1683
+ shutil.copytree(child, dest, symlinks=False, ignore_dangling_symlinks=True)
1684
+ elif child.is_file():
1685
+ shutil.copy2(child, dest)
1686
+ else:
1687
+ continue
1688
+ copied += 1
1689
+ except Exception as ce:
1690
+ log(f"webDir normalize skip {child.name}: {ce}")
1691
+ if cfg_json.exists():
1692
+ try:
1693
+ data = json.loads(cfg_json.read_text(encoding="utf-8", errors="ignore"))
1694
+ data["webDir"] = "www"
1695
+ cfg_json.write_text(json.dumps(data, indent=2), encoding="utf-8")
1696
+ except Exception as je:
1697
+ log(f"webDir config rewrite note: {je}")
1698
+ else:
1699
+ for cn in ("capacitor.config.ts", "capacitor.config.js"):
1700
+ cp = work_base / cn
1701
+ if cp.is_file():
1702
+ try:
1703
+ ctxt = cp.read_text(encoding="utf-8", errors="ignore")
1704
+ ntxt = re.sub(r"(webDir\s*:\s*)['\"][^'\"]*['\"]", r'\1"www"', ctxt, count=1)
1705
+ if ntxt != ctxt:
1706
+ cp.write_text(ntxt, encoding="utf-8")
1707
+ except Exception as te:
1708
+ log(f"webDir config rewrite note: {te}")
1709
+ web_dir_name = "www"
1710
+ log(f"webDir '.' is rejected by Capacitor CLI — normalized root web assets into www/ ({copied} entries) in work copy, upload untouched")
1711
+ except Exception as e:
1712
+ log(f"webDir normalize note: {e}")
1713
  # --- env preflight (versions only) + JDK gate (Cap7+ cannot compile on JDK17) ---
1714
  try:
1715
  res = await _run_cmd(["node", "-v"], timeout=15)
 
1851
  # used as-is (extra files under android/ preserved).
1852
  try:
1853
  andra = work_base / "android"
1854
+ # Baked manifest sources, in order: partial-shell manifest, then
1855
+ # a flat AndroidManifest.xml at project root next to the web
1856
+ # files (same baked-perms intent, minus scaffolding). First hit
1857
+ # wins; the restore below is source-agnostic.
1858
  baked_bytes = None
1859
+ baked_src = ""
1860
+ for cand in (andra / "app" / "src" / "main" / "AndroidManifest.xml",
1861
+ work_base / "AndroidManifest.xml"):
1862
+ if cand.is_file():
1863
+ try:
1864
+ baked_bytes = cand.read_bytes()
1865
+ baked_src = str(cand.relative_to(work_base))
1866
+ break
1867
+ except Exception:
1868
+ baked_bytes = None
1869
+ baked_src = ""
1870
  shell_complete = (
1871
  (andra / "app" / "build.gradle").is_file()
1872
  or (andra / "app" / "build.gradle.kts").is_file()
 
1887
  log("cap: local binary missing — using npx @capacitor/cli")
1888
  if not andra.exists() or not shell_complete:
1889
  if baked_bytes is not None:
1890
+ if baked_src == "AndroidManifest.xml":
1891
+ log("Root-level AndroidManifest.xml found alongside web files — cap add builds the shell first, your manifest replaces the generated one afterwards")
1892
+ else:
1893
+ log("Partial baked android/ detected (manifest without Gradle shell) — cap add builds the shell first, baked manifest replaces the generated one afterwards")
1894
  else:
1895
  log("android/ missing or incomplete — running cap add android")
1896
  # Move the partial shell aside (never rmtree): on `cap add`
 
1907
  res = await _run_cmd(cap_add, cwd=work_base, timeout=180)
1908
  if res.returncode != 0:
1909
  try:
1910
+ if partial_bak.exists():
1911
+ # Failed `cap add` can leave a half-created android/
1912
+ # behind (skeleton is made before the copy step that
1913
+ # failed). That output is disposable; the moved-aside
1914
+ # original is the only thing worth keeping. The rmtree
1915
+ # is safe exactly because partial_bak exists — it proves
1916
+ # the original was moved aside, so current android/
1917
+ # can only be cap's failed output, never user files.
1918
+ if andra.exists():
1919
+ shutil.rmtree(andra, ignore_errors=True)
1920
  partial_bak.rename(andra)
1921
  log("Restored partial android/ after cap add failure")
1922
  except Exception: