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..885d2d5 --- /dev/null +++ b/hands_on/populate_remote.py @@ -0,0 +1,71 @@ +import os + +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): + _initialize_workspace(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.""" + _, return_code = run_command_with_code(["gh", "repo", "view", _get_full_repo_name(verbose)], verbose) + if return_code == 0: + run_command(["gh", "repo", "delete", REPO_NAME, "--yes"], verbose) + + 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 _initialize_workspace(verbose: bool): + os.makedirs("things") + os.chdir("things") + init(verbose) + + +def _get_full_repo_name(verbose: bool) -> str: + username = run_command(["gh", "api", "user", "-q", ".login"], verbose).strip() + return f"{username}/{REPO_NAME}"