Example #1
0
    def readVersion(self, fileName, args):
        config = grapeConfig.grapeConfig()
        prefix = args["--prefix"]
        if args["--suffix"]:
            suffix = args["--suffix"]
        else:
            try:
                suffixMapping = config.getMapping("versioning", "branchSuffixMappings")
                suffix = suffixMapping[config.getPublicBranchFor(git.currentBranch())]
            except KeyError:
                suffix = ""
        args["--suffix"] = suffix
        regex = args["--matchTo"]
        try:
            regexMappings = config.getMapping("versioning", "branchVersionRegexMappings")
            public = config.getPublicBranchFor(git.currentBranch())
            regex = regexMappings[public]
        except ConfigParser.NoOptionError:
            pass

        #tweaked from http://stackoverflow.com/questions/2020180/increment-a-version-id-by-one-and-write-to-mk-file
        regex = regex.replace("<prefix>", prefix)
        regex = regex.replace("<suffix>", suffix)
        self.r = re.compile(regex)

        VERSION_ID = None
        for l in fileName:
            m1 = self.r.match(l)
            if m1:
                VERSION_ID = map(int, m1.group(3).split("."))
                self.matchedLine = l
        if VERSION_ID is None:
            print("GRAPE: .")

        return VERSION_ID
Example #2
0
    def mergeSubproject(self, args, subproject, subPublic, subprojects, cwd, isSubmodule=True):
        # if we did this merge in a previous run, don't do it again
        try:
            if self.progress["Subproject: %s" % subproject] == "finished":
                return True
        except KeyError:
            pass
        os.chdir(os.path.join(git.baseDir(), subproject))
        mergeArgs = args.copy()
        mergeArgs["--public"] = subPublic

        utility.printMsg("Merging %s into %s for %s %s" % 
                         (subPublic, git.currentBranch(), "submodule" if isSubmodule else "subproject", subproject))
        git.fetch("origin")
        # update our local reference to the remote branch so long as it's fast-forwardable or we don't have it yet..)
        hasRemote = git.hasBranch("origin/%s" % subPublic)
        hasBranch = git.hasBranch(subPublic)
        if  hasRemote and  (git.branchUpToDateWith(subPublic, "origin/%s" % subPublic) or not hasBranch):
            git.fetch("origin %s:%s" % (subPublic, subPublic))
        ret = self.mergeIntoCurrent(subPublic, mergeArgs, subproject)
        conflict = not ret
        if conflict:
            self.progress["stopPoint"] = "Subproject: %s" % subproject
            subprojectKey = "submodules" if isSubmodule else "nested"
            self.progress[subprojectKey] = subprojects
            self.progress["cwd"] = cwd
            conflictedFiles = git.conflictedFiles()
            if conflictedFiles:
                if isSubmodule: 
                    typeStr = "submodule"
                else:
                    typeStr = "nested subproject"
                
                utility.printMsg("Merge in %s %s from %s to %s issued conflicts. Resolve and commit those changes \n"
                                 "using git mergetool and git commit in the submodule, then continue using grape\n"
                                 "%s --continue" % (typeStr, subproject, subPublic, git.currentBranch(), args["<<cmd>>"]))
            else:
                utility.printMsg("Merge in %s failed for an unhandled reason. You may need to stash / commit your current\n"
                                 "changes before doing the merge. Inspect git output above to troubleshoot. Continue using\n"
                                 "grape %s --continue." % (subproject, args["<<cmd>>"]))
            return False
        # if we are resuming from a conflict, the above grape m call would have taken care of continuing.
        # clear out the --continue flag.
        args["--continue"] = False
        # stage the updated submodule
        os.chdir(cwd)
        if isSubmodule:
            git.add(subproject)
        self.progress["Subproject: %s" % subproject] = "finished"
        return True
Example #3
0
def ensureLocalUpToDateWithRemote(repo='', branch='master'):
    utility.printMsg(
        "Ensuring local branch %s in %s is up to date with origin" %
        (branch, repo))
    with utility.cd(repo):
        # attempt to fetch the requested branch
        try:
            git.fetch("origin", "%s:%s" % (branch, branch))
        except:
            # the branch may not exist, but this is ok
            pass

        if git.currentBranch() == branch:
            return

        if not git.hasBranch(branch):
            # switch to corresponding public branch if the branch does not exist
            public = grapeConfig.workspaceConfig().getPublicBranchFor(branch)
            # figure out if this is a submodule
            relpath = os.path.relpath(repo, utility.workspaceDir())
            relpath = relpath.replace('\\', "/")
            with utility.cd(utility.workspaceDir()):
                # if this is a submodule, get the appropriate public mapping
                if relpath in git.getAllSubmoduleURLMap().keys():
                    public = grapeConfig.workspaceConfig().getMapping(
                        "workspace", "submodulepublicmappings")[public]
            utility.printMsg(
                "Branch %s does not exist in %s, switching to %s and detaching"
                % (branch, repo, public))
            git.checkout(public)
            git.pull("origin %s" % (public))
            git.checkout("--detach HEAD")
