From 166be7d7684b4bd309661603a35710e0ed752680 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Fri, 7 Dec 2018 23:24:39 +0100 Subject: Save existing configuration to ..old in write_config() Add a default-True 'save_old' flag to write_config(). If 'save_old' is True and an existing configuration file is being overwritten, a copy of the old configuration file is saved to ..old (e.g. .config.old) in the same directory. Errors are ignored, as the old configuration would usually just be a nice-to-have, and not essential. The same functionality could be added for minimal configuration files and headers, but it's probably most useful for configuration files. --- kconfiglib.py | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/kconfiglib.py b/kconfiglib.py index 6ffac90..b854186 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -1244,7 +1244,8 @@ class Kconfig(object): .format(self.config_prefix, sym.name, val)) def write_config(self, filename, - header="# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n"): + header="# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n", + save_old=True): r""" Writes out symbol values in the .config format. The format matches the C implementation, including ordering. @@ -1264,7 +1265,19 @@ class Kconfig(object): Text that will be inserted verbatim at the beginning of the file. You would usually want each line to start with '#' to make it a comment, and include a final terminating newline. + + save_old (default: True): + If True and already exists, a copy of it will be saved to + ..old in the same directory before the new configuration is + written. The leading dot is added only if the filename doesn't + already start with a dot. + + Errors are silently ignored if ..old cannot be written + (e.g. due to being a directory). """ + if save_old: + _save_old(filename) + with self._open(filename, "w") as f: f.write(header) @@ -5776,6 +5789,31 @@ def _touch_dep_file(sym_name): os.close(os.open( sym_path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o644)) +def _save_old(path): + # See write_config() + + dirname, basename = os.path.split(path) + if basename.startswith("."): + basename += ".old" + else: + basename = "." + basename + ".old" + backup = os.path.join(dirname, basename) + + try: + # os.replace() would be nice here, but it's Python 3 (3.3+) only + if os.name == "posix": + # Will remove ..old if it already exists on POSIX + # systems + os.rename(path, backup) + else: + import shutil + shutil.copyfile(path, backup) + except: + # Ignore errors from 'filename' missing as well as other errors. The + # backup file is more of a nice-to-have, and not worth erroring out + # over e.g. if ..old happens to be a directory. + pass + def _decoding_error(e, filename, macro_linenr=None): # Gives the filename and context for UnicodeDecodeError's, which are a pain # to debug otherwise. 'e' is the UnicodeDecodeError object. -- cgit v1.2.3