2
# -*- coding: utf-8 -*-
3
# Copyright 2009 Canonical Ltd.
4
# Author 2009 Didier Roche
6
# This file is part of Quickly
8
#This program is free software: you can redistribute it and/or modify it
9
#under the terms of the GNU General Public License version 3, as published
10
#by the Free Software Foundation.
12
#This program is distributed in the hope that it will be useful, but
13
#WITHOUT ANY WARRANTY; without even the implied warranties of
14
#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15
#PURPOSE. See the GNU General Public License for more details.
17
#You should have received a copy of the GNU General Public License along
18
#with this program. If not, see <http://www.gnu.org/licenses/>.
25
from gettext import gettext as _
27
# add quickly root directory (especially for trunk execution)
28
pathname = os.path.dirname(sys.argv[0])
29
quickly_root_directory = pathname + '/..'
30
quickly_root_directory = os.path.abspath(quickly_root_directory)
31
if os.path.exists(quickly_root_directory + '/quickly') and quickly_root_directory not in sys.path:
32
sys.path.insert(0, quickly_root_directory)
33
os.putenv('PYTHONPATH', quickly_root_directory) # for subprocesses
36
from quickly import commands, configurationhandler, tools, quicklyconfig
38
command_followed_by_template = ('create', 'quickly')
42
quickly [OPTIONS] command ...
45
-t, --template <template> Template to use if it differs from default
47
one used to create the project)
48
--staging Target launchpad staging server
49
--verbose Verbose mode
50
-h, --help Show help information
53
create <template> <project-name> (template is mandatory for this command)
54
quickly <template_origin> <template_dest> to create a create derived template
55
getstarted to get some starting hints
58
quickly create ubuntu-project foobar
59
quickly push 'awesome new comment system'
60
quickly -t cool-template push 'awesome new comment system'""")
63
""" print version information """
67
Python interpreter: %s %s
68
Python standard library: /usr/lib/python2.6
70
Quickly used library: %s
72
Quickly detected template directories:
75
Copyright 2009 Canonical Ltd.
76
#Author 2009 Rick Spencer
77
#Author 2009 Didier Roche
78
https://launchpad.net/quickly
80
quickly comes with ABSOLUTELY NO WARRANTY. quickly is free software, and
81
you may use, modify and redistribute it under the terms of the GNU
82
General Public License version 3 or later.""") % (
83
quicklyconfig.__version__, sys.executable, ".".join([str(x) for x in sys.version_info[0:3]]),
84
os.path.dirname(quickly.__file__), tools.get_quickly_data_path(),
85
"\n ".join(tools.get_template_directories()))
89
"""seek for available commands for shell completion
91
: return tuples with list of available commands and origin (default or template)
94
available_completion = []
97
if sys.argv[-1].startswith("-"):
98
options = ("-h", "--help", "-t", "--template", "--staging", "--verbose", "--version")
99
available_completion = [option for option in options if option.startswith(sys.argv[-1])]
102
(opt_command, need_template, opt_has_template, opt_template,
103
out_off_project_tree_command) = process_command_line(sys.argv[3:])
105
# seek for template if exists
108
project_dir = tools.get_root_project_path()
109
configurationhandler.loadConfig()
110
opt_template = configurationhandler.project_config['template']
111
except tools.project_path_not_found:
114
# get available templates
115
if sys.argv[-2] in ("-t", "--template"):
116
for template_dir in tools.get_template_directories():
117
for template in os.listdir(template_dir):
118
available_completion.append(os.path.basename(template))
120
elif len(opt_command) > 1:
121
# if no template, check the create command for templates proposal or -t completion
122
# (-1 is space or template begining)
123
if (opt_command[len(opt_command) - 2] in command_followed_by_template and not opt_template):
124
for template_dir in tools.get_template_directories():
125
for template in os.listdir(template_dir):
126
available_completion.append(os.path.basename(template))
128
# get the template path if exists
130
template_path = tools.get_template_directory(opt_template)
132
for fullname in os.listdir(template_path):
133
files.append(os.path.basename(fullname))
135
for found_file in files:
136
command = re.search('(.*)\.py$', found_file)
138
available_completion.append(command.group(1))
141
not_real_commands = ['quicklyconfig', 'configurationhandler', 'gettext', 'os', 'shutil', 'tools']
142
commands_in_module = [ command for command in dir(commands) if not command.startswith('_') and not command.startswith('pre_') \
143
and not command.startswith('post_') and not command in not_real_commands]
144
commands_in_module.append('create')
145
available_completion.extend(commands_in_module)
147
print " ".join(available_completion)
151
def check_this_command(command_name, template_path, opt_template):
152
"""check if the command exist in a template
154
For instance, for a command like foo, the inside template foo.py script
155
file is preferred to built-in foo() function.
156
There can be pre_foo() and post_foo() built-in functions.
161
return list of commands ready to be launched
164
commands_available = {}
166
# check for template command
167
command_path = template_path + "/" + command_name + ".py"
168
if os.path.exists(command_path):
169
commands_available[opt_template] = command_path
171
#check for built-in command
172
if hasattr(commands, command_name):
173
commands_available[opt_template] = getattr(commands, command_name)
175
print _("ERROR: command '%s' in '%s' not found.") % (command_name, opt_template)
179
#check for pre-post built-in commands
180
for hook in ("pre", "post"):
181
if hasattr(commands, hook + '_' + command_name):
182
commands_available[hook] = getattr(commands, hook + '_' + command_name)
184
return commands_available
187
def process_command_line(argv):
188
"""Entry point for command line processing
189
use sys.argv by default if no args to parse
196
out_off_project_tree_command = False
197
opt_has_template = False
208
if arg == '--template' or arg == '-t':
209
opt_has_template = True
210
opt_template = argv[i + 1]
212
elif arg == '--staging':
214
if os.environ.has_key('QUICKLY'):
215
oldenv = os.environ['QUICKLY']
216
os.environ['QUICKLY'] = "staging " + oldenv
217
elif arg == '--verbose':
219
if os.environ.has_key('QUICKLY'):
220
oldenv = os.environ['QUICKLY']
221
os.environ['QUICKLY'] = "verbose " + oldenv
222
elif arg == '--version':
224
elif arg == '--help' or arg == '-h':
227
if arg in command_followed_by_template: # need template (default) and out of tree command
228
out_off_project_tree_command = True
229
elif arg == 'getstarted':
230
out_off_project_tree_command = True
231
need_template = False
232
opt_command.append(arg)
235
return (opt_command, need_template, opt_has_template, opt_template, out_off_project_tree_command)
238
"""Main ubuntu command line processor
240
:return: exit code of quickly command.
243
(opt_command, need_template, opt_has_template, opt_template, out_off_project_tree_command) = process_command_line(sys.argv[1:])
245
# ensure the command exists
247
print _("ERROR: No command found")
252
# create command can't be launched in an existing project (don't create mess for the user)
253
if 'create' in opt_command:
255
project_path = tools.get_root_project_path()
256
except tools.project_path_not_found:
258
else: # no error, so we are in a project path, not good!
259
print _("ERROR: %s is already a project. You can't create a project within another project. " \
260
"Please choose another path." % project_path)
263
# get the template if needed
265
# if processing a "out_off_project_tree_command", template argument
266
# and project name must be there (with -t, --template or just following the command): create, quickly
267
if out_off_project_tree_command:
268
if not opt_has_template:
269
if len(opt_command) < 3 or opt_command[1].startswith('-'):
270
print _("ERROR: %s command must be followed by a template and destination name" % opt_command[0])
275
opt_template = opt_command[1]
276
opt_command.remove(opt_command[1])
277
opt_has_template = True
279
#in every cases, the project name is now in first position.
280
project_name = opt_command[1]
281
project_dir = os.path.abspath(os.getcwd() + '/' + project_name)
284
# the config file already exist, get project path and load configuration.
287
project_dir = tools.get_root_project_path()
288
except tools.project_path_not_found:
289
print _("ERROR: Can't find project in %s.\nEnsure you launch this command from a quickly project directory.") % os.getcwd()
291
configurationhandler.loadConfig()
293
#if no template provided, guess it from the current tree
294
if not opt_has_template and need_template:
296
opt_template = configurationhandler.project_config['template']
298
print _("ERROR: No template provided and none found in the current tree. Ensure you " \
299
"don't want to create a new project or that your are in your directory project.")
303
# get the template path
304
template_path = tools.get_template_directory(opt_template)
306
# no template needed, empty them
313
# execute the command
314
commands_to_execute = check_this_command(opt_command[0], template_path, opt_template)
317
if 'pre' in commands_to_execute:
318
return_code = commands_to_execute['pre'](opt_template, project_dir, opt_command[1:])
320
print _("ERROR: pre_%s command failed") % opt_command[0]
325
if callable(commands_to_execute[opt_template]):
326
return_code = commands_to_execute[opt_template](opt_template, project_dir, opt_command[1:])
328
return_code = subprocess.call(["python", commands_to_execute[opt_template]] + opt_command[1:], cwd=project_dir)
331
print _("ERROR: %s command failed") % opt_command[0]
336
if 'post' in commands_to_execute:
337
commands_to_execute['post'](opt_template, project_dir, opt_command[1:])
339
print _("ERROR: post_%s command failed") % opt_command[0]
345
if __name__ == '__main__':
347
gettext.textdomain('quickly')
349
# process the command line to send the right instructions
350
if 'shell-completion' in sys.argv: