Repository: ishepard/pydriller
Pull request #73 (2019-12-21 12:47:35)

Implements functionality requested in issue #71.
In short, this commit adds a "clone_repo_to" option to allow a user
to provide a directory in which to place clone a remote repo. This
enables the user to access the files within that directory that
aren't altered by a specific commit.

A corresponding test has also been added.


Patch:
diff --git a/pydriller/repository_mining.py b/pydriller/repository_mining.py
index 0ac40cd..fa48aa2 100644
--- a/pydriller/repository_mining.py
+++ b/pydriller/repository_mining.py
@@ -21,6 +21,7 @@ import os
 import tempfile
 from datetime import datetime
 from typing import List, Generator, Union
+from pathlib import Path
 
 from git import Repo
 
@@ -51,7 +52,8 @@ class RepositoryMining:
                  only_releases: bool = False,
                  filepath: str = None,
                  histogram_diff: bool = False,
-                 skip_whitespaces: bool = False):
+                 skip_whitespaces: bool = False,
+                 clone_repo_to: str = None):
         """
         Init a repository mining. The only required parameter is
         "path_to_repo": to analyze a single repo, pass the absolute path to
@@ -108,7 +110,8 @@ class RepositoryMining:
             "filepath": filepath,
             "filepath_commits": None,
             "tagged_commits": None,
-            "histogram": histogram_diff
+            "histogram": histogram_diff,
+            "clone_repo_to": clone_repo_to
         }
         self._conf = Conf(options)
 
@@ -133,9 +136,17 @@ class RepositoryMining:
         for path_repo in self._conf.get('path_to_repos'):
             # if it is a remote repo, clone it first in a temporary folder!
             if self._is_remote(path_repo):
-                tmp_folder = tempfile.TemporaryDirectory()
-                path_repo = self._clone_remote_repos(tmp_folder.name,
-                                                     path_repo)
+                if self._conf.get('clone_repo_to'):
+                    clone_folder = str(Path(self._conf.get('clone_repo_to')))
+                    if not os.path.isdir(clone_folder):
+                        raise Exception("Not a directory: "\
+                                "{0}".format(clone_folder))
+                    path_repo = self._clone_remote_repos(clone_folder,
+                                                         path_repo)
+                else:
+                    tmp_folder = tempfile.TemporaryDirectory()
+                    path_repo = self._clone_remote_repos(tmp_folder.name,
+                                                         path_repo)
 
             git_repo = GitRepository(path_repo, self._conf)
             self._conf.put("git_repo", git_repo)


Test patch:
diff --git a/tests/test_repository_mining.py b/tests/test_repository_mining.py
index 1d3563b..245b0b9 100644
--- a/tests/test_repository_mining.py
+++ b/tests/test_repository_mining.py
@@ -1,5 +1,9 @@
 import logging
 from datetime import datetime
+import tempfile
+import os
+import shutil
+import platform
 
 import pytest
 
@@ -182,3 +186,14 @@ def test_ignore_add_whitespaces_and_changed_file():
                                    skip_whitespaces=True,
                                    single="532068e9d64b8a86e07eea93de3a57bf9e5b4ae0").traverse_commits())[0]
     assert len(commit.modifications) == 1
+
+
+@pytest.mark.skipif(platform.system() == "Windows", reason="Sometimes Windows give an error 'Handle is not valid' in this test, though it works anyway outside the test.")
+def test_clone_repo_to():
+    tmp_folder = tempfile.TemporaryDirectory()
+    dt2 = datetime(2018, 10, 20)
+    url = "https://github.com/ishepard/pydriller.git"
+    assert len(list(RepositoryMining(
+        path_to_repo=url,
+        to=dt2,
+        clone_repo_to=tmp_folder.name).traverse_commits())) == 159