diff options
author | Tom Zanussi <tom.zanussi@linux.intel.com> | 2014-12-16 18:41:00 -0600 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2014-12-18 10:08:37 +0000 |
commit | ed99aeeb682ed0ab04e2a02ece88b6d90059b774 (patch) | |
tree | 0d9127e351868a814a3c577975c2afbdae82dfe4 /scripts/lib/bsp/engine.py | |
parent | 8657c2fd57600e0b0eaf2a14692de7453c78e1bb (diff) | |
download | poky-ed99aeeb682ed0ab04e2a02ece88b6d90059b774.tar.gz |
yocto-bsp: Add a processing pass to get rid of 'strange' filenames
Operating systems that can't handle filenames containing anything but
uppercase letters don't like to see 'strange' characters in filenames
such as the file and directory names yocto-bsp uses as part of its
templating mechanism. To fix this, we essentially add another level
of metadata into the template files themselves rather than into their
names, and add a processing pass that internally gives us what we had
before. Specifically:
- strange characters in filenames are moved inside the files they
apply to, to the first line of the file prepended with '#
yocto-bsp-filename {{...}} filename | this'
- strange characters in directory names are moved inside a new file
of the same name but ending in .noinstall and with the first (and
only) line of the file prepended with '# yocto-bsp-dirname {{...}}
dirname'
If the new filename contained in the yocto-bsp-* tag is 'this', the
filename is the existing name of the file. For a dirname, this would
be the filename with .noinstall removed.
"Fixes" [YOCTO #5312].
(From meta-yocto rev: 3dad2decbd682713f717950fc39fa0f63f1b8c98)
Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib/bsp/engine.py')
-rw-r--r-- | scripts/lib/bsp/engine.py | 173 |
1 files changed, 170 insertions, 3 deletions
diff --git a/scripts/lib/bsp/engine.py b/scripts/lib/bsp/engine.py index 681720d20a..7d6be239da 100644 --- a/scripts/lib/bsp/engine.py +++ b/scripts/lib/bsp/engine.py | |||
@@ -756,6 +756,8 @@ class CheckInputLine(ListValInputLine): | |||
756 | return None | 756 | return None |
757 | 757 | ||
758 | 758 | ||
759 | dirname_substitutions = {} | ||
760 | |||
759 | class SubstrateBase(object): | 761 | class SubstrateBase(object): |
760 | """ | 762 | """ |
761 | Base class for both expanded and unexpanded file and dir container | 763 | Base class for both expanded and unexpanded file and dir container |
@@ -764,6 +766,7 @@ class SubstrateBase(object): | |||
764 | def __init__(self, filename, filebase, out_filebase): | 766 | def __init__(self, filename, filebase, out_filebase): |
765 | self.filename = filename | 767 | self.filename = filename |
766 | self.filebase = filebase | 768 | self.filebase = filebase |
769 | self.translated_filename = filename | ||
767 | self.out_filebase = out_filebase | 770 | self.out_filebase = out_filebase |
768 | self.raw_lines = [] | 771 | self.raw_lines = [] |
769 | self.expanded_lines = [] | 772 | self.expanded_lines = [] |
@@ -869,6 +872,167 @@ class SubstrateBase(object): | |||
869 | 872 | ||
870 | return self.expand_input_tag(tag, lineno) | 873 | return self.expand_input_tag(tag, lineno) |
871 | 874 | ||
875 | def append_translated_filename(self, filename): | ||
876 | """ | ||
877 | Simply append filename to translated_filename | ||
878 | """ | ||
879 | self.translated_filename = os.path.join(self.translated_filename, filename) | ||
880 | |||
881 | def get_substituted_file_or_dir_name(self, first_line, tag): | ||
882 | """ | ||
883 | If file or dir names contain name substitutions, return the name | ||
884 | to substitute. Note that this is just the file or dirname and | ||
885 | doesn't include the path. | ||
886 | """ | ||
887 | filename = first_line.find(tag) | ||
888 | if filename != -1: | ||
889 | filename += len(tag) | ||
890 | substituted_filename = first_line[filename:].strip() | ||
891 | this = substituted_filename.find(" this") | ||
892 | if this != -1: | ||
893 | head, tail = os.path.split(self.filename) | ||
894 | substituted_filename = substituted_filename[:this + 1] + tail | ||
895 | if tag == DIRNAME_TAG: # get rid of .noinstall in dirname | ||
896 | substituted_filename = substituted_filename.split('.')[0] | ||
897 | |||
898 | return substituted_filename | ||
899 | |||
900 | def get_substituted_filename(self, first_line): | ||
901 | """ | ||
902 | If a filename contains a name substitution, return the name to | ||
903 | substitute. Note that this is just the filename and doesn't | ||
904 | include the path. | ||
905 | """ | ||
906 | return self.get_substituted_file_or_dir_name(first_line, FILENAME_TAG) | ||
907 | |||
908 | def get_substituted_dirname(self, first_line): | ||
909 | """ | ||
910 | If a dirname contains a name substitution, return the name to | ||
911 | substitute. Note that this is just the dirname and doesn't | ||
912 | include the path. | ||
913 | """ | ||
914 | return self.get_substituted_file_or_dir_name(first_line, DIRNAME_TAG) | ||
915 | |||
916 | def substitute_filename(self, first_line): | ||
917 | """ | ||
918 | Find the filename in first_line and append it to translated_filename. | ||
919 | """ | ||
920 | substituted_filename = self.get_substituted_filename(first_line) | ||
921 | self.append_translated_filename(substituted_filename); | ||
922 | |||
923 | def substitute_dirname(self, first_line): | ||
924 | """ | ||
925 | Find the dirname in first_line and append it to translated_filename. | ||
926 | """ | ||
927 | substituted_dirname = self.get_substituted_dirname(first_line) | ||
928 | self.append_translated_filename(substituted_dirname); | ||
929 | |||
930 | def is_filename_substitution(self, line): | ||
931 | """ | ||
932 | Do we have a filename subustition? | ||
933 | """ | ||
934 | if line.find(FILENAME_TAG) != -1: | ||
935 | return True | ||
936 | return False | ||
937 | |||
938 | def is_dirname_substitution(self, line): | ||
939 | """ | ||
940 | Do we have a dirname subustition? | ||
941 | """ | ||
942 | if line.find(DIRNAME_TAG) != -1: | ||
943 | return True | ||
944 | return False | ||
945 | |||
946 | def translate_dirname(self, first_line): | ||
947 | """ | ||
948 | Just save the first_line mapped by filename. The later pass | ||
949 | through the directories will look for a dirname.noinstall | ||
950 | match and grab the substitution line. | ||
951 | """ | ||
952 | dirname_substitutions[self.filename] = first_line | ||
953 | |||
954 | def translate_dirnames_in_path(self, path): | ||
955 | """ | ||
956 | Translate dirnames below this file or dir, not including tail. | ||
957 | dirname_substititions is keyed on actual untranslated filenames. | ||
958 | translated_path contains the subsititutions for each element. | ||
959 | """ | ||
960 | remainder = path[len(self.filebase)+1:] | ||
961 | translated_path = untranslated_path = self.filebase | ||
962 | |||
963 | untranslated_dirs = remainder.split(os.sep) | ||
964 | |||
965 | for dir in untranslated_dirs: | ||
966 | key = os.path.join(untranslated_path, dir + '.noinstall') | ||
967 | try: | ||
968 | first_line = dirname_substitutions[key] | ||
969 | except KeyError: | ||
970 | translated_path = os.path.join(translated_path, dir) | ||
971 | untranslated_path = os.path.join(untranslated_path, dir) | ||
972 | continue | ||
973 | substituted_dir = self.get_substituted_dirname(first_line) | ||
974 | translated_path = os.path.join(translated_path, substituted_dir) | ||
975 | untranslated_path = os.path.join(untranslated_path, dir) | ||
976 | |||
977 | return translated_path | ||
978 | |||
979 | def translate_file_or_dir_name(self): | ||
980 | """ | ||
981 | Originally we were allowed to use open/close/assign tags and python | ||
982 | code in the filename, which fit in nicely with the way we | ||
983 | processed the templates and generated code. Now that we can't | ||
984 | do that, we make those tags proper file contents and have this | ||
985 | pass substitute the nice but non-functional names with those | ||
986 | 'strange' ones, and then proceed as usual. | ||
987 | |||
988 | So, if files or matching dir<.noinstall> files contain | ||
989 | filename substitutions, this function translates them into the | ||
990 | corresponding 'strange' names, which future passes will expand | ||
991 | as they always have. The resulting pathname is kept in the | ||
992 | file or directory's translated_filename. Another way to think | ||
993 | about it is that self.filename is the input filename, and | ||
994 | translated_filename is the output filename before expansion. | ||
995 | """ | ||
996 | # remove leaf file or dirname | ||
997 | head, tail = os.path.split(self.filename) | ||
998 | translated_path = self.translate_dirnames_in_path(head) | ||
999 | self.translated_filename = translated_path | ||
1000 | |||
1001 | # This is a dirname - does it have a matching .noinstall with | ||
1002 | # a substitution? If so, apply the dirname subsititution. | ||
1003 | if not os.path.isfile(self.filename): | ||
1004 | key = self.filename + ".noinstall" | ||
1005 | try: | ||
1006 | first_line = dirname_substitutions[key] | ||
1007 | except KeyError: | ||
1008 | self.append_translated_filename(tail) | ||
1009 | return | ||
1010 | self.substitute_dirname(first_line) | ||
1011 | return | ||
1012 | |||
1013 | f = open(self.filename) | ||
1014 | first_line = f.readline() | ||
1015 | f.close() | ||
1016 | |||
1017 | # This is a normal filename not needing translation, just use | ||
1018 | # it as-is. | ||
1019 | if not first_line or not first_line.startswith("#"): | ||
1020 | self.append_translated_filename(tail) | ||
1021 | return | ||
1022 | |||
1023 | # If we have a filename substitution (first line in the file | ||
1024 | # is a FILENAME_TAG line) do the substitution now. If we have | ||
1025 | # a dirname substitution (DIRNAME_TAG in dirname.noinstall | ||
1026 | # meta-file), hash it so we can apply it when we see the | ||
1027 | # matching dirname later. Otherwise we have a regular | ||
1028 | # filename, just use it as-is. | ||
1029 | if self.is_filename_substitution(first_line): | ||
1030 | self.substitute_filename(first_line) | ||
1031 | elif self.is_dirname_substitution(first_line): | ||
1032 | self.translate_dirname(first_line) | ||
1033 | else: | ||
1034 | self.append_translated_filename(tail) | ||
1035 | |||
872 | def expand_file_or_dir_name(self): | 1036 | def expand_file_or_dir_name(self): |
873 | """ | 1037 | """ |
874 | Expand file or dir names into codeline. Dirnames and | 1038 | Expand file or dir names into codeline. Dirnames and |
@@ -878,7 +1042,7 @@ class SubstrateBase(object): | |||
878 | """ | 1042 | """ |
879 | lineno = 0 | 1043 | lineno = 0 |
880 | 1044 | ||
881 | line = self.filename[len(self.filebase):] | 1045 | line = self.translated_filename[len(self.filebase):] |
882 | if line.startswith("/"): | 1046 | if line.startswith("/"): |
883 | line = line[1:] | 1047 | line = line[1:] |
884 | opentag_start = -1 | 1048 | opentag_start = -1 |
@@ -897,7 +1061,6 @@ class SubstrateBase(object): | |||
897 | self.parse_error("No close tag found for open tag", lineno, line) | 1061 | self.parse_error("No close tag found for open tag", lineno, line) |
898 | # we have a {{ tag i.e. code | 1062 | # we have a {{ tag i.e. code |
899 | tag = line[opentag_start + len(OPEN_TAG):end].strip() | 1063 | tag = line[opentag_start + len(OPEN_TAG):end].strip() |
900 | |||
901 | if not tag.lstrip().startswith(IF_TAG): | 1064 | if not tag.lstrip().startswith(IF_TAG): |
902 | self.parse_error("Only 'if' tags are allowed in file or directory names", | 1065 | self.parse_error("Only 'if' tags are allowed in file or directory names", |
903 | lineno, line) | 1066 | lineno, line) |
@@ -933,6 +1096,7 @@ class SubstrateBase(object): | |||
933 | Expand the file or dir name first, eventually this ends up | 1096 | Expand the file or dir name first, eventually this ends up |
934 | creating the file or dir. | 1097 | creating the file or dir. |
935 | """ | 1098 | """ |
1099 | self.translate_file_or_dir_name() | ||
936 | self.expand_file_or_dir_name() | 1100 | self.expand_file_or_dir_name() |
937 | 1101 | ||
938 | 1102 | ||
@@ -955,6 +1119,9 @@ class SubstrateFile(SubstrateBase): | |||
955 | self.read() | 1119 | self.read() |
956 | 1120 | ||
957 | for lineno, line in enumerate(self.raw_lines): | 1121 | for lineno, line in enumerate(self.raw_lines): |
1122 | # only first line can be a filename substitition | ||
1123 | if lineno == 0 and line.startswith("#") and FILENAME_TAG in line: | ||
1124 | continue # skip it - we've already expanded it | ||
958 | expanded_line = self.expand_tag(line, lineno + 1) # humans not 0-based | 1125 | expanded_line = self.expand_tag(line, lineno + 1) # humans not 0-based |
959 | if not expanded_line: | 1126 | if not expanded_line: |
960 | expanded_line = NormalLine(line.rstrip()) | 1127 | expanded_line = NormalLine(line.rstrip()) |
@@ -1141,7 +1308,7 @@ def gather_inputlines(files): | |||
1141 | for file in files: | 1308 | for file in files: |
1142 | if isinstance(file, SubstrateFile): | 1309 | if isinstance(file, SubstrateFile): |
1143 | group = None | 1310 | group = None |
1144 | basename = os.path.basename(file.filename) | 1311 | basename = os.path.basename(file.translated_filename) |
1145 | 1312 | ||
1146 | codeline = conditional_filename(basename) | 1313 | codeline = conditional_filename(basename) |
1147 | if codeline: | 1314 | if codeline: |