Skip to content

Instantly share code, notes, and snippets.

@AI0867
Forked from anonymous/coverity-submit
Last active June 10, 2016 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AI0867/9702292baa81e9863df21a18358d02c2 to your computer and use it in GitHub Desktop.
Save AI0867/9702292baa81e9863df21a18358d02c2 to your computer and use it in GitHub Desktop.
#!/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 \
https://scan.coverity.com/builds?project=Wesnoth \
''' % 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