Moodle update command
authorFrederic Massart <fred@moodle.com>
Wed, 8 Aug 2012 07:07:23 +0000 (15:07 +0800)
committerFrederic Massart <fred@moodle.com>
Wed, 8 Aug 2012 07:07:23 +0000 (15:07 +0800)
lib/git.py
lib/moodle.py
lib/workplace.py
moodle-update.py [new file with mode: 0755]
moodle-upgrade.py

index e10d90a..99ce9d6 100644 (file)
@@ -117,11 +117,33 @@ class Git(object):
                cmd = 'rebase %s%s' % (onto, branch)
                return self.execute(cmd)
 
+       def remoteBranches(self, remote):
+               pattern = 'refs/remotes/%s' % remote
+               cmd = 'show-ref'
+
+               result = self.execute(cmd)
+               if result[0] != 0:
+                       return []
+
+               refs = []
+               for ref in result[1].split('\n'):
+                       try:
+                               (hash, ref) = ref.split(' ', 1)
+                       except ValueError:
+                               continue
+                       if not ref.startswith(pattern):
+                               continue
+                       ref = ref.replace(pattern, '').strip('/')
+                       if ref == 'HEAD':
+                               continue
+                       refs.append([hash, ref])
+               return refs
+
        def reset(self, to, hard = False):
                mode = ''
                if hard:
-                       mode == '--hard'
-               cmd = 'reset --hard %s' % (to)
+                       mode = '--hard'
+               cmd = 'reset %s %s' % (mode, to)
                result = self.execute(cmd)
                return result[0] == 0
 
@@ -145,4 +167,3 @@ class Git(object):
 
        def setPath(self, path):
                self._path = str(path)
-
index 45ee062..4063ed6 100644 (file)
@@ -305,9 +305,44 @@ class Moodle(object):
         self._loaded = False
         return self._load()
 
-    def update(self):
+    def update(self, remote = 'origin'):
         """Update the instance from the remote"""
-        pass
+
+        originalbranch = self.currentBranch()
+        stablebranch = self.get('stablebranch')
+
+        # Fetch
+        if not self.git().fetch(remote):
+            raise Exception('Could not fetch remote %s' % remote)
+
+        # Stash
+        hasStash = True
+        stash = self.git().stash(untracked=True)
+        if stash[0] != 0:
+            raise Exception('Error while stashing your changes')
+        if stash[1].startswith('No local changes'):
+            hasStash = False
+
+        # Checkout STABLE
+        if not self.git().checkout(stablebranch):
+            raise Exception('Could not checkout %s' % stablebranch)
+
+        # Reset HARD
+        upstream = '%s/%s' % (remote, stablebranch)
+        if not self.git().reset(to = upstream, hard = True):
+            raise Exception('Error while executing git reset')
+
+        # Unstash
+        if hasStash:
+            pop = self.git().stash('pop')
+            if pop[0] != 0:
+                raise Exception('Error while popping the stash. Probably got conflicts.')
+
+        # Checkout original branch
+        if not self.git().checkout(originalbranch):
+            raise Exception('Could not checkout working branch %s' % originalbranch)
+
+        return True
 
     def upgrade(self):
         """Calls the upgrade script"""
index cc76f6b..2dceb6b 100644 (file)
@@ -7,6 +7,7 @@ import shutil
 from tools import debug, process
 import config
 import db
+import git
 import moodle
 
 C = config.Conf().get
@@ -255,6 +256,41 @@ class Workplace(object):
                 debug('Could not find instance called %s' % name)
         return result
 
-    def updateCachedClones(self, integration = True, stable = True):
+    def updateCachedClones(self, integration = True, stable = True, verbose = True):
         """Update the cached clone of the repositories"""
-        pass
+
+        caches = []
+        remote = 'origin'
+
+        if integration:
+            caches.append(os.path.join(self.cache, 'integration.git'))
+        if stable:
+            caches.append(os.path.join(self.cache, 'moodle.git'))
+
+        for cache in caches:
+            if not os.path.isdir(cache):
+                continue
+
+            repo = git.Git(cache, C('git'))
+
+            verbose and debug('Working on %s...' % cache)
+            verbose and debug('Fetching %s' % remote)
+            if not repo.fetch(remote):
+                raise Exception('Could not fetch %s in repository %s' % (remote, cache))
+
+            remotebranches = repo.remoteBranches(remote)
+            for hash, branch in remotebranches:
+                verbose and debug('Updating branch %s' % branch)
+                track = '%s/%s' % (remote, branch)
+                if not repo.hasBranch(branch) and not repo.createBranch(branch, track = track):
+                    raise Exception('Could not create branch %s tracking %s in repository %s' % (branch, track, cache))
+
+                if not repo.checkout(branch):
+                    raise exception('error while checking out branch %s in repository %s' % (branch, cache))
+
+                if not repo.reset(to = track, hard = True):
+                    raise Exception('Could not hard reset to %s in repository %s' % (branch, cache))
+
+            verbose and debug('')
+
+        return True
diff --git a/moodle-update.py b/moodle-update.py
new file mode 100755 (executable)
index 0000000..144dff7
--- /dev/null
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+import argparse
+from lib import config, workplace, moodle, tools
+from lib.tools import debug
+
+C = config.Conf().get
+Wp = workplace.Workplace()
+
+# Arguments
+parser = argparse.ArgumentParser(description='Updates the instance from remote')
+parser.add_argument('-a', '--all', action='store_true', help='runs the script on every instances', dest='all')
+parser.add_argument('-i', '--integration', action='store_true', help='runs the script on the integration instances', dest='integration')
+parser.add_argument('-s', '--stable', action='store_true', help='runs the script on the stable instances', dest='stable')
+parser.add_argument('-u', '--upgrade', action='store_true', help='upgrade the instance after successful update', dest='upgrade')
+parser.add_argument('-c', '--update-cache', action='store_true', help='only update the cached remotes. Useful when using cache as remote.', dest='updatecache')
+parser.add_argument('names', metavar='names', default=None, nargs='*', help='name of the instances')
+args = parser.parse_args()
+
+# Updating cache only
+if args.updatecache:
+       debug('Updating cached remote')
+       Wp.updateCachedClones()
+       debug('Done.')
+       sys.exit(0)
+
+# Updating instances
+names = args.names
+if args.all:
+       names = Wp.list()
+elif args.integration or args.stable:
+       names = Wp.list(integration = args.integration, stable = args.stable)
+
+Mlist = Wp.resolveMultiple(names)
+if len(Mlist) < 1:
+    debug('No instances to work on. Exiting...')
+    sys.exit(1)
+
+for M in Mlist:
+       debug('Updating %s...' % M.get('identifier'))
+       try:
+               M.update()
+               if args.upgrade:
+                       M.upgrade()
+       except Exception as e:
+               debug('Error during the update of %s' % M.get('identifier'))
+               debug(e)
+       else:
+               debug('')
+
+debug('Done.')
index 8f7ae66..6ec19ef 100755 (executable)
@@ -32,7 +32,12 @@ if len(Mlist) < 1:
 for M in Mlist:
        if args.update:
                debug('Updating %s...' % M.get('identifier'))
-               M.update()
+               try:
+                       M.update()
+               except Exception as e:
+                       debug('Error during update. Skipping...')
+                       debug(e)
+                       continue
        debug('Upgrading %s...' % M.get('identifier'))
        if M.upgrade():
                debug('Error during the upgrade of %s' % M.get('identifier'))