def checkoutBranch(self, CASE_NO, fromSpec,fbConnection): # get output from git branch command (branchStatus, branchOutput) = self.statusOutput("git branch") #fetch git repo information self.fetch() # check if a branch for CASE_NO exists # if it does, check it out if self.__checkoutExistingBranch(CASE_NO): if fromSpec: juche.warn("Ignoring your fromspec. To override, re-try with after a git checkout master && git branch -D work-%d && git push origin :work-%d" %(CASE_NO,CASE_NO)) juche.warn("THIS DESTRUCTIVE COMMAND DELETES ANY WORK ON work-%d, USE WITH CAUTION!" % CASE_NO) self.pull() return # if a branch does not exist, create one and check it out else: if not fromSpec: #try to fill automatically from FB fromSpec = fbConnection.getIntegrationBranch(CASE_NO) self.createNewWorkBranch(CASE_NO, fromSpec) return
def checkForUnsavedChanges(self): output = self.checkForRepository() #if "git status" returns an error..." if self.statusOutput("git status --porcelain")[1]: juche.warn("changes have been made to source code!") juche.warn(" use git stash or git commit to save changes") raise Exception("stacktraceplease") else: return
def recharge(fr,to): import dateutil.parser fbConnection = FogBugzConnect() fbConnection.setParentIfUnset(fr,to) #cannot create a time record for a closed case... mustOpen = not fbConnection.isOpen(to) if mustOpen: fbConnection.reopen(to,"work.py recharge") results = fbConnection.listTimeRecords(fr) time_interval = 0 my_records = [] for record in results: #print record if record.fdeleted.contents[0]!="false": juche.warn("Skipping deleted record %s" % record) continue if len(record.dtend)==0: juche.warn("Skipping open time record %s" % record) continue my_records.append(record) r = 0 for record in my_records: juche.info("%d: %s-%s" % (r,record.dtstart.contents[0],record.dtend.contents[0])) r += 1 def parse_range(astr): # http://stackoverflow.com/questions/4726168/parsing-command-line-input-for-numbers result=set() for part in astr.split(','): x=part.split('-') result.update(range(int(x[0]),int(x[-1])+1)) return sorted(result) strl = raw_input("records (syntax like 22-27,51-64): ") results = parse_range(strl) for result in results: record = my_records[result] record_desc = "From %s to %s ixPerson %s ixBug %s" % (record.dtstart.contents[0],record.dtend.contents[0],record.ixperson.contents[0],record.ixbug.contents[0]) from_time = dateutil.parser.parse(record.dtstart.contents[0]) to_time = dateutil.parser.parse(record.dtend.contents[0]) time_interval += (to_time-from_time).total_seconds() juche.info("from_time %s to_time %s time_interval %s" % (from_time,to_time,time_interval)) fbConnection.commentOn(fr,"recharge: A record was removed from this ticket: %s, see case %d" % (record_desc,to)) fbConnection.commentOn(to,"recharge: A record was added to this ticket: %s, see case %d" % (record_desc, fr)) fbConnection.createTimeRecord(to,str(record.dtstart.contents[0]),str(record.dtend.contents[0])) oldEst = fbConnection.getEstimate(fr) * 60.0 * 60.0 newEst = (oldEst - time_interval) / 60.0 / 60.0 if newEst <= 0: newEst = 1/60.0 juche.info("Setting estimate to",newEst) fbConnection.setEstimate(fr,timespan="%f hours" % newEst) #fbConnection.deleteTimeRecord(record.ixinterval.contents[0]) if mustOpen: fbConnection.closeCase(to)
def workConfig(settingString): ALLOWED_SETTINGS = ["viewOnStart"] if len(settingString.split("=")) < 2: printUsageString() raise Exception("stacktraceplease") setting = settingString.split("=")[0] value = settingString.split("=")[1] if setting and value: fbConnection = FogBugzConnect() settings = fbConnection.getCredentials() if(not setting in ALLOWED_SETTINGS): juche.warn("setting not known. Will be added anyway.") fbConnection.setSetting(setting, value) else: printUsageString() raise Exception("stacktraceplease")
def exec_tests(self,proj): import subprocess import shlex shortdesc = "" files = {} passed = True #WARNING: YOU MUST PATCH $DEVELOPER/Platforms/iPhoneSimulator.platform/Developer/Tools/RunPlatformUnitTests for this to work. #See http://longweekendmobile.com/2011/04/17/xcode4-running-application-tests-from-the-command-line-in-ios/ if proj["tests"]: juche.dictate(project=proj) for test in proj["tests"]: juche.dictate(running_test=test) juche.info("running test") r = subprocess.Popen(test["cmd"],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd=WORK_DIR+proj["name"]) (status,output) = self.wait_for(r) if status and test["type"]!="kif": #kif tests always return a status code of 1 shortdesc += "Failing in part because test %s returned a non-zero return code %d\n" % (test,status) passed = False if test["type"]=="xcode": (passed,shortdesc,files) = self.parse_xcodelike_response(passed,shortdesc,files,output,test["name"]+".log") elif test["type"]=="python": (passed,shortdesc,files) = self.parse_python_response(passed,shortdesc,files,output,test["name"]+".log",status) elif test["type"]=="kif": (passed,shortdesc,files) = self.parse_kif_response(passed,shortdesc,files,output,test["name"]+".log") else: raise Exception("Unknown test type.") if passed: if "commit-files" in test: upload_files = test["commit-files"] juche.dictate(upload_files=upload_files) juche.info("commit-files") git = GitConnect(wd=WORK_DIR+proj["name"]) git.add(upload_files) try: git.commit("If the subject survived the test, we let them purchase the pictures for $5. If the subject died, we gave the photo to their next of kin free of charge") git.pushChangesToOriginBranch() except Exception as e: juche.exception(e) juche.warn("Was not able to upload the files successfully. Perhaps they have not changed?") return (passed,shortdesc,files)
def projectIntegrate(CASE_NO,defaultgitConnection=GitConnect()): if not defaultgitConnection: interactive = True else: interactive = False gitConnection = defaultgitConnection gitConnection.checkForUnsavedChanges() #see referencing note on line 369 fbConnection = FogBugzConnect() #still open here # make sure integration is even worth it... fbConnection.ensureReadyForTest(CASE_NO) gitConnection.checkoutExistingBranch(CASE_NO) integrate_to = fbConnection.getIntegrationBranch(CASE_NO) gitConnection.checkoutExistingBranchRaw(integrate_to) gitConnection.resetHard_INCREDIBLY_DESTRUCTIVE_COMMAND() #this is safe because we check for unsafe changes on line 357. gitHubConnection = GitHubConnect(gitConnect=gitConnection) gitHubConnection.closePullRequestbyName("work-%d" % CASE_NO) #check for test case try: (parent, test) = fbConnection.getCaseTuple(CASE_NO,oldTestCasesOK=True) except: if interactive: juche.warn("no test case! Press enter to continue") raw_input() if not interactive: if not gitConnection.mergeIn("work-%d" % CASE_NO,pretend=True): return False gitConnection.mergeIn("work-%d" % CASE_NO) fbConnection.commentOn(CASE_NO,"Merged into %s" % integrate_to) fbConnection.closeCase(CASE_NO) if not interactive: gitConnection.pushChangesToOriginBranch(branch=integrate_to) return True
def _fixFors_test_quickly_dates(abbreviatedTest=False): juche.dictate(fixing_test_milestones=1) fbConnection = FogBugzConnect() fixfors_raw = fbConnection.listFixFors() fixfors = fbConnection.dependencyOrder(fixfors_raw) from dateutil.parser import parse import datetime if abbreviatedTest: fixfors = fixfors[:5] for testMilestone in fixfors: testMilestone_raw = fbConnection.fixForDetail(testMilestone) testName = fbConnection.nameForFixFor(testMilestone_raw) if testName.startswith("Never"): continue juche.dictate(testMilestone=testMilestone,testName=testName) if not testName.endswith("-test"): continue if testName=="Undecided-test": continue matched = False if testMilestone_raw.ixproject.contents==[]: continue for item in fbConnection.listFixFors(ixProject=int(testMilestone_raw.ixproject.contents[0])): #print testName[:-5],fbConnection.nameForFixFor(item) if item.sfixfor.contents[0]==testName[:-5]: #print "matching",testName,fbConnection.nameForFixFor(item) matched = True break if not matched: juche.info(testMilestone_raw) raise Exception("Cannot match "+testName) if item.dt.contents==[]: juche.info("Can't set %s because the non-test milestone has no completion date." % testName) continue date = item.dt.contents[0] newDate = parse(date)+datetime.timedelta(hours=6) #turns out that using 1 day produces weird results. If the next implementation milestone is completed within 24 hours, lots of weird things can happen juche.info("setting %s to %s"% (testName,newDate)) if not abbreviatedTest: fbConnection.editFixForShipDate(testMilestone,newDate) #It's bad to leave EBS in a partially-edited state. Therefore we simply log the output and don't actually write any changes when in abbreviated test mode. else: juche.warn("Not editing the ship date in %s to %s because this is an abbreviated test." % (testMilestone,newDate))
def pull(self): self.checkForRepository() import ConfigParser c = ConfigParser.ConfigParser() if self.wd: path = self.wd + "/.git/config" else: path =".git/config" import os for i in range(0,30): if os.path.exists(path): break path = "../" + path if i==30: raise Exception("Not a git repository?") file = open(path) str = file.read() file.close() juche.dictate(pull=1) if self.getBranch() not in str: juche.warn( "%s is not a tracking branch. Attempting to fix..." % self.getBranch()) try: self.setUpstream(self.getBranch(),"remotes/origin/{0}".format(self.getBranch())) juche.info("Success!") except: juche.error("DID NOT AUTOMATICALLY FIX BRANCH UPSTREAM / TRACKING. PLEASE FILE A BUG.") (status,output) = self.statusOutput("git pull origin %s" % self.getBranch()) if status: juche.error("Cannot pull! %s" % output) else: (status,output) = self.statusOutput("git pull") if status: juche.error("ERROR: Cannot pull! %s" % output) raise Exception("stacktraceplease") self.submoduleUpdate() juche.info("Success!")
def setUp(self): juche.warn("Unit test begin") self.a = Atlas() self.a.fetch_all(deploy=False) pass