Add "run" command and refactor grep

Add a run command for running shell commands in projects and refactor
grep to use the same base class.
This commit is contained in:
Doug Hellmann 2015-01-21 20:57:52 -05:00
parent afe9eafba5
commit 820caf5555
4 changed files with 81 additions and 19 deletions

View File

@ -6,26 +6,21 @@ import os
from aeromancer import project
from aeromancer import project_filter
from cliff.command import Command
from aeromancer.cli.run import ProjectShellCommandBase
class Grep(Command):
class Grep(ProjectShellCommandBase):
"""Search the contents of files"""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Grep, self).get_parser(prog_name)
project_filter.ProjectFilter.add_arguments(parser)
parser.add_argument('pattern',
action='store',
help='regular expression',
)
return parser
def take_action(self, parsed_args):
session = self.app.get_db_session()
pm = project.ProjectManager(session)
prj_filt = project_filter.ProjectFilter.from_parsed_args(parsed_args)
for l in pm.grep(parsed_args.pattern, prj_filt):
print(l)
def _get_command(self, parsed_args):
return ['git', 'grep', parsed_args.pattern]

68
aeromancer/cli/run.py Normal file
View File

@ -0,0 +1,68 @@
from __future__ import print_function
import logging
import os
import shlex
from aeromancer import project
from aeromancer import project_filter
from cliff.command import Command
class ProjectShellCommandBase(Command):
"""Run a command for each project"""
log = logging.getLogger(__name__)
DEFAULT_SEP = ''
def get_parser(self, prog_name):
parser = super(ProjectShellCommandBase, self).get_parser(prog_name)
project_filter.ProjectFilter.add_arguments(parser)
parser.add_argument(
'--sep',
action='store',
default=self.DEFAULT_SEP,
help=('separator between project name and command output, '
'defaults to %(default)r'),
)
return parser
def _show_text_output(self, parsed_args, project, out):
for line in out.decode('utf-8').splitlines():
print(project.name + parsed_args.sep + line)
def _get_command(self, parsed_args):
raise NotImplementedError()
def _show_output(self, parsed_args, proj_obj, out, err):
self._show_text_output(parsed_args, proj_obj, err or out)
def take_action(self, parsed_args):
session = self.app.get_db_session()
pm = project.ProjectManager(session)
prj_filt = project_filter.ProjectFilter.from_parsed_args(parsed_args)
command = self._get_command(parsed_args)
results = pm.run(command, prj_filt)
for proj_obj, out, err in results:
self._show_output(parsed_args, proj_obj, out, err)
class Run(ProjectShellCommandBase):
"""Run a command for each project"""
log = logging.getLogger(__name__)
DEFAULT_SEP = ':'
def get_parser(self, prog_name):
parser = super(Run, self).get_parser(prog_name)
parser.add_argument('command',
action='store',
help='the command to run, probably quoted',
)
return parser
def _get_command(self, parsed_args):
return shlex.shlex(parsed_args.command)

View File

@ -194,11 +194,11 @@ class ProjectManager(object):
self._remove_file_data(obj, reason='file no longer exists')
self.session.flush()
def grep(self, pattern, prj_filter):
"""Given a pattern, search for lines in files in all projects that match it.
def run(self, command, prj_filter):
"""Given a command, run it for all projects.
Returns results of the query, including the four columns line
number, line content, filename, and project name.
Returns sequence of tuples containing project objects, the
output, and the errors from the command.
"""
# TODO: Would it be more efficient to register the regexp
@ -212,13 +212,11 @@ class ProjectManager(object):
#return query.yield_per(20).all()
for project in query.all():
cmd = subprocess.Popen(
['git', 'grep', pattern],
command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=project.path,
env={'PAGER': ''},
env={'PAGER': ''}, # override pager for git commands
)
out, err = cmd.communicate()
if not out:
continue
for line in out.decode('utf-8').splitlines():
yield project.name + line
yield (project, out, err)

View File

@ -62,6 +62,7 @@ aeromancer.cli =
oslo list = aeromancer.oslo.cli:List
oslo uses = aeromancer.oslo.cli:Uses
grep = aeromancer.cli.grep:Grep
run = aeromancer.cli.run:Run
aeromancer.filehandler =
requirements = aeromancer.requirements.handler:RequirementsHandler