Example #4
0
File: hooks.py Project: LLNL/GRAPE
 def postCommit(args):
     #applies the autoPush hook
     autoPush = args["--autopush"]
     if autoPush.lower().strip() != "false":
         try:
             git.push("-u origin HEAD")
         except git.GrapeGitError:
             pass
         autoPush = True
     else:
         autoPush = False
     #applies the cascade hook
     print("GRAPE: checking for cascades...")
     cascadeDict = grapeConfig.GrapeConfigParser.parseConfigPairList(args["--cascade"])
     if cascadeDict:
         currentBranch = git.currentBranch()
         while currentBranch in cascadeDict:
             source = currentBranch
             target = cascadeDict[source]
             fastForward = False
             print("GRAPE: Cascading commit from %s to %s..." % (source, target))
             if git.branchUpToDateWith(source, target):
                 fastForward = True
                 print("GRAPE: should be a fastforward cascade...")
             git.checkout("%s" % target)
             git.merge("%s -m 'Cascade from %s to %s'" % (source, source, target))
             # we need to kick off the next one if it was a fast forward merge.
             # otherwise, another post-commit hook should be called from the merge commit.
             if fastForward:
                 if autoPush:
                     git.push("origin %s" % target)
                     print("GRAPE: auto push done")
                 currentBranch = target
             else:
                 currentBranch = None
Example #5
0
def ensureLocalUpToDateWithRemote(repo = '', branch = 'master'):
    utility.printMsg( "Ensuring local branch %s in %s is up to date with origin" % (branch, repo))
    with utility.cd(repo):
        # attempt to fetch the requested branch
        try:
            git.fetch("origin", "%s:%s" % (branch, branch))
        except:
            # the branch may not exist, but this is ok
            pass
        
        if git.currentBranch() == branch:
            return

        if not git.hasBranch(branch):
            # switch to corresponding public branch if the branch does not exist
            public = grapeConfig.workspaceConfig().getPublicBranchFor(branch)
            # figure out if this is a submodule
            relpath = os.path.relpath(repo, utility.workspaceDir())
            relpath = relpath.replace('\\',"/")
            with utility.cd(utility.workspaceDir()):
                # if this is a submodule, get the appropriate public mapping
                if relpath in git.getAllSubmoduleURLMap().keys():
                    public = grapeConfig.workspaceConfig().getMapping("workspace", "submodulepublicmappings")[public]
            utility.printMsg("Branch %s does not exist in %s, switching to %s and detaching" % (branch, repo, public))
            git.checkout(public)
            git.pull("origin %s" % (public))
            git.checkout("--detach HEAD")
Example #6
0
File: pull.py Project: LLNL/GRAPE
    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
Example #7
0
 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]        
Example #8
0
File: pull.py Project: LLNL/GRAPE
    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
Example #9
0
    def description(self):
        try: 
            currentBranch = git.currentBranch()
        except git.GrapeGitError:
            currentBranch = 'unknown'
        publicBranch = self.lookupPublicBranch()

        return "Merge latest changes on %s into %s" % (publicBranch, currentBranch)
Example #10
0
 def getDesiredSubmoduleBranch(config):
     publicBranches = config.getPublicBranchList()
     currentBranch = git.currentBranch()
     if currentBranch in publicBranches:
         desiredSubmoduleBranch = config.getMapping("workspace", "submodulepublicmappings")[currentBranch]
     else:
         desiredSubmoduleBranch = currentBranch
     return desiredSubmoduleBranch
Example #11
0
 def getDesiredSubmoduleBranch(config):
     publicBranches = config.getPublicBranchList()
     currentBranch = git.currentBranch()
     if currentBranch in publicBranches:
         desiredSubmoduleBranch = config.getMapping(
             "workspace", "submodulepublicmappings")[currentBranch]
     else:
         desiredSubmoduleBranch = currentBranch
     return desiredSubmoduleBranch
Example #12
0
    def description(self):
        try:
            currentBranch = git.currentBranch()
        except git.GrapeGitError:
            currentBranch = 'unknown'
        publicBranch = self.lookupPublicBranch()

        return "Merge latest changes on %s into %s" % (publicBranch,
                                                       currentBranch)
Example #13
0
File: status.py Project: LLNL/GRAPE
    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
Example #14
0
    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)
Example #15
0
File: push.py Project: LLNL/GRAPE
    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
