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 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 projectPassTest(): gitConnection = GitConnect() gitConnection.checkForUnsavedChanges() caseno = gitConnection.extractCaseFromBranch() gitConnection.pushChangesToOriginBranch(gitConnection.getBranch()) gitConnection.checkoutMaster() fbConnection = FogBugzConnect() (parent,test) = fbConnection.getCaseTuple(caseno) statuses = fbConnection.getStatuses(test) for i in range(0,len(statuses.keys())): print i,": ",statuses[sorted(statuses.keys())[i]] print "Choose your adventure: ", choice = input() ix = sorted(statuses.keys())[choice] fbConnection.resolveCase(test,ixstatus=ix) fbConnection.closeCase(test) fbConnection.fbConnection.assign(ixBug=parent,ixPersonAssignedTo=magic.BUILDBOT_IXPERSON) # play sounds! getstatusoutput("afplay -v 7 %s/media/longcheer.aiff" % sys.prefix)
class MockRepo: git = None dir = None fb = None def __init__(self, dir=None): if not dir: dir = "%s/mockrepo/" % tempfile.gettempdir() if not os.path.exists(dir): os.makedirs(dir) self.dir = dir self.git = GitConnect(self.dir) self.fb = FogBugzConnect() def createFile(self, name, contents): self.editFile(name, contents) def editFile(self, name, contents): with open(self.dir+name, "w") as file: file.write(contents) def readFile(self, name): with open(self.dir+name, "r") as file: return file.read() def gitInit(self): self.git.statusOutput("git init", self.dir) def gitAdd(self, file): self.git.add(file) def gitCommit(self, message): self.git.commitAll(message) def gitPush(self, forceful=False): if forceful: self.git.statusOutput("git push -u -f") else: self.git.statusOutput("git push -u") def gitPull(self): self.git.fetch() self.git.pull() self.git.submoduleUpdate() #Drew would like to document that this is redundant. Bion would like to document that this redundancy is not clear. def gitMerge(self, branch): self.git.mergeIn(branch) def gitCheckout(self, branch): self.git.checkoutExistingBranchRaw(branch) #is this name really necessary? def wipeRepo__INCREDIBLY__DESTRUCTIVE_COMMAND(self): self.git.statusOutputExcept("git push -f --all --delete") self.git.statusOutput("rm -Rf .git") self.git.statusOutputExcept("git init") self.git = GetConnect(self.dir) self.git.statusOutputExcept("git remote add origin [email protected]:drewcrawford/SampleProject.git") self.createFile("README.txt", "test") self.gitAdd("README.txt") self.gitCommit("First Commit") self.gitPush() def ticketReactivate(self, ticket): if "Closed" in self.fb.getStatuses(ticket): self.fb.reactivate(ticket, 7, "Just testing...") def ticketResolve(self, ticket): self.fb.resolveCase(ticket) def ticketClose(self, ticket): self.fb.closeCase(ticket) def ticketAssign(self, ticket, ixUser): self.fb.assignCase(ticket, ixUser) def ticketCreate(self, title): return self.fb.createCase(title, 1, 1, 7) def ticketSetEstimate(self, ticket, estimate): self.fb.setEstimate(ticket, estimate)