import os import subprocess import shutil import tempfile from git import Repo, GitCommandError CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) GIT_EXTRAS_BIN = os.path.abspath(os.path.join(CURRENT_DIR, "..", "bin")) GIT_EXTRAS_HELPER = os.path.abspath(os.path.join(CURRENT_DIR, "..", "helper")) GITHUB_ORIGIN = "https://github.com/tj/git-extras.git" GITLAB_ORIGIN = "https://gitlab.com/tj/git-extras.git" BITBUCKET_ORIGIN = "https://bitbucket.org/tj/git-extras.git" class TempRepository: def __init__(self, repo_work_dir=None): self._system_tmpdir = tempfile.gettempdir() if repo_work_dir is None: repo_work_dir = tempfile.mkdtemp() else: repo_work_dir = os.path.join(self._system_tmpdir, repo_work_dir) self._cwd = repo_work_dir self._tempdirname = self._cwd[len(self._system_tmpdir) + 1 :] self._git_repo = Repo.init(repo_work_dir, b="default") self._files = [] self.change_origin_to_github() def switch_cwd_under_repo(self): os.chdir(self._cwd) print(f"The current work directory has switched to {self._cwd}") def get_cwd(self): return self._cwd def get_repo_dirname(self): return self._tempdirname def get_repo_git(self): return self._git_repo.git def get_file(self, index): return self._files[index] def get_filename(self, index): file = self._files[index] return file[1:] def get_files(self): return self._files def create_tmp_dir(self): tmp_dir = tempfile.mkdtemp() return tmp_dir def create_tmp_file(self, temp_dir=None): if temp_dir is None: temp_dir = self._cwd tmp_file = tempfile.mkstemp(dir=temp_dir) self._files.append(tmp_file[1]) return tmp_file def remove_tmp_file(self, file_path): os.remove(file_path) print(f"File {file_path} has been removed") def writefile(self, temp_file, data): if data is None: return with open(temp_file, "w", encoding="utf-8") as f: f.write(data) def teardown(self): shutil.rmtree(self._cwd, ignore_errors=True) print(f"The temp directory {self._cwd} has been removed") def invoke_extras_command(self, name, *params): command_name = "git-" + name print(f"Invoke the git-extras command - {command_name} at {self._cwd}") script = [os.path.join(GIT_EXTRAS_BIN, command_name), *list(params)] print(f"Run the script \"{' '.join(script)}\"") return subprocess.run(script, capture_output=True) def invoke_installed_extras_command(self, name, *params): command_name = "git-" + name print(f"Invoke the git-extras command - {command_name} at {self._cwd}") origin_extras_command = os.path.join(GIT_EXTRAS_BIN, command_name) temp_extras_command = os.path.join(self._cwd, command_name) helpers = [ os.path.join(GIT_EXTRAS_HELPER, "git-extra-utility"), os.path.join(GIT_EXTRAS_HELPER, "is-git-repo"), ] if not os.path.exists(temp_extras_command): whole = [] with open(temp_extras_command, "w") as t: for helper in helpers: with open(helper) as h: content = h.read() whole.extend(content.splitlines()) with open(origin_extras_command) as o: content = o.read() first, *rest = content.splitlines() whole.extend(rest) whole.insert(0, first) t.write("\n".join(whole)) print(f"Update file {temp_extras_command}") os.chmod(temp_extras_command, 0o775) script = [temp_extras_command, *params] print(f'Run the script "{script}"') return subprocess.run(script, capture_output=True) def change_origin(self, origin_url): try: self._git_repo.git.remote("add", "origin", origin_url) except GitCommandError as err: print(err) self._git_repo.git.remote("set-url", "origin", origin_url) def change_origin_to_github(self): self.change_origin(GITHUB_ORIGIN) def change_origin_to_gitlab(self): self.change_origin(GITLAB_ORIGIN) def change_origin_to_bitbucket(self): self.change_origin(BITBUCKET_ORIGIN)