Example #16
0
 def tickVersion(self, args):
     config = grapeConfig.grapeConfig()
     fileName = config.get("versioning", "file")
     with open(fileName) as f:
         slots = self.readVersion(f, args)
         self.ver = self.slotsToString(args, slots)
         
     if not args["--notick"]:
         slot = args["--slot"]
         if not slot:
             slotMappings = config.getMapping("versioning", "branchSlotMappings")
             if args["--public"]:
                 publicBranch = args["--public"]
             else:
                 publicBranch = config.getPublicBranchFor(git.currentBranch())
             slot = int(slotMappings[publicBranch])
         else:
             slot = int(slot)
         if args["--minor"]:
             slot = 2
         if args["--major"]:
             slot = 1
         # extend the version number if slot comes in too large.
         while len(slots) < slot:
             slots.append(0)
         slots[slot - 1] += 1
         while slot < len(slots):
             slots[slot] = 0
             slot += 1
         # write the new version number to the version file. 
         with open(fileName, 'r+') as f:
             self.ver = self.writeVersion(f, slots, args)
         self.stageVersionFile(fileName)
         if not args["--nocommit"]:
             git.commit("-m \"GRAPE: ticked version to %s\"" % self.ver)
             
     if (not args["--nocommit"]) or args["--tag"]:
         self.tagVersion(self.ver, args)
         if args["--tagNested"]:
             cwd = os.getcwd()
             wsDir = utility.workspaceDir()
             for subproject in grapeConfig.GrapeConfigParser.getAllActiveNestedSubprojectPrefixes():
                 os.chdir(os.path.join(wsDir, subproject))
                 self.tagVersion(self.ver, args)
             os.chdir(cwd)
Example #17
0
 def lookupPublicBranch():
     config = grapeConfig.grapeConfig()
     try:
         currentBranch = git.currentBranch()
     except git.GrapeGitError:
         return 'unknown'
     if currentBranch in config.get('flow', 'publicBranches'):
         return currentBranch
     try:
         branch = config.getPublicBranchFor(currentBranch)
     except KeyError:
         branchPrefix = git.branchPrefix(currentBranch)
         print("WARNING: prefix %s does not have an associated topic branch, nor is a default"
               "public branch configured. \n"
               "use --public=<branch> to define, or add %s:<branch> or ?:<branch> to \n"
               "[flow].publicBranches in your .grapeconfig or .git/.grapeuserconfig. " % (branchPrefix, branchPrefix))
         branch = None
     return branch
Example #18
0
File: push.py Project: LLNL/GRAPE
    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
Example #19
0
def fetchLocal(repo='unknown', branch='master'):
    # branch is actually the list of branches
    branches = branch
    with utility.cd(repo):
        currentBranch = git.currentBranch()

        if len(branches) > 0:
            git.fetch("--prune --tags")
            allRemoteBranches = git.remoteBranches()
            fetchArgs = "origin "
            toFetch = []
            for b in branches:
                if b != currentBranch:
                    if "origin/%s" % b in allRemoteBranches:
                        fetchArgs += "%s:%s " % (b, b)
                        toFetch.append(b)
                else:
                    try:
                        utility.printMsg("Pulling current branch %s in %s" %
                                         (currentBranch, repo))
                        git.pull("origin %s" % currentBranch)
                    except git.GrapeGitError:
                        print(
                            "GRAPE: Could not pull %s from origin. Maybe you haven't pushed it yet?"
                            % currentBranch)
            try:
                if toFetch:
                    utility.printMsg("updating %s in %s" %
                                     (','.join(toFetch), repo))
                    git.fetch(fetchArgs)
            except git.GrapeGitError as e:
                # let non-fast-forward fetches slide
                if "rejected" in e.gitOutput and "non-fast-forward" in e.gitOutput:
                    print e.gitCommand
                    print e.gitOutput
                    print(
                        "GRAPE: WARNING:  one of your public branches %s in %s has local commits! "
                        "Did you forget to create a topic branch?" %
                        (",".join(branches), repo))
                    pass
                elif "Refusing to fetch into current branch" in e.gitOutput:
                    print e.gitOutput
                else:
                    raise e
Example #20
0
 def lookupPublicBranch():
     config = grapeConfig.grapeConfig()
     try:
         currentBranch = git.currentBranch()
     except git.GrapeGitError:
         return 'unknown'
     if currentBranch in config.get('flow', 'publicBranches'):
         return currentBranch
     try:
         branch = config.getPublicBranchFor(currentBranch)
     except KeyError:
         branchPrefix = git.branchPrefix(currentBranch)
         print(
             "WARNING: prefix %s does not have an associated topic branch, nor is a default"
             "public branch configured. \n"
             "use --public=<branch> to define, or add %s:<branch> or ?:<branch> to \n"
             "[flow].publicBranches in your .grapeconfig or .git/.grapeuserconfig. "
             % (branchPrefix, branchPrefix))
         branch = None
     return branch
