create ProjectManager class to avoid reloading plugins
This commit is contained in:
parent
ef76f4b15c
commit
053acaab52
|
@ -27,9 +27,10 @@ class Add(Command):
|
|||
|
||||
def take_action(self, parsed_args):
|
||||
session = self.app.get_db_session()
|
||||
pm = project.ProjectManager(session)
|
||||
for project_name in parsed_args.project:
|
||||
project_path = os.path.join(self.app.options.repo_root, project_name)
|
||||
proj_obj = project.add_or_update(session, project_name, project_path)
|
||||
pm.add_or_update(project_name, project_path)
|
||||
session.commit()
|
||||
|
||||
|
||||
|
@ -65,10 +66,11 @@ class Discover(Command):
|
|||
|
||||
def take_action(self, parsed_args):
|
||||
session = self.app.get_db_session()
|
||||
pm = project.ProjectManager(session)
|
||||
for project_name in project.discover(self.app.options.repo_root):
|
||||
full_path = os.path.join(self.app.options.repo_root,
|
||||
project_name)
|
||||
project.add_or_update(session, project_name, full_path)
|
||||
pm.add_or_update(project_name, full_path)
|
||||
session.commit()
|
||||
|
||||
|
||||
|
@ -90,6 +92,7 @@ class Remove(Command):
|
|||
|
||||
def take_action(self, parsed_args):
|
||||
session = self.app.get_db_session()
|
||||
pm = project.ProjectManager(session)
|
||||
for project_name in parsed_args.project:
|
||||
project.remove(session, project_name)
|
||||
session.commit()
|
||||
pm.remove(project_name)
|
||||
session.commit()
|
||||
|
|
|
@ -16,48 +16,16 @@ from aeromancer import utils
|
|||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _delete_filehandler_data_from_project(session, proj_obj):
|
||||
# We have to explicitly have the handlers delete their data
|
||||
# because the parent-child relationship of the tables is reversed
|
||||
# because the plugins define the relationships.
|
||||
file_handlers = filehandler.load_handlers()
|
||||
LOG.debug('deleting plugin data for %s', proj_obj.name)
|
||||
for file_obj in proj_obj.files:
|
||||
for fh in file_handlers:
|
||||
if fh.obj.supports_file(file_obj):
|
||||
fh.obj.delete_data_for_file(session, file_obj)
|
||||
|
||||
|
||||
def add_or_update(session, name, path):
|
||||
"""Create a new project definition or update an existing one"""
|
||||
query = session.query(Project).filter(Project.name == name)
|
||||
try:
|
||||
proj_obj = query.one()
|
||||
proj_obj.path = path
|
||||
LOG.info('updating project %s from %s', name, path)
|
||||
except NoResultFound:
|
||||
proj_obj = Project(name=name, path=path)
|
||||
LOG.info('adding project %s from %s', name, path)
|
||||
session.add(proj_obj)
|
||||
update(session, proj_obj)
|
||||
return proj_obj
|
||||
|
||||
|
||||
def remove(session, name):
|
||||
"""Delete stored data for the named project"""
|
||||
query = session.query(Project).filter(Project.name == name)
|
||||
try:
|
||||
proj_obj = query.one()
|
||||
LOG.info('removing project %s', name)
|
||||
except NoResultFound:
|
||||
return
|
||||
_delete_filehandler_data_from_project(session, proj_obj)
|
||||
session.delete(proj_obj)
|
||||
|
||||
|
||||
def update(session, proj_obj):
|
||||
_update_project_files(session, proj_obj)
|
||||
|
||||
def discover(repo_root):
|
||||
"""Discover project-like directories under the repository root"""
|
||||
with utils.working_dir(repo_root):
|
||||
return itertools.ifilter(
|
||||
lambda x: os.path.isdir(os.path.join(repo_root, x)),
|
||||
itertools.chain(
|
||||
glob.glob('openstack*/*'),
|
||||
glob.glob('stackforge/*'),
|
||||
)
|
||||
)
|
||||
|
||||
def _find_files_in_project(path):
|
||||
"""Return a list of the files managed in the project.
|
||||
|
@ -71,88 +39,104 @@ def _find_files_in_project(path):
|
|||
return output.split('\0')
|
||||
|
||||
|
||||
_DO_NOT_READ = [
|
||||
'*.doc',
|
||||
'*.docx',
|
||||
'*.graffle',
|
||||
'*.odp',
|
||||
'*.pptx',
|
||||
'*.vsd',
|
||||
class ProjectManager(object):
|
||||
|
||||
'*.gif',
|
||||
'*.ico',
|
||||
'*.jpeg',
|
||||
'*.jpg',
|
||||
'*.png',
|
||||
'*.ttf',
|
||||
_DO_NOT_READ = [
|
||||
'*.doc', '*.docx', '*.graffle', '*.odp', '*.pptx', '*.vsd',
|
||||
'*.gif', '*.ico', '*.jpeg', '*.jpg', '*.png', '*.ttf',
|
||||
'*.gpg',
|
||||
'*.jar', # Why do we check in jar files?!
|
||||
'*.swf', '*.eot',
|
||||
'*.woff', # webfont; horizon
|
||||
'*.xml',
|
||||
'*.gz', '*.zip', '*.z',
|
||||
]
|
||||
|
||||
'*.gpg',
|
||||
def __init__(self, session):
|
||||
self.file_handlers = filehandler.load_handlers()
|
||||
self.session = session
|
||||
|
||||
'*.jar', # Why do we check in jar files?!
|
||||
def _delete_filehandler_data_from_project(self, proj_obj):
|
||||
# We have to explicitly have the handlers delete their data
|
||||
# because the parent-child relationship of the tables is reversed
|
||||
# because the plugins define the relationships.
|
||||
LOG.debug('deleting plugin data for %s', proj_obj.name)
|
||||
for file_obj in proj_obj.files:
|
||||
for fh in self.file_handlers:
|
||||
if fh.obj.supports_file(file_obj):
|
||||
fh.obj.delete_data_for_file(self.session, file_obj)
|
||||
|
||||
'*.swf',
|
||||
'*.eot',
|
||||
'*.woff', # webfont; horizon
|
||||
def get_project(self, name):
|
||||
"""Return an existing project, if there is one"""
|
||||
query = self.session.query(Project).filter(Project.name == name)
|
||||
try:
|
||||
return query.one()
|
||||
except NoResultFound:
|
||||
return None
|
||||
|
||||
'*.xml',
|
||||
|
||||
'*.gz',
|
||||
'*.zip',
|
||||
'*.z',
|
||||
]
|
||||
|
||||
|
||||
def _update_project_files(session, proj_obj):
|
||||
"""Update the files stored for each project"""
|
||||
LOG.debug('reading file contents in %s', proj_obj.name)
|
||||
# Delete any existing files in case the list of files being
|
||||
# managed has changed. This naive, and we can do better, but as a
|
||||
# first version it's OK.
|
||||
_delete_filehandler_data_from_project(session, proj_obj)
|
||||
for file_obj in proj_obj.files:
|
||||
session.delete(file_obj)
|
||||
|
||||
file_handlers = filehandler.load_handlers()
|
||||
|
||||
# FIXME(dhellmann): Concurrency?
|
||||
|
||||
# Now load the files currently being managed by git.
|
||||
for filename in _find_files_in_project(proj_obj.path):
|
||||
fullname = os.path.join(proj_obj.path, filename)
|
||||
if not os.path.isfile(fullname):
|
||||
continue
|
||||
new_file = File(project=proj_obj, name=filename, path=fullname)
|
||||
session.add(new_file)
|
||||
if any(fnmatch.fnmatch(filename, dnr) for dnr in _DO_NOT_READ):
|
||||
LOG.debug('ignoring contents of %s', fullname)
|
||||
def add_or_update(self, name, path):
|
||||
"""Create a new project definition or update an existing one"""
|
||||
proj_obj = self.get_project(name)
|
||||
if proj_obj:
|
||||
proj_obj.path = path
|
||||
LOG.info('updating project %s from %s', name, path)
|
||||
else:
|
||||
with io.open(fullname, mode='r', encoding='utf-8') as f:
|
||||
try:
|
||||
body = f.read()
|
||||
except UnicodeDecodeError:
|
||||
# FIXME(dhellmann): Be smarter about trying other
|
||||
# encodings?
|
||||
LOG.warn('Could not read %s as a UTF-8 encoded file, ignoring',
|
||||
fullname)
|
||||
continue
|
||||
lines = body.splitlines()
|
||||
LOG.debug('%s/%s has %s lines', proj_obj.name, filename, len(lines))
|
||||
for num, content in enumerate(lines, 1):
|
||||
session.add(Line(file=new_file, number=num, content=content))
|
||||
proj_obj = Project(name=name, path=path)
|
||||
LOG.info('adding project %s from %s', name, path)
|
||||
self.session.add(proj_obj)
|
||||
self.update(proj_obj)
|
||||
return proj_obj
|
||||
|
||||
# Invoke plugins for processing files in special ways
|
||||
for fh in file_handlers:
|
||||
if fh.obj.supports_file(new_file):
|
||||
fh.obj.process_file(session, new_file)
|
||||
def update(self, proj_obj):
|
||||
"""Update the settings for an existing project"""
|
||||
self._update_project_files(proj_obj)
|
||||
|
||||
def remove(self, name):
|
||||
"""Delete stored data for the named project"""
|
||||
query = self.session.query(Project).filter(Project.name == name)
|
||||
try:
|
||||
proj_obj = query.one()
|
||||
LOG.info('removing project %s', name)
|
||||
except NoResultFound:
|
||||
return
|
||||
self._delete_filehandler_data_from_project(proj_obj)
|
||||
self.session.delete(proj_obj)
|
||||
|
||||
def discover(repo_root):
|
||||
"""Discover project-like directories under the repository root"""
|
||||
with utils.working_dir(repo_root):
|
||||
return itertools.ifilter(
|
||||
lambda x: os.path.isdir(os.path.join(repo_root, x)),
|
||||
itertools.chain(
|
||||
glob.glob('openstack*/*'),
|
||||
glob.glob('stackforge/*'),
|
||||
)
|
||||
)
|
||||
def _update_project_files(self, proj_obj):
|
||||
"""Update the files stored for each project"""
|
||||
LOG.debug('reading file contents in %s', proj_obj.name)
|
||||
# Delete any existing files in case the list of files being
|
||||
# managed has changed. This naive, and we can do better, but as a
|
||||
# first version it's OK.
|
||||
self._delete_filehandler_data_from_project(proj_obj)
|
||||
for file_obj in proj_obj.files:
|
||||
self.session.delete(file_obj)
|
||||
|
||||
# Now load the files currently being managed by git.
|
||||
for filename in _find_files_in_project(proj_obj.path):
|
||||
fullname = os.path.join(proj_obj.path, filename)
|
||||
if not os.path.isfile(fullname):
|
||||
continue
|
||||
new_file = File(project=proj_obj, name=filename, path=fullname)
|
||||
self.session.add(new_file)
|
||||
if any(fnmatch.fnmatch(filename, dnr) for dnr in self._DO_NOT_READ):
|
||||
LOG.debug('ignoring contents of %s', fullname)
|
||||
else:
|
||||
with io.open(fullname, mode='r', encoding='utf-8') as f:
|
||||
try:
|
||||
body = f.read()
|
||||
except UnicodeDecodeError:
|
||||
# FIXME(dhellmann): Be smarter about trying other
|
||||
# encodings?
|
||||
LOG.warn('Could not read %s as a UTF-8 encoded file, ignoring',
|
||||
fullname)
|
||||
continue
|
||||
lines = body.splitlines()
|
||||
LOG.debug('%s/%s has %s lines', proj_obj.name, filename, len(lines))
|
||||
for num, content in enumerate(lines, 1):
|
||||
self.session.add(Line(file=new_file, number=num, content=content))
|
||||
|
||||
# Invoke plugins for processing files in special ways
|
||||
for fh in self.file_handlers:
|
||||
if fh.obj.supports_file(new_file):
|
||||
fh.obj.process_file(self.session, new_file)
|
||||
|
|
Loading…
Reference in New Issue