summaryrefslogtreecommitdiff
path: root/kconfiglib.py
diff options
context:
space:
mode:
authorUlf Magnusson <ulfalizer@gmail.com>2018-12-07 23:24:39 +0100
committerUlf Magnusson <ulfalizer@gmail.com>2018-12-08 00:14:42 +0100
commit166be7d7684b4bd309661603a35710e0ed752680 (patch)
treeb5fcd0a2f412ecec2cd593880967c01ad336c98f /kconfiglib.py
parent6f096161ec8415aa585d431ebb85e2738de2108f (diff)
Save existing configuration to .<filename>.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 .<filename>.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.
Diffstat (limited to 'kconfiglib.py')
-rw-r--r--kconfiglib.py40
1 files changed, 39 insertions, 1 deletions
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 <filename> already exists, a copy of it will be saved to
+ .<filename>.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 .<filename>.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 .<filename>.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 .<filename>.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.