Example #21
0
 def postCommit(args):
     #applies the autoPush hook
     autoPush = args["--autopush"]
     if autoPush.lower().strip() != "false":
         try:
             git.push("-u origin HEAD")
         except git.GrapeGitError:
             pass
         autoPush = True
     else:
         autoPush = False
     #applies the cascade hook
     print("GRAPE: checking for cascades...")
     cascadeDict = grapeConfig.GrapeConfigParser.parseConfigPairList(
         args["--cascade"])
     if cascadeDict:
         currentBranch = git.currentBranch()
         while currentBranch in cascadeDict:
             source = currentBranch
             target = cascadeDict[source]
             fastForward = False
             print("GRAPE: Cascading commit from %s to %s..." %
                   (source, target))
             if git.branchUpToDateWith(source, target):
                 fastForward = True
                 print("GRAPE: should be a fastforward cascade...")
             git.checkout("%s" % target)
             git.merge("%s -m 'Cascade from %s to %s'" %
                       (source, source, target))
             # we need to kick off the next one if it was a fast forward merge.
             # otherwise, another post-commit hook should be called from the merge commit.
             if fastForward:
                 if autoPush:
                     git.push("origin %s" % target)
                     print("GRAPE: auto push done")
                 currentBranch = target
             else:
                 currentBranch = None
Example #22
0
def fetchLocal(repo='unknown', branch='master'):
    # branch is actually the list of branches
    branches = branch
    with utility.cd(repo):
        currentBranch = git.currentBranch()

        if len(branches) > 0:
            git.fetch("--prune --tags")
            allRemoteBranches = git.remoteBranches()
            fetchArgs = "origin "
            toFetch = []
            for b in branches:
                if b != currentBranch:
                    if "origin/%s" % b in allRemoteBranches:
                        fetchArgs += "%s:%s " % (b, b)
                        toFetch.append(b)
                else:
                    try:
                        utility.printMsg("Pulling current branch %s in %s" % (currentBranch, repo))
                        git.pull("origin %s" % currentBranch)
                    except git.GrapeGitError:
                        print("GRAPE: Could not pull %s from origin. Maybe you haven't pushed it yet?" % currentBranch)                    
            try:
                if toFetch:
                    utility.printMsg("updating %s in %s" % (','.join(toFetch), repo))                         
                    git.fetch(fetchArgs)
            except git.GrapeGitError as e:
                # let non-fast-forward fetches slide
                if "rejected" in e.gitOutput and "non-fast-forward" in e.gitOutput:
                    print e.gitCommand
                    print e.gitOutput
                    print("GRAPE: WARNING:  one of your public branches %s in %s has local commits! "
                          "Did you forget to create a topic branch?" % (",".join(branches), repo))
                    pass
                elif "Refusing to fetch into current branch" in e.gitOutput:
                    print e.gitOutput
                else:
                    raise e
Example #23
0
    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
