Revision control

Copy as Markdown

#!/usr/bin/env python3
# Purpose: Publish android packages to local maven repo, but only if changed since last publish.
# Dependencies: None
# Usage: ./automation/publish_to_maven_local_if_modified.py
import os
import sys
import time
import hashlib
import argparse
from shared import run_cmd_checked, find_app_services_root, fatal_err
import re
LAST_CONTENTS_HASH_FILE = ".lastAutoPublishContentsHash"
GITIGNORED_FILES_THAT_AFFECT_THE_BUILD = ["local.properties"]
parser = argparse.ArgumentParser(description="Publish android packages to local maven repo, but only if changed since last publish")
parser.parse_args()
root_dir = find_app_services_root()
if str(root_dir) != os.path.abspath(os.curdir):
fatal_err(f"This only works if run from the repo root ({root_dir!r} != {os.path.abspath(os.curdir)!r})")
# This doesn't work on "native" windows, so let's get that out of the way now.
if sys.platform.startswith("win"):
print("NOTE: The autoPublish workflows do not work on native windows.")
print("You must follow the instructions in /docs/howtos/setup-android-build-environment.md#using-windows")
print("then, manually ensure that the following command has completed successfully in WSL:")
print(sys.argv)
print(f"(from the '{root_dir}' directory)")
print("Then restart the build")
# We don't want to fail here - the intention is that building, eg,
# android-components on native Windows still works, just that it prints the
# warning above.
sys.exit(0)
# Calculate a hash reflecting the current state of the repo.
contents_hash = hashlib.sha256()
contents_hash.update(
run_cmd_checked(["git", "rev-parse", "HEAD"], capture_output=True).stdout
)
contents_hash.update(b"\x00")
# Git can efficiently tell us about changes to tracked files, including
# the diff of their contents, if you give it enough "-v"s.
changes = run_cmd_checked(["git", "status", "-v", "-v"], capture_output=True).stdout
contents_hash.update(changes)
contents_hash.update(b"\x00")
# But unfortunately it can only tell us the names of untracked
# files, and it won't tell us anything about files that are in
# .gitignore but can still affect the build.
untracked_files = []
changes_lines = iter(ln.strip() for ln in changes.split(b"\n"))
try:
ln = next(changes_lines)
# Skip the tracked files.
while not ln.startswith(b"Untracked files:"):
ln = next(changes_lines)
# Skip instructional line about using `git add`.
ln = next(changes_lines)
# Now we're at the list of untracked files.
ln = next(changes_lines)
while ln:
untracked_files.append(ln)
ln = next(changes_lines)
except StopIteration:
pass
untracked_files.extend(GITIGNORED_FILES_THAT_AFFECT_THE_BUILD)
# So, we'll need to slurp the contents of such files for ourselves.
for nm in untracked_files:
try:
with open(nm, "rb") as f:
contents_hash.update(f.read())
except (FileNotFoundError, IsADirectoryError):
pass
contents_hash.update(b"\x00")
contents_hash.update(b"\x00")
contents_hash = contents_hash.hexdigest()
# If the contents hash has changed since last publish, re-publish.
last_contents_hash = ""
try:
with open(LAST_CONTENTS_HASH_FILE) as f:
last_contents_hash = f.read().strip()
except FileNotFoundError:
pass
if contents_hash == last_contents_hash:
print("Contents have not changed, no need to publish")
else:
print("Contents have changed, publishing")
run_cmd_checked(["./gradlew", "publishToMavenLocal", f"-Plocal={time.time_ns()}"])
with open(LAST_CONTENTS_HASH_FILE, "w") as f:
f.write(contents_hash)
f.write("\n")