From: Gabe Black Date: Thu, 9 Nov 2017 02:45:08 +0000 (-0800) Subject: scons: Pull style hook management out of the main SConstruct. X-Git-Tag: v19.0.0.0~2575 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=902b3e34beaadaa2ac2932a9ff93f08008a4b16f;p=gem5.git scons: Pull style hook management out of the main SConstruct. Put the code which supports style hooks for mercurial and git into two scons "tools". Change-Id: I3ffed85a177be4f9e458fff7b1cf16a3a479914e Reviewed-on: https://gem5-review.googlesource.com/5563 Reviewed-by: Gabe Black Maintainer: Gabe Black --- diff --git a/SConstruct b/SConstruct index 7cf2c9c83..f0a3b655d 100755 --- a/SConstruct +++ b/SConstruct @@ -196,195 +196,6 @@ if not ('CC' in main_dict_keys and 'CXX' in main_dict_keys): # as well main.AppendENVPath('PYTHONPATH', extra_python_paths) -######################################################################## -# -# Mercurial Stuff. -# -# If the gem5 directory is a mercurial repository, we should do some -# extra things. -# -######################################################################## - -hgdir = main.root.Dir(".hg") - - -style_message = """ -You're missing the gem5 style hook, which automatically checks your code -against the gem5 style rules on %s. -This script will now install the hook in your %s. -Press enter to continue, or ctrl-c to abort: """ - -mercurial_style_message = """ -You're missing the gem5 style hook, which automatically checks your code -against the gem5 style rules on hg commit and qrefresh commands. -This script will now install the hook in your .hg/hgrc file. -Press enter to continue, or ctrl-c to abort: """ - -git_style_message = """ -You're missing the gem5 style or commit message hook. These hooks help -to ensure that your code follows gem5's style rules on git commit. -This script will now install the hook in your .git/hooks/ directory. -Press enter to continue, or ctrl-c to abort: """ - -mercurial_style_upgrade_message = """ -Your Mercurial style hooks are not up-to-date. This script will now -try to automatically update them. A backup of your hgrc will be saved -in .hg/hgrc.old. -Press enter to continue, or ctrl-c to abort: """ - -mercurial_style_hook = """ -# The following lines were automatically added by gem5/SConstruct -# to provide the gem5 style-checking hooks -[extensions] -hgstyle = %s/util/hgstyle.py - -[hooks] -pretxncommit.style = python:hgstyle.check_style -pre-qrefresh.style = python:hgstyle.check_style -# End of SConstruct additions - -""" % (main.root.abspath) - -mercurial_lib_not_found = """ -Mercurial libraries cannot be found, ignoring style hook. If -you are a gem5 developer, please fix this and run the style -hook. It is important. -""" - -# Check for style hook and prompt for installation if it's not there. -# Skip this if --ignore-style was specified, there's no interactive -# terminal to prompt, or no recognized revision control system can be -# found. -ignore_style = GetOption('ignore_style') or not sys.stdin.isatty() - -# Try wire up Mercurial to the style hooks -if not ignore_style and hgdir.exists(): - style_hook = True - style_hooks = tuple() - hgrc = hgdir.File('hgrc') - hgrc_old = hgdir.File('hgrc.old') - try: - from mercurial import ui - ui = ui.ui() - ui.readconfig(hgrc.abspath) - style_hooks = (ui.config('hooks', 'pretxncommit.style', None), - ui.config('hooks', 'pre-qrefresh.style', None)) - style_hook = all(style_hooks) - style_extension = ui.config('extensions', 'style', None) - except ImportError: - print mercurial_lib_not_found - - if "python:style.check_style" in style_hooks: - # Try to upgrade the style hooks - print mercurial_style_upgrade_message - # continue unless user does ctrl-c/ctrl-d etc. - try: - raw_input() - except: - print "Input exception, exiting scons.\n" - sys.exit(1) - shutil.copyfile(hgrc.abspath, hgrc_old.abspath) - re_style_hook = re.compile(r"^([^=#]+)\.style\s*=\s*([^#\s]+).*") - re_style_extension = re.compile("style\s*=\s*([^#\s]+).*") - old, new = open(hgrc_old.abspath, 'r'), open(hgrc.abspath, 'w') - for l in old: - m_hook = re_style_hook.match(l) - m_ext = re_style_extension.match(l) - if m_hook: - hook, check = m_hook.groups() - if check != "python:style.check_style": - print "Warning: %s.style is using a non-default " \ - "checker: %s" % (hook, check) - if hook not in ("pretxncommit", "pre-qrefresh"): - print "Warning: Updating unknown style hook: %s" % hook - - l = "%s.style = python:hgstyle.check_style\n" % hook - elif m_ext and m_ext.group(1) == style_extension: - l = "hgstyle = %s/util/hgstyle.py\n" % main.root.abspath - - new.write(l) - elif not style_hook: - print mercurial_style_message, - # continue unless user does ctrl-c/ctrl-d etc. - try: - raw_input() - except: - print "Input exception, exiting scons.\n" - sys.exit(1) - hgrc_path = '%s/.hg/hgrc' % main.root.abspath - print "Adding style hook to", hgrc_path, "\n" - try: - with open(hgrc_path, 'a') as f: - f.write(mercurial_style_hook) - except: - print "Error updating", hgrc_path - sys.exit(1) - -def install_git_style_hooks(): - try: - gitdir = Dir(readCommand( - ["git", "rev-parse", "--git-dir"]).strip("\n")) - except Exception, e: - print "Warning: Failed to find git repo directory: %s" % e - return - - git_hooks = gitdir.Dir("hooks") - def hook_exists(hook_name): - hook = git_hooks.File(hook_name) - return hook.exists() - - def hook_install(hook_name, script): - hook = git_hooks.File(hook_name) - if hook.exists(): - print "Warning: Can't install %s, hook already exists." % hook_name - return - - if hook.islink(): - print "Warning: Removing broken symlink for hook %s." % hook_name - os.unlink(hook.get_abspath()) - - if not git_hooks.exists(): - mkdir(git_hooks.get_abspath()) - git_hooks.clear() - - abs_symlink_hooks = git_hooks.islink() and \ - os.path.isabs(os.readlink(git_hooks.get_abspath())) - - # Use a relative symlink if the hooks live in the source directory, - # and the hooks directory is not a symlink to an absolute path. - if hook.is_under(main.root) and not abs_symlink_hooks: - script_path = os.path.relpath( - os.path.realpath(script.get_abspath()), - os.path.realpath(hook.Dir(".").get_abspath())) - else: - script_path = script.get_abspath() - - try: - os.symlink(script_path, hook.get_abspath()) - except: - print "Error updating git %s hook" % hook_name - raise - - if hook_exists("pre-commit") and hook_exists("commit-msg"): - return - - print git_style_message, - try: - raw_input() - except: - print "Input exception, exiting scons.\n" - sys.exit(1) - - git_style_script = File("util/git-pre-commit.py") - git_msg_script = File("ext/git-commit-msg") - - hook_install("pre-commit", git_style_script) - hook_install("commit-msg", git_msg_script) - -# Try to wire up git to the style hooks -if not ignore_style and main.root.Entry(".git").exists(): - install_git_style_hooks() - ################################################### # # Figure out which configurations to set up based on the path(s) of diff --git a/site_scons/gem5_scons/__init__.py b/site_scons/gem5_scons/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/site_scons/gem5_scons/util.py b/site_scons/gem5_scons/util.py new file mode 100644 index 000000000..4781cc543 --- /dev/null +++ b/site_scons/gem5_scons/util.py @@ -0,0 +1,47 @@ +# Copyright (c) 2013, 2015-2017 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Copyright (c) 2011 Advanced Micro Devices, Inc. +# Copyright (c) 2009 The Hewlett-Packard Development Company +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import sys + +import SCons.Script + +def ignore_style(): + """Determine whether we should ignore style checks""" + return SCons.Script.GetOption('ignore_style') or not sys.stdin.isatty() diff --git a/site_scons/site_tools/default.py b/site_scons/site_tools/default.py index f7eeb28f6..2d32b56bd 100644 --- a/site_scons/site_tools/default.py +++ b/site_scons/site_tools/default.py @@ -72,6 +72,8 @@ def common_config(env): env.srcdir = env.root.Dir('src') gem5_tool_list = [ + 'git', + 'mercurial', ] def generate(env): diff --git a/site_scons/site_tools/git.py b/site_scons/site_tools/git.py new file mode 100644 index 000000000..d9f8ab89f --- /dev/null +++ b/site_scons/site_tools/git.py @@ -0,0 +1,118 @@ +# Copyright (c) 2013, 2015-2017 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Copyright (c) 2011 Advanced Micro Devices, Inc. +# Copyright (c) 2009 The Hewlett-Packard Development Company +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os + +import gem5_scons.util +from m5.util import readCommand + +git_style_message = """ +You're missing the gem5 style or commit message hook. These hooks help +to ensure that your code follows gem5's style rules on git commit. +This script will now install the hook in your .git/hooks/ directory. +Press enter to continue, or ctrl-c to abort: """ + +def install_style_hooks(env): + try: + gitdir = env.Dir(readCommand( + ["git", "rev-parse", "--git-dir"]).strip("\n")) + except Exception, e: + print "Warning: Failed to find git repo directory: %s" % e + return + + git_hooks = gitdir.Dir("hooks") + def hook_exists(hook_name): + hook = git_hooks.File(hook_name) + return hook.exists() + + def hook_install(hook_name, script): + hook = git_hooks.File(hook_name) + if hook.exists(): + print "Warning: Can't install %s, hook already exists." % hook_name + return + + if hook.islink(): + print "Warning: Removing broken symlink for hook %s." % hook_name + os.unlink(hook.get_abspath()) + + if not git_hooks.exists(): + os.mkdir(git_hooks.get_abspath()) + git_hooks.clear() + + abs_symlink_hooks = git_hooks.islink() and \ + os.path.isabs(os.readlink(git_hooks.get_abspath())) + + # Use a relative symlink if the hooks live in the source directory, + # and the hooks directory is not a symlink to an absolute path. + if hook.is_under(env.root) and not abs_symlink_hooks: + script_path = os.path.relpath( + os.path.realpath(script.get_abspath()), + os.path.realpath(hook.Dir(".").get_abspath())) + else: + script_path = script.get_abspath() + + try: + os.symlink(script_path, hook.get_abspath()) + except: + print "Error updating git %s hook" % hook_name + raise + + if hook_exists("pre-commit") and hook_exists("commit-msg"): + return + + print git_style_message, + try: + raw_input() + except: + print "Input exception, exiting scons.\n" + sys.exit(1) + + git_style_script = env.root.Dir("util").File("git-pre-commit.py") + git_msg_script = env.root.Dir("ext").File("git-commit-msg") + + hook_install("pre-commit", git_style_script) + hook_install("commit-msg", git_msg_script) + +def generate(env): + if exists(env) and not gem5_scons.util.ignore_style(): + install_style_hooks(env) + +def exists(env): + return env.Entry('#.git').exists() diff --git a/site_scons/site_tools/mercurial.py b/site_scons/site_tools/mercurial.py new file mode 100644 index 000000000..a38449f43 --- /dev/null +++ b/site_scons/site_tools/mercurial.py @@ -0,0 +1,146 @@ +# Copyright (c) 2013, 2015-2017 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Copyright (c) 2011 Advanced Micro Devices, Inc. +# Copyright (c) 2009 The Hewlett-Packard Development Company +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import re +import sys + +import gem5_scons.util + +mercurial_style_message = """ +You're missing the gem5 style hook, which automatically checks your code +against the gem5 style rules on hg commit and qrefresh commands. +This script will now install the hook in your .hg/hgrc file. +Press enter to continue, or ctrl-c to abort: """ + +mercurial_style_upgrade_message = """ +Your Mercurial style hooks are not up-to-date. This script will now +try to automatically update them. A backup of your hgrc will be saved +in .hg/hgrc.old. +Press enter to continue, or ctrl-c to abort: """ + +mercurial_style_hook_template = """ +# The following lines were automatically added by gem5/SConstruct +# to provide the gem5 style-checking hooks +[extensions] +hgstyle = %s/util/hgstyle.py + +[hooks] +pretxncommit.style = python:hgstyle.check_style +pre-qrefresh.style = python:hgstyle.check_style +# End of SConstruct additions + +""" + +mercurial_lib_not_found = """ +Mercurial libraries cannot be found, ignoring style hook. If +you are a gem5 developer, please fix this and run the style +hook. It is important. +""" + +def install_style_hooks(env): + hgdir = env.Dir('#.hg') + + style_hook = True + style_hooks = tuple() + hgrc = hgdir.File('hgrc') + hgrc_old = hgdir.File('hgrc.old') + try: + from mercurial import ui + ui = ui.ui() + ui.readconfig(hgrc.abspath) + style_hooks = (ui.config('hooks', 'pretxncommit.style', None), + ui.config('hooks', 'pre-qrefresh.style', None)) + style_hook = all(style_hooks) + style_extension = ui.config('extensions', 'style', None) + except ImportError: + print mercurial_lib_not_found + + if "python:style.check_style" in style_hooks: + # Try to upgrade the style hooks + print mercurial_style_upgrade_message + # continue unless user does ctrl-c/ctrl-d etc. + try: + raw_input() + except: + print "Input exception, exiting scons.\n" + sys.exit(1) + shutil.copyfile(hgrc.abspath, hgrc_old.abspath) + re_style_hook = re.compile(r"^([^=#]+)\.style\s*=\s*([^#\s]+).*") + re_style_extension = re.compile("style\s*=\s*([^#\s]+).*") + old, new = open(hgrc_old.abspath, 'r'), open(hgrc.abspath, 'w') + for l in old: + m_hook = re_style_hook.match(l) + m_ext = re_style_extension.match(l) + if m_hook: + hook, check = m_hook.groups() + if check != "python:style.check_style": + print "Warning: %s.style is using a non-default " \ + "checker: %s" % (hook, check) + if hook not in ("pretxncommit", "pre-qrefresh"): + print "Warning: Updating unknown style hook: %s" % hook + + l = "%s.style = python:hgstyle.check_style\n" % hook + elif m_ext and m_ext.group(1) == style_extension: + l = "hgstyle = %s/util/hgstyle.py\n" % env.root.abspath + + new.write(l) + elif not style_hook: + print mercurial_style_message, + # continue unless user does ctrl-c/ctrl-d etc. + try: + raw_input() + except: + print "Input exception, exiting scons.\n" + sys.exit(1) + hgrc_path = '%s/.hg/hgrc' % env.root.abspath + print "Adding style hook to", hgrc_path, "\n" + try: + with open(hgrc_path, 'a') as f: + f.write(mercurial_style_hook_template % env.root.abspath) + except: + print "Error updating", hgrc_path + sys.exit(1) + +def generate(env): + if exists(env) and not gem5_scons.util.ignore_style(): + install_style_hooks(env) + +def exists(env): + return env.Dir('#.hg').exists()