Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion packages/coreutils/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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() {
Expand Down
5 changes: 5 additions & 0 deletions scripts/build_engine/defaults.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down
7 changes: 7 additions & 0 deletions scripts/build_engine/entry_point.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
77 changes: 77 additions & 0 deletions scripts/repoexe/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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.
Expand Down
15 changes: 11 additions & 4 deletions scripts/repoexe/site_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 ([email protected])\"\n")

html_content = f"""<!DOCTYPE html>
<html lang="en">
Expand Down Expand Up @@ -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); }}

Expand All @@ -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; }}
Expand Down Expand Up @@ -541,7 +547,8 @@ def generate_html(dists_root, output_file, repo_url):
<p>Generated by RepoExe Automated System.</p>
<p style="font-size: 0.8em; color: var(--meta-color);">Last Updated: {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC')}</p>
<div class="footer-links">
<a href="https://github.com/{repo_owner}">👤 Owner</a>
<a href="https://github.com/{repo_owner}">By SjnExe</a>
<a href="mailto:[email protected]">Contact</a>
</div>
</footer>
</div>
Expand Down Expand Up @@ -600,9 +607,9 @@ def generate_html(dists_root, output_file, repo_url):

let metaHtml = `<span class="meta-tag">Arch: ${{pkg.archs_str}}</span>`;
if (pkg.section) metaHtml += `<span class="meta-tag">Sec: ${{escapeHtml(pkg.section)}}</span>`;
if (pkg.installed_size) metaHtml += `<span class="meta-tag">Size: ${{escapeHtml(pkg.installed_size)}}</span>`;
// Removed Size badge as requested
if (pkg.license) metaHtml += `<span class="meta-tag">Lic: ${{escapeHtml(pkg.license)}}</span>`;
if (pkg.maintainer) metaHtml += `<span class="meta-tag" title="Maintainer">👤 ${{escapeHtml(pkg.maintainer)}}</span>`;
if (pkg.maintainer) metaHtml += `<span class="meta-tag" title="Maintainer">Author: ${{escapeHtml(pkg.maintainer)}}</span>`;

let depsHtml = "";
if (pkg.depends_html) {{
Expand Down
3 changes: 2 additions & 1 deletion scripts/setup_env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down
Loading
Loading