Example #24
0
File: review.py Project: LLNL/GRAPE
    def execute(self, args):
        """
        A fair chunk of this stuff relies on stashy's wrapping of the STASH REST API, which is posted at
        https://developer.atlassian.com/static/rest/stash/2.12.1/stash-rest.html
        """
        config = grapeConfig.grapeConfig()
        name = args["--user"]
        if not name:
            name = utility.getUserName()

        utility.printMsg("Logging onto %s" % args["--bitbucketURL"])
        if args["--test"]:
            bitbucket = Atlassian.TestAtlassian(name)
        else:
            verify = True if args["--verifySSL"].lower() == "true" else False
            bitbucket = Atlassian.Atlassian(name,
                                            url=args["--bitbucketURL"],
                                            verify=verify)

        # default project (outer level project)
        project_name = args["--project"]

        # default repo (outer level repo)
        repo_name = args["--repo"]

        # determine source branch and target branch
        branch = args["--source"]
        if not branch:
            branch = git.currentBranch()

        # make sure we are in the outer level repo before we push
        wsDir = utility.workspaceDir()
        os.chdir(wsDir)

        #ensure branch is pushed
        utility.printMsg("Pushing %s to bitbucket..." % branch)
        git.push("origin %s" % branch)
        #target branch for outer level repo
        target_branch = args["--target"]
        if not target_branch:
            target_branch = config.getPublicBranchFor(branch)
        # load pull request from Bitbucket if it already exists
        wsRepo = bitbucket.project(project_name).repo(repo_name)
        existingOuterLevelRequest = getReposPullRequest(
            wsRepo, branch, target_branch, args)

        # determine pull request title
        title = args["--title"]
        if existingOuterLevelRequest is not None and not title:
            title = existingOuterLevelRequest.title()

        #determine pull request URL
        outerLevelURL = None
        if existingOuterLevelRequest:
            outerLevelURL = existingOuterLevelRequest.link()

        # determine pull request description
        descr = self.parseDescriptionArgs(args)

        if not descr and existingOuterLevelRequest:
            descr = existingOuterLevelRequest.description()

        # determine pull request reviewers
        reviewers = self.parseReviewerArgs(args)
        if reviewers is None and existingOuterLevelRequest is not None:
            reviewers = [r[0] for r in existingOuterLevelRequest.reviewers()]

        # if we're in append mode, only append what was asked for:
        if args["--append"] or args["--prepend"]:
            title = args["--title"]
            descr = self.parseDescriptionArgs(args)
            reviewers = self.parseReviewerArgs(args)

        ##  Submodule Repos
        missing = utility.getModifiedInactiveSubmodules(target_branch, branch)
        if missing:
            utility.printMsg(
                "The following submodules that you've modified are not currently present in your workspace.\n"
                "You should activate them using grape uv  and then call grape review again. If you haven't modified "
                "these submodules, you may need to do a grape md to proceed.")
            utility.printMsg(','.join(missing))
            return False
        pullRequestLinks = {}
        if not args["--norecurse"] and (args["--recurse"] or config.getboolean(
                "workspace", "manageSubmodules")):

            modifiedSubmodules = git.getModifiedSubmodules(
                target_branch, branch)
            submoduleBranchMappings = config.getMapping(
                "workspace", "submoduleTopicPrefixMappings")

            for submodule in modifiedSubmodules:
                if not submodule:
                    continue
                # push branch
                os.chdir(submodule)
                utility.printMsg("Pushing %s to bitbucket..." % branch)
                git.push("origin %s" % branch)
                os.chdir(wsDir)
                repo = bitbucket.repoFromWorkspaceRepoPath(submodule,
                                                           isSubmodule=True)
                # determine branch prefix
                prefix = branch.split('/')[0]
                sub_target_branch = submoduleBranchMappings[prefix]

                prevSubDescr = getReposPullRequestDescription(
                    repo, branch, sub_target_branch, args)
                #amend the subproject pull request description with the link to the outer pull request
                subDescr = addLinkToDescription(descr, outerLevelURL, True)
                if args["--prepend"] or args["--append"]:
                    subDescr = descr
                newRequest = postPullRequest(repo, title, branch,
                                             sub_target_branch, subDescr,
                                             reviewers, args)
                if newRequest:
                    pullRequestLinks[newRequest.link()] = True
                else:
                    # if a pull request could not be generated, just add a link to browse the branch
                    pullRequestLinks[
                        "%s%s/browse?at=%s" %
                        (bitbucket.rzbitbucketURL, repo.repo.url(),
                         urllib.quote_plus("refs/heads/%s" % branch))] = False

        ## NESTED SUBPROJECT REPOS
        nestedProjects = grapeConfig.GrapeConfigParser.getAllModifiedNestedSubprojects(
            target_branch)
        nestedProjectPrefixes = grapeConfig.GrapeConfigParser.getAllModifiedNestedSubprojectPrefixes(
            target_branch)

        for proj, prefix in zip(nestedProjects, nestedProjectPrefixes):
            with utility.cd(prefix):
                git.push("origin %s" % branch)
            repo = bitbucket.repoFromWorkspaceRepoPath(proj,
                                                       isSubmodule=False,
                                                       isNested=True)

            newRequest = postPullRequest(repo, title, branch, target_branch,
                                         descr, reviewers, args)
            if newRequest:
                pullRequestLinks[newRequest.link()] = True
            else:
                # if a pull request could not be generated, just add a link to browse the branch
                pullRequestLinks["%s%s/browse?at=%s" %
                                 (bitbucket.rzbitbucketURL, repo.repo.url(),
                                  urllib.quote_plus(
                                      "refs/heads/%s" % branch))] = False

        ## OUTER LEVEL REPO
        # load the repo level REST resource
        if not args["--subprojectsOnly"]:
            if not git.hasBranch(branch):
                utility.printMsg(
                    "Top level repository does not have a branch %s, not generating a Pull Request"
                    % (branch))
                return True
            if git.branchUpToDateWith(target_branch, branch):
                utility.printMsg(
                    "%s up to date with %s, not generating a Pull Request in Top Level repo"
                    % (target_branch, branch))
                return True

            repo_name = args["--repo"]
            repo = bitbucket.repoFromWorkspaceRepoPath(
                wsDir, topLevelRepo=repo_name, topLevelProject=project_name)
            utility.printMsg("Posting pull request to %s,%s" %
                             (project_name, repo_name))
            request = postPullRequest(repo, title, branch, target_branch,
                                      descr, reviewers, args)
            updatedDescription = request.description()
            for link in pullRequestLinks:
                updatedDescription = addLinkToDescription(
                    updatedDescription, link, pullRequestLinks[link])

            if updatedDescription != request.description():
                request = postPullRequest(repo, title, branch, target_branch,
                                          updatedDescription, reviewers, args)

            utility.printMsg("Request generated/updated:\n\n%s" % request)
        return True
