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 execute(self, args): try: clonePath = git.baseDir() if clonePath == "": return False except git.GrapeGitError: pass clonePath = args["--source"] if not clonePath: clonePath = utility.userInput("Enter path to original clone", clonePath) newTree = args["--dest"] if not newTree: newTree = utility.userInput("Enter name of new working tree") newTreePath = args["--destPath"] if not newTreePath: newTreePath = utility.userInput("Enter desired location of new working tree (must exist)", os.path.realpath(os.path.join(clonePath, "../"))) newRepo = os.path.join(newTreePath, newTree) #TODO: When grape is installed to PUBLIC, the first argument here should be the # publically available git-new-workdir, instead of the version in the local repo. p = utility.executeSubProcess(os.path.join(os.path.dirname(__file__), "..", "git-new-workdir") + " " + clonePath + " " + newRepo, workingDirectory=os.getcwd()) p.wait() os.chdir(newRepo) if not args["--noSparse"]: print "created new working tree %s in %s. Calling grape uv from new workspace now." % (newTree, newTreePath) menu = grapeMenu.menu() return menu.applyMenuChoice('uv', ["uv"] + args["<uvargs>"]) else: git.checkout("HEAD") return True
def merge(self, branch, strategy, args): squashArg = "--squash" if args["--squash"] else "" try: git.merge("%s %s %s" % (squashArg, branch, strategy)) return True except git.GrapeGitError as error: print error.gitOutput if "conflict" in error.gitOutput.lower(): if args['--at'] or args['--ay']: if args['--at']: utility.printMsg("Resolving conflicted files by accepting changes from %s." % branch) checkoutArg = "--theirs" else: utility.printMsg("Resolving conflicted files by accepting changes from your branch.") checkoutArg = "--ours" try: path = git.baseDir() git.checkout("%s %s" % (checkoutArg, path)) git.add("%s" % path) git.commit("-m 'Resolve conflicts using %s'" % checkoutArg) return True except git.GrapeGitError as resolveError: print resolveError.gitOutput return False else: utility.printMsg("Conflicts generated. Resolve using git mergetool, then continue " "with grape %s --continue. " % args["<<cmd>>"]) return False else: print("Merge command %s failed. Quitting." % error.gitCommand) return False
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 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 createNewBranches(repo='', branch='', args={}): project = repo checkoutargs = args["checkout"] with utility.cd(project): utility.printMsg("Creating new branch %s in %s." % (branch, project)) git.checkout(checkoutargs + " -b " + branch) git.push("-u origin %s" % branch) return True
def createNewBranches(repo='', branch='', args={}): project = repo checkoutargs = args["checkout"] with utility.cd(project): utility.printMsg("Creating new branch %s in %s." % (branch, project)) git.checkout(checkoutargs+" -b "+branch) git.push("-u origin %s" % branch) return True
def detachThenForceDeleteBranch(repo='', branch='master', args=None): with utility.cd(repo): utility.printMsg( "*** WARNING ***: Detaching in order to delete %s in %s. You will be in a headless state." % (branch, repo)) git.checkout("--detach HEAD") git.branch("-D %s" % branch) if "origin/%s" % branch in git.remoteBranches(): git.push("--delete origin %s" % branch, throwOnFail=False)
def handledCheckout(repo='', branch='master', args=[]): checkoutargs = args[0] sync = args[1] with utility.cd(repo): if sync: # attempt to fetch the requested branch try: git.fetch("origin", "%s:%s" % (branch, branch)) except: # the branch may not exist, but ignore the exception # and allow the checkout to throw the exception. pass git.checkout(checkoutargs + ' ' + branch) utility.printMsg("Checked out %s in %s" % (branch, repo)) return True
def handledCheckout(repo = '', branch = 'master', args = []): checkoutargs = args[0] sync = args[1] with utility.cd(repo): if sync: # attempt to fetch the requested branch try: git.fetch("origin", "%s:%s" % (branch, branch)) except: # the branch may not exist, but ignore the exception # and allow the checkout to throw the exception. pass git.checkout(checkoutargs + ' ' + branch) utility.printMsg("Checked out %s in %s" % (branch, repo)) return True
def createBranch(repo="unknown", branch="master", args=[]): branchPoint = branch fullBranch = args with utility.cd(repo): utility.printMsg("creating and switching to %s in %s" % (fullBranch, repo)) try: git.checkout("-b %s %s " % (fullBranch, branchPoint)) except git.GrapeGitError as e: print "%s:%s" % (repo, e.gitOutput) utility.printMsg("WARNING: %s in %s will not be pushed." % (fullBranch, repo)) return utility.printMsg("pushing %s to origin in %s" % (fullBranch, repo)) try: git.push("-u origin %s" % fullBranch) except git.GrapeGitError as e: print "%s: %s" % (repo, e.gitOutput) return
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 merge(self, branch, strategy, args): squashArg = "--squash" if args["--squash"] else "" try: git.merge("%s %s %s" % (squashArg, branch, strategy)) return True except git.GrapeGitError as error: print error.gitOutput if "conflict" in error.gitOutput.lower(): if args['--at'] or args['--ay']: if args['--at']: utility.printMsg( "Resolving conflicted files by accepting changes from %s." % branch) checkoutArg = "--theirs" else: utility.printMsg( "Resolving conflicted files by accepting changes from your branch." ) checkoutArg = "--ours" try: path = git.baseDir() git.checkout("%s %s" % (checkoutArg, path)) git.add("%s" % path) git.commit("-m 'Resolve conflicts using %s'" % checkoutArg) return True except git.GrapeGitError as resolveError: print resolveError.gitOutput return False else: utility.printMsg( "Conflicts generated. Resolve using git mergetool, then continue " "with grape %s --continue. " % args["<<cmd>>"]) return False else: print("Merge command %s failed. Quitting." % error.gitCommand) return False
def handleCheckoutMRE(mre): global _skipBranchCreation global _createNewBranch newBranchReposArgTuples = [] newBranches = [] for e1, branch, project, checkoutargs in zip(mre.exceptions(), mre.branches(), mre.repos(), mre.args()): try: raise e1 except git.GrapeGitError as e: with utility.cd(project): if "pathspec" in e.gitOutput: createNewBranch = _createNewBranch if _skipBranchCreation: utility.printMsg("Skipping checkout of %s in %s" % (branch, project)) createNewBranch = False elif not createNewBranch: createNewBranch = utility.userInput( "Branch not found locally or remotely. Would you like to create a " "new branch called %s in %s? \n" "(select 'a' to say yes for (a)ll, 's' to (s)kip creation for branches that don't exist )" "\n(y,n,a,s)" % (branch, project), 'y') if str(createNewBranch).lower()[0] == 'a': _createNewBranch = True createNewBranch = True if str(createNewBranch).lower()[0] == 's': _skipBranchCreation = True createNewBranch = False if createNewBranch: newBranchReposArgTuples.append((project, branch, { "checkout": checkoutargs[0] })) else: continue elif "already exists" in e.gitOutput: utility.printMsg("Branch %s already exists in %s." % (branch, project)) branchDescription = git.commitDescription(branch) headDescription = git.commitDescription("HEAD") if branchDescription == headDescription: utility.printMsg( "Branch %s and HEAD are the same. Switching to %s." % (branch, branch)) action = "k" else: utility.printMsg( "Branch %s and HEAD are not the same." % branch) action = '' valid = False while not valid: action = utility.userInput( "Would you like to \n (k)eep it as is at: %s \n" " or \n (f)orce it to: %s? \n(k,f)" % (branchDescription, headDescription), 'k') valid = (action == 'k') or (action == 'f') if not valid: utility.printMsg( "Invalid input. Enter k or f. ") if action == 'k': git.checkout(branch) elif action == 'f': git.checkout("-B %s" % branch) elif "conflict" in e.gitOutput.lower(): utility.printMsg( "CONFLICT occurred when pulling %s from origin." % branch) elif "does not appear to be a git repository" in e.gitOutput.lower( ): utility.printMsg( "Remote 'origin' does not exist. " "This branch was not updated from a remote repository." ) elif "Couldn't find remote ref" in e.gitOutput: utility.printMsg( "Remote of %s does not have reference to %s. You may want to push this branch. " % (project, branch)) else: raise e if len(newBranchReposArgTuples) > 0: utility.MultiRepoCommandLauncher( createNewBranches, listOfRepoBranchArgTuples=newBranchReposArgTuples ).launchFromWorkspaceDir(handleMRE=createNewBranchesMREHandler)
def handleCheckoutMRE(mre): global _skipBranchCreation global _createNewBranch newBranchReposArgTuples = [] newBranches = [] for e1, branch, project, checkoutargs in zip(mre.exceptions(), mre.branches(), mre.repos(), mre.args()): try: raise e1 except git.GrapeGitError as e: with utility.cd(project): if "pathspec" in e.gitOutput: createNewBranch = _createNewBranch if _skipBranchCreation: utility.printMsg("Skipping checkout of %s in %s" % (branch, project)) createNewBranch = False elif not createNewBranch: createNewBranch = utility.userInput("Branch not found locally or remotely. Would you like to create a " "new branch called %s in %s? \n" "(select 'a' to say yes for (a)ll, 's' to (s)kip creation for branches that don't exist )" "\n(y,n,a,s)" % (branch, project), 'y') if str(createNewBranch).lower()[0] == 'a': _createNewBranch = True createNewBranch = True if str(createNewBranch).lower()[0] == 's': _skipBranchCreation = True createNewBranch = False if createNewBranch: newBranchReposArgTuples.append((project, branch, {"checkout": checkoutargs[0]})) else: continue elif "already exists" in e.gitOutput: utility.printMsg("Branch %s already exists in %s." % (branch, project)) branchDescription = git.commitDescription(branch) headDescription = git.commitDescription("HEAD") if branchDescription == headDescription: utility.printMsg("Branch %s and HEAD are the same. Switching to %s." % (branch, branch)) action = "k" else: utility.printMsg("Branch %s and HEAD are not the same." % branch) action = '' valid = False while not valid: action = utility.userInput("Would you like to \n (k)eep it as is at: %s \n" " or \n (f)orce it to: %s? \n(k,f)" % (branchDescription, headDescription), 'k') valid = (action == 'k') or (action == 'f') if not valid: utility.printMsg("Invalid input. Enter k or f. ") if action == 'k': git.checkout(branch) elif action == 'f': git.checkout("-B %s" % branch) elif "conflict" in e.gitOutput.lower(): utility.printMsg("CONFLICT occurred when pulling %s from origin." % branch) elif "does not appear to be a git repository" in e.gitOutput.lower(): utility.printMsg("Remote 'origin' does not exist. " "This branch was not updated from a remote repository.") elif "Couldn't find remote ref" in e.gitOutput: utility.printMsg("Remote of %s does not have reference to %s. You may want to push this branch. " %(project, branch)) else: raise e if len(newBranchReposArgTuples) > 0: utility.MultiRepoCommandLauncher(createNewBranches, listOfRepoBranchArgTuples=newBranchReposArgTuples).launchFromWorkspaceDir(handleMRE=createNewBranchesMREHandler)