Conditions | 11 |
Total Lines | 75 |
Code Lines | 49 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like cookiecutter.vcs.clone() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | """Helper functions for working with version control systems.""" |
||
59 | def clone( |
||
60 | repo_url: str, |
||
61 | checkout: Optional[str] = None, |
||
62 | clone_to_dir: "os.PathLike[str]" = ".", |
||
63 | no_input: bool = False, |
||
64 | ): |
||
65 | """Clone a repo to the current directory. |
||
66 | |||
67 | :param repo_url: Repo URL of unknown type. |
||
68 | :param checkout: The branch, tag or commit ID to checkout after clone. |
||
69 | :param clone_to_dir: The directory to clone to. |
||
70 | Defaults to the current directory. |
||
71 | :param no_input: Do not prompt for user input and eventually force a refresh of |
||
72 | cached resources. |
||
73 | :returns: str with path to the new directory of the repository. |
||
74 | """ |
||
75 | # Ensure that clone_to_dir exists |
||
76 | clone_to_dir = Path(clone_to_dir).expanduser() |
||
77 | make_sure_path_exists(clone_to_dir) |
||
78 | |||
79 | # identify the repo_type |
||
80 | repo_type, repo_url = identify_repo(repo_url) |
||
81 | |||
82 | # check that the appropriate VCS for the repo_type is installed |
||
83 | if not is_vcs_installed(repo_type): |
||
84 | msg = f"'{repo_type}' is not installed." |
||
85 | raise VCSNotInstalled(msg) |
||
86 | |||
87 | repo_url = repo_url.rstrip('/') |
||
88 | repo_name = os.path.split(repo_url)[1] |
||
89 | if repo_type == 'git': |
||
90 | repo_name = repo_name.split(':')[-1].rsplit('.git')[0] |
||
91 | repo_dir = os.path.normpath(os.path.join(clone_to_dir, repo_name)) |
||
92 | if repo_type == 'hg': |
||
93 | repo_dir = os.path.normpath(os.path.join(clone_to_dir, repo_name)) |
||
94 | logger.debug(f'repo_dir is {repo_dir}') |
||
95 | |||
96 | if os.path.isdir(repo_dir): |
||
|
|||
97 | clone = prompt_and_delete(repo_dir, no_input=no_input) |
||
98 | else: |
||
99 | clone = True |
||
100 | |||
101 | if clone: |
||
102 | try: |
||
103 | subprocess.check_output( # nosec |
||
104 | [repo_type, 'clone', repo_url], |
||
105 | cwd=clone_to_dir, |
||
106 | stderr=subprocess.STDOUT, |
||
107 | ) |
||
108 | if checkout is not None: |
||
109 | checkout_params = [checkout] |
||
110 | # Avoid Mercurial "--config" and "--debugger" injection vulnerability |
||
111 | if repo_type == "hg": |
||
112 | checkout_params.insert(0, "--") |
||
113 | subprocess.check_output( # nosec |
||
114 | [repo_type, 'checkout', *checkout_params], |
||
115 | cwd=repo_dir, |
||
116 | stderr=subprocess.STDOUT, |
||
117 | ) |
||
118 | except subprocess.CalledProcessError as clone_error: |
||
119 | output = clone_error.output.decode('utf-8') |
||
120 | if 'not found' in output.lower(): |
||
121 | raise RepositoryNotFound( |
||
122 | f'The repository {repo_url} could not be found, ' |
||
123 | 'have you made a typo?' |
||
124 | ) from clone_error |
||
125 | if any(error in output for error in BRANCH_ERRORS): |
||
126 | raise RepositoryCloneFailed( |
||
127 | f'The {checkout} branch of repository ' |
||
128 | f'{repo_url} could not found, have you made a typo?' |
||
129 | ) from clone_error |
||
130 | logger.error('git clone failed with error: %s', output) |
||
131 | raise |
||
132 | |||
133 | return repo_dir |
||
134 |