Example #25
0
    def execute(self, args):
        if TkinterImportError:
            utility.printMsg(
                "grape w requires Tkinter.\n  The following error was raised during the import:\n\n%s\n"
                % TkinterImportError)
            return True
        config = grapeConfig.grapeConfig()
        difftool = args["--difftool"]
        height = args["--height"]
        width = args["--width"]
        doMergeDiff = True
        if args["--rawDiff"]:
            doMergeDiff = False
        elif args["--mergeDiff"]:
            # This is already the default
            doMergeDiff = True

        cwd = os.getcwd()
        os.chdir(utility.workspaceDir())

        b1 = args["<b1>"]
        if not b1:
            b1 = git.currentBranch()

        b2 = args["<b2>"]

        if args["--staged"]:
            b2 = b1
            b1 = "--cached"
            doMergeDiff = False
        elif args["--workspace"]:
            b2 = "--"
            doMergeDiff = False
        else:
            if not b2:
                try:
                    # put the public branch first so merge diff shows
                    # changes on the current branch.
                    b2 = b1
                    b1 = config.getPublicBranchFor(b2)
                except:
                    b2 = ""
                    doMergeDiff = False

        diffargs = ""

        root = Tk.Tk()
        root.title("GRAPE walkthrough")

        diffmanager = DiffManager(
            master=root,
            height=height,
            width=width,
            branchA=b1,
            branchB=b2,
            difftool=difftool,
            diffargs=diffargs,
            doMergeDiff=doMergeDiff,
            showUnchanged=args["--showUnchanged"],
            showInactive=not args["--noInactive"],
            showToplevel=not args["--noTopLevel"],
            showSubmodules=not args["--noSubmodules"],
            showSubtrees=not args["--noSubtrees"],
            showNestedSubprojects=not args["--noNestedSubprojects"],
            noFetch=args["--noFetch"])

        root.mainloop()

        os.chdir(cwd)

        try:
            root.destroy()
        except:
            pass
        return True
Example #26
0
    def mergeSubproject(self,
                        args,
                        subproject,
                        subPublic,
                        subprojects,
                        cwd,
                        isSubmodule=True):
        # if we did this merge in a previous run, don't do it again
        try:
            if self.progress["Subproject: %s" % subproject] == "finished":
                return True
        except KeyError:
            pass
        os.chdir(os.path.join(git.baseDir(), subproject))
        mergeArgs = args.copy()
        mergeArgs["--public"] = subPublic

        utility.printMsg(
            "Merging %s into %s for %s %s" %
            (subPublic, git.currentBranch(),
             "submodule" if isSubmodule else "subproject", subproject))
        git.fetch("origin")
        # update our local reference to the remote branch so long as it's fast-forwardable or we don't have it yet..)
        hasRemote = git.hasBranch("origin/%s" % subPublic)
        hasBranch = git.hasBranch(subPublic)
        if hasRemote and (git.branchUpToDateWith(
                subPublic, "origin/%s" % subPublic) or not hasBranch):
            git.fetch("origin %s:%s" % (subPublic, subPublic))
        ret = self.mergeIntoCurrent(subPublic, mergeArgs, subproject)
        conflict = not ret
        if conflict:
            self.progress["stopPoint"] = "Subproject: %s" % subproject
            subprojectKey = "submodules" if isSubmodule else "nested"
            self.progress[subprojectKey] = subprojects
            self.progress["cwd"] = cwd
            conflictedFiles = git.conflictedFiles()
            if conflictedFiles:
                if isSubmodule:
                    typeStr = "submodule"
                else:
                    typeStr = "nested subproject"

                utility.printMsg(
                    "Merge in %s %s from %s to %s issued conflicts. Resolve and commit those changes \n"
                    "using git mergetool and git commit in the submodule, then continue using grape\n"
                    "%s --continue" % (typeStr, subproject, subPublic,
                                       git.currentBranch(), args["<<cmd>>"]))
            else:
                utility.printMsg(
                    "Merge in %s failed for an unhandled reason. You may need to stash / commit your current\n"
                    "changes before doing the merge. Inspect git output above to troubleshoot. Continue using\n"
                    "grape %s --continue." % (subproject, args["<<cmd>>"]))
            return False
        # if we are resuming from a conflict, the above grape m call would have taken care of continuing.
        # clear out the --continue flag.
        args["--continue"] = False
        # stage the updated submodule
        os.chdir(cwd)
        if isSubmodule:
            git.add(subproject)
        self.progress["Subproject: %s" % subproject] = "finished"
        return True
