New JS command
authorFrederic Massart <fred@moodle.com>
Fri, 9 May 2014 09:36:09 +0000 (17:36 +0800)
committerFrederic Massart <fred@moodle.com>
Fri, 9 May 2014 09:37:51 +0000 (17:37 +0800)
config-dist.json
lib/commands/__init__.py
lib/commands/js.py [new file with mode: 0644]
lib/js.py [new file with mode: 0644]
lib/plugins.py

index 5211cc3..a9340a5 100644 (file)
     "recess": "/usr/local/bin/recess",
     // Path to lessc
     "lessc": "/usr/local/bin/lessc",
+    // Path to shifter
+    "shifter": "/usr/bin/shifter",
     // Path to your favourite editor. Set to null to guess it from the System environment.
     "editor": null,
 
index cccce6b..44176de 100644 (file)
@@ -41,6 +41,7 @@ commandsList = [
     'info',
     'init',
     'install',
+    'js',
     'phpunit',
     'plugin',
     'pull',
diff --git a/lib/commands/js.py b/lib/commands/js.py
new file mode 100644 (file)
index 0000000..c21f68c
--- /dev/null
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Moodle Development Kit
+
+Copyright (c) 2014 Frédéric Massart - FMCorz.net
+
+This program 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.
+
+This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+
+http://github.com/FMCorz/mdk
+"""
+
+import logging
+import os
+from lib.command import Command
+from lib import js, plugins
+
+
+class JsCommand(Command):
+
+    _arguments = [
+        (
+            ['mode'],
+            {
+                'metavar': 'mode',
+                'help': 'the type of action to perform',
+                'sub-commands':
+                    {
+                        'shift': (
+                            {
+                                'help': 'keen to use shifter?'
+                            },
+                            [
+                                (
+                                    ['-p', '--plugin'],
+                                    {
+                                        'action': 'store',
+                                        'dest': 'plugin',
+                                        'default': None,
+                                        'help': 'the name of the plugin or subsystem to target. If not passed, we do our best to guess from the current path.'
+                                    }
+                                ),
+                                (
+                                    ['-m', '--module'],
+                                    {
+                                        'action': 'store',
+                                        'dest': 'module',
+                                        'default': None,
+                                        'help': 'the name of the module in the plugin or subsystem. If omitted all the modules will be shifted, except we are in a module.'
+                                    }
+                                ),
+                                # (
+                                #     ['-w', '--watch'],
+                                #     {
+                                #         'action': 'store_true',
+                                #         'dest': 'watch',
+                                #         'help': 'watch for changes to re-shift'
+                                #     }
+                                # ),
+                                (
+                                    ['names'],
+                                    {
+                                        'default': None,
+                                        'help': 'name of the instances',
+                                        'metavar': 'names',
+                                        'nargs': '*'
+                                    }
+                                )
+                            ]
+                        )
+                    }
+            }
+        )
+    ]
+    _description = 'Wrapper for JS functions'
+
+    def run(self, args):
+        if args.mode == 'shift':
+            self.shift(args)
+
+
+    def shift(self, args):
+        """The shift mode"""
+
+        Mlist = self.Wp.resolveMultiple(args.names)
+        if len(Mlist) < 1:
+            raise Exception('No instances to work on. Exiting...')
+
+        cwd = os.path.realpath(os.path.abspath(os.getcwd()))
+        mpath = Mlist[0].get('path')
+        relpath = cwd.replace(mpath, '').strip('/')
+
+        if not args.plugin:
+            (subsystemOrPlugin, pluginName) = plugins.PluginManager.getSubsystemOrPluginFromPath(cwd, Mlist[0])
+            if subsystemOrPlugin:
+                args.plugin = subsystemOrPlugin + ('_' + pluginName) if pluginName else ''
+                logging.info("I guessed the plugin/subsystem to work on as '%s'" % (args.plugin))
+            else:
+                self.argumentError('The argument --plugin is required, I could not guess it.')
+
+        if not args.module:
+            candidate = relpath
+            module = None
+            while '/yui/src' in candidate:
+                (head, tail) = os.path.split(candidate)
+                if head.endswith('/yui/src'):
+                    module = tail
+                    break
+                candidate = head
+
+            if module:
+                args.module = module
+                logging.info("I guessed the JS module to work on as '%s'" % (args.module))
+
+
+        for M in Mlist:
+            if len(Mlist) > 1:
+                logging.info('Let\'s shift everything you wanted on \'%s\'' % (M.get('identifier')))
+
+            processor = js.Js(M)
+            processor.shift(subsystemOrPlugin=args.plugin, module=args.module)
diff --git a/lib/js.py b/lib/js.py
new file mode 100644 (file)
index 0000000..ba1b381
--- /dev/null
+++ b/lib/js.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Moodle Development Kit
+
+Copyright (c) 2014 Frédéric Massart - FMCorz.net
+
+This program 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.
+
+This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+
+http://github.com/FMCorz/mdk
+"""
+
+import logging
+import os
+from tools import process
+from config import Conf
+from plugins import PluginManager
+
+C = Conf()
+
+
+class Js(object):
+    """Class wrapping JS related functions"""
+
+    _M = None
+
+    def __init__(self, M):
+        self._M = M
+
+    def shift(self, subsystemOrPlugin=None, module=None):
+        """Runs shifter"""
+        path = self.getYUISrcPath(subsystemOrPlugin, module=module)
+        if not os.path.isdir(path):
+            raise ValueError("The directory '%s' was not found" % (path))
+
+        paths = []
+        if module:
+            paths.append(path)
+
+        else:
+            dirs = os.listdir(path)
+            for d in dirs:
+                if os.path.isdir(os.path.join(path, d, 'js')):
+                    paths.append(os.path.join(path, d))
+
+        shifter = Shifter(path)
+        for path in paths:
+            readablePath = path.replace(self._M.get('path'), '')
+            logging.info('Shifting in %s' % readablePath)
+            shifter.setCwd(path)
+            shifter.compile()
+
+    def getYUISrcPath(self, subsystemOrPlugin, module=None):
+        """Returns the path to the module, or the component"""
+
+        try:
+            path = PluginManager.getSubsystemDirectory(subsystemOrPlugin, M=self._M)
+        except ValueError:
+            (pluginType, name) = PluginManager.getTypeAndName(subsystemOrPlugin)
+            path = PluginManager.getTypeDirectory(pluginType, M=self._M)
+            # An exception will be thrown here if we do not find the plugin or component, that is fine.
+            path = os.path.join(path, name)
+
+        path = os.path.join(path, 'yui', 'src')
+        if module:
+            path = os.path.join(path, module)
+
+        return path
+
+
+class Shifter(object):
+
+    _cwd = None
+
+    def __init__(self, cwd=None):
+        self.setCwd(cwd)
+
+    def compile(self):
+        """Runs the shifter command in cwd"""
+        executable = C.get('shifter')
+        if not executable or not os.path.isfile(executable):
+            raise Exception('Could not find executable path %s' % (executable))
+
+        cmd = [executable]
+        (code, out, err) = process(cmd, cwd=self._cwd)
+        if code != 0:
+            raise ShifterCompileFailed('Error during shifting at %s' % (self._cwd))
+
+    def setCwd(self, cwd):
+        self._cwd = cwd
+
+
+class ShifterCompileFailed(Exception):
+    pass
index 11eee83..77e1acc 100644 (file)
@@ -195,6 +195,7 @@ class PluginManager(object):
         """
 
         subtypes = {}
+        path = os.path.realpath(os.path.abspath(path))
         if M:
             path = '/' + path.replace(M.get('path'), '').strip('/')
             admindir = M.get('admin', 'admin')