diff --git a/packages/coreutils/build.sh b/packages/coreutils/build.sh index 54c628b..6f024ad 100644 --- a/packages/coreutils/build.sh +++ b/packages/coreutils/build.sh @@ -29,6 +29,8 @@ gl_cv_func_mktime_works=no ac_cv_func_mktime=no gl_cv_func_working_mktime=no gl_cv_func_tzset_clobber=no +ac_cv_func_tzalloc=no +gl_cv_func_tzalloc=no " termux_step_pre_configure() { @@ -38,11 +40,22 @@ termux_step_pre_configure() { if [ "$TERMUX_ARCH" = "arm" ] || [ "$TERMUX_ARCH" = "i686" ]; then TERMUX_PKG_EXTRA_CONFIGURE_ARGS+=" --disable-year2038" fi + + # Fix clang error: operand argument to checked integer operation must be an integer type ... ('bool' invalid) + sed -i 's/ckd_add (&t, t, leapsec)/ckd_add (\&t, t, (int) leapsec)/' lib/posixtm.c } termux_step_post_configure() { # Fix mktime_z missing on Android by defining it in config.h - echo "#define mktime_z(tz, tm) mktime(tm)" >> lib/config.h + # Stub missing functions. + # Gnulib detects them as missing but might still try to use them in parse-datetime. + # We provide no-op/fallback macros. + { + echo "#define mktime_z(tz, tm) mktime(tm)" + echo "#define tzalloc(z) NULL" + echo "#define tzfree(z) do {} while (0)" + echo "#define localtime_rz(z, t, tm) localtime_r(t, tm)" + } >> lib/config.h } termux_step_configure() { diff --git a/scripts/build_engine/defaults.sh b/scripts/build_engine/defaults.sh index 0472a40..48350d4 100755 --- a/scripts/build_engine/defaults.sh +++ b/scripts/build_engine/defaults.sh @@ -76,6 +76,11 @@ EOF echo "Depends: $TERMUX_PKG_DEPENDS" >> "$TERMUX_PKG_MASSAGEDIR/DEBIAN/control" fi + # Add RepoExe Build Hash if available + if [ -n "${TERMUX_REPOEXE_HASH:-}" ]; then + echo "X-RepoExe-Hash: $TERMUX_REPOEXE_HASH" >> "$TERMUX_PKG_MASSAGEDIR/DEBIAN/control" + fi + # Build the package dpkg-deb --build "$TERMUX_PKG_MASSAGEDIR" "$TERMUX_SCRIPTDIR/output/${PKG_NAME}_${TERMUX_PKG_VERSION}_${TERMUX_ARCH}.deb" } diff --git a/scripts/build_engine/entry_point.sh b/scripts/build_engine/entry_point.sh index c13f621..28e5ccf 100755 --- a/scripts/build_engine/entry_point.sh +++ b/scripts/build_engine/entry_point.sh @@ -28,6 +28,13 @@ if [ -f "$PKG_PATH/build.sh" ]; then echo "[*] Sourcing build.sh for $PKG_NAME..." source "$PKG_PATH/build.sh" + # Source Architecture Specific Build Script + if [ -f "$PKG_PATH/build.${TERMUX_ARCH}.sh" ]; then + echo "[*] Sourcing build.${TERMUX_ARCH}.sh for $PKG_NAME..." + # shellcheck disable=SC1090 + source "$PKG_PATH/build.${TERMUX_ARCH}.sh" + fi + # Load Mixins if requested if [ -n "${TERMUX_PKG_MIXINS:-}" ]; then IFS=',' read -ra MIXINS <<< "$TERMUX_PKG_MIXINS" diff --git a/scripts/repoexe/builder.py b/scripts/repoexe/builder.py index 31d4123..55dbb13 100644 --- a/scripts/repoexe/builder.py +++ b/scripts/repoexe/builder.py @@ -129,6 +129,12 @@ def build_package(self, pkg: Package, arch: str, channel: str) -> bool: pkg.content_hash = self.hasher.get_hash(pkg.name, pkg.dependencies, env_vars) logger.info(f"[{pkg.name}] Hash: {pkg.content_hash}") + # Check Remote Cache (Stable/Beta) + if self.check_remote_cache(pkg, arch, channel): + logger.info(f"[{pkg.name}] Found in Remote Cache. Skipping build.") + pkg.status = "cached" + return True + # Write Hash File for Storage # Format: {pkg.name}_{version}_{arch}.hash to allow multi-arch cache in same PR # Or just {pkg.name}_{version}.hash? @@ -184,6 +190,8 @@ def _build_arch(self, pkg: Package, arch: str) -> bool: env = os.environ.copy() # Use arch-specific sysroot env["TERMUX_COMMON_SYSROOT"] = str(self.get_sysroot(arch).resolve()) + # Pass Hash to Build Script + env["TERMUX_REPOEXE_HASH"] = pkg.content_hash # Use separate log file per package and arch to avoid collisions log_file = self.output_dir / f"{pkg.name}_{arch}.log" @@ -302,6 +310,75 @@ def check_pr_cache(self, pr_id: str, pkg: Package, arch: str) -> bool: return False return False + def check_remote_cache(self, pkg: Package, arch: str, current_channel: str) -> bool: + """ + Checks if the package with the same hash exists in available channels (main, beta). + If found, downloads the artifact to output_dir and returns True. + """ + import requests + repo_slug = os.environ.get("GITHUB_REPOSITORY") + if not repo_slug: return False + owner, repo_name = repo_slug.split("/") + site_url = f"https://{owner}.github.io/{repo_name}" + + # Check all channels for potential promotion or caching + channels = ["main", "beta"] + + for channel in channels: + try: + # Fetch Packages index + index_url = f"{site_url}/dists/{channel}/main/binary-{arch}/Packages" + logger.info(f"Checking cache in {channel} ({index_url})...") + resp = requests.get(index_url, timeout=10) + if resp.status_code != 200: continue + + content = resp.text + # Simple parse + stanzas = content.split("\n\n") + for stanza in stanzas: + if not stanza.strip(): continue + + p_name = None + p_hash = None + p_filename = None + + for line in stanza.split("\n"): + if line.startswith("Package: "): + p_name = line.split(": ", 1)[1].strip() + elif line.startswith("X-RepoExe-Hash: "): + p_hash = line.split(": ", 1)[1].strip() + elif line.startswith("Filename: "): + p_filename = line.split(": ", 1)[1].strip() + + if p_name == pkg.name and p_hash == pkg.content_hash: + logger.info(f"[{pkg.name}] Cache HIT in {channel}!") + + # Construct full URL + if not p_filename.startswith("http"): + download_url = f"{site_url}/{p_filename}" + else: + download_url = p_filename + + logger.info(f"Downloading artifact from {download_url}...") + + # Target filename: pkgname_version_arch.deb + target_deb = self.output_dir / f"{pkg.name}_{pkg.metadata.get('TERMUX_PKG_VERSION')}_{arch}.deb" + + # Download to temp then move + r = requests.get(download_url, stream=True) + if r.status_code == 200: + with open(target_deb, 'wb') as f: + for chunk in r.iter_content(chunk_size=8192): + f.write(chunk) + return True + else: + logger.warning(f"Failed to download cached artifact: {r.status_code}") + + except Exception as e: + logger.warning(f"Error checking remote cache: {e}") + + return False + def check_pr_cache_only(self, pkg: Package, pr_id: str, arch: str) -> bool: """ Public wrapper to check cache without running build logic. diff --git a/scripts/repoexe/site_generator.py b/scripts/repoexe/site_generator.py index 8a1d0e5..dcdd6e8 100644 --- a/scripts/repoexe/site_generator.py +++ b/scripts/repoexe/site_generator.py @@ -188,6 +188,7 @@ def generate_html(dists_root, output_file, repo_url): f.write("echo \"deb [signed-by=$PREFIX/etc/apt/trusted.gpg.d/repoexe.gpg] $REPO_URL main main\" > \"$PREFIX/etc/apt/sources.list.d/repoexe.list\"\n") f.write("apt update\n") f.write("echo \"[*] Installation Complete!\"\n") + f.write("echo \"Repo maintained by SjnExe (sjnexecontact@gmail.com)\"\n") html_content = f""" @@ -395,6 +396,9 @@ def generate_html(dists_root, output_file, repo_url): .pkg-list {{ list-style: none; padding: 0; display: grid; gap: 15px; }} + /* Responsive Grid: 1 column mobile, auto-fit desktop */ + .pkg-list {{ grid-template-columns: 1fr; }} + .pkg-item {{ background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 8px; padding: 20px; transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s; position: relative; }} .pkg-item:hover {{ border-color: var(--accent-color); box-shadow: 0 4px 12px rgba(0,0,0,0.1); transform: translateY(-2px); }} @@ -415,7 +419,9 @@ def generate_html(dists_root, output_file, repo_url): .downloads-grid {{ display: grid; grid-template-columns: 1fr; gap: 15px; }} @media (min-width: 600px) {{ - .downloads-grid {{ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }} + /* Desktop Grid for Cards */ + .pkg-list {{ grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); }} + .downloads-grid {{ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }} }} .suite-group {{ display: flex; flex-direction: column; gap: 8px; }} @@ -541,7 +547,8 @@ def generate_html(dists_root, output_file, repo_url):