Example #27
0
    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
Example #28
0
    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
Example #29
0
File: review.py Project: LLNL/GRAPE
    def execute(self, args):
        """
        A fair chunk of this stuff relies on stashy's wrapping of the STASH REST API, which is posted at
        https://developer.atlassian.com/static/rest/stash/2.12.1/stash-rest.html
        """
        config = grapeConfig.grapeConfig()
        name = args["--user"]
        if not name:
            name = utility.getUserName()
            
        utility.printMsg("Logging onto %s" % args["--bitbucketURL"])
        if args["--test"]:
            bitbucket = Atlassian.TestAtlassian(name)
        else:
            verify = True if args["--verifySSL"].lower() == "true" else False
            bitbucket = Atlassian.Atlassian(name, url=args["--bitbucketURL"], verify=verify)

        # default project (outer level project)
        project_name = args["--project"]
        
        # default repo (outer level repo)
        repo_name = args["--repo"]

        # determine source branch and target branch
        branch = args["--source"]
        if not branch:
            branch = git.currentBranch()

        # make sure we are in the outer level repo before we push
        wsDir = utility.workspaceDir()
        os.chdir(wsDir)

        #ensure branch is pushed
        utility.printMsg("Pushing %s to bitbucket..." % branch)
        git.push("origin %s" % branch)
        #target branch for outer level repo
        target_branch = args["--target"]
        if not target_branch:
            target_branch = config.getPublicBranchFor(branch)        
        # load pull request from Bitbucket if it already exists
        wsRepo =  bitbucket.project(project_name).repo(repo_name)
        existingOuterLevelRequest = getReposPullRequest(wsRepo, branch, target_branch, args)  

        # determine pull request title
        title = args["--title"]
        if existingOuterLevelRequest is not None and not title:
            title = existingOuterLevelRequest.title()

        
        #determine pull request URL
        outerLevelURL = None
        if existingOuterLevelRequest:
            outerLevelURL = existingOuterLevelRequest.link()
        
        # determine pull request description
        descr = self.parseDescriptionArgs(args)

        if not descr and existingOuterLevelRequest:
            descr = existingOuterLevelRequest.description()

    
        # determine pull request reviewers
        reviewers = self.parseReviewerArgs(args)
        if reviewers is None and existingOuterLevelRequest is not None:
            reviewers = [r[0] for r in existingOuterLevelRequest.reviewers()]

        # if we're in append mode, only append what was asked for:
        if args["--append"] or args["--prepend"]:
            title = args["--title"]
            descr = self.parseDescriptionArgs(args)
            reviewers = self.parseReviewerArgs(args)
            
        ##  Submodule Repos
        missing = utility.getModifiedInactiveSubmodules(target_branch, branch)
        if missing:
            utility.printMsg("The following submodules that you've modified are not currently present in your workspace.\n"
                             "You should activate them using grape uv  and then call grape review again. If you haven't modified "
                             "these submodules, you may need to do a grape md to proceed.")
            utility.printMsg(','.join(missing))
            return False        
        pullRequestLinks = {}
        if not args["--norecurse"] and (args["--recurse"] or config.getboolean("workspace", "manageSubmodules")):
            
            modifiedSubmodules = git.getModifiedSubmodules(target_branch, branch)
            submoduleBranchMappings = config.getMapping("workspace", "submoduleTopicPrefixMappings")
                        
            for submodule in modifiedSubmodules:
                if not submodule:
                    continue
                # push branch
                os.chdir(submodule)
                utility.printMsg("Pushing %s to bitbucket..." % branch)
                git.push("origin %s" % branch)
                os.chdir(wsDir)
                repo = bitbucket.repoFromWorkspaceRepoPath(submodule, 
                                                         isSubmodule=True)
                # determine branch prefix
                prefix = branch.split('/')[0]
                sub_target_branch = submoduleBranchMappings[prefix]
                
                prevSubDescr = getReposPullRequestDescription(repo, branch, 
                                                             sub_target_branch, 
                                                             args)
                #amend the subproject pull request description with the link to the outer pull request
                subDescr = addLinkToDescription(descr, outerLevelURL, True)
                if args["--prepend"] or args["--append"]:
                    subDescr = descr
                newRequest = postPullRequest(repo, title, branch, sub_target_branch, subDescr, reviewers, args)
                if newRequest:
                    pullRequestLinks[newRequest.link()] = True
                else:
                    # if a pull request could not be generated, just add a link to browse the branch
                    pullRequestLinks["%s%s/browse?at=%s" % (bitbucket.rzbitbucketURL,
                                                            repo.repo.url(),
                                                            urllib.quote_plus("refs/heads/%s" % branch))] = False
        
        ## NESTED SUBPROJECT REPOS 
        nestedProjects = grapeConfig.GrapeConfigParser.getAllModifiedNestedSubprojects(target_branch)
        nestedProjectPrefixes = grapeConfig.GrapeConfigParser.getAllModifiedNestedSubprojectPrefixes(target_branch)
        
        for proj, prefix in zip(nestedProjects, nestedProjectPrefixes):
            with utility.cd(prefix):
                git.push("origin %s" % branch)
            repo = bitbucket.repoFromWorkspaceRepoPath(proj, isSubmodule=False, isNested=True)
            
            newRequest = postPullRequest(repo, title, branch, target_branch,descr, reviewers, args)
            if newRequest:
                pullRequestLinks[newRequest.link()] = True
            else:
                # if a pull request could not be generated, just add a link to browse the branch
                pullRequestLinks["%s%s/browse?at=%s" % (bitbucket.rzbitbucketURL,
                                                        repo.repo.url(),
                                                        urllib.quote_plus("refs/heads/%s" % branch))] = False
            

        ## OUTER LEVEL REPO
        # load the repo level REST resource
        if not args["--subprojectsOnly"]:
            if not git.hasBranch(branch):
                utility.printMsg("Top level repository does not have a branch %s, not generating a Pull Request" % (branch))
                return True
            if git.branchUpToDateWith(target_branch, branch):
                utility.printMsg("%s up to date with %s, not generating a Pull Request in Top Level repo" % (target_branch, branch))
                return True
            
                
            repo_name = args["--repo"]
            repo = bitbucket.repoFromWorkspaceRepoPath(wsDir, topLevelRepo=repo_name, topLevelProject=project_name)
            utility.printMsg("Posting pull request to %s,%s" % (project_name, repo_name))
            request = postPullRequest(repo, title, branch, target_branch, descr, reviewers, args)
            updatedDescription = request.description()
            for link in pullRequestLinks:
                updatedDescription = addLinkToDescription(updatedDescription, link, pullRequestLinks[link])

            if updatedDescription != request.description(): 
                request = postPullRequest(repo, title, branch, target_branch, 
                                         updatedDescription, 
                                         reviewers, 
                                         args)
                       
            utility.printMsg("Request generated/updated:\n\n%s" % request)
        return True
