#!/usr/bin/env python """ generate a diff appropriate for mirroring https://github.com/mozilla/mozbase to http://hg.mozilla.org/mozilla-central/file/tip/testing/mozbase Note that this shells out to `cp` for simplicity, so you should run this somewhere that has the `cp` command available. See: - https://bugzilla.mozilla.org/show_bug.cgi?id=787263 - https://bugzilla.mozilla.org/show_bug.cgi?id=722451 """ import optparse import os import shutil import subprocess import sys import tempfile try: from subprocess import check_call as call except ImportError: from subprocess import call # globals HOME = os.environ['HOME'] MOZILLA_TRY = os.path.join(HOME, 'mozilla/src/mozilla-try') MOZBASE = 'git://github.com/mozilla/mozbase.git' # paths we don't want in m-c from mozbase's github repo excludes = ['.git', '.gitignore', 'versionbump.py'] # paths we want to keep in m-c that aren't in the github repo keep = [('Makefile.in',)] def latest_commit(git_dir): """returns last commit hash from a git repository directory""" command = ['git', 'log', '--pretty=format:%H', 'HEAD^..HEAD'] process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=git_dir) stdout, stderr = process.communicate() return stdout.strip() def revert(hg_dir): """revert a hg repository directory""" call(['hg', 'revert', '--no-backup', '--all'], cwd=hg_dir) process = subprocess.Popen(['hg', 'st'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=hg_dir) stdout, stderr = process.communicate() lines = [line.strip() for line in stdout.strip().splitlines()] status = [line.split(None, 1) for line in lines] newfiles = [j for i, j in status if i == '?'] for f in newfiles: path = os.path.join(hg_dir, f) os.remove(path) def main(args=sys.argv[1:]): """command line entry point""" # parse command line options usage = '%prog output' class PlainDescriptionFormatter(optparse.IndentedHelpFormatter): """description formatter for console script entry point""" def format_description(self, description): if description: return description.strip() + '\n' else: return '' parser = optparse.OptionParser(usage=usage, description=__doc__) options, args = parser.parse_args(args) if len(args) > 1: parser.print_help() parser.exit() if args: output = args[0] else: output = None # update m-c assert os.path.exists(MOZILLA_TRY) and os.path.isdir(MOZILLA_TRY) hg_dir = os.path.join(MOZILLA_TRY, '.hg') assert os.path.exists(hg_dir) and os.path.isdir(hg_dir) call(['hg', 'qpop', '--all'], cwd=MOZILLA_TRY) revert(MOZILLA_TRY) call(['hg', 'pull'], cwd=MOZILLA_TRY) call(['hg', 'update'], cwd=MOZILLA_TRY) tempdir = tempfile.mkdtemp() try: dest = os.path.join(MOZILLA_TRY, 'testing') mozbase = os.path.join(dest, 'mozbase') # download mozbase call(['git', 'clone', MOZBASE], cwd=tempdir) src = os.path.join(tempdir, 'mozbase') assert os.path.isdir(src) if output is None: commit_hash = latest_commit(src) output = os.path.join(os.getcwd(), '%s.diff' % commit_hash) for path in excludes: _path = os.path.join(src, path) if not os.path.exists(_path): continue if os.path.isfile(_path): os.remove(_path) if os.path.isdir(_path): shutil.rmtree(_path) # copy files we need to keep keepdir = os.path.join(tempdir, 'keep') os.makedirs(keepdir) for path in keep: if len(path) > 1: directory = os.path.join(keepdir, *path[:-1]) os.makedirs(directory) call(['cp', '-r', os.path.join(path), directory], cwd=mozbase) else: call(['cp', '-r', path[0], keepdir], cwd=mozbase) # remove mozbase directory shutil.rmtree(mozbase) # copy mozbase to m-c assert os.path.isdir(dest) call(['cp', '-r', 'mozbase', dest], cwd=tempdir) # add the files back we actually want to keep for path in os.listdir(keepdir): call(['cp', '-r', path, mozbase], cwd=keepdir) # generate the diff call(['hg', 'addremove'], cwd=MOZILLA_TRY) # add new files process = subprocess.Popen(['hg', 'diff'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=MOZILLA_TRY) stdout, stderr = process.communicate() f = file(output, 'w') f.write(stdout) f.close() finally: # cleanup revert(MOZILLA_TRY) shutil.rmtree(tempdir) print "Diff at %s" % output if __name__ == '__main__': main()