def readVersion(self, fileName, args): config = grapeConfig.grapeConfig() prefix = args["--prefix"] if args["--suffix"]: suffix = args["--suffix"] else: try: suffixMapping = config.getMapping("versioning", "branchSuffixMappings") suffix = suffixMapping[config.getPublicBranchFor(git.currentBranch())] except KeyError: suffix = "" args["--suffix"] = suffix regex = args["--matchTo"] try: regexMappings = config.getMapping("versioning", "branchVersionRegexMappings") public = config.getPublicBranchFor(git.currentBranch()) regex = regexMappings[public] except ConfigParser.NoOptionError: pass #tweaked from http://stackoverflow.com/questions/2020180/increment-a-version-id-by-one-and-write-to-mk-file regex = regex.replace("<prefix>", prefix) regex = regex.replace("<suffix>", suffix) self.r = re.compile(regex) VERSION_ID = None for l in fileName: m1 = self.r.match(l) if m1: VERSION_ID = map(int, m1.group(3).split(".")) self.matchedLine = l if VERSION_ID is None: print("GRAPE: .") return VERSION_ID
def mergeSubproject(self, args, subproject, subPublic, subprojects, cwd, isSubmodule=True): # if we did this merge in a previous run, don't do it again try: if self.progress["Subproject: %s" % subproject] == "finished": return True except KeyError: pass os.chdir(os.path.join(git.baseDir(), subproject)) mergeArgs = args.copy() mergeArgs["--public"] = subPublic utility.printMsg("Merging %s into %s for %s %s" % (subPublic, git.currentBranch(), "submodule" if isSubmodule else "subproject", subproject)) git.fetch("origin") # update our local reference to the remote branch so long as it's fast-forwardable or we don't have it yet..) hasRemote = git.hasBranch("origin/%s" % subPublic) hasBranch = git.hasBranch(subPublic) if hasRemote and (git.branchUpToDateWith(subPublic, "origin/%s" % subPublic) or not hasBranch): git.fetch("origin %s:%s" % (subPublic, subPublic)) ret = self.mergeIntoCurrent(subPublic, mergeArgs, subproject) conflict = not ret if conflict: self.progress["stopPoint"] = "Subproject: %s" % subproject subprojectKey = "submodules" if isSubmodule else "nested" self.progress[subprojectKey] = subprojects self.progress["cwd"] = cwd conflictedFiles = git.conflictedFiles() if conflictedFiles: if isSubmodule: typeStr = "submodule" else: typeStr = "nested subproject" utility.printMsg("Merge in %s %s from %s to %s issued conflicts. Resolve and commit those changes \n" "using git mergetool and git commit in the submodule, then continue using grape\n" "%s --continue" % (typeStr, subproject, subPublic, git.currentBranch(), args["<<cmd>>"])) else: utility.printMsg("Merge in %s failed for an unhandled reason. You may need to stash / commit your current\n" "changes before doing the merge. Inspect git output above to troubleshoot. Continue using\n" "grape %s --continue." % (subproject, args["<<cmd>>"])) return False # if we are resuming from a conflict, the above grape m call would have taken care of continuing. # clear out the --continue flag. args["--continue"] = False # stage the updated submodule os.chdir(cwd) if isSubmodule: git.add(subproject) self.progress["Subproject: %s" % subproject] = "finished" return True
def ensureLocalUpToDateWithRemote(repo='', branch='master'): utility.printMsg( "Ensuring local branch %s in %s is up to date with origin" % (branch, repo)) with utility.cd(repo): # attempt to fetch the requested branch try: git.fetch("origin", "%s:%s" % (branch, branch)) except: # the branch may not exist, but this is ok pass if git.currentBranch() == branch: return if not git.hasBranch(branch): # switch to corresponding public branch if the branch does not exist public = grapeConfig.workspaceConfig().getPublicBranchFor(branch) # figure out if this is a submodule relpath = os.path.relpath(repo, utility.workspaceDir()) relpath = relpath.replace('\\', "/") with utility.cd(utility.workspaceDir()): # if this is a submodule, get the appropriate public mapping if relpath in git.getAllSubmoduleURLMap().keys(): public = grapeConfig.workspaceConfig().getMapping( "workspace", "submodulepublicmappings")[public] utility.printMsg( "Branch %s does not exist in %s, switching to %s and detaching" % (branch, repo, public)) git.checkout(public) git.pull("origin %s" % (public)) git.checkout("--detach HEAD")
def postCommit(args): #applies the autoPush hook autoPush = args["--autopush"] if autoPush.lower().strip() != "false": try: git.push("-u origin HEAD") except git.GrapeGitError: pass autoPush = True else: autoPush = False #applies the cascade hook print("GRAPE: checking for cascades...") cascadeDict = grapeConfig.GrapeConfigParser.parseConfigPairList(args["--cascade"]) if cascadeDict: currentBranch = git.currentBranch() while currentBranch in cascadeDict: source = currentBranch target = cascadeDict[source] fastForward = False print("GRAPE: Cascading commit from %s to %s..." % (source, target)) if git.branchUpToDateWith(source, target): fastForward = True print("GRAPE: should be a fastforward cascade...") git.checkout("%s" % target) git.merge("%s -m 'Cascade from %s to %s'" % (source, source, target)) # we need to kick off the next one if it was a fast forward merge. # otherwise, another post-commit hook should be called from the merge commit. if fastForward: if autoPush: git.push("origin %s" % target) print("GRAPE: auto push done") currentBranch = target else: currentBranch = None
def ensureLocalUpToDateWithRemote(repo = '', branch = 'master'): utility.printMsg( "Ensuring local branch %s in %s is up to date with origin" % (branch, repo)) with utility.cd(repo): # attempt to fetch the requested branch try: git.fetch("origin", "%s:%s" % (branch, branch)) except: # the branch may not exist, but this is ok pass if git.currentBranch() == branch: return if not git.hasBranch(branch): # switch to corresponding public branch if the branch does not exist public = grapeConfig.workspaceConfig().getPublicBranchFor(branch) # figure out if this is a submodule relpath = os.path.relpath(repo, utility.workspaceDir()) relpath = relpath.replace('\\',"/") with utility.cd(utility.workspaceDir()): # if this is a submodule, get the appropriate public mapping if relpath in git.getAllSubmoduleURLMap().keys(): public = grapeConfig.workspaceConfig().getMapping("workspace", "submodulepublicmappings")[public] utility.printMsg("Branch %s does not exist in %s, switching to %s and detaching" % (branch, repo, public)) git.checkout(public) git.pull("origin %s" % (public)) git.checkout("--detach HEAD")
def execute(self, args): mrArgs = {} currentBranch = git.currentBranch() mrArgs["<branch>"] = currentBranch # the <<cmd>> stuff is for consistent --continue output if not "<<cmd>>" in args: args["<<cmd>>"] = "pull" mrArgs["<<cmd>>"] = args["<<cmd>>"] mrArgs["--am"] = True mrArgs["--as"] = False mrArgs["--at"] = False mrArgs["--aT"] = False mrArgs["--ay"] = False mrArgs["--aY"] = False mrArgs["--askAll"] = False mrArgs["--continue"] = args["--continue"] mrArgs["--noRecurse"] = False mrArgs["--squash"] = False if args["--noRecurse"]: git.pull("origin %s" % currentBranch) utility.printMsg("Pulled current branch from origin") return True else: val = grapeMenu.menu().getOption("mr").execute(mrArgs) if val: utility.printMsg("Pulled current branch from origin") return val
def initializeCommands(self): config = grapeConfig.grapeConfig() currentBranch = git.currentBranch() if not self.branchArg else self.branchArg publicBranches = config.getPublicBranchList() wsDir = dir # don't reinit if self.repos: return if self.launchTuple is not None: self.repos = [os.path.abspath(x[0]) for x in self.launchTuple] self.branches = [x[1] for x in self.launchTuple] self.perRepoArgs = [x[2] for x in self.launchTuple] else: if self.runSubprojects: activeSubprojects = grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes() self.repos = self.repos + [os.path.join(workspaceDir(), sub) for sub in activeSubprojects] self.branches = self.branches + [currentBranch for x in activeSubprojects] if self.runSubmodules: activeSubmodules = git.getActiveSubmodules() self.repos = self.repos + [os.path.join(workspaceDir(), r) for r in activeSubmodules] subPubMap = config.getMapping("workspace", "submodulepublicmappings") submoduleBranch = subPubMap[currentBranch] if currentBranch in publicBranches else currentBranch self.branches = self.branches + [ submoduleBranch for x in activeSubmodules ] if self.runOuter: self.repos.append(self.outer) self.branches.append(currentBranch) if not self.perRepoArgs: if not self.globalArgs: self.perRepoArgs = [[] for x in self.repos] else: self.perRepoArgs = [self.globalArgs for x in self.repos]
def description(self): try: currentBranch = git.currentBranch() except git.GrapeGitError: currentBranch = 'unknown' publicBranch = self.lookupPublicBranch() return "Merge latest changes on %s into %s" % (publicBranch, currentBranch)
def getDesiredSubmoduleBranch(config): publicBranches = config.getPublicBranchList() currentBranch = git.currentBranch() if currentBranch in publicBranches: desiredSubmoduleBranch = config.getMapping("workspace", "submodulepublicmappings")[currentBranch] else: desiredSubmoduleBranch = currentBranch return desiredSubmoduleBranch
def getDesiredSubmoduleBranch(config): publicBranches = config.getPublicBranchList() currentBranch = git.currentBranch() if currentBranch in publicBranches: desiredSubmoduleBranch = config.getMapping( "workspace", "submodulepublicmappings")[currentBranch] else: desiredSubmoduleBranch = currentBranch return desiredSubmoduleBranch
def checkForConsistentWorkspaceBranches(self, args): consistentBranchState = True cfg = config.grapeConfig.grapeConfig() publicBranches = cfg.getPublicBranchList() wsDir = utility.workspaceDir() os.chdir(wsDir) wsBranch = git.currentBranch() subPubMap = cfg.getMapping("workspace", "submodulepublicmappings") if wsBranch in publicBranches: for sub in git.getActiveSubmodules(): os.chdir(os.path.join(wsDir, sub)) subbranch = git.currentBranch() if subbranch != subPubMap[wsBranch]: consistentBranchState = False utility.printMsg( "Submodule %s on branch %s when grape expects it to be on %s" % (sub, subbranch, subPubMap[wsBranch])) else: for sub in git.getActiveSubmodules(): os.chdir(os.path.join(wsDir, sub)) subbranch = git.currentBranch() if subbranch != wsBranch: consistentBranchState = False utility.printMsg( "Submodule %s on branch %s when grape expects it to be on %s" % (sub, subbranch, wsBranch)) # check that nested subproject branching is consistent for nested in config.grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes( ): os.chdir(os.path.join(wsDir, nested)) nestedbranch = git.currentBranch() if nestedbranch != wsBranch: consistentBranchState = False utility.printMsg( "Nested Project %s on branch %s when grape expects it to be on %s" % (nested, nestedbranch, wsBranch)) return consistentBranchState
def execute(self,args): if not "<<cmd>>" in args: args["<<cmd>>"] = "mr" otherBranch = args['<branch>'] if not otherBranch: # list remote branches that are available print git.branch('-r') otherBranch = utility.userInput("Enter name of branch you would like to merge into this branch (without the origin/ prefix)") # make sure remote references are up to date utility.printMsg("Fetching remote references in all projects...") try: utility.MultiRepoCommandLauncher(fetchHelper).launchFromWorkspaceDir() except utility.MultiRepoException as mre: commError = False commErrorRepos = [] for e, r in zip(mre.exceptions(), mre.repos()): if e.commError: commErrorRepos.append(r) commError = True if commError: utility.printMsg("ERROR: can't communicate with remotes for %s. Halting remote merge." % commErrorRepos) return False # update our local reference to the remote branch so long as it's fast-forwardable or we don't have it yet..) hasRemote = ("origin/%s" % otherBranch) in git.remoteBranches() hasBranch = git.hasBranch(otherBranch) currentBranch = git.currentBranch() remoteUpToDateWithLocal = git.branchUpToDateWith("remotes/origin/%s" % otherBranch, otherBranch) updateLocal = hasRemote and (remoteUpToDateWithLocal or not hasBranch) and currentBranch != otherBranch if updateLocal: utility.printMsg("updating local branch %s from %s" % (otherBranch, "origin/%s" % otherBranch)) utility.MultiRepoCommandLauncher(updateBranchHelper, branch=otherBranch).launchFromWorkspaceDir(handleMRE=updateBranchHandleMRE) args["<branch>"] = otherBranch if updateLocal else "origin/%s" % otherBranch # we've handled the update, we don't want m or md to update the local branch. args["--noUpdate"] = True # if mr is called by the user, need to initialize the --continue argument. # if it is called by md, it will be set already. if not "--continue" in args: args["--continue"] = False return grapeMenu.menu().getOption('m').execute(args)
def execute(self, args): baseDir = utility.workspaceDir() cwd = os.getcwd() os.chdir(baseDir) currentBranch = git.currentBranch() config = grapeConfig.grapeConfig() publicBranches = config.getPublicBranchList() submodules = git.getActiveSubmodules() retvals = utility.MultiRepoCommandLauncher( push).launchFromWorkspaceDir(handleMRE=handlePushMRE) os.chdir(cwd) utility.printMsg("Pushed current branch to origin") return False not in retvals
def tickVersion(self, args): config = grapeConfig.grapeConfig() fileName = config.get("versioning", "file") with open(fileName) as f: slots = self.readVersion(f, args) self.ver = self.slotsToString(args, slots) if not args["--notick"]: slot = args["--slot"] if not slot: slotMappings = config.getMapping("versioning", "branchSlotMappings") if args["--public"]: publicBranch = args["--public"] else: publicBranch = config.getPublicBranchFor(git.currentBranch()) slot = int(slotMappings[publicBranch]) else: slot = int(slot) if args["--minor"]: slot = 2 if args["--major"]: slot = 1 # extend the version number if slot comes in too large. while len(slots) < slot: slots.append(0) slots[slot - 1] += 1 while slot < len(slots): slots[slot] = 0 slot += 1 # write the new version number to the version file. with open(fileName, 'r+') as f: self.ver = self.writeVersion(f, slots, args) self.stageVersionFile(fileName) if not args["--nocommit"]: git.commit("-m \"GRAPE: ticked version to %s\"" % self.ver) if (not args["--nocommit"]) or args["--tag"]: self.tagVersion(self.ver, args) if args["--tagNested"]: cwd = os.getcwd() wsDir = utility.workspaceDir() for subproject in grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes(): os.chdir(os.path.join(wsDir, subproject)) self.tagVersion(self.ver, args) os.chdir(cwd)
def lookupPublicBranch(): config = grapeConfig.grapeConfig() try: currentBranch = git.currentBranch() except git.GrapeGitError: return 'unknown' if currentBranch in config.get('flow', 'publicBranches'): return currentBranch try: branch = config.getPublicBranchFor(currentBranch) except KeyError: branchPrefix = git.branchPrefix(currentBranch) print("WARNING: prefix %s does not have an associated topic branch, nor is a default" "public branch configured. \n" "use --public=<branch> to define, or add %s:<branch> or ?:<branch> to \n" "[flow].publicBranches in your .grapeconfig or .git/.grapeuserconfig. " % (branchPrefix, branchPrefix)) branch = None return branch
def execute(self, args): baseDir = utility.workspaceDir() cwd = os.getcwd() os.chdir(baseDir) currentBranch = git.currentBranch() config = grapeConfig.grapeConfig() publicBranches = config.getPublicBranchList() submodules = git.getActiveSubmodules() retvals = utility.MultiRepoCommandLauncher(push).launchFromWorkspaceDir(handleMRE=handlePushMRE) os.chdir(cwd) utility.printMsg("Pushed current branch to origin") return False not in retvals
def fetchLocal(repo='unknown', branch='master'): # branch is actually the list of branches branches = branch with utility.cd(repo): currentBranch = git.currentBranch() if len(branches) > 0: git.fetch("--prune --tags") allRemoteBranches = git.remoteBranches() fetchArgs = "origin " toFetch = [] for b in branches: if b != currentBranch: if "origin/%s" % b in allRemoteBranches: fetchArgs += "%s:%s " % (b, b) toFetch.append(b) else: try: utility.printMsg("Pulling current branch %s in %s" % (currentBranch, repo)) git.pull("origin %s" % currentBranch) except git.GrapeGitError: print( "GRAPE: Could not pull %s from origin. Maybe you haven't pushed it yet?" % currentBranch) try: if toFetch: utility.printMsg("updating %s in %s" % (','.join(toFetch), repo)) git.fetch(fetchArgs) except git.GrapeGitError as e: # let non-fast-forward fetches slide if "rejected" in e.gitOutput and "non-fast-forward" in e.gitOutput: print e.gitCommand print e.gitOutput print( "GRAPE: WARNING: one of your public branches %s in %s has local commits! " "Did you forget to create a topic branch?" % (",".join(branches), repo)) pass elif "Refusing to fetch into current branch" in e.gitOutput: print e.gitOutput else: raise e
def lookupPublicBranch(): config = grapeConfig.grapeConfig() try: currentBranch = git.currentBranch() except git.GrapeGitError: return 'unknown' if currentBranch in config.get('flow', 'publicBranches'): return currentBranch try: branch = config.getPublicBranchFor(currentBranch) except KeyError: branchPrefix = git.branchPrefix(currentBranch) print( "WARNING: prefix %s does not have an associated topic branch, nor is a default" "public branch configured. \n" "use --public=<branch> to define, or add %s:<branch> or ?:<branch> to \n" "[flow].publicBranches in your .grapeconfig or .git/.grapeuserconfig. " % (branchPrefix, branchPrefix)) branch = None return branch
def postCommit(args): #applies the autoPush hook autoPush = args["--autopush"] if autoPush.lower().strip() != "false": try: git.push("-u origin HEAD") except git.GrapeGitError: pass autoPush = True else: autoPush = False #applies the cascade hook print("GRAPE: checking for cascades...") cascadeDict = grapeConfig.GrapeConfigParser.parseConfigPairList( args["--cascade"]) if cascadeDict: currentBranch = git.currentBranch() while currentBranch in cascadeDict: source = currentBranch target = cascadeDict[source] fastForward = False print("GRAPE: Cascading commit from %s to %s..." % (source, target)) if git.branchUpToDateWith(source, target): fastForward = True print("GRAPE: should be a fastforward cascade...") git.checkout("%s" % target) git.merge("%s -m 'Cascade from %s to %s'" % (source, source, target)) # we need to kick off the next one if it was a fast forward merge. # otherwise, another post-commit hook should be called from the merge commit. if fastForward: if autoPush: git.push("origin %s" % target) print("GRAPE: auto push done") currentBranch = target else: currentBranch = None
def fetchLocal(repo='unknown', branch='master'): # branch is actually the list of branches branches = branch with utility.cd(repo): currentBranch = git.currentBranch() if len(branches) > 0: git.fetch("--prune --tags") allRemoteBranches = git.remoteBranches() fetchArgs = "origin " toFetch = [] for b in branches: if b != currentBranch: if "origin/%s" % b in allRemoteBranches: fetchArgs += "%s:%s " % (b, b) toFetch.append(b) else: try: utility.printMsg("Pulling current branch %s in %s" % (currentBranch, repo)) git.pull("origin %s" % currentBranch) except git.GrapeGitError: print("GRAPE: Could not pull %s from origin. Maybe you haven't pushed it yet?" % currentBranch) try: if toFetch: utility.printMsg("updating %s in %s" % (','.join(toFetch), repo)) git.fetch(fetchArgs) except git.GrapeGitError as e: # let non-fast-forward fetches slide if "rejected" in e.gitOutput and "non-fast-forward" in e.gitOutput: print e.gitCommand print e.gitOutput print("GRAPE: WARNING: one of your public branches %s in %s has local commits! " "Did you forget to create a topic branch?" % (",".join(branches), repo)) pass elif "Refusing to fetch into current branch" in e.gitOutput: print e.gitOutput else: raise e
def execute(self, args): if not "<<cmd>>" in args: args["<<cmd>>"] = "md" branch = args["--public"] if not branch: currentBranch = git.currentBranch() branch = grapeConfig.grapeConfig().getPublicBranchFor( git.currentBranch()) if not branch: utility.printMsg( "ERROR: public branches must be configured for grape md to work." ) args["--public"] = branch # determine whether to merge in subprojects that have changed try: submodules = self.progress["submodules"] except KeyError: modifiedSubmodules = git.getModifiedSubmodules( branch, git.currentBranch()) activeSubmodules = git.getActiveSubmodules() submodules = [ sub for sub in modifiedSubmodules if sub in activeSubmodules ] try: nested = self.progress["nested"] except KeyError: nested = grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes( ) config = grapeConfig.grapeConfig() recurse = config.getboolean("workspace", "manageSubmodules") or args["--recurse"] recurse = recurse and (not args["--noRecurse"]) and len(submodules) > 0 args["--recurse"] = recurse # if we stored cwd in self.progress, make sure we end up there if "cwd" in self.progress: cwd = self.progress["cwd"] else: cwd = utility.workspaceDir() os.chdir(cwd) if "conflictedFiles" in self.progress: conflictedFiles = self.progress["conflictedFiles"] else: conflictedFiles = [] # take note of whether all submodules are currently present, assume user wants to add any new submodules to WS if so activeSubmodulesCheck0 = git.getActiveSubmodules() self.progress["allActive"] = set(git.getAllSubmodules()) == set( git.getActiveSubmodules()) # checking for a consistent workspace before doing a merge utility.printMsg( "Checking for a consistent workspace before performing merge...") ret = grapeMenu.menu().applyMenuChoice("status", ['--failIfInconsistent']) if ret is False: utility.printMsg( "Workspace inconsistent! Aborting attempt to do the merge. Please address above issues and then try again." ) return False if not "updateLocalDone" in self.progress and not args["--noUpdate"]: # make sure public branches are to date in outer level repo. utility.printMsg( "Calling grape up to ensure topic and public branches are up-to-date. " ) grapeMenu.menu().applyMenuChoice( 'up', ['up', '--public=%s' % args["--public"]]) self.progress["updateLocalDone"] = True # do an outer merge if we haven't done it yet if not "outerLevelDone" in self.progress: self.progress["outerLevelDone"] = False if not self.progress["outerLevelDone"]: conflictedFiles = self.outerLevelMerge(args, branch) # outerLevelMerge returns False if there was a non-conflict related issue if conflictedFiles is False: utility.printMsg( "Initial merge failed. Resolve issue and try again. ") return False # merge nested subprojects for subproject in nested: if not self.mergeSubproject( args, subproject, branch, nested, cwd, isSubmodule=False): # stop for user to resolve conflicts self.progress["nested"] = nested self.dumpProgress(args) os.chdir(cwd) return False os.chdir(cwd) # merge submodules if recurse: if len(submodules) > 0: if args["--subpublic"]: # respect the callers wishes (usually this is grape m , mr, or pull) subPublic = args["--subpublic"] else: # default is to merge the submodule branch that is mapped to the public branch subBranchMappings = config.getMapping( "workspace", "submodulePublicMappings") subPublic = subBranchMappings[config.getPublicBranchFor( branch)] for submodule in submodules: if not self.mergeSubproject(args, submodule, subPublic, submodules, cwd, isSubmodule=True): # stop for user to resolve conflicts self.progress["conflictedFiles"] = conflictedFiles self.dumpProgress(args) return False os.chdir(cwd) conflictedFiles = git.conflictedFiles() # now that we resolved the submodule conflicts, continue the outer level merge if len(conflictedFiles) == 0: self.continueLocalMerge(args) conflictedFiles = git.conflictedFiles() if conflictedFiles: self.progress["stopPoint"] = "resolve conflicts" self.progress["cwd"] = cwd self.dumpProgress( args, "GRAPE: Outer level merge generated conflicts. Please resolve using git mergetool " "and then \n continue by calling 'grape md --continue' .") return False else: grapeMenu.menu().applyMenuChoice("runHook", ["post-merge", '0', "--noExit"]) # ensure all submodules are currently present in WS if all submodules were present at the beginning of merge if self.progress["allActive"]: activeSubmodulesCheck1 = git.getActiveSubmodules() if (set(activeSubmodulesCheck0) != set(activeSubmodulesCheck1)): utility.printMsg( "Updating new submodules using grape uv --allSubmodules") grapeMenu.menu().applyMenuChoice( "uv", ["--allSubmodules", "--skipNestedSubprojects"]) return True
def execute(self, args): """ A fair chunk of this stuff relies on stashy's wrapping of the STASH REST API, which is posted at https://developer.atlassian.com/static/rest/stash/2.12.1/stash-rest.html """ config = grapeConfig.grapeConfig() name = args["--user"] if not name: name = utility.getUserName() utility.printMsg("Logging onto %s" % args["--bitbucketURL"]) if args["--test"]: bitbucket = Atlassian.TestAtlassian(name) else: verify = True if args["--verifySSL"].lower() == "true" else False bitbucket = Atlassian.Atlassian(name, url=args["--bitbucketURL"], verify=verify) # default project (outer level project) project_name = args["--project"] # default repo (outer level repo) repo_name = args["--repo"] # determine source branch and target branch branch = args["--source"] if not branch: branch = git.currentBranch() # make sure we are in the outer level repo before we push wsDir = utility.workspaceDir() os.chdir(wsDir) #ensure branch is pushed utility.printMsg("Pushing %s to bitbucket..." % branch) git.push("origin %s" % branch) #target branch for outer level repo target_branch = args["--target"] if not target_branch: target_branch = config.getPublicBranchFor(branch) # load pull request from Bitbucket if it already exists wsRepo = bitbucket.project(project_name).repo(repo_name) existingOuterLevelRequest = getReposPullRequest( wsRepo, branch, target_branch, args) # determine pull request title title = args["--title"] if existingOuterLevelRequest is not None and not title: title = existingOuterLevelRequest.title() #determine pull request URL outerLevelURL = None if existingOuterLevelRequest: outerLevelURL = existingOuterLevelRequest.link() # determine pull request description descr = self.parseDescriptionArgs(args) if not descr and existingOuterLevelRequest: descr = existingOuterLevelRequest.description() # determine pull request reviewers reviewers = self.parseReviewerArgs(args) if reviewers is None and existingOuterLevelRequest is not None: reviewers = [r[0] for r in existingOuterLevelRequest.reviewers()] # if we're in append mode, only append what was asked for: if args["--append"] or args["--prepend"]: title = args["--title"] descr = self.parseDescriptionArgs(args) reviewers = self.parseReviewerArgs(args) ## Submodule Repos missing = utility.getModifiedInactiveSubmodules(target_branch, branch) if missing: utility.printMsg( "The following submodules that you've modified are not currently present in your workspace.\n" "You should activate them using grape uv and then call grape review again. If you haven't modified " "these submodules, you may need to do a grape md to proceed.") utility.printMsg(','.join(missing)) return False pullRequestLinks = {} if not args["--norecurse"] and (args["--recurse"] or config.getboolean( "workspace", "manageSubmodules")): modifiedSubmodules = git.getModifiedSubmodules( target_branch, branch) submoduleBranchMappings = config.getMapping( "workspace", "submoduleTopicPrefixMappings") for submodule in modifiedSubmodules: if not submodule: continue # push branch os.chdir(submodule) utility.printMsg("Pushing %s to bitbucket..." % branch) git.push("origin %s" % branch) os.chdir(wsDir) repo = bitbucket.repoFromWorkspaceRepoPath(submodule, isSubmodule=True) # determine branch prefix prefix = branch.split('/')[0] sub_target_branch = submoduleBranchMappings[prefix] prevSubDescr = getReposPullRequestDescription( repo, branch, sub_target_branch, args) #amend the subproject pull request description with the link to the outer pull request subDescr = addLinkToDescription(descr, outerLevelURL, True) if args["--prepend"] or args["--append"]: subDescr = descr newRequest = postPullRequest(repo, title, branch, sub_target_branch, subDescr, reviewers, args) if newRequest: pullRequestLinks[newRequest.link()] = True else: # if a pull request could not be generated, just add a link to browse the branch pullRequestLinks[ "%s%s/browse?at=%s" % (bitbucket.rzbitbucketURL, repo.repo.url(), urllib.quote_plus("refs/heads/%s" % branch))] = False ## NESTED SUBPROJECT REPOS nestedProjects = grapeConfig.GrapeConfigParser.getAllModifiedNestedSubprojects( target_branch) nestedProjectPrefixes = grapeConfig.GrapeConfigParser.getAllModifiedNestedSubprojectPrefixes( target_branch) for proj, prefix in zip(nestedProjects, nestedProjectPrefixes): with utility.cd(prefix): git.push("origin %s" % branch) repo = bitbucket.repoFromWorkspaceRepoPath(proj, isSubmodule=False, isNested=True) newRequest = postPullRequest(repo, title, branch, target_branch, descr, reviewers, args) if newRequest: pullRequestLinks[newRequest.link()] = True else: # if a pull request could not be generated, just add a link to browse the branch pullRequestLinks["%s%s/browse?at=%s" % (bitbucket.rzbitbucketURL, repo.repo.url(), urllib.quote_plus( "refs/heads/%s" % branch))] = False ## OUTER LEVEL REPO # load the repo level REST resource if not args["--subprojectsOnly"]: if not git.hasBranch(branch): utility.printMsg( "Top level repository does not have a branch %s, not generating a Pull Request" % (branch)) return True if git.branchUpToDateWith(target_branch, branch): utility.printMsg( "%s up to date with %s, not generating a Pull Request in Top Level repo" % (target_branch, branch)) return True repo_name = args["--repo"] repo = bitbucket.repoFromWorkspaceRepoPath( wsDir, topLevelRepo=repo_name, topLevelProject=project_name) utility.printMsg("Posting pull request to %s,%s" % (project_name, repo_name)) request = postPullRequest(repo, title, branch, target_branch, descr, reviewers, args) updatedDescription = request.description() for link in pullRequestLinks: updatedDescription = addLinkToDescription( updatedDescription, link, pullRequestLinks[link]) if updatedDescription != request.description(): request = postPullRequest(repo, title, branch, target_branch, updatedDescription, reviewers, args) utility.printMsg("Request generated/updated:\n\n%s" % request) return True
def execute(self, args): if TkinterImportError: utility.printMsg( "grape w requires Tkinter.\n The following error was raised during the import:\n\n%s\n" % TkinterImportError) return True config = grapeConfig.grapeConfig() difftool = args["--difftool"] height = args["--height"] width = args["--width"] doMergeDiff = True if args["--rawDiff"]: doMergeDiff = False elif args["--mergeDiff"]: # This is already the default doMergeDiff = True cwd = os.getcwd() os.chdir(utility.workspaceDir()) b1 = args["<b1>"] if not b1: b1 = git.currentBranch() b2 = args["<b2>"] if args["--staged"]: b2 = b1 b1 = "--cached" doMergeDiff = False elif args["--workspace"]: b2 = "--" doMergeDiff = False else: if not b2: try: # put the public branch first so merge diff shows # changes on the current branch. b2 = b1 b1 = config.getPublicBranchFor(b2) except: b2 = "" doMergeDiff = False diffargs = "" root = Tk.Tk() root.title("GRAPE walkthrough") diffmanager = DiffManager( master=root, height=height, width=width, branchA=b1, branchB=b2, difftool=difftool, diffargs=diffargs, doMergeDiff=doMergeDiff, showUnchanged=args["--showUnchanged"], showInactive=not args["--noInactive"], showToplevel=not args["--noTopLevel"], showSubmodules=not args["--noSubmodules"], showSubtrees=not args["--noSubtrees"], showNestedSubprojects=not args["--noNestedSubprojects"], noFetch=args["--noFetch"]) root.mainloop() os.chdir(cwd) try: root.destroy() except: pass return True
def mergeSubproject(self, args, subproject, subPublic, subprojects, cwd, isSubmodule=True): # if we did this merge in a previous run, don't do it again try: if self.progress["Subproject: %s" % subproject] == "finished": return True except KeyError: pass os.chdir(os.path.join(git.baseDir(), subproject)) mergeArgs = args.copy() mergeArgs["--public"] = subPublic utility.printMsg( "Merging %s into %s for %s %s" % (subPublic, git.currentBranch(), "submodule" if isSubmodule else "subproject", subproject)) git.fetch("origin") # update our local reference to the remote branch so long as it's fast-forwardable or we don't have it yet..) hasRemote = git.hasBranch("origin/%s" % subPublic) hasBranch = git.hasBranch(subPublic) if hasRemote and (git.branchUpToDateWith( subPublic, "origin/%s" % subPublic) or not hasBranch): git.fetch("origin %s:%s" % (subPublic, subPublic)) ret = self.mergeIntoCurrent(subPublic, mergeArgs, subproject) conflict = not ret if conflict: self.progress["stopPoint"] = "Subproject: %s" % subproject subprojectKey = "submodules" if isSubmodule else "nested" self.progress[subprojectKey] = subprojects self.progress["cwd"] = cwd conflictedFiles = git.conflictedFiles() if conflictedFiles: if isSubmodule: typeStr = "submodule" else: typeStr = "nested subproject" utility.printMsg( "Merge in %s %s from %s to %s issued conflicts. Resolve and commit those changes \n" "using git mergetool and git commit in the submodule, then continue using grape\n" "%s --continue" % (typeStr, subproject, subPublic, git.currentBranch(), args["<<cmd>>"])) else: utility.printMsg( "Merge in %s failed for an unhandled reason. You may need to stash / commit your current\n" "changes before doing the merge. Inspect git output above to troubleshoot. Continue using\n" "grape %s --continue." % (subproject, args["<<cmd>>"])) return False # if we are resuming from a conflict, the above grape m call would have taken care of continuing. # clear out the --continue flag. args["--continue"] = False # stage the updated submodule os.chdir(cwd) if isSubmodule: git.add(subproject) self.progress["Subproject: %s" % subproject] = "finished" return True
def execute(self, args): sync = args["--sync"].lower().strip() sync = sync == "true" or sync == "yes" args["--sync"] = sync config = grapeConfig.grapeConfig() origwd = os.getcwd() wsDir = utility.workspaceDir() os.chdir(wsDir) base = git.baseDir() if base == "": return False hasSubmodules = len(git.getAllSubmodules()) > 0 and not args["--skipSubmodules"] includedSubmodules = {} includedNestedSubprojectPrefixes = {} allSubmodules = git.getAllSubmodules() allNestedSubprojects = config.getAllNestedSubprojects() addedSubmodules = [] addedNestedSubprojects = [] addedProjects = args["--add"] notFound = [] for proj in addedProjects: if proj in allSubmodules: addedSubmodules.append(proj) elif proj in allNestedSubprojects: addedNestedSubprojects.append(proj) else: notFound.append(proj) rmSubmodules = [] rmNestedSubprojects = [] rmProjects = args["--rm"] for proj in rmProjects: if proj in allSubmodules: rmSubmodules.append(proj) elif proj in allNestedSubprojects: rmNestedSubprojects.append(proj) else: notFound.append(proj) if notFound: utility.printMsg("\"%s\" not found in submodules %s \nor\n nested subprojects %s" % (",".join(notFound),",".join(allSubmodules),",".join(allNestedSubprojects))) return False if not args["--checkSubprojects"]: # get submodules to update if hasSubmodules: if args["--allSubmodules"]: includedSubmodules = {sub:True for sub in allSubmodules} elif args["--add"] or args["--rm"]: includedSubmodules = {sub:True for sub in git.getActiveSubmodules()} includedSubmodules.update({sub:True for sub in addedSubmodules}) includedSubmodules.update({sub:False for sub in rmSubmodules}) else: includedSubmodules = self.defineActiveSubmodules() # get subprojects to update if not args["--skipNestedSubprojects"]: nestedPrefixLookup = lambda x : config.get("nested-%s" % x, "prefix") if args["--allNestedSubprojects"]: includedNestedSubprojectPrefixes = {nestedPrefixLookup(sub):True for sub in allNestedSubprojects} elif args["--add"] or args["--rm"]: includedNestedSubprojectPrefixes = {sub:True for sub in grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes()} includedNestedSubprojectPrefixes.update({nestedPrefixLookup(sub):True for sub in addedNestedSubprojects}) includedNestedSubprojectPrefixes.update({nestedPrefixLookup(sub):False for sub in rmNestedSubprojects}) else: includedNestedSubprojectPrefixes = self.defineActiveNestedSubprojects() if hasSubmodules: initStr = "" deinitStr = "" rmCachedStr = "" resetStr = "" for submodule, nowActive in includedSubmodules.items(): if nowActive: initStr += ' %s' % submodule else: deinitStr += ' %s' % submodule rmCachedStr += ' %s' % submodule resetStr += ' %s' % submodule if args["-f"] and deinitStr: deinitStr = "-f"+deinitStr utility.printMsg("Configuring submodules...") utility.printMsg("Initializing submodules...") git.submodule("init %s" % initStr.strip()) if deinitStr: utility.printMsg("Deiniting submodules that were not requested... (%s)" % deinitStr) done = False while not done: try: git.submodule("deinit %s" % deinitStr.strip()) done = True except git.GrapeGitError as e: if "the following file has local modifications" in e.gitOutput: print e.gitOutput utility.printMsg("A submodule that you wanted to remove has local modifications. " "Use grape uv -f to force removal.") return False elif "use 'rm -rf' if you really want to remove it including all of its history" in e.gitOutput: if not args["-f"]: raise e # it is safe to move the .git of the submodule to the .git/modules area of the workspace... module = None for l in e.gitOutput.split('\n'): if "Submodule work tree" in l and "contains a .git directory" in l: module = l.split("'")[1] break if module: src = os.path.join(module, ".git") dest = os.path.join(wsDir, ".git", "modules", module) utility.printMsg("Moving %s to %s"%(src, dest)) shutil.move(src, dest ) else: raise e else: raise e git.rm("--cached %s" % rmCachedStr) git.reset(" %s" % resetStr) if initStr: utility.printMsg("Updating active submodules...(%s)" % initStr) git.submodule("update") # handle nested subprojects if not args["--skipNestedSubprojects"]: reverseLookupByPrefix = {nestedPrefixLookup(sub) : sub for sub in allNestedSubprojects} userConfig = grapeConfig.grapeUserConfig() updatedActiveList = [] for subproject, nowActive in includedNestedSubprojectPrefixes.items(): subprojectName = reverseLookupByPrefix[subproject] section = "nested-%s" % reverseLookupByPrefix[subproject] userConfig.ensureSection(section) previouslyActive = userConfig.getboolean(section, "active") previouslyActive = previouslyActive and os.path.exists(os.path.join(base, subproject, ".git")) userConfig.set(section, "active", "True" if previouslyActive else "False") if nowActive and previouslyActive: updatedActiveList.append(subprojectName) if nowActive and not previouslyActive: utility.printMsg("Activating Nested Subproject %s" % subproject) if not addSubproject.AddSubproject.activateNestedSubproject(subprojectName, userConfig): utility.printMsg("Can't activate %s. Exiting..." % subprojectName) return False updatedActiveList.append(subprojectName) if not nowActive and not previouslyActive: pass if not nowActive and previouslyActive: #remove the subproject subprojectdir = os.path.join(base, utility.makePathPortable(subproject)) proceed = args["-f"] or \ utility.userInput("About to delete all contents in %s. Any uncommitted changes, committed changes " "that have not been pushed, or ignored files will be lost. Proceed?" % subproject, 'n') if proceed: shutil.rmtree(subprojectdir) userConfig.setActiveNestedSubprojects(updatedActiveList) grapeConfig.writeConfig(userConfig, os.path.join(utility.workspaceDir(), ".git", ".grapeuserconfig")) checkoutArgs = "-b" if args["-b"] else "" safeSwitchWorkspaceToBranch( git.currentBranch(), checkoutArgs, sync) os.chdir(origwd) return True
def execute(self, args): sync = args["--sync"].lower().strip() sync = sync == "true" or sync == "yes" args["--sync"] = sync config = grapeConfig.grapeConfig() origwd = os.getcwd() wsDir = utility.workspaceDir() os.chdir(wsDir) base = git.baseDir() if base == "": return False hasSubmodules = len( git.getAllSubmodules()) > 0 and not args["--skipSubmodules"] includedSubmodules = {} includedNestedSubprojectPrefixes = {} allSubmodules = git.getAllSubmodules() allNestedSubprojects = config.getAllNestedSubprojects() addedSubmodules = [] addedNestedSubprojects = [] addedProjects = args["--add"] notFound = [] for proj in addedProjects: if proj in allSubmodules: addedSubmodules.append(proj) elif proj in allNestedSubprojects: addedNestedSubprojects.append(proj) else: notFound.append(proj) rmSubmodules = [] rmNestedSubprojects = [] rmProjects = args["--rm"] for proj in rmProjects: if proj in allSubmodules: rmSubmodules.append(proj) elif proj in allNestedSubprojects: rmNestedSubprojects.append(proj) else: notFound.append(proj) if notFound: utility.printMsg( "\"%s\" not found in submodules %s \nor\n nested subprojects %s" % (",".join(notFound), ",".join(allSubmodules), ",".join(allNestedSubprojects))) return False if not args["--checkSubprojects"]: # get submodules to update if hasSubmodules: if args["--allSubmodules"]: includedSubmodules = {sub: True for sub in allSubmodules} elif args["--add"] or args["--rm"]: includedSubmodules = { sub: True for sub in git.getActiveSubmodules() } includedSubmodules.update( {sub: True for sub in addedSubmodules}) includedSubmodules.update( {sub: False for sub in rmSubmodules}) else: includedSubmodules = self.defineActiveSubmodules() # get subprojects to update if not args["--skipNestedSubprojects"]: nestedPrefixLookup = lambda x: config.get( "nested-%s" % x, "prefix") if args["--allNestedSubprojects"]: includedNestedSubprojectPrefixes = { nestedPrefixLookup(sub): True for sub in allNestedSubprojects } elif args["--add"] or args["--rm"]: includedNestedSubprojectPrefixes = { sub: True for sub in grapeConfig.GrapeConfigParser. getAllActiveNestedSubprojectPrefixes() } includedNestedSubprojectPrefixes.update({ nestedPrefixLookup(sub): True for sub in addedNestedSubprojects }) includedNestedSubprojectPrefixes.update({ nestedPrefixLookup(sub): False for sub in rmNestedSubprojects }) else: includedNestedSubprojectPrefixes = self.defineActiveNestedSubprojects( ) if hasSubmodules: initStr = "" deinitStr = "" rmCachedStr = "" resetStr = "" for submodule, nowActive in includedSubmodules.items(): if nowActive: initStr += ' %s' % submodule else: deinitStr += ' %s' % submodule rmCachedStr += ' %s' % submodule resetStr += ' %s' % submodule if args["-f"] and deinitStr: deinitStr = "-f" + deinitStr utility.printMsg("Configuring submodules...") utility.printMsg("Initializing submodules...") git.submodule("init %s" % initStr.strip()) if deinitStr: utility.printMsg( "Deiniting submodules that were not requested... (%s)" % deinitStr) done = False while not done: try: git.submodule("deinit %s" % deinitStr.strip()) done = True except git.GrapeGitError as e: if "the following file has local modifications" in e.gitOutput: print e.gitOutput utility.printMsg( "A submodule that you wanted to remove has local modifications. " "Use grape uv -f to force removal.") return False elif "use 'rm -rf' if you really want to remove it including all of its history" in e.gitOutput: if not args["-f"]: raise e # it is safe to move the .git of the submodule to the .git/modules area of the workspace... module = None for l in e.gitOutput.split('\n'): if "Submodule work tree" in l and "contains a .git directory" in l: module = l.split("'")[1] break if module: src = os.path.join(module, ".git") dest = os.path.join( wsDir, ".git", "modules", module) utility.printMsg("Moving %s to %s" % (src, dest)) shutil.move(src, dest) else: raise e else: raise e git.rm("--cached %s" % rmCachedStr) git.reset(" %s" % resetStr) if initStr: utility.printMsg("Updating active submodules...(%s)" % initStr) git.submodule("update") # handle nested subprojects if not args["--skipNestedSubprojects"]: reverseLookupByPrefix = { nestedPrefixLookup(sub): sub for sub in allNestedSubprojects } userConfig = grapeConfig.grapeUserConfig() updatedActiveList = [] for subproject, nowActive in includedNestedSubprojectPrefixes.items( ): subprojectName = reverseLookupByPrefix[subproject] section = "nested-%s" % reverseLookupByPrefix[subproject] userConfig.ensureSection(section) previouslyActive = userConfig.getboolean(section, "active") previouslyActive = previouslyActive and os.path.exists( os.path.join(base, subproject, ".git")) userConfig.set(section, "active", "True" if previouslyActive else "False") if nowActive and previouslyActive: updatedActiveList.append(subprojectName) if nowActive and not previouslyActive: utility.printMsg("Activating Nested Subproject %s" % subproject) if not addSubproject.AddSubproject.activateNestedSubproject( subprojectName, userConfig): utility.printMsg("Can't activate %s. Exiting..." % subprojectName) return False updatedActiveList.append(subprojectName) if not nowActive and not previouslyActive: pass if not nowActive and previouslyActive: #remove the subproject subprojectdir = os.path.join( base, utility.makePathPortable(subproject)) proceed = args["-f"] or \ utility.userInput("About to delete all contents in %s. Any uncommitted changes, committed changes " "that have not been pushed, or ignored files will be lost. Proceed?" % subproject, 'n') if proceed: shutil.rmtree(subprojectdir) userConfig.setActiveNestedSubprojects(updatedActiveList) grapeConfig.writeConfig( userConfig, os.path.join(utility.workspaceDir(), ".git", ".grapeuserconfig")) checkoutArgs = "-b" if args["-b"] else "" safeSwitchWorkspaceToBranch(git.currentBranch(), checkoutArgs, sync) os.chdir(origwd) return True
def execute(self, args): """ A fair chunk of this stuff relies on stashy's wrapping of the STASH REST API, which is posted at https://developer.atlassian.com/static/rest/stash/2.12.1/stash-rest.html """ config = grapeConfig.grapeConfig() name = args["--user"] if not name: name = utility.getUserName() utility.printMsg("Logging onto %s" % args["--bitbucketURL"]) if args["--test"]: bitbucket = Atlassian.TestAtlassian(name) else: verify = True if args["--verifySSL"].lower() == "true" else False bitbucket = Atlassian.Atlassian(name, url=args["--bitbucketURL"], verify=verify) # default project (outer level project) project_name = args["--project"] # default repo (outer level repo) repo_name = args["--repo"] # determine source branch and target branch branch = args["--source"] if not branch: branch = git.currentBranch() # make sure we are in the outer level repo before we push wsDir = utility.workspaceDir() os.chdir(wsDir) #ensure branch is pushed utility.printMsg("Pushing %s to bitbucket..." % branch) git.push("origin %s" % branch) #target branch for outer level repo target_branch = args["--target"] if not target_branch: target_branch = config.getPublicBranchFor(branch) # load pull request from Bitbucket if it already exists wsRepo = bitbucket.project(project_name).repo(repo_name) existingOuterLevelRequest = getReposPullRequest(wsRepo, branch, target_branch, args) # determine pull request title title = args["--title"] if existingOuterLevelRequest is not None and not title: title = existingOuterLevelRequest.title() #determine pull request URL outerLevelURL = None if existingOuterLevelRequest: outerLevelURL = existingOuterLevelRequest.link() # determine pull request description descr = self.parseDescriptionArgs(args) if not descr and existingOuterLevelRequest: descr = existingOuterLevelRequest.description() # determine pull request reviewers reviewers = self.parseReviewerArgs(args) if reviewers is None and existingOuterLevelRequest is not None: reviewers = [r[0] for r in existingOuterLevelRequest.reviewers()] # if we're in append mode, only append what was asked for: if args["--append"] or args["--prepend"]: title = args["--title"] descr = self.parseDescriptionArgs(args) reviewers = self.parseReviewerArgs(args) ## Submodule Repos missing = utility.getModifiedInactiveSubmodules(target_branch, branch) if missing: utility.printMsg("The following submodules that you've modified are not currently present in your workspace.\n" "You should activate them using grape uv and then call grape review again. If you haven't modified " "these submodules, you may need to do a grape md to proceed.") utility.printMsg(','.join(missing)) return False pullRequestLinks = {} if not args["--norecurse"] and (args["--recurse"] or config.getboolean("workspace", "manageSubmodules")): modifiedSubmodules = git.getModifiedSubmodules(target_branch, branch) submoduleBranchMappings = config.getMapping("workspace", "submoduleTopicPrefixMappings") for submodule in modifiedSubmodules: if not submodule: continue # push branch os.chdir(submodule) utility.printMsg("Pushing %s to bitbucket..." % branch) git.push("origin %s" % branch) os.chdir(wsDir) repo = bitbucket.repoFromWorkspaceRepoPath(submodule, isSubmodule=True) # determine branch prefix prefix = branch.split('/')[0] sub_target_branch = submoduleBranchMappings[prefix] prevSubDescr = getReposPullRequestDescription(repo, branch, sub_target_branch, args) #amend the subproject pull request description with the link to the outer pull request subDescr = addLinkToDescription(descr, outerLevelURL, True) if args["--prepend"] or args["--append"]: subDescr = descr newRequest = postPullRequest(repo, title, branch, sub_target_branch, subDescr, reviewers, args) if newRequest: pullRequestLinks[newRequest.link()] = True else: # if a pull request could not be generated, just add a link to browse the branch pullRequestLinks["%s%s/browse?at=%s" % (bitbucket.rzbitbucketURL, repo.repo.url(), urllib.quote_plus("refs/heads/%s" % branch))] = False ## NESTED SUBPROJECT REPOS nestedProjects = grapeConfig.GrapeConfigParser.getAllModifiedNestedSubprojects(target_branch) nestedProjectPrefixes = grapeConfig.GrapeConfigParser.getAllModifiedNestedSubprojectPrefixes(target_branch) for proj, prefix in zip(nestedProjects, nestedProjectPrefixes): with utility.cd(prefix): git.push("origin %s" % branch) repo = bitbucket.repoFromWorkspaceRepoPath(proj, isSubmodule=False, isNested=True) newRequest = postPullRequest(repo, title, branch, target_branch,descr, reviewers, args) if newRequest: pullRequestLinks[newRequest.link()] = True else: # if a pull request could not be generated, just add a link to browse the branch pullRequestLinks["%s%s/browse?at=%s" % (bitbucket.rzbitbucketURL, repo.repo.url(), urllib.quote_plus("refs/heads/%s" % branch))] = False ## OUTER LEVEL REPO # load the repo level REST resource if not args["--subprojectsOnly"]: if not git.hasBranch(branch): utility.printMsg("Top level repository does not have a branch %s, not generating a Pull Request" % (branch)) return True if git.branchUpToDateWith(target_branch, branch): utility.printMsg("%s up to date with %s, not generating a Pull Request in Top Level repo" % (target_branch, branch)) return True repo_name = args["--repo"] repo = bitbucket.repoFromWorkspaceRepoPath(wsDir, topLevelRepo=repo_name, topLevelProject=project_name) utility.printMsg("Posting pull request to %s,%s" % (project_name, repo_name)) request = postPullRequest(repo, title, branch, target_branch, descr, reviewers, args) updatedDescription = request.description() for link in pullRequestLinks: updatedDescription = addLinkToDescription(updatedDescription, link, pullRequestLinks[link]) if updatedDescription != request.description(): request = postPullRequest(repo, title, branch, target_branch, updatedDescription, reviewers, args) utility.printMsg("Request generated/updated:\n\n%s" % request) return True
def execute(self, args): if not "<<cmd>>" in args: args["<<cmd>>"] = "md" branch = args["--public"] if not branch: currentBranch = git.currentBranch() branch = grapeConfig.grapeConfig().getPublicBranchFor(git.currentBranch()) if not branch: utility.printMsg("ERROR: public branches must be configured for grape md to work.") args["--public"] = branch # determine whether to merge in subprojects that have changed try: submodules = self.progress["submodules"] except KeyError: modifiedSubmodules = git.getModifiedSubmodules(branch, git.currentBranch()) activeSubmodules = git.getActiveSubmodules() submodules = [sub for sub in modifiedSubmodules if sub in activeSubmodules] try: nested = self.progress["nested"] except KeyError: nested = grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes() config = grapeConfig.grapeConfig() recurse = config.getboolean("workspace", "manageSubmodules") or args["--recurse"] recurse = recurse and (not args["--noRecurse"]) and len(submodules) > 0 args["--recurse"] = recurse # if we stored cwd in self.progress, make sure we end up there if "cwd" in self.progress: cwd = self.progress["cwd"] else: cwd = utility.workspaceDir() os.chdir(cwd) if "conflictedFiles" in self.progress: conflictedFiles = self.progress["conflictedFiles"] else: conflictedFiles = [] # take note of whether all submodules are currently present, assume user wants to add any new submodules to WS if so activeSubmodulesCheck0 = git.getActiveSubmodules() self.progress["allActive"] = set(git.getAllSubmodules()) == set(git.getActiveSubmodules()) # checking for a consistent workspace before doing a merge utility.printMsg("Checking for a consistent workspace before performing merge...") ret = grapeMenu.menu().applyMenuChoice("status", ['--failIfInconsistent']) if ret is False: utility.printMsg("Workspace inconsistent! Aborting attempt to do the merge. Please address above issues and then try again.") return False if not "updateLocalDone" in self.progress and not args["--noUpdate"]: # make sure public branches are to date in outer level repo. utility.printMsg("Calling grape up to ensure topic and public branches are up-to-date. ") grapeMenu.menu().applyMenuChoice('up', ['up','--public=%s' % args["--public"]]) self.progress["updateLocalDone"] = True # do an outer merge if we haven't done it yet if not "outerLevelDone" in self.progress: self.progress["outerLevelDone"] = False if not self.progress["outerLevelDone"]: conflictedFiles = self.outerLevelMerge(args, branch) # outerLevelMerge returns False if there was a non-conflict related issue if conflictedFiles is False: utility.printMsg("Initial merge failed. Resolve issue and try again. ") return False # merge nested subprojects for subproject in nested: if not self.mergeSubproject(args, subproject, branch, nested, cwd, isSubmodule=False): # stop for user to resolve conflicts self.progress["nested"] = nested self.dumpProgress(args) os.chdir(cwd) return False os.chdir(cwd) # merge submodules if recurse: if len(submodules) > 0: if args["--subpublic"]: # respect the callers wishes (usually this is grape m , mr, or pull) subPublic = args["--subpublic"] else: # default is to merge the submodule branch that is mapped to the public branch subBranchMappings = config.getMapping("workspace", "submodulePublicMappings") subPublic = subBranchMappings[config.getPublicBranchFor(branch)] for submodule in submodules: if not self.mergeSubproject(args, submodule, subPublic, submodules, cwd, isSubmodule=True): # stop for user to resolve conflicts self.progress["conflictedFiles"] = conflictedFiles self.dumpProgress(args) return False os.chdir(cwd) conflictedFiles = git.conflictedFiles() # now that we resolved the submodule conflicts, continue the outer level merge if len(conflictedFiles) == 0: self.continueLocalMerge(args) conflictedFiles = git.conflictedFiles() if conflictedFiles: self.progress["stopPoint"] = "resolve conflicts" self.progress["cwd"] = cwd self.dumpProgress(args, "GRAPE: Outer level merge generated conflicts. Please resolve using git mergetool " "and then \n continue by calling 'grape md --continue' .") return False else: grapeMenu.menu().applyMenuChoice("runHook", ["post-merge", '0', "--noExit"]) # ensure all submodules are currently present in WS if all submodules were present at the beginning of merge if self.progress["allActive"]: activeSubmodulesCheck1 = git.getActiveSubmodules() if (set(activeSubmodulesCheck0) != set(activeSubmodulesCheck1)): utility.printMsg("Updating new submodules using grape uv --allSubmodules") grapeMenu.menu().applyMenuChoice("uv", ["--allSubmodules", "--skipNestedSubprojects"]) return True
def execute(self,args): if TkinterImportError: utility.printMsg("grape w requires Tkinter.\n The following error was raised during the import:\n\n%s\n" % TkinterImportError) return True config = grapeConfig.grapeConfig() difftool = args["--difftool"] height = args["--height"] width = args["--width"] doMergeDiff = True if args["--rawDiff"]: doMergeDiff = False elif args["--mergeDiff"]: # This is already the default doMergeDiff = True cwd = os.getcwd() os.chdir(utility.workspaceDir()) b1 = args["<b1>"] if not b1: b1 = git.currentBranch() b2 = args["<b2>"] if args["--staged"]: b2 = b1 b1 = "--cached" doMergeDiff = False elif args["--workspace"]: b2 = "--" doMergeDiff = False else: if not b2: try: # put the public branch first so merge diff shows # changes on the current branch. b2 = b1 b1 = config.getPublicBranchFor(b2) except: b2 = "" doMergeDiff = False diffargs = "" root = Tk.Tk() root.title("GRAPE walkthrough") diffmanager = DiffManager(master=root, height=height, width=width, branchA=b1, branchB=b2, difftool=difftool, diffargs=diffargs, doMergeDiff=doMergeDiff, showUnchanged=args["--showUnchanged"], showInactive=not args["--noInactive"], showToplevel=not args["--noTopLevel"], showSubmodules=not args["--noSubmodules"], showSubtrees=not args["--noSubtrees"], showNestedSubprojects=not args["--noNestedSubprojects"], noFetch=args["--noFetch"]) root.mainloop() os.chdir(cwd) try: root.destroy() except: pass return True
def parseArgs(self, args): config = grapeConfig.grapeConfig() # parse tagSuffix for version mappings if args["--tagSuffix"] is None: branch2suffix = config.getMapping("versioning", "branchtagsuffixmappings") args["--tagSuffix"] = branch2suffix[git.currentBranch()]