Example #30
0
    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
Example #31
0
    def execute(self,args):
        if TkinterImportError:
           utility.printMsg("grape w requires Tkinter.\n  The following error was raised during the import:\n\n%s\n" % TkinterImportError)
           return True
        config = grapeConfig.grapeConfig()
        difftool = args["--difftool"]
        height = args["--height"]
        width = args["--width"]
        doMergeDiff = True
        if args["--rawDiff"]:
           doMergeDiff = False
        elif args["--mergeDiff"]:
           # This is already the default
           doMergeDiff = True

        cwd = os.getcwd()
        os.chdir(utility.workspaceDir())

        b1 = args["<b1>"] 
        if not b1: 
           b1 = git.currentBranch()

        b2 = args["<b2>"]

        if args["--staged"]:
           b2 = b1
           b1 = "--cached"
           doMergeDiff = False
        elif args["--workspace"]:
           b2 = "--"
           doMergeDiff = False
        else:
           if not b2: 
              try:
                 # put the public branch first so merge diff shows
                 # changes on the current branch.
                 b2 = b1
                 b1 = config.getPublicBranchFor(b2)
              except:
                 b2 = ""
                 doMergeDiff = False

        diffargs = ""
               
        root = Tk.Tk()
        root.title("GRAPE walkthrough")
        
        diffmanager = DiffManager(master=root, height=height, width=width,
                                  branchA=b1, branchB=b2,
                                  difftool=difftool, diffargs=diffargs, doMergeDiff=doMergeDiff,
                                  showUnchanged=args["--showUnchanged"],
                                  showInactive=not args["--noInactive"], showToplevel=not args["--noTopLevel"],
                                  showSubmodules=not args["--noSubmodules"], showSubtrees=not args["--noSubtrees"],
                                  showNestedSubprojects=not args["--noNestedSubprojects"],
                                  noFetch=args["--noFetch"])
        
        root.mainloop()
        
        os.chdir(cwd)

        try:
           root.destroy()
        except:
           pass
        return True
Example #32
0
 def parseArgs(self, args): 
     config = grapeConfig.grapeConfig()
     # parse tagSuffix for version mappings
     if args["--tagSuffix"] is None: 
         branch2suffix = config.getMapping("versioning", "branchtagsuffixmappings")
         args["--tagSuffix"] = branch2suffix[git.currentBranch()]