cpplint --root: support non-subdirectories
Using cpplint.py --root with directories at a more outer level
will now prepend the header guard with all the directories from the
root to the file.
For example given
ls /a/b/c # /a/b/c/.git /a/b/c/filename.h
cpplint.py --root=/a/b /a/b/c/filename.h # C_FILENAME_H_
# no root behavior:
cpplint.py /a/b/c/filename.h # FILENAME_H_
Also supports relative paths:
cd /a/b/c
cpplint.py --root=.. filename.h # C_FILENAME_H_
Note that the old usage is still supported:
cd /a/b/c
mkdir -p d/e/f
touch /a/b/c/d/e/f/filename.h
cpplint.py --root=d/e/f d/e/f/filename.h # FILENAME_H_
which would "strip" the prefix rather than prepend an extra prefix.
(Invalid root prefixes are as before also ignored)
diff --git a/cpplint/cpplint.py b/cpplint/cpplint.py
index 52cb7d0..7c624f2 100755
--- a/cpplint/cpplint.py
+++ b/cpplint/cpplint.py
@@ -1754,6 +1754,30 @@
else:
return 0
+def PathSplitToList(path):
+ """Returns the path split into a list by the separator.
+
+ Args:
+ path: An absolute or relative path (e.g. '/a/b/c/' or '../a')
+
+ Returns:
+ A list of path components (e.g. ['a', 'b', 'c]).
+ """
+ lst = []
+ while True:
+ (head, tail) = os.path.split(path)
+ if head == path: # absolute paths end
+ lst.append(head)
+ break
+ if tail == path: # relative paths end
+ lst.append(tail)
+ break
+
+ path = head
+ lst.append(tail)
+
+ lst.reverse()
+ return lst
def GetHeaderGuardCPPVariable(filename):
"""Returns the CPP variable that should be used as a header guard.
@@ -1776,13 +1800,39 @@
fileinfo = FileInfo(filename)
file_path_from_root = fileinfo.RepositoryName()
- if _root:
- suffix = os.sep
- # On Windows using directory separator will leave us with
- # "bogus escape error" unless we properly escape regex.
- if suffix == '\\':
- suffix += '\\'
- file_path_from_root = re.sub('^' + _root + suffix, '', file_path_from_root)
+
+ def FixupPathFromRoot():
+ # Process the file path with the --root flag if it was set.
+ if not _root:
+ return file_path_from_root
+
+ def StripListPrefix(lst, prefix):
+ # f(['x', 'y'], ['w, z']) -> None (not a valid prefix)
+ if lst[:len(prefix)] != prefix:
+ return None
+ # f(['a, 'b', 'c', 'd'], ['a', 'b']) -> ['c', 'd']
+ return lst[(len(prefix)):]
+
+ # root behavior:
+ # --root=subdir , lstrips subdir from the header guard
+ maybe_path = StripListPrefix(PathSplitToList(file_path_from_root),
+ PathSplitToList(_root))
+ if maybe_path:
+ return os.path.join(*maybe_path)
+
+ # --root=.. , will prepend the outer directory to the header guard
+ full_path = fileinfo.FullName()
+ root_abspath = os.path.abspath(_root)
+
+ maybe_path = StripListPrefix(PathSplitToList(full_path),
+ PathSplitToList(root_abspath))
+ if maybe_path:
+ return os.path.join(*maybe_path)
+
+ # --root=FAKE_DIR is ignored
+ return file_path_from_root
+
+ file_path_from_root = FixupPathFromRoot()
return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_'