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 getModifiedInactiveSubmodules(branch1, branch2): modifiedSubs = git.getModifiedSubmodules(branch1=branch1, branch2=branch2) activeSubs = git.getActiveSubmodules() missing = [] for sub in modifiedSubs: if sub not in activeSubs: missing.append(sub) return missing
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): 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 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 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 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 defineActiveSubmodules(projectType="submodule"): """ Queries the user for the submodules (projectType == "submodule") or nested subprojects (projectType == "nested subproject") they would like to activate. """ if projectType == "submodule": allSubprojects = git.getAllSubmodules() activeSubprojects = git.getActiveSubmodules() if projectType == "nested subproject": config = grapeConfig.grapeConfig() allSubprojectNames = config.getAllNestedSubprojects() allSubprojects = [] for project in allSubprojectNames: allSubprojects.append( config.get("nested-%s" % project, "prefix")) activeSubprojects = grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes( ) toplevelDirs = {} toplevelActiveDirs = {} toplevelSubs = [] for sub in allSubprojects: # we are taking advantage of the fact that branchPrefixes are the same as directory prefixes for local # top-level dirs. prefix = git.branchPrefix(sub) if sub != prefix: toplevelDirs[prefix] = [] toplevelActiveDirs[prefix] = [] for sub in allSubprojects: prefix = git.branchPrefix(sub) if sub != prefix: toplevelDirs[prefix].append(sub) else: toplevelSubs.append(sub) for sub in activeSubprojects: prefix = git.branchPrefix(sub) if sub != prefix: toplevelActiveDirs[prefix].append(sub) included = {} for directory, subprojects in toplevelDirs.items(): activeDir = toplevelActiveDirs[directory] if len(activeDir) == 0: defaultValue = "none" elif set(activeDir) == set(subprojects): defaultValue = "all" else: defaultValue = "some" opt = utility.userInput( "Would you like all, some, or none of the %ss in %s?" % (projectType, directory), default=defaultValue) if opt.lower()[0] == "a": for subproject in subprojects: included[subproject] = True if opt.lower()[0] == "n": for subproject in subprojects: included[subproject] = False if opt.lower()[0] == "s": for subproject in subprojects: included[subproject] = utility.userInput( "Would you like %s %s? [y/n]" % (projectType, subproject), 'y' if (subproject in activeSubprojects) else 'n') for subproject in toplevelSubs: included[subproject] = utility.userInput( "Would you like %s %s? [y/n]" % (projectType, subproject), 'y' if (subproject in activeSubprojects) else 'n') return included
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 defineActiveSubmodules(projectType="submodule"): """ Queries the user for the submodules (projectType == "submodule") or nested subprojects (projectType == "nested subproject") they would like to activate. """ if projectType == "submodule": allSubprojects = git.getAllSubmodules() activeSubprojects = git.getActiveSubmodules() if projectType == "nested subproject": config = grapeConfig.grapeConfig() allSubprojectNames = config.getAllNestedSubprojects() allSubprojects = [] for project in allSubprojectNames: allSubprojects.append(config.get("nested-%s" % project, "prefix")) activeSubprojects = grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes() toplevelDirs = {} toplevelActiveDirs = {} toplevelSubs = [] for sub in allSubprojects: # we are taking advantage of the fact that branchPrefixes are the same as directory prefixes for local # top-level dirs. prefix = git.branchPrefix(sub) if sub != prefix: toplevelDirs[prefix] = [] toplevelActiveDirs[prefix] = [] for sub in allSubprojects: prefix = git.branchPrefix(sub) if sub != prefix: toplevelDirs[prefix].append(sub) else: toplevelSubs.append(sub) for sub in activeSubprojects: prefix = git.branchPrefix(sub) if sub != prefix: toplevelActiveDirs[prefix].append(sub) included = {} for directory, subprojects in toplevelDirs.items(): activeDir = toplevelActiveDirs[directory] if len(activeDir) == 0: defaultValue = "none" elif set(activeDir) == set(subprojects): defaultValue = "all" else: defaultValue = "some" opt = utility.userInput("Would you like all, some, or none of the %ss in %s?" % (projectType,directory), default=defaultValue) if opt.lower()[0] == "a": for subproject in subprojects: included[subproject] = True if opt.lower()[0] == "n": for subproject in subprojects: included[subproject] = False if opt.lower()[0] == "s": for subproject in subprojects: included[subproject] = utility.userInput("Would you like %s %s? [y/n]" % (projectType, subproject), 'y' if (subproject in activeSubprojects) else 'n') for subproject in toplevelSubs: included[subproject] = utility.userInput("Would you like %s %s? [y/n]" % (projectType, subproject), 'y' if (subproject in activeSubprojects) else 'n') return included
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 getActiveSubprojects(): return git.getActiveSubmodules() + grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes()
def __init__(self, master, **kwargs): height = kwargs.get('height', 0) width = kwargs.get('width', 0) self.master = master self.grapeconfig = grapeConfig.grapeConfig() self.oldprojindex = 0 self.showInactive = kwargs.get('showInactive', True) self.showToplevel = kwargs.get('showToplevel', True) self.showSubmodules = kwargs.get('showSubmodules', True) self.showSubtrees = kwargs.get('showSubtrees', True) self.showNestedSubprojects = kwargs.get('showNestedSubprojects', True) # Colors self.fginit = kwargs.get('fginit', 'black') self.bginit = kwargs.get('bginit', 'gray') self.fgvisited = kwargs.get('fgvisited', 'slate gray') self.bgvisited = kwargs.get('bgvisited', 'light gray') self.fgselected = kwargs.get('fgselected', 'black') self.bgselected = kwargs.get('bgselected', 'goldenrod') self.fgactive = kwargs.get('fgactive', 'black') self.bgactive = kwargs.get('bgactive', 'light goldenrod') # Panel labels # These variables should be set by derived classes self.filepanelabel = Tk.StringVar() self.projpanelabel = Tk.StringVar() # Main resizable window self.main = Tk.PanedWindow(master, height=height, width=width, sashwidth=4) # Create file navigation pane widgets self.filepanel = Tk.Frame() self.filelabel = Tk.Label(self.filepanel, textvariable=self.filepanelabel) self.filescroll = Tk.Scrollbar(self.filepanel, width=10) self.filelist = Tk.Listbox(self.filepanel, background=self.bginit, foreground=self.fginit, selectbackground=self.bgselected, selectforeground=self.fgselected, yscrollcommand=self.filescroll.set, selectmode=Tk.SINGLE) self.filescroll.config(command=self.filelist.yview) self.filelist.bind("<Double-Button-1>", lambda e: self.spawnDiff()) # Place file navigation pane widgets self.filelabel.pack(side=Tk.TOP, fill=Tk.X) self.filescroll.pack(side=Tk.RIGHT, fill=Tk.Y) self.filelist.pack(side=Tk.LEFT, fill=Tk.BOTH, expand=1) self.filepanel.pack(fill=Tk.BOTH, expand=1) # Create subproject navigation widgets self.projpanel = Tk.Frame() self.projlabel = Tk.Label(self.projpanel, textvariable=self.projpanelabel) self.projscroll = Tk.Scrollbar(self.projpanel, width=10) self.projlist = Tk.Listbox(self.projpanel, background=self.bginit, foreground=self.fginit, selectbackground=self.bgselected, selectforeground=self.fgselected, yscrollcommand=self.projscroll.set, selectmode=Tk.SINGLE) self.projscroll.config(command=self.projlist.yview) self.projlist.bind("<Double-Button-1>", lambda e: self.chooseProject()) # Place subproject navigation widgets self.projscroll.pack(side=Tk.LEFT, fill=Tk.Y) self.projlabel.pack(side=Tk.TOP, fill=Tk.X) self.projlist.pack(side=Tk.LEFT, fill=Tk.BOTH, expand=1) self.projpanel.pack(fill=Tk.BOTH, expand=1) # Populate subproject navigation list utility.printMsg("Populating projects list...") self.projects = [] self.projstatus = [] self.projtype = [] # Outer level repo if self.showToplevel: status = "?" self.projects.append("") self.projlist.insert(Tk.END, "%s <Outer Level Project>" % status) self.projstatus.append(status) self.projtype.append("Outer") # Nested subprojects self.subprojects = [] if self.showNestedSubprojects: activeNestedSubprojects = (grapeConfig.GrapeConfigParser. getAllActiveNestedSubprojectPrefixes()) self.projects.extend(activeNestedSubprojects) self.subprojects.extend(activeNestedSubprojects) for proj in activeNestedSubprojects: status = "?" self.projlist.insert( Tk.END, "%s %s <Nested Subproject>" % (status, proj)) self.projstatus.append(status) self.projtype.append("Active Nested") if self.showInactive: inactiveNestedSubprojects = list( set(grapeConfig.grapeConfig().getAllNestedSubprojects()) - set(grapeConfig.GrapeConfigParser. getAllActiveNestedSubprojects())) self.projects.extend(inactiveNestedSubprojects) self.subprojects.extend(inactiveNestedSubprojects) for proj in inactiveNestedSubprojects: status = "?" self.projlist.insert( Tk.END, "%s %s <Inactive Nested Subproject>" % (status, proj)) self.projstatus.append(status) self.projtype.append("Inactive Nested") # Submodules self.submodules = [] if self.showSubmodules: activeSubmodules = (git.getActiveSubmodules()) self.projects.extend(activeSubmodules) self.submodules.extend(activeSubmodules) for proj in activeSubmodules: status = "?" self.projlist.insert(Tk.END, "%s %s <Submodule>" % (status, proj)) self.projstatus.append(status) self.projtype.append("Submodule") if self.showInactive: inactiveSubmodules = list( set(git.getAllSubmodules()) - set(git.getActiveSubmodules())) self.projects.extend(inactiveSubmodules) self.submodules.extend(inactiveSubmodules) for proj in inactiveSubmodules: status = "?" self.projlist.insert( Tk.END, "%s %s <Inactive Submodule>" % (status, proj)) self.projstatus.append(status) self.projtype.append("Inactive Submodule") # Subtrees self.subtrees = [] if self.showSubtrees: self.subtrees = [ self.grapeconfig.get('subtree-%s' % proj, 'prefix') for proj in self.grapeconfig.get('subtrees', 'names').strip().split() ] self.projects.extend(self.subtrees) for proj in self.subtrees: status = "?" self.projlist.insert(Tk.END, "%s %s <Subtree>" % (status, proj)) self.projstatus.append(status) self.projtype.append("Subtree") utility.printMsg("Done.") # Resize the project pane based on its contents self.projlistwidth = 0 self.numprojects = 0 for proj in self.projlist.get(0, Tk.END): if len(proj) > self.projlistwidth: self.projlistwidth = len(proj) self.numprojects += 1 self.projlist.config(width=self.projlistwidth) # Place the panes in the main window self.main.add(self.projpanel) self.main.add(self.filepanel) self.main.pack(fill=Tk.BOTH, expand=1, side=Tk.BOTTOM)
def __init__(self, master, **kwargs): height = kwargs.get('height', 0) width = kwargs.get('width', 0) self.master = master self.grapeconfig = grapeConfig.grapeConfig() self.oldprojindex = 0 self.showInactive = kwargs.get('showInactive', True) self.showToplevel = kwargs.get('showToplevel', True) self.showSubmodules = kwargs.get('showSubmodules', True) self.showSubtrees = kwargs.get('showSubtrees', True) self.showNestedSubprojects = kwargs.get('showNestedSubprojects', True) # Colors self.fginit = kwargs.get('fginit', 'black') self.bginit = kwargs.get('bginit', 'gray') self.fgvisited = kwargs.get('fgvisited', 'slate gray') self.bgvisited = kwargs.get('bgvisited', 'light gray') self.fgselected = kwargs.get('fgselected', 'black') self.bgselected = kwargs.get('bgselected', 'goldenrod') self.fgactive = kwargs.get('fgactive', 'black') self.bgactive = kwargs.get('bgactive', 'light goldenrod') # Panel labels # These variables should be set by derived classes self.filepanelabel = Tk.StringVar() self.projpanelabel = Tk.StringVar() # Main resizable window self.main = Tk.PanedWindow(master, height=height, width=width, sashwidth=4) # Create file navigation pane widgets self.filepanel = Tk.Frame() self.filelabel = Tk.Label(self.filepanel, textvariable=self.filepanelabel) self.filescroll = Tk.Scrollbar(self.filepanel, width=10) self.filelist = Tk.Listbox(self.filepanel, background=self.bginit, foreground=self.fginit, selectbackground=self.bgselected, selectforeground=self.fgselected, yscrollcommand=self.filescroll.set, selectmode=Tk.SINGLE) self.filescroll.config(command=self.filelist.yview) self.filelist.bind("<Double-Button-1>", lambda e: self.spawnDiff()) # Place file navigation pane widgets self.filelabel.pack(side=Tk.TOP, fill=Tk.X) self.filescroll.pack(side=Tk.RIGHT, fill=Tk.Y) self.filelist.pack(side=Tk.LEFT, fill=Tk.BOTH, expand=1) self.filepanel.pack(fill=Tk.BOTH, expand=1) # Create subproject navigation widgets self.projpanel = Tk.Frame() self.projlabel = Tk.Label(self.projpanel, textvariable=self.projpanelabel) self.projscroll = Tk.Scrollbar(self.projpanel, width=10) self.projlist = Tk.Listbox(self.projpanel, background=self.bginit, foreground=self.fginit, selectbackground=self.bgselected, selectforeground=self.fgselected, yscrollcommand=self.projscroll.set, selectmode=Tk.SINGLE) self.projscroll.config(command=self.projlist.yview) self.projlist.bind("<Double-Button-1>", lambda e: self.chooseProject()) # Place subproject navigation widgets self.projscroll.pack(side=Tk.LEFT, fill=Tk.Y) self.projlabel.pack(side=Tk.TOP, fill=Tk.X) self.projlist.pack(side=Tk.LEFT, fill=Tk.BOTH, expand=1) self.projpanel.pack(fill=Tk.BOTH, expand=1) # Populate subproject navigation list utility.printMsg("Populating projects list...") self.projects = [] self.projstatus = [] self.projtype = [] # Outer level repo if self.showToplevel: status = "?" self.projects.append("") self.projlist.insert(Tk.END, "%s <Outer Level Project>" % status) self.projstatus.append(status) self.projtype.append("Outer") # Nested subprojects self.subprojects = [] if self.showNestedSubprojects: activeNestedSubprojects = (grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes()) self.projects.extend(activeNestedSubprojects) self.subprojects.extend(activeNestedSubprojects) for proj in activeNestedSubprojects: status = "?" self.projlist.insert(Tk.END, "%s %s <Nested Subproject>" % (status, proj)) self.projstatus.append(status) self.projtype.append("Active Nested") if self.showInactive: inactiveNestedSubprojects = list(set(grapeConfig.grapeConfig().getAllNestedSubprojects()) - set(grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojects())) self.projects.extend(inactiveNestedSubprojects) self.subprojects.extend(inactiveNestedSubprojects) for proj in inactiveNestedSubprojects: status = "?" self.projlist.insert(Tk.END, "%s %s <Inactive Nested Subproject>" % (status, proj)) self.projstatus.append(status) self.projtype.append("Inactive Nested") # Submodules self.submodules = [] if self.showSubmodules: activeSubmodules = (git.getActiveSubmodules()) self.projects.extend(activeSubmodules) self.submodules.extend(activeSubmodules) for proj in activeSubmodules: status = "?" self.projlist.insert(Tk.END, "%s %s <Submodule>" % (status, proj)) self.projstatus.append(status) self.projtype.append("Submodule") if self.showInactive: inactiveSubmodules = list(set(git.getAllSubmodules()) - set(git.getActiveSubmodules())) self.projects.extend(inactiveSubmodules) self.submodules.extend(inactiveSubmodules) for proj in inactiveSubmodules: status = "?" self.projlist.insert(Tk.END, "%s %s <Inactive Submodule>" % (status, proj)) self.projstatus.append(status) self.projtype.append("Inactive Submodule") # Subtrees self.subtrees = [] if self.showSubtrees: self.subtrees = [ self.grapeconfig.get('subtree-%s' % proj, 'prefix') for proj in self.grapeconfig.get('subtrees', 'names').strip().split() ] self.projects.extend(self.subtrees) for proj in self.subtrees: status = "?" self.projlist.insert(Tk.END, "%s %s <Subtree>" % (status, proj)) self.projstatus.append(status) self.projtype.append("Subtree") utility.printMsg("Done.") # Resize the project pane based on its contents self.projlistwidth = 0 self.numprojects = 0 for proj in self.projlist.get(0, Tk.END): if len(proj) > self.projlistwidth: self.projlistwidth = len(proj) self.numprojects += 1 self.projlist.config(width=self.projlistwidth) # Place the panes in the main window self.main.add(self.projpanel) self.main.add(self.filepanel) self.main.pack(fill=Tk.BOTH, expand=1, side=Tk.BOTTOM)
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): 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