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
8 from __future__
import unicode_literals
30 log
= logging
.getLogger(__name__
)
33 class ConfigError(Exception):
37 def readConfig(configfile
):
39 execfile(configfile
, c
)
43 def verify_mozconfigs(
44 mozconfig_pair
, nightly_mozconfig_pair
, platform
, mozconfigWhitelist
46 """Compares mozconfig to nightly_mozconfig and compare to an optional
47 whitelist of known differences. mozconfig_pair and nightly_mozconfig_pair
48 are pairs containing the mozconfig's identifier and the list of lines in
51 # unpack the pairs to get the names, the names are just for
52 # identifying the mozconfigs when logging the error messages
53 mozconfig_name
, mozconfig_lines
= mozconfig_pair
54 nightly_mozconfig_name
, nightly_mozconfig_lines
= nightly_mozconfig_pair
56 if not mozconfig_lines
or not nightly_mozconfig_lines
:
57 log
.info("Missing mozconfigs to compare for %s" % platform
)
62 diff_instance
= difflib
.Differ()
63 diff_result
= diff_instance
.compare(mozconfig_lines
, nightly_mozconfig_lines
)
64 diff_list
= list(diff_result
)
66 for line
in diff_list
:
67 clean_line
= line
[1:].strip()
68 if (line
[0] == "-" or line
[0] == "+") and len(clean_line
) > 1:
70 if clean_line
.startswith("#"):
72 # compare to whitelist
75 # handle lines that move around in diff
76 if "+" + line
[1:] in diff_list
:
78 if platform
in mozconfigWhitelist
.get("release", {}):
79 if clean_line
in mozconfigWhitelist
["release"][platform
]:
82 if "-" + line
[1:] in diff_list
:
84 if platform
in mozconfigWhitelist
.get("nightly", {}):
85 if clean_line
in mozconfigWhitelist
["nightly"][platform
]:
93 mozconfigWhitelist
["nightly"][platform
],
97 log
.error("Skipping line %s!" % line
)
99 message
= "found in %s but not in %s: %s"
102 message
% (mozconfig_name
, nightly_mozconfig_name
, clean_line
)
106 message
% (nightly_mozconfig_name
, mozconfig_name
, clean_line
)
112 def get_mozconfig(path
):
113 """Consumes a path and returns a list of lines from the mozconfig file."""
114 with
open(path
, "rb") as fh
:
115 return fh
.readlines()
118 def compare(topsrcdir
):
119 app
= os
.path
.join(topsrcdir
, "browser")
120 whitelist
= readConfig(os
.path
.join(app
, "config", "mozconfigs", "whitelist"))
124 def normalize_lines(lines
):
125 return {l
.strip() for l
in lines
}
127 for platform
in PLATFORMS
:
128 log
.info("Comparing platform %s" % platform
)
130 mozconfigs_path
= os
.path
.join(app
, "config", "mozconfigs", platform
)
132 nightly_path
= os
.path
.join(mozconfigs_path
, "nightly")
133 beta_path
= os
.path
.join(mozconfigs_path
, "beta")
134 release_path
= os
.path
.join(mozconfigs_path
, "release")
136 nightly_lines
= get_mozconfig(nightly_path
)
137 beta_lines
= get_mozconfig(beta_path
)
138 release_lines
= get_mozconfig(release_path
)
140 # Validate that entries in whitelist['nightly'][platform] are actually
142 whitelist_normalized
= normalize_lines(whitelist
["nightly"].get(platform
, []))
143 nightly_normalized
= normalize_lines(nightly_lines
)
145 for line
in sorted(whitelist_normalized
- nightly_normalized
):
146 log
.error("extra line in nightly whitelist: %s" % line
)
149 log
.info("Comparing beta and nightly mozconfigs")
150 passed
= verify_mozconfigs(
151 (beta_path
, beta_lines
), (nightly_path
, nightly_lines
), platform
, whitelist
157 log
.info("Comparing release and nightly mozconfigs")
158 passed
= verify_mozconfigs(
159 (release_path
, release_lines
),
160 (nightly_path
, nightly_lines
),
170 class TestCompareMozconfigs(unittest
.TestCase
):
171 def test_compare_mozconfigs(self
):
172 topsrcdir
= buildconfig
.substs
["top_srcdir"]
173 self
.assertTrue(compare(topsrcdir
))
176 if __name__
== "__main__":
177 logging
.basicConfig(level
=logging
.INFO
)