2 # This Source Code Form is subject to the terms of the Mozilla Public
3 # License, v. 2.0. If a copy of the MPL was not distributed with this
4 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 # originally from https://hg.mozilla.org/build/tools/file/4ab9c1a4e05b/scripts/release/compare-mozconfigs.py # NOQA: E501
28 log
= logging
.getLogger(__name__
)
31 class ConfigError(Exception):
35 def readConfig(configfile
):
37 execfile(configfile
, c
)
41 def verify_mozconfigs(
42 mozconfig_pair
, nightly_mozconfig_pair
, platform
, mozconfigWhitelist
44 """Compares mozconfig to nightly_mozconfig and compare to an optional
45 whitelist of known differences. mozconfig_pair and nightly_mozconfig_pair
46 are pairs containing the mozconfig's identifier and the list of lines in
49 # unpack the pairs to get the names, the names are just for
50 # identifying the mozconfigs when logging the error messages
51 mozconfig_name
, mozconfig_lines
= mozconfig_pair
52 nightly_mozconfig_name
, nightly_mozconfig_lines
= nightly_mozconfig_pair
54 if not mozconfig_lines
or not nightly_mozconfig_lines
:
55 log
.info("Missing mozconfigs to compare for %s" % platform
)
60 diff_instance
= difflib
.Differ()
61 diff_result
= diff_instance
.compare(mozconfig_lines
, nightly_mozconfig_lines
)
62 diff_list
= list(diff_result
)
64 for line
in diff_list
:
65 clean_line
= line
[1:].strip()
66 if (line
[0] == "-" or line
[0] == "+") and len(clean_line
) > 1:
68 if clean_line
.startswith("#"):
70 # compare to whitelist
73 # handle lines that move around in diff
74 if "+" + line
[1:] in diff_list
:
76 if platform
in mozconfigWhitelist
.get("release", {}):
77 if clean_line
in mozconfigWhitelist
["release"][platform
]:
80 if "-" + line
[1:] in diff_list
:
82 if platform
in mozconfigWhitelist
.get("nightly", {}):
83 if clean_line
in mozconfigWhitelist
["nightly"][platform
]:
91 mozconfigWhitelist
["nightly"][platform
],
95 log
.error("Skipping line %s!" % line
)
97 message
= "found in %s but not in %s: %s"
100 message
% (mozconfig_name
, nightly_mozconfig_name
, clean_line
)
104 message
% (nightly_mozconfig_name
, mozconfig_name
, clean_line
)
110 def get_mozconfig(path
):
111 """Consumes a path and returns a list of lines from the mozconfig file."""
112 with
open(path
, "rb") as fh
:
113 return fh
.readlines()
116 def compare(topsrcdir
):
117 app
= os
.path
.join(topsrcdir
, "browser")
118 whitelist
= readConfig(os
.path
.join(app
, "config", "mozconfigs", "whitelist"))
122 def normalize_lines(lines
):
123 return {l
.strip() for l
in lines
}
125 for platform
in PLATFORMS
:
126 log
.info("Comparing platform %s" % platform
)
128 mozconfigs_path
= os
.path
.join(app
, "config", "mozconfigs", platform
)
130 nightly_path
= os
.path
.join(mozconfigs_path
, "nightly")
131 beta_path
= os
.path
.join(mozconfigs_path
, "beta")
132 release_path
= os
.path
.join(mozconfigs_path
, "release")
134 nightly_lines
= get_mozconfig(nightly_path
)
135 beta_lines
= get_mozconfig(beta_path
)
136 release_lines
= get_mozconfig(release_path
)
138 # Validate that entries in whitelist['nightly'][platform] are actually
140 whitelist_normalized
= normalize_lines(whitelist
["nightly"].get(platform
, []))
141 nightly_normalized
= normalize_lines(nightly_lines
)
143 for line
in sorted(whitelist_normalized
- nightly_normalized
):
144 log
.error("extra line in nightly whitelist: %s" % line
)
147 log
.info("Comparing beta and nightly mozconfigs")
148 passed
= verify_mozconfigs(
149 (beta_path
, beta_lines
), (nightly_path
, nightly_lines
), platform
, whitelist
155 log
.info("Comparing release and nightly mozconfigs")
156 passed
= verify_mozconfigs(
157 (release_path
, release_lines
),
158 (nightly_path
, nightly_lines
),
168 class TestCompareMozconfigs(unittest
.TestCase
):
169 def test_compare_mozconfigs(self
):
170 topsrcdir
= buildconfig
.substs
["top_srcdir"]
171 self
.assertTrue(compare(topsrcdir
))
174 if __name__
== "__main__":
175 logging
.basicConfig(level
=logging
.INFO
)