Generated by RepoExe Automated System.

Last Updated: {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC')}

@@ -600,9 +607,9 @@ def generate_html(dists_root, output_file, repo_url): let metaHtml = `Arch: ${{pkg.archs_str}}`; if (pkg.section) metaHtml += `Sec: ${{escapeHtml(pkg.section)}}`; - if (pkg.installed_size) metaHtml += `Size: ${{escapeHtml(pkg.installed_size)}}`; + // Removed Size badge as requested if (pkg.license) metaHtml += `Lic: ${{escapeHtml(pkg.license)}}`; - if (pkg.maintainer) metaHtml += `👤 ${{escapeHtml(pkg.maintainer)}}`; + if (pkg.maintainer) metaHtml += `Author: ${{escapeHtml(pkg.maintainer)}}`; let depsHtml = ""; if (pkg.depends_html) {{ diff --git a/scripts/setup_env.sh b/scripts/setup_env.sh index b0fbade..7ebf743 100755 --- a/scripts/setup_env.sh +++ b/scripts/setup_env.sh @@ -22,7 +22,8 @@ $CMD_PREFIX apt-get install -yq --no-install-recommends \ python3-yaml \ shellcheck \ pandoc \ - p7zip-full + p7zip-full \ + python3-requests # 3. Setup Android NDK : "${NDK_VERSION:=r29}" diff --git a/site/index.html b/site/index.html deleted file mode 100644 index 3839670..0000000 --- a/site/index.html +++ /dev/null @@ -1,587 +0,0 @@ - - - - - - RepoExe - Termux Repository - - - - - -
-
- -
-
- -
-
-

Termux Repository

-

High-performance, automated, phone-managed packages.

- -
-
-
-
-
-
-
- Quick Install -
-
-
- bash <(curl -fsSL https://owner.github.io/repo/install) - -
-
-
- Manual Configuration / Advanced -
-
- 1. Import GPG Key: - curl -fsSL https://owner.github.io/repo/dists/main/Release.gpg -o $PREFIX/etc/apt/trusted.gpg.d/repoexe.gpg -
-
- 2. Add to Sources (Replace 'main' with 'beta' for beta channel): - echo "deb [signed-by=$PREFIX/etc/apt/trusted.gpg.d/repoexe.gpg] https://owner.github.io/repo main main" > $PREFIX/etc/apt/sources.list.d/repoexe.list -
-
- 3. Update & Install: - apt update && apt install <package> -
-
-
-
-
- -
-
- 🔍 - -
- -
- - -
End of list
- - -
- - - - - - -