diff options
Diffstat (limited to 'src/ventoo/augeas_utils.py')
-rw-r--r-- | src/ventoo/augeas_utils.py | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/src/ventoo/augeas_utils.py b/src/ventoo/augeas_utils.py new file mode 100644 index 0000000..6db6551 --- /dev/null +++ b/src/ventoo/augeas_utils.py @@ -0,0 +1,240 @@ +""" + + This file is part of the Ventoo program. + + This is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + It is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this software. If not, see <http://www.gnu.org/licenses/>. + + Copyright 2010 Christopher Harvey + +""" + +import augeas +import os.path as osp +import getpass +import shutil +import os +import pdb + +""" + Fills the fileSet parameter with the files that augeas loaded. + The returned files are system paths +""" +def accumulateFiles(a, node="/files", fileSet=[]): + aug_root = a.get("/augeas/root") + thisChildren = a.match(osp.join(node, '*')) + for child in thisChildren: + sysPath = osp.join(aug_root, osp.relpath(child, '/files')) + if osp.isfile(sysPath): + fileSet.append(sysPath) + elif osp.isdir(sysPath): + accumulateFiles(a, child, fileSet) + return fileSet + + +""" + Use an augeas file path to get a ventoo module name. +""" +def getVentooModuleNameFromAugPath(a, augPath): + aug_root = a.get("/augeas/root") + sysPath = osp.join(aug_root, osp.relpath(augPath, '/files')) + return str.split(osp.split(sysPath)[1], ".")[0] + +""" + Use a full system path to get a ventoo module name. +""" +def getVentooModuleNameFromSysPath(a, sysPath): + #remove the first character '/' if sysPath is absolute or join wont work. + if sysPath[0] == '/': + augQuery = osp.join('augeas/files', sysPath[1:], 'lens/info') + else: + augQuery = osp.join('augeas/files', sysPath, 'lens/info') + lensFile = a.get(augQuery) + return str.split(osp.split(lensFile)[1], ".")[0] + + +""" + Get an augeas path to a file from a system path +""" +def getAugeasPathFromSystemPath(a, sysPath): + aug_root = a.get("/augeas/root") + if aug_root != '/': + tmp = osp.relpath(sysPath, aug_root) + else: + tmp = sysPath + return osp.join('/files/', stripLeadingSlash(tmp)) + +""" + Return an int that says how much to add to 'have' so that it matches mult. + Mult can be a number, or ?, +, * +""" +def matchDiff(mult, have): + if mult == '*': + return 0 + elif mult == '+': + if have > 0: + return 0 + else: + return 1 + elif mult == '?': + return 0 + else: + return max(0, int(mult) - have) + +""" + True if adding more to 'have' will make the match invalid. +""" +def matchExact(mult, have): + if mult == '*': + return False + elif mult == '+': + return False + elif mult == '?': + if have == 0: + return False + elif have == 1: + return True + else: + raise ValueError("passed ? and "+str(have)+" to matchExact") + elif int(mult) == have: + return True + elif int(mult) < have: + raise ValueError("passed "+mult+" and "+str(have)+" to matchExact") + return False + +""" + True if the children in augPath are + augPath/1 + augPath/2 + etc... +""" +def isDupLevel(a, augPath): + q = osp.join(augPath, '*') + matches = a.match(q) + for match in matches: + try: + int(osp.split(match)[1]) + return True + except ValueError: + pass + return False + +""" + Turn /foo/bar/ into /foo/bar +""" +def stripTrailingSlash(a): + if a.endswith('/'): + ret = a[0:len(a)-1] + else: + ret = a + return ret + +""" + Turn /foo/bar/ into foo/bar/ +""" +def stripLeadingSlash(a): + if a.startswith('/'): + ret = a[1:] + else: + ret = a + return ret + +def stripBothSlashes(a): + return stripTrailingSlash(stripLeadingSlash(a)) + +""" + Get the path to the directory where the diff tree is to be stored. +""" +def getDiffRoot(): + return osp.join('/tmp', getpass.getuser(), 'augeas') + + +""" + Called by makeDiffTree, this actually checks files and performs the copies. + makeDiffTree only walks the directories and sets up the base paths. +""" +def __makeCopies(bases, currentDir, files): + #bases[0] = copyTargetBase + #bases[1] = aug_root + if osp.commonprefix([bases[0], currentDir]) == bases[0]: + return #ignore anything inside where we are copying to. + for f in files: + if f.endswith(".augnew"): + #print 'would copy ' + srcFile + ' to ' + targetDir + srcFile = osp.join(currentDir, f) + targetDir = osp.join(bases[0], osp.relpath(currentDir, bases[1])) + targetFile = osp.join(targetDir, f) + try: + os.makedirs(targetDir) #make sure target dir exists + except: + pass #don't care if it already exists. + shutil.copy(srcFile, targetFile) + +""" + Make a tree in treeRoot that contains a replica of the edited + filesystem except with .augnew files for future comparisions. +""" +def makeDiffTree(a, treeRoot): + saveMethod = a.get('augeas/save') + userName = getpass.getuser() + #if userName == 'root': + # raise ValueError("this function isn't safe to be run as root.") + if saveMethod != 'newfile': + raise ValueError('the save method for augeas is not "newfile"') + if not osp.isdir(treeRoot): + raise ValueError(treeRoot + ' is not a directory') + files = accumulateFiles(a) + for i in range(len(files)): #append .augnew to each file. + files[i] += '.augnew' + a.save() + for f in files: + #each file could exist, copy the ones that do. + if osp.isfile(f): + try: + os.makedirs(osp.join("/tmp", userName, "augeas", stripLeadingSlash(osp.split(f)[0]))) + except: + pass #don't care if it exists. + shutil.move(f, osp.join("/tmp", userName, "augeas", stripLeadingSlash(f))) +""" + Turns a system path like /etc/hosts into a the place where its + diff (edited) version would be saved. Use this function to compare + two files. +""" +def getDiffLocation(a, sysPath): + aug_root = a.get("/augeas/root") + return osp.join(getDiffRoot(), stripBothSlashes(sysPath)) + '.augnew' + + +def getFileErrorList(a, node = "augeas/files", errorList = {}): + aug_root = a.get("/augeas/files/") + thisChildren = a.match(osp.join(node, '*')) + for child in thisChildren: + thisError = a.get(osp.join(child, "error")) + if not thisError == None: + errorList[osp.relpath(child, "/augeas/files")] = thisError + else: + getFileErrorList(a, child, errorList) + return errorList + +""" + Removes numbers form paths. a/1/foo/bar/5/6/blah -> a/foo/bar/blah +""" +def removeNumbers(path): + out = "" + for node in path.split("/"): + try: + tmp = int(node) + except ValueError: + out = osp.join(out, node) + return out + |