Call Git cmd_main directly

This commit is contained in:
Joe Tretter
2026-06-24 13:16:35 -05:00
parent a9d7b0cfc0
commit 0554c736e4
26 changed files with 1141 additions and 661 deletions

View File

@@ -22,6 +22,7 @@ HOST_GIT_DIR="$PROJECT_DIR/build/host-git"
HOST_GIT_STAMP="$HOST_GIT_DIR/.source-fingerprint"
ANDROID_JNI_DIR="$PROJECT_DIR/app/src/main/jniLibs"
ANDROID_ASSET_MANPAGE_DIR="$PROJECT_DIR/app/src/main/assets/manpages"
GIT_PATCH_DIR="$PROJECT_DIR/patches/git"
ANDROID_API=24
ANDROID_CMDLINE_TOOLS_URL="https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip"
@@ -29,6 +30,8 @@ GRADLE_DIST_URL="https://services.gradle.org/distributions/gradle-8.7-bin.zip"
JDK_DIST_URL="https://api.adoptium.net/v3/binary/latest/17/ga/linux/x64/jdk/hotspot/normal/eclipse"
ANDROID_NDK_PACKAGE="ndk;27.2.12479018"
ANDROID_CMAKE_PACKAGE="cmake;3.22.1"
ANDROID_EMULATOR_SYSTEM_IMAGE="system-images;android-35;google_apis;x86_64"
ANDROID_TEST_AVD_NAME="githug_android_api35"
ANDROID_NDK_DIR="$SDK_DIR/ndk/27.2.12479018"
ANDROID_CMAKE_DIR="$SDK_DIR/cmake/3.22.1"
ANDROID_TOOLBIN="$ANDROID_NDK_DIR/toolchains/llvm/prebuilt/linux-x86_64/bin"
@@ -86,6 +89,12 @@ required_sdk_packages_present() {
&& [ -d "$ANDROID_CMAKE_DIR" ]
}
required_emulator_packages_present() {
required_sdk_packages_present \
&& [ -x "$SDK_DIR/emulator/emulator" ] \
&& [ -d "$SDK_DIR/system-images/android-35/google_apis/x86_64" ]
}
auto_commit_if_needed() {
if ! command -v git >/dev/null 2>&1; then
log "Git is not available; skipping automatic commit"
@@ -309,6 +318,36 @@ ensure_git_source() {
else
log "Using existing Git source checkout"
fi
restore_retired_git_patch_changes
apply_git_patches
}
restore_retired_git_patch_changes() {
local common_main="$GIT_SRC_DIR/common-main.c"
if [ ! -f "$common_main" ]; then
return
fi
if grep -q 'githug_git_main' "$common_main" && ! find "$GIT_PATCH_DIR" -maxdepth 1 -type f -name '*githug*git*main*.patch' 2>/dev/null | grep -q .; then
log "Restoring retired Git patch changes from common-main.c"
git -C "$GIT_SRC_DIR" checkout -- common-main.c
fi
}
apply_git_patches() {
if [ ! -d "$GIT_PATCH_DIR" ]; then
return
fi
local patch_file
while IFS= read -r patch_file; do
if git -C "$GIT_SRC_DIR" apply --reverse --check "$patch_file" >/dev/null 2>&1; then
log "Git patch already applied: ${patch_file#$PROJECT_DIR/}"
else
log "Applying Git patch: ${patch_file#$PROJECT_DIR/}"
git -C "$GIT_SRC_DIR" apply "$patch_file"
fi
done < <(find "$GIT_PATCH_DIR" -maxdepth 1 -type f -name '*.patch' | sort)
}
common_git_make_args() {
@@ -329,7 +368,8 @@ common_git_make_args() {
HAVE_CLOCK_MONOTONIC=YesPlease \
HAVE_GETDELIM=YesPlease \
FREAD_READS_DIRECTORIES=UnfortunatelyYes \
CSPRNG_METHOD=
CSPRNG_METHOD= \
LDFLAGS=-Wl,--export-dynamic
}
bundle_git_manpages() {
@@ -350,9 +390,11 @@ git_source_fingerprint() {
local head
local tracked_changes
local make_args
head="$(git -C "$GIT_SRC_DIR" rev-parse HEAD)"
tracked_changes="$(git -C "$GIT_SRC_DIR" diff --binary HEAD -- | git hash-object --stdin)"
printf '%s:%s\n' "$head" "$tracked_changes"
make_args="$(common_git_make_args | git hash-object --stdin)"
printf '%s:%s:%s\n' "$head" "$tracked_changes" "$make_args"
}
target_is_current() {
@@ -507,6 +549,124 @@ ensure_sdk_packages() {
mark_successful_check
}
ensure_emulator_sdk_packages() {
setup_env
if required_emulator_packages_present; then
log "Android emulator SDK packages are already installed locally"
return
fi
log "Accepting Android SDK licenses"
set +e
set +o pipefail
yes | "$CMDLINE_TOOLS_LATEST_DIR/bin/sdkmanager" --sdk_root="$SDK_DIR" --licenses >/dev/null
local license_status=$?
set -o pipefail
set -e
if [ "$license_status" -ne 0 ]; then
echo "sdkmanager --licenses failed with exit code $license_status" >&2
exit "$license_status"
fi
log "Installing Android emulator SDK packages"
"$CMDLINE_TOOLS_LATEST_DIR/bin/sdkmanager" --sdk_root="$SDK_DIR" \
"platform-tools" \
"platforms;android-35" \
"build-tools;35.0.0" \
"$ANDROID_NDK_PACKAGE" \
"$ANDROID_CMAKE_PACKAGE" \
"emulator" \
"$ANDROID_EMULATOR_SYSTEM_IMAGE"
}
ensure_test_avd() {
ensure_emulator_sdk_packages
if "$CMDLINE_TOOLS_LATEST_DIR/bin/avdmanager" list avd | grep -q "Name: $ANDROID_TEST_AVD_NAME"; then
log "Android test AVD already present: $ANDROID_TEST_AVD_NAME"
return
fi
log "Creating Android test AVD: $ANDROID_TEST_AVD_NAME"
set +e
set +o pipefail
printf 'no\n' | "$CMDLINE_TOOLS_LATEST_DIR/bin/avdmanager" create avd \
--name "$ANDROID_TEST_AVD_NAME" \
--package "$ANDROID_EMULATOR_SYSTEM_IMAGE" \
--device "pixel_5" \
--force
local avd_status=$?
set -o pipefail
set -e
if [ "$avd_status" -ne 0 ]; then
echo "avdmanager create avd failed with exit code $avd_status" >&2
exit "$avd_status"
fi
}
connected_android_device() {
"$SDK_DIR/platform-tools/adb" devices | awk 'NR > 1 && $2 == "device" { print $1; exit }'
}
wait_for_emulator_boot() {
local adb="$SDK_DIR/platform-tools/adb"
local boot_completed=""
local attempt
log "Waiting for Android emulator to boot"
"$adb" wait-for-device
for attempt in $(seq 1 180); do
boot_completed="$("$adb" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r' || true)"
if [ "$boot_completed" = "1" ]; then
"$adb" shell input keyevent 82 >/dev/null 2>&1 || true
log "Android emulator booted"
return
fi
sleep 2
done
echo "Timed out waiting for Android emulator to boot" >&2
exit 1
}
start_emulator_if_needed() {
ensure_test_avd
local existing_device
existing_device="$(connected_android_device || true)"
if [ -n "$existing_device" ]; then
log "Using already connected Android device/emulator: $existing_device"
EMULATOR_STARTED_BY_TOOLING=""
return
fi
local emulator_log="$PROJECT_DIR/build/reports/android-emulator.log"
mkdir -p "$(dirname "$emulator_log")"
log "Starting Android emulator: $ANDROID_TEST_AVD_NAME"
"$SDK_DIR/emulator/emulator" \
-avd "$ANDROID_TEST_AVD_NAME" \
-no-window \
-no-audio \
-no-boot-anim \
-gpu swiftshader_indirect \
>"$emulator_log" 2>&1 &
EMULATOR_STARTED_BY_TOOLING="$!"
wait_for_emulator_boot
}
stop_emulator_if_started() {
if [ -z "${EMULATOR_STARTED_BY_TOOLING:-}" ]; then
return
fi
log "Stopping Android emulator started by tooling"
"$SDK_DIR/platform-tools/adb" emu kill >/dev/null 2>&1 || true
wait "$EMULATOR_STARTED_BY_TOOLING" >/dev/null 2>&1 || true
EMULATOR_STARTED_BY_TOOLING=""
}
maybe_run_operation() {
local mode="${1:-}"
local gradle_task=""
@@ -516,7 +676,9 @@ maybe_run_operation() {
local should_bump_version="false"
local should_auto_commit="false"
local should_compile_host_git="false"
local should_compile_android_git="false"
local should_bundle_manpages="false"
local should_run_emulator="false"
case "$mode" in
--build)
@@ -526,6 +688,7 @@ maybe_run_operation() {
artifact_target="$PROJECT_DIR/app/build/outputs/apk/debug/githug-android-debug.apk"
should_bump_version="true"
should_auto_commit="true"
should_compile_android_git="true"
should_bundle_manpages="true"
;;
--build-release-aab)
@@ -535,6 +698,7 @@ maybe_run_operation() {
artifact_target="$PROJECT_DIR/app/build/outputs/bundle/release/githug-android-release.aab"
should_bump_version="true"
should_auto_commit="true"
should_compile_android_git="true"
should_bundle_manpages="true"
;;
--test)
@@ -542,6 +706,13 @@ maybe_run_operation() {
artifact_label="debug unit tests"
should_compile_host_git="true"
;;
--test-emulator)
gradle_task="connectedDebugAndroidTest"
artifact_label="debug instrumentation tests on Android emulator"
should_compile_android_git="true"
should_bundle_manpages="true"
should_run_emulator="true"
;;
--compile-git)
build_all_git_targets
return
@@ -571,10 +742,17 @@ maybe_run_operation() {
build_host_git
export GITHUG_TEST_GIT_BINARY="$HOST_GIT_BINARY"
fi
if [ "$should_compile_android_git" = "true" ]; then
build_android_git
fi
if [ "$should_bundle_manpages" = "true" ]; then
ensure_git_source
bundle_git_manpages
fi
if [ "$should_run_emulator" = "true" ]; then
start_emulator_if_needed
trap stop_emulator_if_started EXIT
fi
log "Running $artifact_label with --no-daemon"
"$PROJECT_DIR/gradlew" --no-daemon "$gradle_task"
@@ -593,22 +771,25 @@ maybe_run_operation() {
log "Stopping any Gradle daemons just in case"
"$PROJECT_DIR/gradlew" --stop >/dev/null 2>&1 || true
stop_emulator_if_started
trap - EXIT
}
print_usage() {
cat <<EOF_USAGE
Usage: bash ./AndroidProjectTooling.sh [--build | --build-release-aab | --test | --compile-git]
Usage: bash ./AndroidProjectTooling.sh [--build | --build-release-aab | --test | --test-emulator | --compile-git]
--build Set up the environment and build the debug APK
--build-release-aab Set up the environment and build a release Android App Bundle (AAB)
--test Set up the environment, compile host Git, and run the debug JVM unit tests with it
--test-emulator Set up an Android emulator and run debug instrumentation tests on it
--compile-git Compile Git for the development host and all Android target ABIs
EOF_USAGE
}
validate_args() {
case "${1:-}" in
""|--build|--build-release-aab|--test|--compile-git)
""|--build|--build-release-aab|--test|--test-emulator|--compile-git)
;;
*)
echo "Unknown argument: $1" >&2
@@ -654,6 +835,7 @@ main() {
log "To set up and build in one step: bash ./AndroidProjectTooling.sh --build"
log "To set up and build a release AAB in one step: bash ./AndroidProjectTooling.sh --build-release-aab"
log "To set up and run unit tests with compiled host Git: bash ./AndroidProjectTooling.sh --test"
log "To set up and run instrumentation tests on an emulator: bash ./AndroidProjectTooling.sh --test-emulator"
}
main "$@"