apt-plus/command/parser/Manifest.py

291 lines
6.1 KiB
Python

#!/usr/bin/env python
import re;
from os import path as ospath;
from Package import Package;
# (1) Initialisation
#--------------------------------------------------------#
# (1) Get absolute path #
ROOT = ospath.dirname( ospath.dirname(ospath.dirname(ospath.realpath(__file__))) );
# (2) Class declaration
#--------------------------------------------------------#
class Manifest:
_grp_re = r'^\[-\] (?P<name>.+)$';
_pkg_re = r'^(?P<pad>\s+)\[(?P<sta>[ x\.])\] (?P<name>[\w\.-]+)(?:\s*(?P<deb>\[deb\])|(?:\s*\[(?P<ppa>[\w\.-]+\/[\w\.-]+)\]))?(?:\s*# (?P<com>.+))?\s*$';
# (1) Constructor
#
# @file<String> Manifest file
#
#--------------------------------------------------------#
def __init__(self):
# (1) Try to read manifest path #
self._path = None;
with open( "%s/manifest" % ROOT, 'r' ) as f:
self._path = f.readline();
# (2) Manage error #
if( self._path == None ):
raise Exception('No manifest file given');
# (3) Initialize attributes #
self._grp = [];
self._pkg = {};
# (4) Parse the manifest file #
self._parse();
# (2) Parser method
#
#--------------------------------------------------------#
def _parse(self):
# (0) Init
#--------------------------------------------------------#
# (1) Create group matcher #
grpMatcher = re.compile(self._grp_re);
# (2) Create pkg matches #
pkgMatcher = re.compile(self._pkg_re);
# (3) Local variables #
grp = False;
grp_name = None;
# (2) Search for groups
#--------------------------------------------------------#
with open( "%s" % self._path, 'r' ) as f:
for l,line in enumerate(f):
# (1) If seeking for group #
if( grp == False ):
## {1} Check regex with the line ##
match = grpMatcher.search(line);
## {2} If don't match -> pass ##
if( match == None ):
continue;
## {3} Register group ##
grp = True;
grp_name = match.group('name');
self._grp.append( grp_name );
self._pkg[grp_name] = {};
# (2) If seeking for group's packages #
else:
## {1} Check regex with the line ##
match = pkgMatcher.search(line);
## {2} If don't match -> back to group seeking ##
if( match == None ):
grp = False;
continue;
## {3} Register package ##
pkg = Package(
name = match.group('name'),
sta = match.group('sta'),
pad = len(match.group('pad')),
deb = match.group('deb') != None,
ppa = match.group('ppa') if match.group('ppa') != None else None,
com = match.group('com') if match.group('com') != None else None
);
self._pkg[grp_name][match.group('name')] = pkg;
# (3) Return if a group exists
#
# @name<String> Group name
#
# @return exists<bool> Whether the group exists
#
#--------------------------------------------------------#
def hasGroup(self, name):
return name in self._grp;
# (4) Creates a group if it does not exist
#
# @name<String> Group name
#
# @return created<id> Created id
#
#--------------------------------------------------------#
def createGroup(self, name):
# (1) Error if already exists #
if( self.hasGroup(name) ):
return None;
# (2) Create group #
self._grp.append(name);
self._pkg[name] = [];
# (3) Return status #
for g,grp in enumerate(self._grp):
if( grp == name ):
return g;
return None;
# (5) Get a group's id
#
# @name<String> Group name
#
# @return id<int> Group id (None on error)
#
#--------------------------------------------------------#
def getGroup(self, name):
# (1) Error if doesn't exist #
if( not self.hasGroup(name) ):
return None;
# (2) Return id #
for g,grp in enumerate(self._grp):
if( grp == name ):
return g;
return None;
# (6) Check if the package exists
#
# @name<String> Package name
#
# @return exists<bool> Whether the package exists
#
#--------------------------------------------------------#
def hasPackage(self, name):
for grp in self._pkg:
for pkg in self._pkg[grp]:
if( pkg == name ):
return True;
return False;
# (7) Get a package by name
#
# @name<String> Package name
#
#--------------------------------------------------------#
def getPackage(self, name):
for grp in self._pkg:
for pkg in self._pkg[grp]:
if( pkg == name ):
return self._pkg[grp][pkg];
return None;
# (8) Adds a new package to a group
#
# @package<Package> Package object
# @group<String> Group name
#
# @return id<(int,int)> (id_group, id_pkg) of the created package (None on error)
#
#--------------------------------------------------------#
def addPackage(self, pkg, group="misc"):
# (1) Check pkg type #
if( not isinstance(pkg, Package) ):
return None;
# (2) Error if already exists #
if( self.hasPackage(pkg._name) ):
return None;
# (3) If missing group -> fail #
if( not self.hasGroup(group) ):
return None;
# (4) Create package #
self._pkg[group][ pkg.getName() ] = pkg;
# (4) Return status #
return True;
# (8) Move a package to another group
#
# @package<Package> Package name
# @group<String> Group name
#
# @return moved<bool> Whether it have been moved
#
#--------------------------------------------------------#
def mvPackage(self, pkg_name, group="misc"):
# (1) Error if not exists #
if( not self.hasPackage(pkg_name) ):
return False;
# (2) If missing group -> fail #
if( not self.hasGroup(group) ):
return False;
# (3) Get package #
pkgRef = self.getPackage(pkg_name);
# (4) Copy package to new group #
self._pkg[group][ pkg_name ] = pkgRef;
# (5) Remove package from old group #
for grp in self._pkg:
if( grp == group ):
continue;
for pkg in self._pkg[grp]:
if( pkg == pkg_name ):
del self._pkg[grp][pkg_name];
break;
# (4) Return status #
return True;
# (9) Save the current manifest
#
#--------------------------------------------------------#
def save(self):
with open( "%s" % self._path, 'w' ) as f:
for grp in self._pkg:
f.write("[-] %s\n" % grp );
for pkg in self._pkg[grp]:
f.write("%s\n" % self._pkg[grp][pkg].serialize());
f.write("\n");