Skip to content

Instantly share code, notes, and snippets.

@valenting
Created February 26, 2024 12:25
Show Gist options
  • Save valenting/a124a49ae7f18071acb9bd9ac1e387be to your computer and use it in GitHub Desktop.
Save valenting/a124a49ae7f18071acb9bd9ac1e387be to your computer and use it in GitHub Desktop.
This script lists all of the WIP revisions in your Gecko mercurial repo and prunes those that have already been published
import subprocess
import re
import requests
import os
# Retrieve the API token from an environment variable
API_TOKEN = os.getenv('PHABRICATOR_API_TOKEN')
PHABRICATOR_URL = 'https://phabricator.services.mozilla.com/api/differential.revision.search'
def get_wip_commits():
command = ["hg", "log", "-r", "draft() and not obsolete()", "--template", "{node}|{desc}\n\n"]
try:
result = subprocess.run(command, check=True, stdout=subprocess.PIPE, universal_newlines=True)
commit_messages = result.stdout
return commit_messages
except subprocess.CalledProcessError as e:
print(f"Error executing hg: {e}")
return ""
def extract_differential_revision_numbers(commit_messages):
pattern = re.compile(r"([a-f0-9]+)\|(.*?)(?:Differential Revision: https://phabricator.services.mozilla.com/D(\d+))?", re.DOTALL)
for commit in commit_messages.strip().split("\n\n"):
match = pattern.search(commit)
if match:
commit_hash = match.group(1)
revision_number = match.group(3) if match.group(3) else ""
yield commit_hash, revision_number
def check_revision_status(revision_number):
if not API_TOKEN:
print("API token not found. Please set the PHABRICATOR_API_TOKEN environment variable.")
return None
payload = {
'api.token': API_TOKEN,
'constraints[ids][0]': revision_number,
}
response = requests.post(PHABRICATOR_URL, data=payload)
if response.status_code == 200:
data = response.json()
if data['result']['data']:
status = data['result']['data'][0]['fields']['status']['value']
return status
return None
def prune_revision(commit_hash):
command = ["hg", "prune", "--rev", commit_hash]
try:
subprocess.run(command, check=True)
print(f"Pruned commit {commit_hash}")
except subprocess.CalledProcessError as e:
print(f"Error pruning commit {commit_hash}: {e}")
def main():
if not API_TOKEN:
print("API token not set. Exiting...")
return
commit_messages = get_wip_commits()
if commit_messages:
for commit_hash, revision_number in extract_differential_revision_numbers(commit_messages):
if revision_number == "":
print(f"Commit {commit_hash} does not have an associated Phabricator Differential Revision. Skipping...")
continue
status = check_revision_status(revision_number)
if status in ['closed', 'abandoned', 'published']:
print(f"Revision {revision_number} (commit {commit_hash}) is {status}. Pruning...")
prune_revision(commit_hash)
else:
print(f"Revision {revision_number} status is {status}. No action taken.")
else:
print("No draft (WIP) commits found or error occurred.")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment