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 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 execute(self, args): remotepath = args["<url>"] destpath = args["<path>"] rstr = "--recursive" if args["--recursive"] else "" utility.printMsg("Cloning %s into %s %s" % (remotepath, destpath, "recursively" if args["--recursive"] else "")) git.clone(" %s %s %s" % (rstr, remotepath, destpath)) utility.printMsg("Clone succeeded!") os.chdir(destpath) grapeConfig.read() # ensure you start on a reasonable publish branch menu = grapeMenu.menu() config = grapeConfig.grapeConfig() publicBranches = config.getPublicBranchList() if publicBranches: if "develop" in publicBranches: initialBranch = "develop" elif "master" in publicBranches: initialBranch = "master" else: initialBranch = publicBranches[0] menu.applyMenuChoice("checkout", args=[initialBranch]) if args["--allNested"]: configArgs = ["--uv", "--uvArg=--allNestedSubprojects"] else: configArgs = [] return menu.applyMenuChoice("config", configArgs)
def execute(self, args): remotepath = args["<url>"] destpath = args["<path>"] rstr = "--recursive" if args["--recursive"] else "" utility.printMsg("Cloning %s into %s %s" % (remotepath, destpath, "recursively" if args["--recursive"] else "")) git.clone(" %s %s %s" % (rstr, remotepath, destpath)) utility.printMsg("Clone succeeded!") os.chdir(destpath) grapeConfig.read() # ensure you start on a reasonable publish branch menu = grapeMenu.menu() config = grapeConfig.grapeConfig() publicBranches = config.getPublicBranchList() if publicBranches: if "develop" in publicBranches: initialBranch = "develop" elif "master" in publicBranches: initialBranch = "master" else: initialBranch = publicBranches[0] menu.applyMenuChoice("checkout", args=[initialBranch]) if args["--allNested"]: configArgs = ["--uv","--uvArg=--allNestedSubprojects"] else: configArgs = [] return menu.applyMenuChoice("config", configArgs)
def execute(self, args): start = args["--start"] if not start: start = self._public # decide whether to recurse recurse = grapeConfig.grapeConfig().get('workspace', 'manageSubmodules') if args["--recurse"]: recurse = True if args["--noRecurse"]: recurse = False if not args["<descr>"]: args["<descr>"] = utility.userInput( "Enter one word description for branch:") if not args["--user"]: args["--user"] = utility.getUserName() branchName = self._key + "/" + args["--user"] + "/" + args["<descr>"] launcher = utility.MultiRepoCommandLauncher(createBranch, runInSubmodules=recurse, runInSubprojects=recurse, runInOuter=True, branch=start, globalArgs=branchName) launcher.initializeCommands() utility.printMsg("About to create the following branches:") for repo, branch in zip(launcher.repos, launcher.branches): utility.printMsg("\t%s off of %s in %s" % (branchName, branch, repo)) proceed = utility.userInput("Proceed? [y/n]", default="y") if proceed: grapeMenu.menu().applyMenuChoice( 'up', ['up', '--public=%s' % start]) launcher.launchFromWorkspaceDir() else: utility.printMsg("branches not created")
def execute(self, args): start = args["--start"] if not start: start = self._public # decide whether to recurse recurse = grapeConfig.grapeConfig().get('workspace', 'manageSubmodules') if args["--recurse"]: recurse = True if args["--noRecurse"]: recurse = False if not args["<descr>"]: args["<descr>"] = utility.userInput("Enter one word description for branch:") if not args["--user"]: args["--user"] = utility.getUserName() branchName = self._key + "/" + args["--user"] + "/" + args["<descr>"] launcher = utility.MultiRepoCommandLauncher(createBranch, runInSubmodules=recurse, runInSubprojects=recurse, runInOuter=True, branch=start, globalArgs=branchName) launcher.initializeCommands() utility.printMsg("About to create the following branches:") for repo, branch in zip(launcher.repos, launcher.branches): utility.printMsg("\t%s off of %s in %s" % (branchName, branch, repo)) proceed = utility.userInput("Proceed? [y/n]", default="y") if proceed: grapeMenu.menu().applyMenuChoice('up', ['up', '--public=%s' % start]) launcher.launchFromWorkspaceDir() else: utility.printMsg("branches not created")
def main(fname): """ dumps documentation to a file. Usage: gendocs.py <fname> Arguments: <fname> The file to write documentation to. """ doc = Documentation(grapeMenu.menu()) with open(fname, 'w') as f: doc.write(f)
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): # this is necessary due to the unholy relationships between mr, m, and md. if not "<<cmd>>" in args: args["<<cmd>>"] = 'm' otherBranch = args["<branch>"] if args["<branch>"] else utility.userInput("Enter name of branch you would like" " to merge into this branch") args["<branch>"] = otherBranch config = grapeConfig.grapeConfig() publicBranches = config.getPublicBranchList() toks = otherBranch.split("origin/") if toks[-1] in publicBranches: public = toks[-1] publicMapping = config.getMapping("workspace", "submodulePublicMappings") subpublic = publicMapping[public] toks[-1] = subpublic subpublic = 'origin/'.join(toks) else: subpublic = otherBranch mdArgs = {} mdArgs["--am"] = args["--am"] mdArgs["--as"] = args["--as"] mdArgs["--at"] = args["--at"] mdArgs["--aT"] = args["--aT"] mdArgs["--ay"] = args["--ay"] mdArgs["--aY"] = args["--aY"] mdArgs["--askAll"] = args["--askAll"] mdArgs["--public"] = args["<branch>"] mdArgs["--subpublic"] = subpublic mdArgs["--recurse"] = not args["--noRecurse"] mdArgs["--noRecurse"] = args["--noRecurse"] mdArgs["--continue"] = args["--continue"] mdArgs["<<cmd>>"] = args["<<cmd>>"] mdArgs["--noUpdate"] = args["--noUpdate"] mdArgs["--squash"] = args["--squash"] return grapeMenu.menu().getOption("md").execute(mdArgs)
def execute(self, args): # this is necessary due to the unholy relationships between mr, m, and md. if not "<<cmd>>" in args: args["<<cmd>>"] = 'm' otherBranch = args["<branch>"] if args[ "<branch>"] else utility.userInput( "Enter name of branch you would like" " to merge into this branch") args["<branch>"] = otherBranch config = grapeConfig.grapeConfig() publicBranches = config.getPublicBranchList() toks = otherBranch.split("origin/") if toks[-1] in publicBranches: public = toks[-1] publicMapping = config.getMapping("workspace", "submodulePublicMappings") subpublic = publicMapping[public] toks[-1] = subpublic subpublic = 'origin/'.join(toks) else: subpublic = otherBranch mdArgs = {} mdArgs["--am"] = args["--am"] mdArgs["--as"] = args["--as"] mdArgs["--at"] = args["--at"] mdArgs["--aT"] = args["--aT"] mdArgs["--ay"] = args["--ay"] mdArgs["--aY"] = args["--aY"] mdArgs["--askAll"] = args["--askAll"] mdArgs["--public"] = args["<branch>"] mdArgs["--subpublic"] = subpublic mdArgs["--recurse"] = not args["--noRecurse"] mdArgs["--noRecurse"] = args["--noRecurse"] mdArgs["--continue"] = args["--continue"] mdArgs["<<cmd>>"] = args["<<cmd>>"] mdArgs["--noUpdate"] = args["--noUpdate"] mdArgs["--squash"] = args["--squash"] return grapeMenu.menu().getOption("md").execute(mdArgs)
elif args["--append"]: descr = currentDescription + "\n" + descr subReviewers = reviewers if request.author() in subReviewers: utility.printMsg("%s is the author of the pull request and cannot be a reviewer" % request.author()) subReviewers.remove(request.author()) if title is not None or descr is not None or subReviewers: utility.printMsg("updating request with title=%s, description=%s, reviewers=%s" % (title, descr, subReviewers)) request = request.update(ver, title=title, description=descr, reviewers=subReviewers) url = request.link() utility.printMsg("Pull request updated at %s ." % url) else: url = request.link() utility.printMsg("Pull request unchanged at %s ." % url) except stashy.errors.GenericException as e: print("BITBUCKET: %s" % e.data["errors"][0]["message"]) print("BITBUCKET: %s" % e.data) if not pullRequestAlreadyMerged(e.data["errors"][0]["message"]): exit(1) else: print ("BITBUCKET: Pull request from %s to %s already exists, can't add a new one" % (branch, target_branch)) return request if __name__ == "__main__": import grapeMenu grapeMenu.menu().applyMenuChoice("review",[])
def readDefaults(config=None): if config is None: config = grapeConfig() grapeMenu.menu().setDefaultConfig(config)
def execute(self, args): base = git.baseDir() if base == "": return False dotGit = git.gitDir() utility.printMsg("Optimizing git performance on slow file systems...") #runs file system intensive tasks such as git status and git commit # in parallel (important for NFS systems such as LC) git.config("core.preloadindex", "true") #have git automatically do some garbage collection / optimization utility.printMsg("Setting up automatic git garbage collection...") git.config("gc.auto", "1") #prevents false conflict detection due to differences in filesystem # time stamps utility.printMsg("Optimizing cross platform portability...") git.config("core.trustctime", "false") # stores login info for 12 hrs (max allowed by RZBitbucket) if not args["--nocredcache"]: cache = args["--credcache"] if not cache: cache = utility.userInput( "Would you like to enable git-managed credential caching?", 'y') if cache: utility.printMsg( "Enabling 12 hr caching of https credentials...") if os.name == "nt": git.config("--global credential.helper", "wincred") else: git.config("--global credential.helper", "cache --timeout=43200") # enables 'as' option for merge strategies -forces a conflict if two branches # modify the same file mergeVerifyPath = os.path.join(os.path.dirname(__file__), "..", "merge-and-verify-driver") if os.path.exists(mergeVerifyPath): utility.printMsg( "Enabling safe merges (triggers conflicts any time same file is modified),\n\t see 'as' option for grape m and grape md..." ) git.config("merge.verify.name", "merge and verify driver") git.config("merge.verify.driver", "%s/merge-and-verify-driver %A %O %B") else: utility.printMsg( "WARNING: merge and verify script not detected, safe merges ('as' option to grape m / md) will not work!" ) # enables lg as an alias to print a pretty-font summary of # key junctions in the history for this branch. utility.printMsg("Setting lg as an alias for a pretty log call...") git.config( "alias.lg", "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative --simplify-by-decoration" ) # perform an update of the active subprojects if asked. ask = not args["--nouv"] updateView = ask and (args["--uv"] or utility.userInput( "Do you want to edit your active subprojects?" " (you can do this later using grape uv) [y/n]", "n")) if updateView: grapeMenu.menu().applyMenuChoice("uv", args["--uvArg"]) # configure git to use p4merge for conflict resolution # and diffing useP4Merge = not args["--nop4merge"] and ( args["--p4merge"] or utility.userInput( "Would you like to use p4merge as your merge tool? [y/n]", "y")) # note that this relies on p4merge being in your path somewhere if (useP4Merge): git.config("merge.keepBackup", "false") git.config("merge.tool", "p4merge") git.config("mergetool.keepBackup", "false") git.config( "mergetool.p4merge.cmd", 'p4merge \"\$BASE\" \"\$LOCAL\" \"\$REMOTE\" \"\$MERGED\"') git.config("mergetool.p4merge.keepTemporaries", "false") git.config("mergetool.p4merge.trustExitCode", "false") git.config("mergetool.p4merge.keepBackup", "false") utility.printMsg( "Configured repo to use p4merge for conflict resolution") else: git.config("merge.tool", "tkdiff") useP4Diff = not args["--nop4diff"] and ( args["--p4diff"] or utility.userInput( "Would you like to use p4merge as your diff tool? [y/n]", "y")) # this relies on p4diff being defined as a custom bash script, with the following one-liner: # [ $# -eq 7 ] && p4merge "$2" "$5" if (useP4Diff): p4diffScript = os.path.join(os.path.dirname(__file__), "..", "p4diff") if os.path.exists(p4diffScript): git.config("diff.external", p4diffScript) utility.printMsg( "Configured repo to use p4merge for diff calls - p4merge must be in your path" ) else: utility.printMsg("Could not find p4diff script at %s" % p4diffScript) useGitP4 = args["--git-p4"] if (useGitP4): git.config("git-p4.useclientspec", "true") # create p4 references to enable imports from p4 p4remotes = os.path.join(dotGit, "refs", "remotes", "p4", "") utility.ensure_dir(p4remotes) commit = utility.userInput( "Please enter a descriptor (e.g. SHA, branch if tip, tag name) of the current git commit that mirrors the p4 repo", "master") sha = git.SHA(commit) with open(os.path.join(p4remotes, "HEAD"), 'w') as f: f.write(sha) with open(os.path.join(p4remotes, "master"), 'w') as f: f.write(sha) # to enable exports to p4, a maindev client needs to be set up haveCopied = False while (not haveCopied): p4settings = utility.userInput( "Enter a path to a .p4settings file describing the maindev client you'd like to use for p4 updates", ".p4settings") try: shutil.copyfile(p4settings, os.path.join(base, ".p4settings")) haveCopied = True except: print( "could not find p4settings file, please check your path and try again" ) return False # install hooks here and in all submodules utility.printMsg("Installing hooks in all repos...") cwd = git.baseDir() grapeMenu.menu().applyMenuChoice("installHooks") # ensure all public branches are available in all repos submodules = git.getActiveSubmodules() config = grapeConfig.grapeConfig() publicBranches = config.getPublicBranchList() submodulePublicBranches = set( config.getMapping('workspace', 'submoduleTopicPrefixMappings').values()) for sub in submodules: self.ensurePublicBranchesExist(grapeConfig.grapeRepoConfig(sub), sub, submodulePublicBranches) # reset config to the workspace grapeconfig, use that one for all nested projects' public branches. wsDir = utility.workspaceDir() config = grapeConfig.grapeRepoConfig(wsDir) for proj in grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes( ): self.ensurePublicBranchesExist(config, os.path.join(wsDir, proj), publicBranches) self.ensurePublicBranchesExist(config, wsDir, publicBranches) 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
os.chdir(cwd) utility.printMsg("Pushed current branch to origin") return False not in retvals def setDefaultConfig(self, config): pass def push(repo='', branch='master'): with utility.cd(repo): utility.printMsg("Pushing %s in %s..." % (branch, repo)) git.push("-u origin %s" % branch, throwOnFail=True) def handlePushMRE(mre): for e1 in mre.exceptions(): try: raise e1 except git.GrapeGitError as e: utility.printMsg("Failed to push branch.") print e.gitCommand print e.cwd print e.gitOutput return False if __name__ is "__main__": import grapeMenu menu = grapeMenu.menu() menu.applyMenuChoice("push", [])
def _resume(self, args): grapeMenu.menu().getOption("md")._resume(args) return True
def execute(self, args): sync = args["--sync"].lower().strip() sync = sync == "true" or sync == "yes" args["--sync"] = sync checkoutargs = '' branch = args["<branch>"] if args['-b']: checkoutargs += " -b" workspaceDir = utility.workspaceDir() os.chdir(workspaceDir) currentSHA = git.shortSHA("HEAD") utility.printMsg("Performing checkout of %s in outer level project." % branch) launcher = utility.MultiRepoCommandLauncher(handledCheckout, listOfRepoBranchArgTuples=[ (workspaceDir, branch, [checkoutargs, sync]) ]) if not launcher.launchFromWorkspaceDir(handleMRE=handleCheckoutMRE)[0]: return False previousSHA = currentSHA submoduleListDidChange = ".gitmodules" in git.diff( "--name-only %s %s" % (previousSHA, branch)) addedModules = [] removedModules = [] uvArgs = [] submodulesDidChange = False if submoduleListDidChange and grapeConfig.grapeConfig().getboolean( "workspace", "manageSubmodules"): self.parseGitModulesDiffOutput( git.diff("%s %s --no-ext-diff -- .gitmodules" % (previousSHA, branch)), addedModules, removedModules) if not addedModules and not removedModules: pass else: submodulesDidChange = True if removedModules: for sub in removedModules: try: os.chdir(os.path.join(workspaceDir, sub)) if git.isWorkingDirectoryClean(): cleanBehaviorSet = args[ "--noUpdateView"] or args["--updateView"] if not cleanBehaviorSet: clean = utility.userInput( "Would you like to remove the submodule %s ?" % sub, 'n') elif args["--noUpdateView"]: clean = False elif args["--updateView"]: clean = True if clean: utility.printMsg( "Removing clean submodule %s." % sub) os.chdir(workspaceDir) shutil.rmtree( os.path.join(workspaceDir, sub)) else: utility.printMsg( "Unstaged / committed changes in %s, not removing." % sub) os.chdir(workspaceDir) except OSError: pass # check to see if nested project list changed addedProjects = [] removedProjects = [] removedProjectPrefices = {} nestedProjectListDidChange = False os.chdir(workspaceDir) if ".grapeconfig" in git.diff("--name-only %s %s" % (previousSHA, branch)): configDiff = git.diff("--no-ext-diff %s %s -- %s" % (previousSHA, branch, ".grapeconfig")) nestedProjectListDidChange = "[nestedprojects]" in configDiff.lower( ) self.parseGrapeConfigNestedProjectDiffOutput( configDiff, addedProjects, removedProjects, removedProjectPrefices) if removedProjects: config = grapeConfig.grapeConfig() for proj in removedProjects: projPrefix = removedProjectPrefices[proj] try: os.chdir(os.path.join(workspaceDir, proj)) except OSError as e: if e.errno == 2: # directory doesn't exist, that's OK since we're thinking about removing it # anyways at this point... continue if git.isWorkingDirectoryClean(): removeBehaviorSet = args["--noUpdateView"] or args[ "--updateView"] if not removeBehaviorSet: remove = utility.userInput( "Would you like to remove the nested subproject %s? \n" "All work that has not been pushed will be lost. " % projPrefix, 'n') elif args["--noUpdateView"]: remove = False elif args["--updateView"]: remove = True if remove: remove = utility.userInput( "Are you sure you want to remove %s? When you switch back to the previous branch, you will have to\n" "reclone %s." % (projPrefix, projPrefix), 'n') if remove: os.chdir(workspaceDir) shutil.rmtree( os.path.join(workspaceDir, projPrefix)) else: utility.printMsg( "Unstaged / committed changes in %s, not removing. \n" "Note this project is NOT active in %s. " % (projPrefix, branch)) os.chdir(workspaceDir) if not submodulesDidChange and not nestedProjectListDidChange: uvArgs.append("--checkSubprojects") else: updateViewSet = args["--noUpdateView"] or args["--updateView"] if not updateViewSet: updateView = utility.userInput( "Submodules or subprojects were added/removed as a result of this checkout. \n" + "%s" % ("Added Projects: %s\n" % ','.join(addedProjects) if addedProjects else "") + "%s" % ("Added Submodules: %s\n" % ','.join(addedModules) if addedModules else "") + "%s" % ("Removed Projects: %s\n" % ','.join(removedProjects) if removedProjects else "") + "%s" % ("Removed Submodules: %s\n" % ','.join(removedModules) if removedModules else "") + "Would you like to update your workspace view? [y/n]", 'n') elif args["--noUpdateView"]: updateView = False elif args["--updateView"]: updateView = True if not updateView: uvArgs.append("--checkSubprojects") if args["-b"]: uvArgs.append("-b") if sync: uvArgs.append("--sync=True") else: uvArgs.append("--sync=False") # in case the user switches to a branch without corresponding branches in the submodules, make sure active submodules # are at the right commit before possibly creating new branches at the current HEAD. git.submodule("update") utility.printMsg( "Calling grape uv %s to ensure branches are consistent across all active subprojects and submodules." % ' '.join(uvArgs)) grapeConfig.read() grapeMenu.menu().applyMenuChoice('uv', uvArgs) os.chdir(workspaceDir) if sync: utility.printMsg( "Switched to %s. Updating from remote...\n\t (use --sync=False or .grapeconfig.post-checkout.syncWithOrigin to change behavior.)" % branch) if args["-b"]: grapeMenu.menu().applyMenuChoice("push") else: grapeMenu.menu().applyMenuChoice("pull") else: utility.printMsg("Switched to %s." % branch) global _skipBranchCreation global _createNewBranch _skipBranchCreation = False _createNewBranch = False return True
def writeDefaultConfig(filename): config = grapeConfig.GrapeConfigParser() grapeMenu.menu().setDefaultConfig(config) with open(filename, 'w') as f: config.write(f)
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
retvals = utility.MultiRepoCommandLauncher(push).launchFromWorkspaceDir(handleMRE=handlePushMRE) os.chdir(cwd) utility.printMsg("Pushed current branch to origin") return False not in retvals def setDefaultConfig(self, config): pass def push(repo='', branch='master'): with utility.cd(repo): utility.printMsg("Pushing %s in %s..." % (branch, repo)) git.push("-u origin %s" % branch, throwOnFail=True) def handlePushMRE(mre): for e1 in mre.exceptions(): try: raise e1 except git.GrapeGitError as e: utility.printMsg("Failed to push branch.") print e.gitCommand print e.cwd print e.gitOutput return False if __name__ is "__main__": import grapeMenu menu = grapeMenu.menu() menu.applyMenuChoice("push", [])
utility.printMsg( "updating request with title=%s, description=%s, reviewers=%s" % (title, descr, subReviewers)) request = request.update(ver, title=title, description=descr, reviewers=subReviewers) url = request.link() utility.printMsg("Pull request updated at %s ." % url) else: url = request.link() utility.printMsg("Pull request unchanged at %s ." % url) except stashy.errors.GenericException as e: print("BITBUCKET: %s" % e.data["errors"][0]["message"]) print("BITBUCKET: %s" % e.data) if not pullRequestAlreadyMerged( e.data["errors"][0]["message"]): exit(1) else: print( "BITBUCKET: Pull request from %s to %s already exists, can't add a new one" % (branch, target_branch)) return request if __name__ == "__main__": import grapeMenu grapeMenu.menu().applyMenuChoice("review", [])
def execute(self, args): sync = args["--sync"].lower().strip() sync = sync == "true" or sync == "yes" args["--sync"] = sync checkoutargs = '' branch = args["<branch>"] if args['-b']: checkoutargs += " -b" workspaceDir = utility.workspaceDir() os.chdir(workspaceDir) currentSHA = git.shortSHA("HEAD") utility.printMsg("Performing checkout of %s in outer level project." % branch) launcher = utility.MultiRepoCommandLauncher(handledCheckout, listOfRepoBranchArgTuples=[(workspaceDir, branch, [checkoutargs, sync])]) if not launcher.launchFromWorkspaceDir(handleMRE=handleCheckoutMRE)[0]: return False previousSHA = currentSHA submoduleListDidChange = ".gitmodules" in git.diff("--name-only %s %s" % (previousSHA, branch)) addedModules = [] removedModules = [] uvArgs = [] submodulesDidChange = False if submoduleListDidChange and grapeConfig.grapeConfig().getboolean("workspace", "manageSubmodules"): self.parseGitModulesDiffOutput(git.diff("%s %s --no-ext-diff -- .gitmodules" % (previousSHA, branch)), addedModules, removedModules) if not addedModules and not removedModules: pass else: submodulesDidChange = True if removedModules: for sub in removedModules: try: os.chdir(os.path.join(workspaceDir, sub)) if git.isWorkingDirectoryClean(): cleanBehaviorSet = args["--noUpdateView"] or args["--updateView"] if not cleanBehaviorSet: clean = utility.userInput("Would you like to remove the submodule %s ?" % sub, 'n') elif args["--noUpdateView"]: clean = False elif args["--updateView"]: clean = True if clean: utility.printMsg("Removing clean submodule %s." % sub) os.chdir(workspaceDir) shutil.rmtree(os.path.join(workspaceDir, sub)) else: utility.printMsg("Unstaged / committed changes in %s, not removing." % sub) os.chdir(workspaceDir) except OSError: pass # check to see if nested project list changed addedProjects = [] removedProjects = [] removedProjectPrefices = {} nestedProjectListDidChange = False os.chdir(workspaceDir) if ".grapeconfig" in git.diff("--name-only %s %s" % (previousSHA, branch)): configDiff = git.diff("--no-ext-diff %s %s -- %s" % (previousSHA, branch, ".grapeconfig")) nestedProjectListDidChange = "[nestedprojects]" in configDiff.lower() self.parseGrapeConfigNestedProjectDiffOutput(configDiff, addedProjects, removedProjects, removedProjectPrefices) if removedProjects: config = grapeConfig.grapeConfig() for proj in removedProjects: projPrefix = removedProjectPrefices[proj] try: os.chdir(os.path.join(workspaceDir, proj)) except OSError as e: if e.errno == 2: # directory doesn't exist, that's OK since we're thinking about removing it # anyways at this point... continue if git.isWorkingDirectoryClean(): removeBehaviorSet = args["--noUpdateView"] or args["--updateView"] if not removeBehaviorSet: remove = utility.userInput("Would you like to remove the nested subproject %s? \n" "All work that has not been pushed will be lost. " % projPrefix, 'n' ) elif args["--noUpdateView"]: remove = False elif args["--updateView"]: remove = True if remove: remove = utility.userInput("Are you sure you want to remove %s? When you switch back to the previous branch, you will have to\n" "reclone %s." % (projPrefix, projPrefix), 'n') if remove: os.chdir(workspaceDir) shutil.rmtree(os.path.join(workspaceDir,projPrefix)) else: utility.printMsg("Unstaged / committed changes in %s, not removing. \n" "Note this project is NOT active in %s. " % (projPrefix, branch)) os.chdir(workspaceDir) if not submodulesDidChange and not nestedProjectListDidChange: uvArgs.append("--checkSubprojects") else: updateViewSet = args["--noUpdateView"] or args["--updateView"] if not updateViewSet: updateView = utility.userInput("Submodules or subprojects were added/removed as a result of this checkout. \n" + "%s" % ("Added Projects: %s\n" % ','.join(addedProjects) if addedProjects else "") + "%s" % ("Added Submodules: %s\n"% ','.join(addedModules) if addedModules else "") + "%s" % ("Removed Projects: %s\n" % ','.join(removedProjects) if removedProjects else "") + "%s" % ("Removed Submodules: %s\n" % ','.join(removedModules) if removedModules else "") + "Would you like to update your workspace view? [y/n]", 'n') elif args["--noUpdateView"]: updateView = False elif args["--updateView"]: updateView = True if not updateView: uvArgs.append("--checkSubprojects") if args["-b"]: uvArgs.append("-b") if sync: uvArgs.append("--sync=True") else: uvArgs.append("--sync=False") # in case the user switches to a branch without corresponding branches in the submodules, make sure active submodules # are at the right commit before possibly creating new branches at the current HEAD. git.submodule("update") utility.printMsg("Calling grape uv %s to ensure branches are consistent across all active subprojects and submodules." % ' '.join(uvArgs)) grapeConfig.read() grapeMenu.menu().applyMenuChoice('uv', uvArgs) os.chdir(workspaceDir) if sync: utility.printMsg("Switched to %s. Updating from remote...\n\t (use --sync=False or .grapeconfig.post-checkout.syncWithOrigin to change behavior.)" % branch) if args["-b"]: grapeMenu.menu().applyMenuChoice("push") else: grapeMenu.menu().applyMenuChoice("pull") else: utility.printMsg("Switched to %s." % branch) global _skipBranchCreation global _createNewBranch _skipBranchCreation = False _createNewBranch = False return True
def execute(self,args): base = git.baseDir() if base == "": return False dotGit = git.gitDir() utility.printMsg("Optimizing git performance on slow file systems...") #runs file system intensive tasks such as git status and git commit # in parallel (important for NFS systems such as LC) git.config("core.preloadindex","true") #have git automatically do some garbage collection / optimization utility.printMsg("Setting up automatic git garbage collection...") git.config("gc.auto","1") #prevents false conflict detection due to differences in filesystem # time stamps utility.printMsg("Optimizing cross platform portability...") git.config("core.trustctime","false") # stores login info for 12 hrs (max allowed by RZBitbucket) if not args["--nocredcache"]: cache = args["--credcache"] if not cache: cache = utility.userInput("Would you like to enable git-managed credential caching?", 'y') if cache: utility.printMsg("Enabling 12 hr caching of https credentials...") if os.name == "nt": git.config("--global credential.helper", "wincred") else : git.config("--global credential.helper", "cache --timeout=43200") # enables 'as' option for merge strategies -forces a conflict if two branches # modify the same file mergeVerifyPath = os.path.join(os.path.dirname(__file__),"..","merge-and-verify-driver") if os.path.exists(mergeVerifyPath): utility.printMsg("Enabling safe merges (triggers conflicts any time same file is modified),\n\t see 'as' option for grape m and grape md...") git.config("merge.verify.name","merge and verify driver") git.config("merge.verify.driver","%s/merge-and-verify-driver %A %O %B") else: utility.printMsg("WARNING: merge and verify script not detected, safe merges ('as' option to grape m / md) will not work!") # enables lg as an alias to print a pretty-font summary of # key junctions in the history for this branch. utility.printMsg("Setting lg as an alias for a pretty log call...") git.config("alias.lg","log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative --simplify-by-decoration") # perform an update of the active subprojects if asked. ask = not args["--nouv"] updateView = ask and (args["--uv"] or utility.userInput("Do you want to edit your active subprojects?" " (you can do this later using grape uv) [y/n]", "n")) if updateView: grapeMenu.menu().applyMenuChoice("uv", args["--uvArg"]) # configure git to use p4merge for conflict resolution # and diffing useP4Merge = not args["--nop4merge"] and (args["--p4merge"] or utility.userInput("Would you like to use p4merge as your merge tool? [y/n]","y")) # note that this relies on p4merge being in your path somewhere if (useP4Merge): git.config("merge.keepBackup","false") git.config("merge.tool","p4merge") git.config("mergetool.keepBackup","false") git.config("mergetool.p4merge.cmd",'p4merge \"\$BASE\" \"\$LOCAL\" \"\$REMOTE\" \"\$MERGED\"') git.config("mergetool.p4merge.keepTemporaries","false") git.config("mergetool.p4merge.trustExitCode","false") git.config("mergetool.p4merge.keepBackup","false") utility.printMsg("Configured repo to use p4merge for conflict resolution") else: git.config("merge.tool","tkdiff") useP4Diff = not args["--nop4diff"] and (args["--p4diff"] or utility.userInput("Would you like to use p4merge as your diff tool? [y/n]","y")) # this relies on p4diff being defined as a custom bash script, with the following one-liner: # [ $# -eq 7 ] && p4merge "$2" "$5" if (useP4Diff): p4diffScript = os.path.join(os.path.dirname(__file__),"..","p4diff") if os.path.exists(p4diffScript): git.config("diff.external",p4diffScript) utility.printMsg("Configured repo to use p4merge for diff calls - p4merge must be in your path") else: utility.printMsg("Could not find p4diff script at %s" % p4diffScript) useGitP4 = args["--git-p4"] if (useGitP4 ): git.config("git-p4.useclientspec","true") # create p4 references to enable imports from p4 p4remotes = os.path.join(dotGit,"refs","remotes","p4","") utility.ensure_dir(p4remotes) commit = utility.userInput("Please enter a descriptor (e.g. SHA, branch if tip, tag name) of the current git commit that mirrors the p4 repo","master") sha = git.SHA(commit) with open(os.path.join(p4remotes,"HEAD"),'w') as f: f.write(sha) with open(os.path.join(p4remotes,"master"),'w') as f: f.write(sha) # to enable exports to p4, a maindev client needs to be set up haveCopied = False while (not haveCopied): p4settings = utility.userInput("Enter a path to a .p4settings file describing the maindev client you'd like to use for p4 updates",".p4settings") try: shutil.copyfile(p4settings,os.path.join(base,".p4settings")) haveCopied = True except: print("could not find p4settings file, please check your path and try again") return False # install hooks here and in all submodules utility.printMsg("Installing hooks in all repos...") cwd = git.baseDir() grapeMenu.menu().applyMenuChoice("installHooks") # ensure all public branches are available in all repos submodules = git.getActiveSubmodules() config = grapeConfig.grapeConfig() publicBranches = config.getPublicBranchList() submodulePublicBranches = set(config.getMapping('workspace', 'submoduleTopicPrefixMappings').values()) for sub in submodules: self.ensurePublicBranchesExist(grapeConfig.grapeRepoConfig(sub),sub, submodulePublicBranches) # reset config to the workspace grapeconfig, use that one for all nested projects' public branches. wsDir = utility.workspaceDir() config = grapeConfig.grapeRepoConfig(wsDir) for proj in grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes(): self.ensurePublicBranchesExist(config, os.path.join(wsDir,proj), publicBranches) self.ensurePublicBranchesExist(config, wsDir, publicBranches) return True