| # Licensed to the Apache Software Foundation (ASF) under one | |
| # or more contributor license agreements. See the NOTICE file | |
| # distributed with this work for additional information | |
| # regarding copyright ownership. The ASF licenses this file | |
| # to you under the Apache License, Version 2.0 (the | |
| # "License"); you may not use this file except in compliance | |
| # with the License. You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, | |
| # software distributed under the License is distributed on an | |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| # KIND, either express or implied. See the License for the | |
| # specific language governing permissions and limitations | |
| # under the License. | |
| import re | |
| import os | |
| import tempfile | |
| import shutil | |
| from .utilities import bash | |
| class configFileOps: | |
| class entry: | |
| def __init__(self, name, value, op, separator): | |
| self.name = name | |
| self.value = value | |
| self.state = "new" | |
| self.op = op | |
| self.separator = separator | |
| def setState(self, state): | |
| self.state = state | |
| def getState(self): | |
| return self.state | |
| def __init__(self, fileName, cfg=None): | |
| self.fileName = fileName | |
| self.entries = [] | |
| self.backups = [] | |
| if cfg is not None: | |
| cfg.cfoHandlers.append(self) | |
| def addEntry(self, name, value, separator="="): | |
| e = self.entry(name, value, "add", separator) | |
| self.entries.append(e) | |
| def rmEntry(self, name, value, separator="="): | |
| entry = self.entry(name, value, "rm", separator) | |
| self.entries.append(entry) | |
| def getEntry(self, name, separator="="): | |
| try: | |
| ctx = open(self.fileName).read(-1) | |
| match = re.search("^" + name + ".*", ctx, re.MULTILINE) | |
| if match is None: | |
| return "" | |
| line = match.group(0).split(separator, 1) | |
| return line[1] | |
| except: | |
| return "" | |
| def save(self): | |
| newLines = [] | |
| if os.path.exists(self.fileName) and os.path.isfile(self.fileName): | |
| fp = open(self.fileName, "r") | |
| for line in fp.readlines(): | |
| matched = False | |
| for entry in self.entries: | |
| if entry.op == "add": | |
| if entry.separator == "=": | |
| matchString = r"^\ *" + entry.name + ".*" | |
| elif entry.separator == " ": | |
| matchString = r"^\ *" + entry.name + r"\ *" + entry.value | |
| else: | |
| if entry.separator == "=": | |
| matchString = r"^\ *" + entry.name + r"\ *=\ *" + entry.value | |
| else: | |
| matchString = r"^\ *" + entry.name + r"\ *" + entry.value | |
| match = re.match(matchString, line) | |
| if match is not None: | |
| if entry.op == "add" and entry.separator == "=": | |
| newline = "\n" + entry.name + "=" + entry.value + "\n" | |
| entry.setState("set") | |
| newLines.append(newline) | |
| self.backups.append([line, newline]) | |
| matched = True | |
| break | |
| elif entry.op == "rm": | |
| entry.setState("set") | |
| self.backups.append([line, None]) | |
| matched = True | |
| break | |
| if not matched: | |
| newLines.append(line) | |
| fp.close() | |
| for entry in self.entries: | |
| if entry.getState() != "set": | |
| if entry.op == "add": | |
| newline = entry.name + entry.separator + entry.value + "\n" | |
| newLines.append(newline) | |
| self.backups.append([None, newline]) | |
| entry.setState("set") | |
| open(self.fileName, "w").writelines(newLines) | |
| def replace_line(self, startswith,stanza,always_add=False): | |
| lines = [ s.strip() for s in open(self.fileName).readlines() ] | |
| newlines = [] | |
| replaced = False | |
| for line in lines: | |
| if re.search(startswith, line): | |
| if stanza is not None: | |
| newlines.append(stanza) | |
| self.backups.append([line, stanza]) | |
| replaced = True | |
| else: newlines.append(line) | |
| if not replaced and always_add: | |
| newlines.append(stanza) | |
| self.backups.append([None, stanza]) | |
| newlines = [ s + '\n' for s in newlines ] | |
| open(self.fileName,"w").writelines(newlines) | |
| def replace_or_add_line(self, startswith,stanza): | |
| return self.replace_line(startswith,stanza,always_add=True) | |
| def add_lines(self, lines, addToBackup=True): | |
| fp = open(self.fileName).read(-1) | |
| sh = re.escape(lines) | |
| match = re.search(sh, fp, re.MULTILINE) | |
| if match is not None: | |
| return | |
| fp += lines | |
| open(self.fileName, "w").write(fp) | |
| self.backups.append([None, lines]) | |
| def replace_lines(self, src, dst, addToBackup=True): | |
| fp = open(self.fileName).read(-1) | |
| sh = re.escape(src) | |
| if dst is None: | |
| dst = "" | |
| repl,nums = re.subn(sh, dst, fp) | |
| if nums <=0: | |
| return | |
| open(self.fileName, "w").write(repl) | |
| if addToBackup: | |
| self.backups.append([src, dst]) | |
| def append_lines(self, match_lines, append_lines): | |
| fp = open(self.fileName).read(-1) | |
| sh = re.escape(match_lines) | |
| match = re.search(sh, fp, re.MULTILINE) | |
| if match is None: | |
| return | |
| sh = re.escape(append_lines) | |
| if re.search(sh, fp, re.MULTILINE) is not None: | |
| return | |
| newlines = [] | |
| for line in open(self.fileName).readlines(): | |
| if re.search(match_lines, line) is not None: | |
| newlines.append(line + append_lines) | |
| self.backups.append([line, line + append_lines]) | |
| else: | |
| newlines.append(line) | |
| open(self.fileName, "w").writelines(newlines) | |
| def backup(self): | |
| for oldLine, newLine in self.backups: | |
| if newLine is None: | |
| self.add_lines(oldLine, False) | |
| else: | |
| self.replace_lines(newLine, oldLine, False) |