1# This Source Code Form is subject to the terms of the Mozilla Public 2# License, v. 2.0. If a copy of the MPL was not distributed with this 3# file, You can obtain one at http://mozilla.org/MPL/2.0/. 4import argparse 5import re 6import subprocess 7 8 9# This script extracts commits that touch third party webrtc code so they can 10# be imported into Git. It filters out commits that are not part of upstream 11# code and rewrites the paths to match upstream. Finally, the commits are 12# combined into a mailbox file that can be applied with `git am`. 13LIBWEBRTC_DIR = "third_party/libwebrtc/webrtc" 14 15 16def build_commit_list(revset): 17 """Build commit list from the specified revset. 18 19 The revset can be a single revision, e.g. 52bb9bb94661, or a range, 20 e.g. 8c08a5bb8a99::52bb9bb94661, or any other valid revset 21 (check hg help revset). Only commits that touch libwebrtc are included. 22 """ 23 res = subprocess.run( 24 ["hg", "log", "-r", revset, "-M", "--template", "{node}\n", LIBWEBRTC_DIR], 25 capture_output=True, 26 text=True, 27 cwd="../../../../", 28 ) 29 return [line.strip() for line in res.stdout.strip().split("\n")] 30 31 32def extract_author_date(sha1): 33 res = subprocess.run( 34 ["hg", "log", "-r", sha1, "--template", "{author}|{date|isodate}"], 35 capture_output=True, 36 text=True, 37 ) 38 return res.stdout.split("|") 39 40 41def extract_description(sha1): 42 res = subprocess.run( 43 ["hg", "log", "-r", sha1, "--template", "{desc}"], 44 capture_output=True, 45 text=True, 46 ) 47 return res.stdout 48 49 50def extract_commit(sha1): 51 res = subprocess.run( 52 ["hg", "log", "-r", sha1, "-pg", "--template", "\n"], 53 capture_output=True, 54 text=True, 55 ) 56 return res.stdout 57 58 59def filter_nonwebrtc(commit): 60 filtered = [] 61 skipping = False 62 for line in commit.split("\n"): 63 # Extract only patches affecting libwebrtc, but avoid commits that 64 # touch build, which is tracked by a separate repo, or that affect 65 # moz.build files which are code generated. 66 if ( 67 line.startswith("diff --git a/" + LIBWEBRTC_DIR) 68 and not line.startswith("diff --git a/" + LIBWEBRTC_DIR + "/build") 69 and not line.endswith("moz.build") 70 ): 71 skipping = False 72 elif line.startswith("diff --git"): 73 skipping = True 74 if not skipping: 75 filtered.append(line) 76 return "\n".join(filtered) 77 78 79def fixup_paths(commit): 80 return re.sub("third_party/libwebrtc/webrtc/", "", commit) 81 82 83def write_as_mbox(sha1, author, date, description, commit, ofile): 84 # Use same magic date as git format-patch 85 ofile.write("From {} Mon Sep 17 00:00:00 2001\n".format(sha1)) 86 ofile.write("From: {}\n".format(author)) 87 ofile.write("Date: {}\n".format(date)) 88 description = description.split("\n") 89 ofile.write("Subject: {}\n".format(description[0])) 90 ofile.write("\n".join(description[1:])) 91 ofile.write( 92 "\nMercurial Revision: https://hg.mozilla.org/mozilla-central/rev/{}\n".format( 93 sha1 94 ) 95 ) 96 ofile.write(commit) 97 ofile.write("\n") 98 ofile.write("\n") 99 100 101if __name__ == "__main__": 102 commits = [] 103 parser = argparse.ArgumentParser( 104 description="Format commits for upstream libwebrtc" 105 ) 106 parser.add_argument( 107 "revsets", metavar="revset", type=str, nargs="+", help="A revset to process" 108 ) 109 args = parser.parse_args() 110 111 for revset in args.revsets: 112 commits.extend(build_commit_list(revset)) 113 114 with open("mailbox.patch", "w") as ofile: 115 for sha1 in commits: 116 author, date = extract_author_date(sha1) 117 description = extract_description(sha1) 118 filtered_commit = filter_nonwebrtc(extract_commit(sha1)) 119 if len(filtered_commit) == 0: 120 continue 121 fixedup_commit = fixup_paths(filtered_commit) 122 write_as_mbox(sha1, author, date, description, fixedup_commit, ofile) 123