diff --git a/exercise_utils/cli.py b/exercise_utils/cli.py index c66057f..45fff1f 100644 --- a/exercise_utils/cli.py +++ b/exercise_utils/cli.py @@ -45,3 +45,21 @@ def run_command_no_exit(command: List[str], verbose: bool) -> Optional[str]: if verbose: print(e.stderr) return None + + +def run_command_with_code(command: List[str], verbose: bool) -> tuple[Optional[str], int]: + """Runs the given command and returns (output, return code).""" + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + ) + if verbose: + print(result.stdout) + return result.stdout, result.returncode + except subprocess.CalledProcessError as e: + if verbose: + print(e.stderr) + return e.stderr, e.returncode diff --git a/exercise_utils/git.py b/exercise_utils/git.py index 5df9919..18f2462 100644 --- a/exercise_utils/git.py +++ b/exercise_utils/git.py @@ -78,3 +78,8 @@ def track_remote_branch(remote: str, branch: str, verbose: bool) -> None: def remove_remote(remote: str, verbose: bool) -> None: """Removes a given remote.""" run_command(["git", "remote", "rm", remote], verbose) + + +def add_remote(remote: str, remote_url: str, verbose: bool) -> None: + """Adds a remote with the given name and URL.""" + run_command(["git", "remote", "add", remote, remote_url], verbose) diff --git a/hands_on/populate_remote.py b/hands_on/populate_remote.py new file mode 100644 index 0000000..9656b21 --- /dev/null +++ b/hands_on/populate_remote.py @@ -0,0 +1,81 @@ +import os +import sys + +from exercise_utils.cli import run_command, run_command_with_code +from exercise_utils.file import create_or_update_file, append_to_file +from exercise_utils.git import add, init, commit, add_remote + +__requires_git__ = True +__requires_github__ = True + +REPO_NAME = "gitmastery-things" + + +def download(verbose: bool): + _setup_local_repository(verbose) + _create_things_repository(verbose) + _link_repositories(verbose) + + +def _setup_local_repository(verbose: bool): + os.makedirs("things") + os.chdir("things") + init(verbose) + + create_or_update_file( + "fruits.txt", + """ + apples + bananas + cherries + dragon fruits + """, + ) + add(["fruits.txt"], verbose) + + append_to_file("fruits.txt", "figs") + add(["fruits.txt"], verbose) + commit("Insert figs into fruits.txt", verbose) + + create_or_update_file( + "colours.txt", + """ + a file for colours + """, + ) + create_or_update_file( + "shapes.txt", + """ + a file for shapes + """, + ) + add(["colours.txt", "shapes.txt"], verbose) + commit("Add colours.txt, shapes.txt", verbose) + + +def _create_things_repository(verbose: bool): + """Create the gitmastery-things repository, deleting any existing ones.""" + full_repo_name = _get_full_repo_name(verbose) + _, return_code = run_command_with_code( + ["gh", "repo", "view", full_repo_name], verbose + ) + + if return_code == 0: + print( + f"\nRepository 'https://github.com/{full_repo_name}' already exists on GitHub.\n" + "Please delete the existing repository before proceeding." + ) + sys.exit(1) + + run_command(["gh", "repo", "create", REPO_NAME, "--public"], verbose) + + +def _link_repositories(verbose: bool): + full_repo_name = _get_full_repo_name(verbose) + add_remote("origin", f"https://github.com/{full_repo_name}", verbose) + + +def _get_full_repo_name(verbose: bool) -> str: + output = run_command(["gh", "api", "user", "-q", ".login"], verbose) + username = output.strip() if output else "" + return f"{username}/{REPO_NAME}"