diff --git a/cpplint/cpplint.py b/cpplint/cpplint.py index 0445454f6..159dbbb07 100755 --- a/cpplint/cpplint.py +++ b/cpplint/cpplint.py @@ -136,6 +136,22 @@ the top-level categories like 'build' and 'whitespace' will also be printed. If 'detailed' is provided, then a count is provided for each category like 'build/class'. + + root=subdir + The root directory used for deriving header guard CPP variable. + By default, the header guard CPP variable is calculated as the relative + path to the directory that contains .git, .hg, or .svn. When this flag + is specified, the relative path is calculated from the specified + directory. If the specified directory does not exist, this flag is + ignored. + + Examples: + Assuing that src/.git exists, the header guard CPP variables for + src/chrome/browser/ui/browser.h are: + + No flag => CHROME_BROWSER_UI_BROWSER_H_ + --root=chrome => BROWSER_UI_BROWSER_H_ + --root=chrome/browser => UI_BROWSER_H_ """ # We categorize each error message we print. Here are the categories. @@ -336,6 +352,10 @@ # on which those errors are expected and should be suppressed. _error_suppressions = {} +# The root directory used for deriving header guard CPP variable. +# This is set by --root flag. +_root = None + def ParseNolintSuppressions(filename, raw_line, linenum, error): """Updates the global list of error-suppressions. @@ -1102,7 +1122,10 @@ def GetHeaderGuardCPPVariable(filename): filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename) fileinfo = FileInfo(filename) - return re.sub(r'[-./\s]', '_', fileinfo.RepositoryName()).upper() + '_' + file_path_from_root = fileinfo.RepositoryName() + if _root: + file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root) + return re.sub(r'[-./\s]', '_', file_path_from_root).upper() + '_' def CheckForHeaderGuard(filename, lines, error): @@ -3933,7 +3956,8 @@ def ParseArguments(args): try: (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', 'counting=', - 'filter=']) + 'filter=', + 'root=']) except getopt.GetoptError: PrintUsage('Invalid arguments.') @@ -3959,6 +3983,9 @@ def ParseArguments(args): if val not in ('total', 'toplevel', 'detailed'): PrintUsage('Valid counting options are total, toplevel, and detailed') counting_style = val + elif opt == '--root': + global _root + _root = val if not filenames: PrintUsage('No files were specified.') diff --git a/cpplint/cpplint_test_header.h b/cpplint/cpplint_test_header.h new file mode 100644 index 000000000..4307e8008 --- /dev/null +++ b/cpplint/cpplint_test_header.h @@ -0,0 +1 @@ +// A test header for cpplint_unittest.py. diff --git a/cpplint/cpplint_unittest.py b/cpplint/cpplint_unittest.py index 907e36415..a195e9132 100755 --- a/cpplint/cpplint_unittest.py +++ b/cpplint/cpplint_unittest.py @@ -2588,6 +2588,29 @@ def testBuildHeaderGuard(self): ' [build/header_guard] [5]' % expected_guard), error_collector.ResultList()) + def testBuildHeaderGuardWithRoot(self): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'cpplint_test_header.h') + file_info = cpplint.FileInfo(file_path) + if file_info.FullName() == file_info.RepositoryName(): + # When FileInfo cannot deduce the root directory of the repository, + # FileInfo.RepositoryName returns the same value as FileInfo.FullName. + # This can happen when this source file was obtained without .svn or + # .git directory. (e.g. using 'svn export' or 'git archive'). + # Skip this test in such a case because --root flag makes sense only + # when the root directory of the repository is properly deduced. + return + + self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_', + cpplint.GetHeaderGuardCPPVariable(file_path)) + cpplint._root = 'cpplint' + self.assertEquals('CPPLINT_TEST_HEADER_H_', + cpplint.GetHeaderGuardCPPVariable(file_path)) + # --root flag is ignored if an non-existent directory is specified. + cpplint._root = 'NON_EXISTENT_DIR' + self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_', + cpplint.GetHeaderGuardCPPVariable(file_path)) + def testBuildInclude(self): # Test that include statements have slashes in them. self.TestLint('#include "foo.h"',