def test_repoStart_onDetached(self): self.runRepo(["start", "topic"]) for sProjectFolder in self.dProjectFolders: with changeWorkingDir(sProjectFolder): assert git.getCurrentBranch() == "topic" assert git.getGitMessages() == [INITIAL_COMMIT_MSG]
def runInRepos(self, dRepos, xFunction, bPrint=True, bCheckTopic=True): if bCheckTopic: lBranches = set() try: for sDirPath in dRepos.values(): if os.path.isdir(sDirPath): with changeWorkingDir(sDirPath): lBranches.add( strOrDefault(git.getCurrentBranch(), "(none)")) except (subprocess.CalledProcessError, OSError) as e: raise FatalError(e) if len(lBranches) > 1: warning("Topic is not consistent across your repositories. " "Found following topics: %s" % ", ".join(lBranches)) sInput = input("Do you wish to proceed anyway? (y/n): ") if sInput != "y": raise FatalError("Operation cancelled") lErrorRepos = [] for sRepoUrl, sDirPath in dRepos.items(): sRepoName = os.path.basename(sDirPath) try: os.makedirs(sDirPath, exist_ok=True) with changeWorkingDir(sDirPath): if bPrint: highlight("\n### %s ###" % os.path.basename(os.getcwd())) xFunction(sRepoUrl) if bPrint: success("Done") except (subprocess.CalledProcessError, FatalError, OSError) as e: error("[%s] %s" % (sRepoName, e)) lErrorRepos.append(sDirPath) return lErrorRepos
def test_repoSync_checkout(self): for sProjectFolder in self.dProjectFolders: with changeWorkingDir(sProjectFolder): lBranches = git.getAllBranches() assert len(lBranches) == 1 assert re.match(r"\(HEAD detached at .*\)", lBranches[0], re.IGNORECASE) is not None assert git.getCurrentBranch() == "" assert git.getGitMessages() == [INITIAL_COMMIT_MSG]
def test_repoDownload_detach(self): iChangeNumber, _ = self.repoDownloadTestSetup() self.runRepo(["download", "-d", next(iter(self.dProjectFolders.values())), "%d/1" % iChangeNumber]) for iIdx, sProjectFolder in enumerate(self.dProjectFolders): with changeWorkingDir(sProjectFolder): if iIdx == 0: assert git.getCurrentBranch() == "" assert os.path.isfile("test_1.txt") assert not os.path.isfile("test_2.txt") assert git.getGitMessages() == ["Test commit (1)", INITIAL_COMMIT_MSG] else: assert git.getCurrentBranch() == "topic_2" assert not os.path.isfile("test_1.txt") assert os.path.isfile("test_2.txt") assert git.getGitMessages() == ["Test commit (2)", INITIAL_COMMIT_MSG]
def END(self): if git.getCurrentBranch() == self.oArgs.topic: print("Detaching HEAD") subprocess.run( ["git", "fetch", git.getFirstRemote(), "HEAD"], check=True) subprocess.run(["git", "checkout", "FETCH_HEAD", "--detach"], check=True) print("Deleting topic %s" % self.oArgs.topic) subprocess.run(["git", "branch", "-D", self.oArgs.topic], check=True)
def test_repoRename(self): self.runRepo(["start", "topic"]) self.runRepo(["rename", "renamed_topic"]) for sProjectFolder in self.dProjectFolders: with changeWorkingDir(sProjectFolder): assert git.getCurrentBranch() == "renamed_topic" assert git.getAllBranches() == ["renamed_topic"]
def RENAME(self): sCurrentBranch = git.getCurrentBranch() if sCurrentBranch: print("Renaming topic: %s -> %s" % (sCurrentBranch, self.oArgs.topic)) subprocess.run(["git", "branch", "-m", self.oArgs.topic], check=True) else: raise FatalError("There is no topic")
def test_repoStart_onOtherTopic(self): self.runRepo(["start", "topic_1"]) self.createCommit() self.runRepo(["start", "topic_2"]) for sProjectFolder in self.dProjectFolders: with changeWorkingDir(sProjectFolder): assert git.getCurrentBranch() == "topic_2" assert git.getGitMessages() == ["Test commit (1)", INITIAL_COMMIT_MSG] assert os.path.isfile("test_1.txt")
def test_repoEnd_whenNotActive(self): self.runRepo(["start", "topic_1"]) self.runRepo(["start", "topic_2"]) self.runRepo(["end", "topic_1"]) for sProjectFolder in self.dProjectFolders: with changeWorkingDir(sProjectFolder): assert git.getAllBranches() == ["topic_2"] assert git.getCurrentBranch() == "topic_2"
def test_repoSync_detach(self): self.runRepo(["start", "topic"]) self.createCommit() self.runRepo(["sync", "-d"]) for sProjectFolder in self.dProjectFolders: with changeWorkingDir(sProjectFolder): assert git.getCurrentBranch() == "" assert git.getGitMessages() == [INITIAL_COMMIT_MSG] assert not os.path.isfile("test_1.txt")
def test_repoDownload_rebase_wrongProject(self): iChangeNumber, _ = self.repoDownloadTestSetup() oProcess = self.runRepo(["download", "foobar", "%d/1" % iChangeNumber], check=False) assert oProcess.returncode != 0 for iIdx, sProjectFolder in enumerate(self.dProjectFolders): with changeWorkingDir(sProjectFolder): assert git.getCurrentBranch() == "topic_2" assert os.path.isfile("test_2.txt") assert not os.path.isfile("test_1.txt") assert git.getGitMessages() == ["Test commit (2)", INITIAL_COMMIT_MSG]
def test_repoEnd_whenActive(self): self.runRepo(["start", "topic"]) self.createCommit() self.runRepo(["end", "topic"]) for sProjectFolder in self.dProjectFolders: with changeWorkingDir(sProjectFolder): lBranches = git.getAllBranches() assert len(lBranches) == 1 assert re.match(r"\(HEAD detached at .*\)", lBranches[0], re.IGNORECASE) is not None assert git.getCurrentBranch() == "" assert git.getGitMessages() == [INITIAL_COMMIT_MSG] assert not os.path.isfile("test_1.txt")
def test_repoRebase_simple(self): self.runRepo(["start", "topic_2"]) self.runRepo(["start", "topic_1"]) self.createCommit(sId="1") self.runRepo(["switch", "topic_2"]) self.createCommit(sId="2") self.runRepo(["rebase", "topic_1"]) for iIdx, sProjectFolder in enumerate(self.dProjectFolders): with changeWorkingDir(sProjectFolder): assert git.getCurrentBranch() == "topic_2" assert os.path.isfile("test_1.txt") assert os.path.isfile("test_2.txt") assert git.getGitMessages() == ["Test commit (2)", "Test commit (1)", INITIAL_COMMIT_MSG]
def SYNC(self, sRepoUrl): if not os.path.isdir(".git"): print("Cloning from %s" % sRepoUrl) subprocess.run(["git", "clone", sRepoUrl, "."], check=True) sCurrentBranch = git.getCurrentBranch() subprocess.run(["git", "checkout", "HEAD", "--detach"], check=True) subprocess.run(["git", "branch", "-d", sCurrentBranch], check=True) else: print("Syncing from %s" % sRepoUrl) subprocess.run( ["git", "fetch", git.getFirstRemote(), "HEAD"], check=True) if self.oArgs.detach: subprocess.run(["git", "checkout", "FETCH_HEAD", "--detach"], check=True) else: gerrit.rebase("FETCH_HEAD", bIgnoreChangeIds=True)
def repoDownloadTestAssertResult(self, iPatch): for iIdx, sProjectFolder in enumerate(self.dProjectFolders): with changeWorkingDir(sProjectFolder): assert git.getCurrentBranch() == "topic_2" assert os.path.isfile("test_2.txt") if iIdx == 0: assert os.path.isfile("test_1.txt") if iPatch == 1: assert git.getGitMessages() == ["Test commit (2)", "Test commit (1)", INITIAL_COMMIT_MSG] elif iPatch == 2: assert git.getGitMessages() == ["Test commit (2)", "Amended test commit (1)", INITIAL_COMMIT_MSG] else: pytest.fail("iPatch parameter must be 1 or 2, received %d" % iPatch) else: assert not os.path.isfile("test_1.txt") assert git.getGitMessages() == ["Test commit (2)", INITIAL_COMMIT_MSG]
def test_repoRebase_complex(self): self.runRepo(["start", "topic_1"]) self.createCommit(sId="1") self.runRepo(["start", "topic_2"]) self.createCommit(sId="2") self.runRepo(["switch", "topic_1"]) self.createCommit(sId="1", bAmend=True) self.runRepo(["switch", "topic_2"]) self.runRepo(["rebase", "topic_1"]) for iIdx, sProjectFolder in enumerate(self.dProjectFolders): with changeWorkingDir(sProjectFolder): assert git.getCurrentBranch() == "topic_2" sFileName = "test_1.txt" assert os.path.isfile(sFileName) with open(sFileName, "r") as oFile: assert oFile.read() == "This is an amended test (1)." assert os.path.isfile("test_2.txt") assert git.getGitMessages() == ["Test commit (2)", "Amended test commit (1)", INITIAL_COMMIT_MSG]
def PULL(self, sRepoUrl): sChangeId = gerrit.getChangeId() if not sChangeId: raise FatalError("Unable to extract Change-Id") sProject = gerrit.getProjectName() try: dChangeData = self.getApiClient().getChangeData( sChangeId, sProject, lAdditionalData=["ALL_REVISIONS"]) except requests.HTTPError as e: if e.response.status_code == 404: warning("No remote patch") return raise e sRemoteCommit = dChangeData["current_revision"] sLocalCommit = git.getLastCommit() sLastPushedCommit = self.getRepoData().getLastPushedCommit( sProject, sChangeId) if sRemoteCommit == sLocalCommit: print("Already up-to-date.") return elif sRemoteCommit == sLastPushedCommit: print("You are ahead of Gerrit.") return elif sLocalCommit in dChangeData["revisions"]: print("Pulling changes from %s" % sRepoUrl) sBranch = git.getCurrentBranch() dFetchData = dChangeData["revisions"][sRemoteCommit]["fetch"][ "ssh"] subprocess.run( ["git", "fetch", dFetchData["url"], dFetchData["ref"]], check=True) subprocess.run(["git", "checkout", "FETCH_HEAD"], check=True) if sBranch: subprocess.run(["git", "branch", "-D", sBranch], check=True) subprocess.run(["git", "checkout", "-b", sBranch], check=True) else: raise FatalError("You have local commits unknown to Gerrit")
def rebase(sTargetBranch, bIgnoreChangeIds=False): sCurrentBranch = git.getCurrentBranch() if not sCurrentBranch: sCurrentBranch = "tmp.%06d" % random.randrange(1e6) subprocess.run(["git", "checkout", "-b", sCurrentBranch], check=True) bDeleteBranch = True else: bDeleteBranch = False subprocess.run(["git", "checkout", "--detach", sTargetBranch], check=True) lChangeIds = cherry( sCurrentBranch).values() if not bIgnoreChangeIds else [] for sCommitIdToPick, sChangeId in cherry("HEAD", sHead=sCurrentBranch).items(): if sChangeId in lChangeIds: continue git.cherryPick(sCommitIdToPick, xOnAbort=lambda: subprocess.run( ["git", "checkout", sCurrentBranch], check=True)) if bDeleteBranch: subprocess.run(["git", "branch", "-D", sCurrentBranch]) else: subprocess.run(["git", "checkout", "-B", sCurrentBranch], check=True)
def topic(): sRepoName = os.path.basename(os.getcwd()) dTopics[sRepoName] = strOrDefault(git.getCurrentBranch(), "(none)")
def SWITCH(self): print( "Switching topic: %s -> %s" % (strOrDefault(git.getCurrentBranch(), "(none)"), self.oArgs.topic)) subprocess.run(["git", "checkout", self.oArgs.topic], check=True)
def START(self): print( "Creating new topic: %s -> %s" % (strOrDefault(git.getCurrentBranch(), "(none)"), self.oArgs.topic)) subprocess.run(["git", "checkout", "-b", self.oArgs.topic], check=True)