result = self.execute(cmd)
return result[0] == 0
+ def apply(self, files):
+ if type(files) == list:
+ files = ' '.join(files)
+ cmd = 'apply --check %s' % (files)
+ result = self.execute(cmd)
+ if result[0] != 0:
+ return False
+ cmd = 'am %s' % (files)
+ result = self.execute(cmd)
+ return result[0] != 0
+
def checkout(self, branch):
if self.currentBranch == branch:
return True
import json
from tools import debug, question
from config import Conf
-from urllib import urlencode
+from urllib import urlencode, urlretrieve
from urlparse import urlparse
from base64 import b64encode
+from datetime import datetime
+import os
import httplib
import getpass
try:
self.version = {}
self._load()
+ def download(self, url, dest):
+ """Download a URL to the destination while authenticating the user"""
+ headers = {}
+ headers['Authorization'] = 'Basic %s' % (b64encode('%s:%s' % (self.username, self.password)))
+
+ if self.ssl:
+ r = httplib.HTTPSConnection(self.host)
+ else:
+ r = httplib.HTTPConnection(self.host)
+ r.request('GET', url, None, headers)
+
+ resp = r.getresponse()
+ if resp.status == 403:
+ raise JiraException('403 Request not authorized. %s %s' % ('GET', url))
+
+ data = resp.read()
+ if len(data) > 0:
+ f = open(dest, 'w')
+ f.write(data)
+ f.close()
+
+ return os.path.isfile(dest)
+
def get(self, param, default=None):
"""Returns a property of this instance"""
return self.info().get(param, default)
- def getIssue(self, key, fields='*all'):
+ def getIssue(self, key, fields='*all,-comment'):
"""Load the issue info from the jira server using a rest api call.
The returned key 'named' of the returned dict is organised by name of the fields, not id.
# Do not die if keyring package is not available.
pass
-
return True
def reload(self):
return {'status': resp.status, 'data': data}
+ @staticmethod
+ def parseDate(value):
+ """Parse a date returned by Jira API"""
+ return datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.000+0000')
+
def setCustomFields(self, key, updates):
"""Set a list of fields for this issue in Jira
import sys
import argparse
import re
+import os
+from datetime import datetime
from lib import workplace, tools, jira
-from lib.tools import debug
+from lib.tools import debug, question
from lib.config import Conf
Wp = workplace.Workplace()
debug('Retrieving information about %s from Moodle Tracker' % (mdl))
J = jira.Jira()
issueInfo = J.getIssue(mdl)
+
+mode = 'pull'
remoteUrl = issueInfo.get('named').get(C.get('tracker.fieldnames.repositoryurl'))
remoteBranch = issueInfo.get('named').get(C.get('tracker.fieldnames.%s.branch' % (branch)))
-if not remoteUrl or not remoteBranch:
- debug('Not enough information to pull the branch')
+patchesToApply = []
+
+if True or not remoteUrl or not remoteBranch:
+ attachments = issueInfo.get('fields').get('attachment')
+ patches = {}
+ for attachment in attachments:
+ if attachment['filename'].endswith('.patch'):
+ patches[attachment['filename']] = attachment
+
+ if len(patches) > 0:
+ mapping = {}
+ i = 1
+ for key in sorted(patches.keys()):
+ patch = patches[key]
+ mapping[i] = patch
+ date = jira.Jira.parseDate(patch['created'])
+ print '{0:<2}: {1:<60} {2}'.format(i, patch['filename'][:60], datetime.strftime(date, '%Y-%m-%d %H:%M'))
+ i += 1
+
+ ids = question('What patches would you like to apply?')
+ if ids:
+ ids = re.split(r'\s*[, ]\s*', ids)
+ for i in ids:
+ i = int(i)
+ if not i in mapping.keys():
+ continue
+ j = 0
+ while True:
+ mapping[i]['mdk-filename'] = mapping[i]['filename'] + (('.' + str(j)) if j > 0 else '')
+ j += 1
+ if not os.path.isfile(mapping[i]['mdk-filename']):
+ break
+ patchesToApply.append(mapping[i])
+ mode = 'patch'
+ else:
+ mode = False
+
+if not mode:
+ debug('Did not find enough information to pull a patch.')
+ sys.exit()
# Stash
stash = M.git().stash(untracked=True)
debug('Could not checkout branch %s' % (M.get('stablebranch')))
debug('Checked out branch %s' % (M.get('stablebranch')))
-# Pull branch from tracker
-debug('Pulling branch %s from %s into %s' % (remoteBranch, remoteUrl, M.currentBranch()))
-M.git().pull(remote=remoteUrl, ref=remoteBranch)
+if mode == 'pull':
+ # Pull branch from tracker
+ debug('Pulling branch %s from %s into %s' % (remoteBranch, remoteUrl, M.currentBranch()))
+ M.git().pull(remote=remoteUrl, ref=remoteBranch)
+elif mode == 'patch':
+ # Apply a patch from tracker
+ files = []
+ for patch in patchesToApply:
+ dest = patch['mdk-filename']
+ debug('Downloading %s' % (patch['filename']))
+ if not J.download(patch['content'], dest):
+ debug('Failed to download. Aborting...')
+ files = []
+ break
+ files.append(dest)
+
+ if len(files) > 0:
+ debug('Applying patch(es)...')
+ if not M.git().apply(files):
+ debug('Could not apply the patch(es), please apply manually')
+ else:
+ for f in files:
+ os.remove(f)
# Stash pop
if not stash[1].startswith('No local changes'):