1010from pathlib import Path
1111from typing import Optional, List, Union, Any, Tuple
1212
13- from git import Repo, Actor
13+ from git import Repo, Actor, GitCommandError
1414from packaging import version
1515
1616from .configuration import configuration, ConfigurationVariable
@@ -48,7 +48,8 @@ def _git_url_ssh_to_https(self, url: str) -> str:
4848 path = url.split("github.com", 1)[1][1:].strip()
4949 new = "https://{GITHUB_TOKEN}:x-oauth-basic@github.com/%s" % path
5050 logger.info("rewriting git url to: %s" % new)
51- return new.format(GITHUB_TOKEN=configuration.get_value(ConfigurationVariable.GIT_TOKEN))
51+ return new.format(GITHUB_TOKEN=configuration.get_value(
52+ ConfigurationVariable.GIT_TOKEN))
5253
5354 def clone(self, path: Path) -> "GitWrapper":
5455 """Clones this repository to the path.
@@ -59,9 +60,20 @@ def clone(self, path: Path) -> "GitWrapper":
5960 Returns:
6061 a wrapper over the cloned repository
6162 """
62- git_clone = self.repo.clone_from(
63- url=self.get_remote_url(), to_path=str(path), multi_options=["--recurse-submodules"]
64- )
63+ try:
64+ git_clone = self.repo.clone_from(
65+ url=self.get_remote_url(), to_path=str(path),
66+ multi_options=["--recurse-submodules"]
67+ )
68+ except GitCommandError as e:
69+ logger.info("failed cloning repository: %s" % e)
70+ logger.info("trying with authentication")
71+ git_clone = self.repo.clone_from(
72+ url=self._git_url_ssh_to_https(self.get_remote_url()),
73+ to_path=str(path),
74+ multi_options=["--recurse-submodules"]
75+ )
76+
6577 clone = GitWrapper(path=path, repo=git_clone)
6678 clone.set_remote_url(self.get_remote_url())
6779 clone.fetch()
@@ -78,8 +90,10 @@ def root(self) -> Path:
7890
7991 def configure_author(self) -> None:
8092 """Sets the author."""
81- self.repo.config_writer().set_value("user", "name", self.author.name).release()
82- self.repo.config_writer().set_value("user", "email", self.author.email).release()
93+ self.repo.config_writer().set_value("user", "name",
94+ self.author.name).release()
95+ self.repo.config_writer().set_value("user", "email",
96+ self.author.email).release()
8397
8498 def checkout_branch(self, branch_name: str) -> Any:
8599 """Checks out a branch from its name.
@@ -114,7 +128,8 @@ def _add_one_path(self, path_model: Path) -> None:
114128 if not path_model.is_absolute():
115129 path_model = Path(self.root).joinpath(path_model)
116130 if not path_model.exists():
117- logger.warning(f"[Git] {path_model} cannot be added because not found.")
131+ logger.warning(
132+ f"[Git] {path_model} cannot be added because not found.")
118133 return
119134 relative_path = str(path_model.relative_to(self.root))
120135 unix_relative_path = relative_path.replace("\\", "/")
@@ -135,7 +150,8 @@ def add(self, path: Union[list, set, str]) -> None:
135150 else:
136151 self._add_one_file_or_one_dir(path)
137152
138- def commit(self, message: str, **kwargs: Optional[Tuple[str, Any]]) -> None:
153+ def commit(self, message: str,
154+ **kwargs: Optional[Tuple[str, Any]]) -> None:
139155 """Commits changes to the repository.
140156
141157 Args:
@@ -151,15 +167,17 @@ def get_master_branch(self) -> Any:
151167 Returns:
152168 corresponding branch
153169 """
154- return self.get_branch(configuration.get_value(ConfigurationVariable.MASTER_BRANCH))
170+ return self.get_branch(
171+ configuration.get_value(ConfigurationVariable.MASTER_BRANCH))
155172
156173 def get_beta_branch(self) -> Any:
157174 """Gets the `beta` branch.
158175
159176 Returns:
160177 corresponding branch
161178 """
162- return self.get_branch(configuration.get_value(ConfigurationVariable.BETA_BRANCH))
179+ return self.get_branch(
180+ configuration.get_value(ConfigurationVariable.BETA_BRANCH))
163181
164182 def is_release_branch(self, branch_name: Optional[str]) -> bool:
165183 """Checks whether the branch is a `release` branch or not.
@@ -170,7 +188,8 @@ def is_release_branch(self, branch_name: Optional[str]) -> bool:
170188 Returns:
171189 True if the branch is used for `release` code; False otherwise
172190 """
173- branch_pattern = configuration.get_value(ConfigurationVariable.RELEASE_BRANCH_PATTERN)
191+ branch_pattern = configuration.get_value(
192+ ConfigurationVariable.RELEASE_BRANCH_PATTERN)
174193 if not branch_pattern or not branch_name:
175194 return False
176195 is_release: Optional[Any] = re.search(branch_pattern, str(branch_name))
@@ -213,7 +232,8 @@ def get_current_branch(self) -> Any:
213232 try:
214233 return self.repo.active_branch
215234 except TypeError as e:
216- logger.warning(f"Could not determine the branch name using GitPython: {e}")
235+ logger.warning(
236+ f"Could not determine the branch name using GitPython: {e}")
217237 current_branch = self._get_branch_from_advanced_feature()
218238 if not current_branch:
219239 current_branch = self._get_branch_from_abbreviation("HEAD")
@@ -222,13 +242,17 @@ def get_current_branch(self) -> Any:
222242 def _get_branch_from_advanced_feature(self) -> Any:
223243 if version.parse(self.git_version()) >= version.parse("2.22"):
224244 current_branch = self.repo.git.branch(show_current=True)
225- current_branch = current_branch if isinstance(current_branch, str) else current_branch.decode("utf-8")
245+ current_branch = current_branch if isinstance(current_branch,
246+ str) else current_branch.decode(
247+ "utf-8")
226248 return self.get_branch(current_branch)
227249 return None
228250
229251 def _get_branch_from_abbreviation(self, abbreviation: str) -> Any:
230252 current_branch = self.repo.git.rev_parse("--abbrev-ref", abbreviation)
231- current_branch = current_branch if isinstance(current_branch, str) else current_branch.decode("utf-8")
253+ current_branch = current_branch if isinstance(current_branch,
254+ str) else current_branch.decode(
255+ "utf-8")
232256 return self.get_branch(current_branch.strip())
233257
234258 def get_commit_count(self) -> int:
@@ -282,7 +306,8 @@ def merge(self, branch: Any) -> None:
282306 current_branch = self.get_current_branch()
283307 merge_base = self.repo.merge_base(branch, current_branch)
284308 self.repo.index.merge_tree(current_branch, base=merge_base)
285- self.commit(f"Merge from {str(branch)}", parent_commits=(branch.commit, current_branch.commit))
309+ self.commit(f"Merge from {str(branch)}",
310+ parent_commits=(branch.commit, current_branch.commit))
286311
287312 def get_remote_url(self) -> str:
288313 """Gets the URL of the remote repository.
@@ -315,7 +340,9 @@ def set_remote_url(self, url: str) -> None:
315340 remote = self._get_remote()
316341 if remote:
317342 self.repo.delete_remote(str(remote))
318- self.repo.create_remote(configuration.get_value(ConfigurationVariable.REMOTE_ALIAS), url=url)
343+ self.repo.create_remote(
344+ configuration.get_value(ConfigurationVariable.REMOTE_ALIAS),
345+ url=url)
319346
320347 def get_remote_branch(self, branch_name: str) -> Optional[Any]:
321348 """Gets the branch present in the remote repository.
@@ -342,7 +369,8 @@ def set_upstream_branch(self, branch_name: str) -> None:
342369 branch_name: name of the remote branch.
343370 """
344371 if self.remote_branch_exists(branch_name):
345- self.repo.git.branch("--set-upstream-to", self.get_remote_branch(branch_name))
372+ self.repo.git.branch("--set-upstream-to",
373+ self.get_remote_branch(branch_name))
346374
347375 def delete_branch(self, branch: Any) -> None:
348376 """Deletes a branch.
@@ -384,17 +412,21 @@ def remote_branch_exists(self, branch_name: str) -> bool:
384412 """
385413 return self.get_remote_branch(branch_name) is not None
386414
387- def _get_specific_changes(self, change_type: Optional[str], commit1: Any, commit2: Any) -> List[str]:
415+ def _get_specific_changes(self, change_type: Optional[str], commit1: Any,
416+ commit2: Any) -> List[str]:
388417 diff = commit1.diff(commit2)
389418 if change_type:
390419 change_type = change_type.upper()
391420 change_type = change_type if change_type in diff.change_type else None
392- diff_iterator = diff.iter_change_type(change_type) if change_type else diff
393- changes = [change.a_path if change.a_path else change.b_path for change in diff_iterator]
421+ diff_iterator = diff.iter_change_type(
422+ change_type) if change_type else diff
423+ changes = [change.a_path if change.a_path else change.b_path for change
424+ in diff_iterator]
394425 return changes
395426
396427 def get_changes_list(
397- self, commit1: Any, commit2: Any, change_type: Optional[str] = None, dir: Optional[str] = None
428+ self, commit1: Any, commit2: Any,
429+ change_type: Optional[str] = None, dir: Optional[str] = None
398430 ) -> List[str]:
399431 """Gets change list.
400432
@@ -414,7 +446,8 @@ def get_changes_list(
414446 if dir:
415447 windows_path = dir.replace("/", "\\")
416448 linux_path = dir.replace("\\", "/")
417- return [change for change in changes if (linux_path in change) or (windows_path in change)]
449+ return [change for change in changes if
450+ (linux_path in change) or (windows_path in change)]
418451 else:
419452 return changes
420453
@@ -425,19 +458,22 @@ def pull_all(self) -> None:
425458 def pull(self) -> None:
426459 """Pulls changes on current branch from the remote repository."""
427460 if self.remote_branch_exists(self.get_current_branch()):
428- self.repo.git.pull(self._get_remote(), self.get_current_branch(), quiet=True)
461+ self.repo.git.pull(self._get_remote(), self.get_current_branch(),
462+ quiet=True)
429463
430464 def force_pull(self) -> None:
431465 """Force pulls changes from the remote repository."""
432- self.repo.git.pull(self._get_remote(), self.get_current_branch(), quiet=True, force=True)
466+ self.repo.git.pull(self._get_remote(), self.get_current_branch(),
467+ quiet=True, force=True)
433468
434469 def push(self) -> None:
435470 """Pushes commits.
436471
437472 Pushes changes to the remote repository.
438473 Pushes also relevant annotated tags when pushing branches out.
439474 """
440- self.repo.git.push("--follow-tags", "--set-upstream", self._get_remote(), self.get_current_branch())
475+ self.repo.git.push("--follow-tags", "--set-upstream",
476+ self._get_remote(), self.get_current_branch())
441477
442478 def push_tag(self) -> None:
443479 """Pushes commits and tags.
@@ -500,21 +536,25 @@ def git_version(self) -> str:
500536 Returns:
501537 the version of git in use.
502538 """
503- return ".".join([str(element) for element in self.repo.git.version_info])
539+ return ".".join(
540+ [str(element) for element in self.repo.git.version_info])
504541
505542 def _get_remote(self) -> Optional[Any]:
506543 try:
507- return self.repo.remote(configuration.get_value(ConfigurationVariable.REMOTE_ALIAS))
544+ return self.repo.remote(
545+ configuration.get_value(ConfigurationVariable.REMOTE_ALIAS))
508546 except (IndexError, ValueError) as e:
509547 logger.warning(e)
510548 return None
511549
512550 def list_files_added_on_current_branch(self) -> List[str]:
513551 """Returns a list of files changed against master branch."""
514- master_branch_commit = self.repo.commit(configuration.get_value(ConfigurationVariable.MASTER_BRANCH))
552+ master_branch_commit = self.repo.commit(
553+ configuration.get_value(ConfigurationVariable.MASTER_BRANCH))
515554 current_branch_commit = self.repo.commit(self.get_current_branch())
516555 changes = self.get_changes_list(
517- self.get_branch_point(master_branch_commit, current_branch_commit), current_branch_commit, change_type="a"
556+ self.get_branch_point(master_branch_commit, current_branch_commit),
557+ current_branch_commit, change_type="a"
518558 )
519559 return changes
520560
@@ -537,7 +577,8 @@ def uncommitted_changes(self) -> List[Path]:
537577 if not status:
538578 return []
539579
540- return [Path(self.root).joinpath(line.strip().split(" ")[-1]) for line in status.splitlines()]
580+ return [Path(self.root).joinpath(line.strip().split(" ")[-1]) for line
581+ in status.splitlines()]
541582
542583 @staticmethod
543584 def _apply_modifications(destination: Path, modified_file: Path) -> None:
@@ -573,8 +614,10 @@ class ProjectGitWrapper(GitWrapper):
573614 def __init__(self) -> None:
574615 """Creates a Git Wrapper."""
575616 super().__init__(
576- path=Path(configuration.get_value(ConfigurationVariable.PROJECT_ROOT)),
577- repo=Repo(configuration.get_value(ConfigurationVariable.PROJECT_ROOT)),
617+ path=Path(
618+ configuration.get_value(ConfigurationVariable.PROJECT_ROOT)),
619+ repo=Repo(
620+ configuration.get_value(ConfigurationVariable.PROJECT_ROOT)),
578621 )
579622
580623
@@ -615,7 +658,8 @@ def __init__(self, path: Path, initial_path: Path, repo: Repo) -> None:
615658 @staticmethod
616659 def wrap(repo: GitWrapper, initial_location: Path) -> "GitClone":
617660 """Wraps around around a repository."""
618- return GitClone(repo=repo.repo, path=repo.root, initial_path=initial_location)
661+ return GitClone(repo=repo.repo, path=repo.root,
662+ initial_path=initial_location)
619663
620664 @property
621665 def initial_location(self) -> Path:
@@ -638,26 +682,31 @@ def get_corresponding_path(self, path_in_initial_repo: Path) -> Path:
638682 return Path(self.root).joinpath(path_in_initial_repo)
639683 try:
640684 # Tyring to find if the path corresponds to a file/directory present in intial repository
641- return Path(self.root).joinpath(path_in_initial_repo.relative_to(self.initial_location))
685+ return Path(self.root).joinpath(
686+ path_in_initial_repo.relative_to(self.initial_location))
642687 except ValueError:
643688 return path_in_initial_repo
644689
645690
646691class GitTempClone:
647692 """Context manager providing a temporary cloned repository."""
648693
649- def __init__(self, desired_branch_name: Optional[str], repository_to_clone: GitWrapper):
694+ def __init__(self, desired_branch_name: Optional[str],
695+ repository_to_clone: GitWrapper):
650696 """Constructor.
651697
652698 Args:
653699 desired_branch_name: the branch to consider. I
654700 repository_to_clone: the repository to clone. If not specified, the project repository will be used.
655701 """
656702 self._temporary_dir = TemporaryDirectory()
657- logger.info(f"Creating a temporary repository in {self._temporary_dir}")
703+ logger.info(
704+ f"Creating a temporary repository in {self._temporary_dir}")
658705 self._repo = repository_to_clone
659- _current_branch_name = desired_branch_name if desired_branch_name else str(self._repo.get_current_branch())
660- self._clone = GitClone.wrap(self._repo.clone(self._temporary_dir.path), initial_location=self._repo.root)
706+ _current_branch_name = desired_branch_name if desired_branch_name else str(
707+ self._repo.get_current_branch())
708+ self._clone = GitClone.wrap(self._repo.clone(self._temporary_dir.path),
709+ initial_location=self._repo.root)
661710 self._clone.checkout(_current_branch_name)
662711 self._repo.apply_uncommitted_changes(self._clone)
663712
@@ -688,4 +737,5 @@ def __init__(self, desired_branch_name: Optional[str] = None):
688737 system will try to identify the current branch in the repository which
689738 will work in most cases but probably not on CI.
690739 """
691- super().__init__(desired_branch_name=desired_branch_name, repository_to_clone=ProjectGitWrapper())
740+ super().__init__(desired_branch_name=desired_branch_name,
741+ repository_to_clone=ProjectGitWrapper())
0 commit comments