ld and ref build has the same base, partial diff cannot be done
# v1.12
# - add project feature
# v1.13
# - change project feature
import time
import re
import requests
#from xml.etree.ElementTree import ElementTree as ETR
import xml.etree.ElementTree as ETR
from xml.etree.ElementTree import Element as ET
from xml.etree.ElementTree import parse
import csv
VERSIONINFO = 'Release Mate v1.13'
BUILD_XML = 'build_data.xml'
BUILDINFOXML = 'buildinfo.xml'
QB_URL = 'https://android.qb.sec.samsung.net/rest/'
QB_TOKENRQ = 'https://android.qb.sec.samsung.net/signin?1-1.IFormSubmitListener-form'
QB_CONFPATH = 'ids?configuration_path='
QB_BUILDRQ = 'build_requests'
QB_BUILDS = 'builds/'
CSVENCODING = 'euc-kr'
INDEXCOL = 1
class QB:
def __init__(self):
self.__qb_cookies = dict()
def qblogin(self, user, password, reflash=False):
if len(self.__qb_cookies) != 0:
return self.session, self.__qb_cookies
token_url = QB_TOKENRQ
token_data = {'userName': user, 'password': password}
self.session = requests.session()
self.session.post(token_url, token_data)
self.__qb_cookies = requests.utils.dict_from_cookiejar(self.session.cookies)
if len(self.__qb_cookies) < 3:
print('### WARNING ### Quickbuild login failed ...\n')
time.sleep(1)
return self.session, self.__qb_cookies
def qb_getconfid(self, path):
if len(self.__qb_cookies) == 0:
print('### WARNING ### quickbuild has not been logged ...')
return 0
txt = requests.get(QB_URL + QB_CONFPATH + path, cookies=self.__qb_cookies, verify=True).text
time.sleep(1)
return txt
def qb_getbuild(self, bid:str):
if len(self.__qb_cookies) == 0:
print('### WARNING ### quickbuild has not been logged ...')
return 0
txt = requests.get(QB_URL + QB_BUILDS + bid, cookies=self.__qb_cookies, verify=True).text
# TO REMOVE XML FILE
# with open(BUILDINFOXML, 'wt', encoding='utf-8') as f:
# n = f.write(txt)
# return n
return txt
def qb_getclinfo(self, xml):
base = ''
partials = ''
# TO REMOVE XML FILE
# with open(BUILDINFOXML, 'rt', encoding='utf-8') as f:
if xml != '':
# tree = parse(BUILDINFOXML)
# root = tree.getroot()
root = ETR.fromstring(xml)
sav = root.find('secretAwareVariableValues')
entlist = sav.getchildren()
for ent in entlist:
l = ent.getchildren()
if l[0].text == 'CL_SYNC':
base = l[1].getchildren()[0].text
if l[0].text == 'CL_PARTIAL' :
sublist = l[1].getchildren()
if len(sublist) != 0:
partials = l[1].getchildren()[0].text
if partials is None:
partials = ''
return base, partials
def __qb_entry(self, vname, vval):
ent = ET('entry')
name = ET('string')
name.text = vname
ent.append(name)
val = ET('string')
val.text = vval
ent.append(val)
return ent
def qb_data(self, confid, base, partials, usermode=True, csc=None):
if type(confid) != str or type(base) != str or (partials != None and type(partials) != str):
raise TypeError
breq = ET('com.pmease.quickbuild.BuildRequest')
cid = ET('configurationId')
cid.text = confid
breq.append(cid)
variables = ET('variables')
if usermode==True:
variables.append(self.__qb_entry('DEFAULT_BUILD_MODE', 'USER_BUILD_DEFAULT_OPTIONS'))
else:
variables.append(self.__qb_entry('DEFAULT_BUILD_MODE', 'ENG_BUILD_DEFAULT_OPTIONS'))
variables.append(self.__qb_entry('CL_SYNC', base))
variables.append(self.__qb_entry('CL_PARTIAL', partials))
variables.append(self.__qb_entry('CL_SHELVE', ''))
if csc!=None:
variables.append(self.__qb_entry('BUILD_CSC', csc))
breq.append(variables)
# TO REMOVE XML FILE
# ETR(breq).write(BUILD_XML, encoding='utf-8', method='xml', xml_declaration=True)
return ETR.tostring(breq)
def qb_build(self, confid, base, partials, usermode=True):
qb_header = {'Content-Type': 'text/xml', 'charset': 'utf-8'}
# TO REMOVE XML FILE
# self.qb_data(confid, base, partials, usermode)
# rtn = requests.post(QB_URL + QB_BUILDRQ, data=open(BUILD_XML, 'rt', encoding='utf-8').read().replace('\n', ''), cookies=self.__qb_cookies, headers = qb_header)
xml = self.qb_data(confid, base, partials, usermode)
rtn = requests.post(QB_URL + QB_BUILDRQ, data=xml, cookies=self.__qb_cookies, headers = qb_header)
time.sleep(1)
return rtn
CLLIST = 'cl_list.txt'
CHKCL = 'checkcl.txt'
CLFORM = re.compile(r'\d+')
ENC = 'utf-8'
ENC2 = 'euc-kr'
ENC3 = 'cp949'
#################################################################################
class CL:
qb = None
client = ''
def reset(self):
self.refmode = 0 # 0 : use base and partial, 1 : user build-id
self.kormode = 0
self.depot = ''
self.rbid = self.cbid = self.pbid = ''
self.e = self.k = self.a = self.s = self.m = self.orgstr = self.resultstr = self.errmsg = self.basecl = self.qb_base = self.qb_partials = ''
self.pbase = self.ppartials = ''
self.pmode = -1 # prev build 저장방식
self.eurclset = set()
self.korclset = set()
self.addclset = set()
self.subclset = set()
self.mustset = set()
self.diff1 = []
self.diff2 = []
self.resultlist = []
self.mustlist = []
self.underlist = []
self.newcllist = []
self.newlist = []
self.config = []
self.confid = dict()
def setfile(self, fn):
self.filename = fn
def __init__(self, qbinst=None, fn=None):
self.qb = qbinst if qbinst != None else None
self.setfile(CLLIST if fn==None else fn)
self.reset()
def setqb(qbinst):
self.qb = qbinst
def str2set(self, cls):
CL = re.compile(r'\w+')
clset = set()
#
for match in CL.finditer(cls):
cl = match.group()
clset.add(cl)
return clset
def set2str(self, clset):
clstr = ''
for cl in clset:
clstr += str(cl)
clstr += ','
return clstr[:-1]
def set2str2(self, clset, chkset):
clstr = ''
for cl in clset:
clstr += str(cl)
if cl in chkset:
clstr += '*'
clstr += ','
return clstr[:-1]
def __match_comment(self, line):
temp = re.findall('^\s*#(.*)', line)
if temp != []:
return True
return False
def __matchcls(self, base, matchstr, line):
match = False
temp = re.findall('^\s*'+matchstr+'\s*=', line)
if len(temp) > 0:
match = True
temp = re.findall('^\s*'+matchstr+'\s*=\s*([\d,\s]*)#{0,1}', line)
if temp != []:
if base != '':
base += ','
base += temp[0].replace(' ','').replace('\n','')
return match, base
def __getcls(self):
self.reset()
with open(self.filename, mode='rt', encoding='utf-8') as f:
#
ln = 0
while(1):
line = f.readline()
ln += 1
self.orgstr += line
if line == '' or line[:13] == '# end of data':
break
temp = []
#
temp = re.findall('\s*', line)
if temp[0] == line:
continue
temp = re.findall('^depot\s*=\s*([\w/\-\.]+)', line)
if temp != []:
self.depot = temp[0]
continue
temp = re.findall('^client\s*=\s*([\w\-]+)', line)
if temp != []:
self.client = temp[0]
continue
temp = re.findall('^qb\s*=\s*([\w\-/]+)', line)
if temp != []:
self.config.append(temp[0])
continue
if self.pmode == -1:
temp = re.findall('^prev_buildid\s*=\s*([\d]+)', line)
if temp != []:
self.pbid = temp[0]
try:
xml = self.qb.qb_getbuild(self.pbid)
self.pbase, self.ppartials = self.qb.qb_getclinfo(xml)
except:
print('### ERROR ### Error occured !!! : prev - self.pbase = %s, self.ppartials = %s' % (self.pbase, self.ppartials))
self.pmode = 1
continue
temp = re.findall('^prev_base\s*=\s*([\d]+)', line)
if temp != []:
self.pbase = temp[0]
self.pmode = 0
continue
temp = re.findall('^ref_buildid', line)
if temp != []:
temp = re.findall('^ref_buildid\s*=\s*([\d]+)', line)
if temp != []:
self.rbid = temp[0]
try:
xml = self.qb.qb_getbuild(self.rbid)
self.basecl, self.e = self.qb.qb_getclinfo(xml)
except:
print('### ERROR ### Error occured !!! : ref - self.basecl = %s, self.e = %s' % (self.basecl, self.e))
self.refmode = 1
continue
temp = re.findall('^cur_buildid', line)
if temp != []:
temp = re.findall('^cur_buildid\s*=\s*([\d]+)', line)
if temp != []:
self.cbid = temp[0]
try:
xml = self.qb.qb_getbuild(self.cbid)
tempbase, self.k = self.qb.qb_getclinfo(xml)
except:
print('### ERROR ### Error occured !!! : cur - tempbase = %s, self.k = %s' % (tempbase, self.k))
if tempbase != self.basecl:
print("### WARNING ### ... current base is not the same one as ref base's ")
self.kormode = 1
continue
if(self.refmode == 0):
temp = re.findall('^base\s*=\s*([\d]+)', line)
if temp != []:
self.basecl = temp[0]
continue
#
match = mt = False
if self.pmode == 0:
mt, self.ppartials = self.__matchcls(self.e, 'prev_partials', line)
match |= mt
if self.refmode == 0:
mt, self.e = self.__matchcls(self.e, 'ref_partials', line)
match |= mt
if self.kormode == 0:
mt, self.k = self.__matchcls(self.k, 'cur_partials', line)
match |= mt
mt, self.a = self.__matchcls(self.a, 'add_partials', line)
match |= mt
mt, self.s = self.__matchcls(self.s, 'sub_partials', line)
match |= mt
mt, self.m = self.__matchcls(self.m, 'must_partials', line)
match |= mt
match |= self.__match_comment(line)
if match == False :
print('### ERROR ### Error in line #%d' % ln)
self.errmsg += 'Error in line #'
self.errmsg += str(ln)
self.errmsg += '\n'
self.eurclset = self.str2set(self.e)
self.korclset = self.str2set(self.k)
self.addclset = self.str2set(self.a)
self.subclset = self.str2set(self.s)
self.mustset = self.str2set(self.m)
def __putcls(self):
result_str = '------------------------------------------\n' + \
self.errmsg + '\n' \
'1. REF - CUR : \n' + \
str([int(x) for x in self.diff1]).replace(', ',',')[1:-1] + '\n\n' + \
'2. CUR - REF : (Please check whether to add or not!) \n' + \
str([int(x) for x in self.diff2]).replace(', ',',')[1:-1] + '\n\n' + \
'3. New CL list = REF + ADD CL - SUB CL (' + str(len(self.newcllist)) + ' CLs)\n\n' + 'Base : ' + str(self.basecl) + '\nPartial : \n' + \
str([int(x) for x in self.newcllist]).replace(', ',',')[1:-1] + '\n\n' + \
'***** CLs below the Base *****\n' + \
str([int(x) for x in self.underlist]).replace(', ',',')[1:-1] + '\n'
#
with open(self.filename, mode='wt+', encoding='utf-8') as f:
f.write(self.orgstr)
f.write(result_str)
return result_str
def update(self):
print('########### process CL list "%s" ... ###########' % self.filename)
self.reset()
self.__getcls()
self.diff1 = list(self.eurclset - self.korclset) # - subclset
self.diff2 = list(self.korclset - self.eurclset) # - addclset
self.diff1.sort()
self.diff2.sort()
# self.korclset = self.korclset.union(eurclset)
# self.korclset = self.korclset.union(addclset)
self.korclset = self.eurclset | self.addclset # korclset에 넣어둔 CL때문에 잘못 나오는 것이 있어 로직 변경
self.resultlist = list(self.korclset - self.subclset)
self.mustlist = list(self.mustset)
if self.resultlist != '' and self.basecl != '':
self.underlist = [ x for x in self.resultlist if int(x) < int(self.basecl) ]
self.newcllist = [ x for x in self.resultlist if int(x) > int(self.basecl) ]
self.underlist.sort()
self.newcllist.sort()
self.mustlist.sort()
for cl in self.mustlist:
if cl not in self.newcllist:
self.newcllist.append(cl)
self.resultstr = self.__putcls()
print('########## Completed ##########\n')
# prepare variables to build
self.qb_base = str(self.basecl)
self.qb_partials = str([int(x) for x in self.newcllist]).replace(', ',',')[1:-1]
return self.resultstr
##################################################################
from P4 import P4
CHKCL = 'checkcl.txt'
CLFORM = re.compile(r'\d+')
ENC = 'utf-8'
ENC2 = 'euc-kr'
ENC3 = 'cp949'
def p4con(client, user, password):
p4 = P4()
p4.user = user
p4.password = password
p4.port = '165.213.202.46:1716'
p4.client = client
p4.connect()
p4.run_login()
return p4
def p4discon(p4):
p4.disconnect()
# p4_run_changes()
def readfile():
cllist = []
with open(CHKCL, mode='r', encoding=ENC) as f:
orgfile = ''
while(1):
line = f.readline()
orgfile += line
if line == '' or line[:13] == '# end of data':
break
cls = re.findall(CLFORM, line)
for cl in cls:
cllist.append(int(cl))
return cllist, orgfile
def getchginfo(p4, cl):
# i = p4.fetch_change(cl)
i = p4.run('describe', cl)
info = ''
info += '=======================================================\n'
info += '- CL ' + str(i[0].get('change')) + ', DATE ' + i[0].get('time') + ', User : ' + i[0].get('user') + '\n'
info += '-------------------------------------\n'
info += '- Description : \n'
info += i[0].get('desc')
info += '-------------------------------------\n'
files = i[0].get('depotFile')
if files :
info += '- Files : ' + str(len(files)) + ' file(s)\n'
for f in files:
info += f
info += '\n'
info += '\n'
return info
def getinfo(p4, cllist):
info = ''
for cl in cllist:
info += getchginfo(p4, cl)
return info
def writefile(orgstr, newstr):
with open(CHKCL, mode='w', encoding=ENC) as f:
f.write(orgstr)
f.write(newstr)
def viewcls(client, user, password):
cllist, orgstr = readfile()
try:
p4 = p4con(client, user, password)
info = getinfo(p4, cllist)
writefile(orgstr, info)
p4discon(p4)
except:
for e in p4.errors:
print('### ERROR ###')
print(e)
def viewcl(client, user, password, cl):
info = ''
try:
p4 = p4con(client, user, password)
info = getchginfo(p4, cl)
p4discon(p4)
except:
for e in p4.errors:
print('### ERROR ###')
print(e)
return info
def yesno(str):
while True:
resp = input(str)
resp = re.findall(r'(\w)', resp)
if len(resp) == 0:
continue
resp = [x.lower() for x in resp]
break
print('')
if resp[0] != 'y':
return 0
return 1
##################################################################
class Release:
def __init__(self, qb=None):
filechecked = False
while True:
self.project = input('Enter Project Name : ').strip()
if self.project != '':
cllistfn = 'cl_list_' + self.project + '.txt'
else:
cllistfn = CLLIST
try:
with open(cllistfn, 'rt'):
filechecked = True
except:
print('### Warning ### File not found : %s' % cllistfn)
if filechecked == True:
print('===> OK!, File checked !!!\n')
break
self.cllistfn = cllistfn
self.qb = QB() if qb == None else qb
self.cl = CL(self.qb, cllistfn)
self.csvin = 'in.csv'
self.csvout = 'out.csv'
def update(self):
return self.cl.update()
def build(self, target='all'):
if len(self.cl.config) == 0:
print('### WARNING ### Threre is no configurations to build ...\n')
return
print('Builds ... (base : %s, partials : %s)' % (self.cl.qb_base, self.cl.qb_partials))
for x in self.cl.config:
print(' Triggering build for %s ... ' % x)
cid = self.cl.confid.get(x, self.qb.qb_getconfid(x))
if target=='user':
self.qb.qb_build(cid, self.cl.qb_base, self.cl.qb_partials, True)
if target=='eng' :
self.qb.qb_build(cid, self.cl.qb_base, self.cl.qb_partials, False)
if target=='all' :
self.qb.qb_build(cid, self.cl.qb_base, self.cl.qb_partials, True)
time.sleep(2)
self.qb.qb_build(cid, self.cl.qb_base, self.cl.qb_partials, False)
print(' Finished ...\n')
time.sleep(2)
def build_check(self):
print('Build check ... (base : %s, partials : %s)' % (self.cl.qb_base, self.cl.qb_partials))
print('Build configurations are ...')
for x in self.cl.config:
print('- %s' % x)
print('\n')
def getNewCL(self, client, user, password):
if self.cl.pmode == -1:
print('### WARNING ### You must assign previous build-id.\n')
return []
try:
p4 = p4con(client, user, password)
relcls = []
print(' Checking new cls between two builds for depot : %s' % self.cl.depot)
print(' self.cl.pbase = %s, self.cl.qb_base = %s' % (self.cl.pbase, self.cl.qb_base))
if self.cl.pbase == self.cl.qb_base:
# partial 추가된 것만 뽑기
print(' two builds have the same base, check partials...')
qb_p = [x.strip() for x in self.cl.qb_partials.split(',')]
p_p = [x.strip() for x in self.cl.ppartials.split(',')]
relcls = sorted(list(set(qb_p)-set(p_p)))
else:
# base 사이에 추가된 것 뽑기
added = p4.run('changes', '-ssubmitted', self.cl.depot+'@'+self.cl.pbase+','+self.cl.qb_base)
for x in added:
cl = x.get('change')
# 이전 partial에 포함된 것은 빼기
if cl in self.cl.ppartials:
continue
relcls.append(cl)
# 이번 partial에 추가된 것은 더하기
addcls = self.cl.qb_partials.split(',')
if len(addcls) == 1 and addcls[0] != '':
relcls += addcls
# 중복된 것 삭제
relcls = list(set(relcls))
relcls = sorted(relcls)
p4discon(p4)
except:
print('### ERROR ### Something wrong ... ')
for e in p4.errors:
print(e)
return relcls
def REL2FLUMEN(self, client, user, password, relcls):
resultlist = []
resultstr = ''
chg = r'\*+\sCherry-picking\s([\d]+)'
flm = r'/FLUMEN/'
resultdict = dict()
try:
p4 = p4con(client, user, password)
for relcl in relcls:
p4cl = p4.run('describe', relcl)
if len(p4cl) == 0:
errstr = ' @........ -> @???????? : cannot find' + relcl
resultstr = resultstr + errstr + '\n'
print(errstr)
continue
fcl = re.findall(chg, p4cl[0].get('desc'))
if len(fcl) == 0:
errstr = ' @........ -> @' + relcl + ' : cannot process description for ' + relcl
resultstr = resultstr + errstr + '\n'
print(errstr)
continue
p4fcl = p4.run('describe', fcl[0])
if len(p4fcl) == 0:
errstr = ' @???????? -> @' + relcl + ' : Cannot find cherry picked cl ' + fcl[0] + ' for org cl ' + relcl
resultstr = resultstr + errstr + '\n'
print(errstr)
continue
depotfiles = p4fcl[0].get('depotFile')
chkflm = False
for x in depotfiles:
if len(re.findall(flm, x)) > 0:
chkflm = True
if chkflm != True:
errstr = ' @' + fcl[0] + ' -> @' + relcl + ' : Found a cherry picked cl! But not FLUMEN'
resultstr = resultstr + errstr + '\n'
print(errstr)
continue
errstr = ' @' + fcl[0] + ' -> @' + relcl
resultstr = resultstr + errstr + '\n'
print(errstr)
resultlist.append((fcl[0], relcl))
resultdict = dict(resultlist)
p4discon(p4)
except:
for e in p4.errors:
print('### ERROR ###')
print(e)
return (resultstr, resultdict)
def checkNewCL(self, client, user, password):
resultstr = ''
relcls = self.getNewCL(client, user, password)
if len(relcls) <= 0:
print('### WARNING ### There is nothing new or failed to obtain new cls due to unknown errors.\n')
return '', dict()
resultlist = []
if yesno('Do you wanna convert REL CLs into FLUMEN CLs ? : ') == 0:
print('Newly added CLs are ...')
for x in relcls:
print('@' + str(x))
resultstr = resultstr + '@' + str(x) + '\n'
resultlist.append((str(x), ''))
resultdict = dict(resultlist)
return (resultstr, resultdict)
return self.REL2FLUMEN(client, user, password, relcls)
def updateCSV(self, clmap):
with open(self.csvin, 'rt') as i:
with open(self.csvout, 'wt') as o:
cr = csv.reader(i)
cw = csv.writer(o)
orglist = []
newlist = []
for x in cr:
orglist.append(x)
titlefound = False
titlepass = False
for x in orglist:
newitem = []
lval = ''
for i in range(len(x)):
newitem.append(x[i])
if i == INDEXCOL:
if x[0] == 'NO':
newitem.append('Release CL')
titlefound = True
else:
lval = clmap.get(str(x[i]), '')
newitem.append(lval)
if titlepass == False or lval != '':
newlist.append(newitem)
if titlefound == True:
titlepass = True
cw.writerows(newlist)
##################################################################
# release = Release()
# update = lambda : release.u()
# build = lambda : release.b()
##################################################################
class ReleaseUI:
user = ''
password = ''
def __qblogin(self):
if self.user == '' or self.password == '':
print('### WARNING ### You should enter login information agian.\nMenu login finished.')
print('Quickbuild log-in ...\n')
self.release.qb.qblogin(self.user, self.password)
def doLogin(self):
if self.user == '':
self.user = input('userName cannot be null.\nPlease enter userName : ')
if self.password == '':
self.password = input('password cannot be null.\nPlease enter password : ')
self.__qblogin()
def doReLogin(self):
self.user = input('Please enter userName : ')
self.password = input('Please tner password : ')
self.doLogin()
def __printVer(self):
print(VERSIONINFO + '\n' + '-'*30 + '\n')
def __init__(self):
self.__printVer()
self.qb = QB()
self.release = Release(self.qb)
self.doReLogin()
def doNewProject(self):
self.release = Release(self.qb)
def doUpdate(self):
print(self.release.update())
def doBuild(self, target='all'):
if target == 'all' or target == 'user' or target == 'eng':
self.release.build(target)
else:
print('### WARNING ### Cannot recognize build option : %s' % target)
def doCheckBuild(self, target='all'):
self.release.build_check()
def doCheckCL(self):
viewcls(self.release.cl.client, self.user, self.password)
print('CL info has been updated ...\n')
def doCheckNewCL(self):
resultstr, clmap = self.release.checkNewCL(self.release.cl.client, self.user, self.password)
with open(self.release.cllistfn, 'wt', encoding=ENC) as f:
f.write(self.release.cl.orgstr)
f.write(self.release.cl.resultstr)
f.write('\n' + '\n****** Newly append CLs are ... ******\n\n')
f.write(resultstr)
f.write('\n')
if len(clmap) == 0:
return
try:
self.release.updateCSV(clmap)
except:
print("### WARNING ### Something happened while updating Release CLs with CSV...")
def doHelp(self):
self.__printVer()
print('Please be sure to place "cl_list.txt" at the same folder with this Program !!! \n')
print('commands')
print('- help or ? : this screen')
print('- update : update cl_list.txt')
print('- login : log on Quickbuild server')
print('- relogin : log on Quickbuild server with new user and password')
print('- build : build with respect to the CLs on cl_list.txt')
print(' build or build all - build user and eng binary')
print(' build user - build user binary')
print(' build eng - build eng binary')
print(' to use this, you should login on QB server')
print('- newbuild : same as what "build" does.')
print(' But "update" will be performed before build is processed')
print('- check build : display parameters when build command is performed')
print(' newcl : check newly added cl w.r.t the previous build ')
print(' to use this, ')
print(' prev_buildid or prev_base and prev_partials should be provided')
print(' and log on P4 server \( assume that P4 user info is the same as QB \) ')
print('- newprj : change project')
print('- exit : Exit from menu')
print('')
def __call__(self):
# 나중에... commands와 sub-commands 처리 routine화 시키기 ...
# commands = {'update': self.doUpdate, 'login' : self.doLogin, 'relogin' : self.doReLogin,
# 'help' : self.doHelp, '?' : self.doHelp }
while True:
prompt = '[' + self.release.project + ']' + ' Enter commands ? '
instr = input(prompt)
command = re.findall(r'([\w]+|\?)', instr)
cmd = [x.lower() for x in command]
if len(cmd) == 0:
continue
if cmd[0] == 'newprj':
self.doNewProject()
elif cmd[0] == 'update':
self.doUpdate()
elif cmd[0] == 'login':
self.doLogin()
elif cmd[0] == 'relogin':
self.doReLogin()
elif cmd[0] == 'build' :
if len(cmd) > 1:
self.doBuild(target=cmd[1])
else:
self.doBuild()
elif cmd[0] == 'newbuild' :
self.doUpdate()
if yesno('=> Wanna build ? (Y/N) : ') != 0:
continue
if len(cmd) > 1:
self.doBuild(target=cmd[1])
else:
self.doBuild()
elif cmd[0] == 'check' :
if len(cmd) > 1:
if cmd[1] == 'cl':
self.doCheckCL()
elif cmd[1] == 'build':
self.doCheckBuild()
elif cmd[1] == 'newcl':
self.doCheckNewCL()
elif cmd[0] == 'help' or cmd[0] == '?':
self.doHelp()
elif cmd[0] == 'exit':
break;
else:
print('Invalid command : %s' % command[0])
if __name__ == '__main__':
ReleaseUI()()