Created
June 10, 2016 13:18
-
-
Save anonymous/c043a21666c34da190f6cb1a8da389e3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# | |
# coverity-submit - submit project to Coverity for scanning | |
# | |
# By Eric S. Raymond, May 2012. BSD terms apply. | |
# | |
import os, pwd, sys, ConfigParser, getopt, tempfile, shutil, datetime, commands | |
version = "1.12" | |
def commit_id(): | |
"If we're in a repository directory, try to extract a commit description." | |
methods = ( | |
("git rev-parse HEAD", "git describe HEAD"), | |
("hg root", "hg id -i"), | |
("bzr root", "bzr version-info --custom --template='{revision_id}\n'"), | |
("svn info", "svnversion") | |
) | |
for (probe, extract) in methods: | |
if os.system(probe + " >/dev/null 2>&1") == 0: | |
(status, output) = commands.getstatusoutput(extract) | |
if status == 0: | |
return output | |
return None | |
def deduce_name(): | |
"Deduce user's full name." | |
if 'USERNAME' in os.environ: | |
p = pwd.getpwnam(os.environ['USERNAME']) | |
elif 'LOGNAME' in os.environ: | |
p = pwd.getpwnam(os.environ['LOGNAME']) | |
else: | |
return None | |
return p.pw_gecos.split(',')[0] | |
def deduce_userid(): | |
"Deduce user's (local) username." | |
if 'USERNAME' in os.environ: | |
p = pwd.getpwnam(os.environ['USERNAME']) | |
elif 'LOGNAME' in os.environ: | |
p = pwd.getpwnam(os.environ['LOGNAME']) | |
else: | |
return None | |
return p.pw_name | |
if __name__ == '__main__': | |
name = email = project = token = url = None | |
config = ConfigParser.RawConfigParser() | |
if os.path.exists(os.path.expanduser("~/.config/coverity-submit")): | |
config.read(os.path.expanduser("~/.config/coverity-submit")) | |
else: | |
config.read(os.path.expanduser("~/.coverity-submit")) | |
def die(complaint): | |
sys.stderr.write(complaint + "\n") | |
sys.exit(1) | |
# Gather information that is not project-specific | |
if not "ALL" in config.sections(): | |
config.add_section("ALL") | |
if not config.has_option("ALL", "name"): | |
config.set("ALL", "name", deduce_name()) | |
if not config.has_option("ALL", "userid"): | |
config.set("ALL", "userid", deduce_userid()) | |
name = config.get("ALL", "name") | |
userid = config.get("ALL", "userid") | |
if config.has_option("ALL", "tools"): | |
tools = config.get("ALL", "tools") | |
os.environ["PATH"] += ":"+tools | |
# Deduce what project and directory to operate on (and go there). | |
noexec = False | |
verbose = False | |
build_version = commit_id() | |
description = datetime.datetime.now().isoformat() | |
(opts, args) = getopt.getopt(sys.argv[1:], "b:nt:v") | |
for (opt, arg) in opts: | |
if opt == '-b': | |
build_version = arg | |
if opt == '-n': | |
noexec = True | |
if opt == '-t': | |
description = arg | |
if opt == '-v': | |
verbose = True | |
where = os.path.basename(os.getcwd()) | |
if args: | |
project = args[0] | |
else: | |
project = where | |
if project not in config.sections(): | |
die("No such project as %s" % project) | |
# Collect project-specific variables | |
if config.has_option(project, "name"): | |
covname = config.get(project, "name") | |
else: | |
covname = project | |
if config.has_option(project, "token"): | |
token = config.get(project, "token") | |
elif config.has_option(project, "password"): | |
token = config.get(project, "password") | |
else: | |
die("Every project requires a token option.") | |
if config.has_option(project, "email"): | |
email = config.get(project, "email") | |
elif config.has_option("ALL", "email"): | |
email = config.get("ALL", "email") | |
else: | |
die("Every project requires an email option.") | |
if config.has_option(project, "prebuild"): | |
prebuild = config.get(project, "prebuild") | |
else: | |
prebuild = None | |
if config.has_option(project, "build"): | |
build = config.get(project, "build") | |
else: | |
die("Every project requires a build option.") | |
if config.has_option(project, "postbuild"): | |
postbuild = config.get(project, "postbuild") | |
else: | |
postbuild = None | |
def do_or_die(cmd): | |
if verbose: | |
print(cmd) | |
if not noexec: | |
if os.system(cmd) != 0: | |
sys.stderr.write("Command failed.\n") | |
sys.stderr.write("Command was: {}\n".format(cmd)) | |
sys.exit(1) | |
# Announce self | |
print("coverity-submit version %s..." % version) | |
# Work around a known bug in environment restoration under cov-build. | |
# Without this, xmlto won't run. | |
os.environ["XML_CATALOG_FILES"] = '/etc/xml/catalog' | |
# Build local stuff | |
print("Rebuilding and scanning...") | |
if prebuild: | |
do_or_die(prebuild) | |
do_or_die("rm -fr cov-int && cov-build --dir cov-int " + build) | |
if postbuild: | |
do_or_die(postbuild) | |
# Create the tarball | |
if verbose: | |
print("Bundling up required metadata...") | |
readme = """\ | |
Name: %(name)s | |
Email: %(email)s | |
Project: %(covname)s | |
Build-Version: %(build_version)s | |
Description: %(description)s | |
Submitted-by: coverity-submit %(version)s | |
""" % globals() | |
if verbose: | |
sys.stdout.write(readme) | |
tmpdir = tempfile.mkdtemp() | |
if not noexec: | |
with open(os.path.join(tmpdir, "README"), "w") as wfp: | |
wfp.write(readme) | |
tarball = "%s-scan.tgz" % covname | |
if verbose and not noexec: | |
shutil.copy("cov-int/build-log.txt", "build-log.txt") | |
do_or_die("mv cov-int %s; (cd %s; tar -czf %s README cov-int; rm -fr README cov-int)" % (tmpdir, tmpdir, tarball)) | |
print("Posting the analysis request...") | |
do_or_die('''curl \ | |
-o /tmp/cov-output \ | |
--form file=@%(tmpdir)s/%(tarball)s \ | |
--form project=%(covname)s \ | |
--form token=%(token)s \ | |
--form email=%(email)s \ | |
--form version=%(build_version)s \ | |
--form description=%(description)s \ | |
http://scan5.coverity.com/cgi-bin/upload.py \ | |
''' % globals()) | |
try: | |
print("You may want to remove %s" % (os.path.join(tmpdir, tarball))) | |
except OSError: | |
pass | |
print("Done. You'll get mail at %s." % email) | |
# The following sets edit modes for GNU EMACS | |
# Local Variables: | |
# mode:python | |
# End: | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment