Esempio n. 1
0
def test_get_commits_modified_file(repo: GitRepository):
    commits = repo.get_commits_modified_file('file2.java')

    assert len(commits) == 3
    assert '09f6182cef737db02a085e1d018963c7a29bde5a' in commits
    assert '6411e3096dd2070438a17b225f44475136e54e3a' in commits
    assert 'a88c84ddf42066611e76e6cb690144e5357d132c' in commits
Esempio n. 2
0
    def traverse_commits(self) -> Generator[Commit, None, None]:
        """
        Analyze all the specified commits (all of them by default), returning
        a generator of commits.
        """
        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):
                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.set_value("git_repo", git_repo)
            self._conf.sanity_check_filters()

            logger.info('Analyzing git repository in %s', git_repo.path)

            # Get the commits that modified the filepath. In this case, we can not use
            # git rev-list since it doesn't have the option --follow, necessary to follow
            # the renames. Hence, we manually call git log instead
            if self._conf.get('filepath') is not None:
                self._conf.set_value(
                    'filepath_commits',
                    git_repo.get_commits_modified_file(
                        self._conf.get('filepath')))

            # Gets only the commits that are tagged
            if self._conf.get('only_releases'):
                self._conf.set_value('tagged_commits',
                                     git_repo.get_tagged_commits())

            # Build the arguments to pass to git rev-list.
            rev, kwargs = self._conf.build_args()

            # Iterate over all the commits returned by git rev-list
            for commit in git_repo.get_list_commits(rev, **kwargs):
                logger.info('Commit #%s in %s from %s', commit.hash,
                            commit.committer_date, commit.author.name)

                if self._conf.is_commit_filtered(commit):
                    logger.info('Commit #%s filtered', commit.hash)
                    continue

                yield commit

            # cleaning, this is necessary since GitPython issues on memory leaks
            self._conf.set_value("git_repo", None)
            git_repo.clear()
Esempio n. 3
0
    def traverse_commits(self) -> Generator[Commit, None, None]:
        """
        Analyze all the specified commits (all of them by default), returning
        a generator of commits.
        """
        for path_repo in self._conf.get('path_to_repos'):
            if self._is_remote(path_repo):
                path_repo = self._clone_remote_repos(self._clone_folder(),
                                                     path_repo)

            git_repo = GitRepository(path_repo, self._conf)
            # saving the GitRepository object for further use
            self._conf.set_value("git_repo", git_repo)

            # when multiple repos are given in input, this variable will serve as a reminder
            # of which one we are currently analyzing
            self._conf.set_value('path_to_repo', path_repo)

            # checking that the filters are set correctly
            self._conf.sanity_check_filters()

            logger.info('Analyzing git repository in %s', git_repo.path)

            # Get the commits that modified the filepath. In this case, we can not use
            # git rev-list since it doesn't have the option --follow, necessary to follow
            # the renames. Hence, we manually call git log instead
            if self._conf.get('filepath') is not None:
                self._conf.set_value(
                    'filepath_commits',
                    git_repo.get_commits_modified_file(
                        self._conf.get('filepath')))

            # Gets only the commits that are tagged
            if self._conf.get('only_releases'):
                self._conf.set_value('tagged_commits',
                                     git_repo.get_tagged_commits())

            # Build the arguments to pass to git rev-list.
            rev, kwargs = self._conf.build_args()

            # Iterate over all the commits returned by git rev-list
            for commit in git_repo.get_list_commits(rev, **kwargs):
                logger.info('Commit #%s in %s from %s', commit.hash,
                            commit.committer_date, commit.author.name)

                if self._conf.is_commit_filtered(commit):
                    logger.info('Commit #%s filtered', commit.hash)
                    continue

                yield commit

            # cleaning, this is necessary since GitPython issues on memory leaks
            self._conf.set_value("git_repo", None)
            git_repo.clear()
Esempio n. 4
0
    def traverse_commits(self) -> Generator[Commit, None, None]:
        """
        Analyze all the specified commits (all of them by default), returning
        a generator of commits.
        """
        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):
                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.set_value("git_repo", git_repo)
            self._conf.sanity_check_filters()

            logger.info('Analyzing git repository in %s', git_repo.path)

            if self._conf.get('filepath') is not None:
                self._conf.set_value(
                    'filepath_commits',
                    git_repo.get_commits_modified_file(
                        self._conf.get('filepath')))

            if self._conf.get('only_releases'):
                self._conf.set_value('tagged_commits',
                                     git_repo.get_tagged_commits())

            for commit in git_repo.get_list_commits(
                    self._conf.get('only_in_branch'),
                    not self._conf.get('reversed_order')):
                logger.info('Commit #%s in %s from %s', commit.hash,
                            commit.committer_date, commit.author.name)

                if self._conf.is_commit_filtered(commit):
                    logger.info('Commit #%s filtered', commit.hash)
                    continue

                yield commit

            # cleaning
            self._conf.set_value("git_repo", None)
            git_repo.clear()
Esempio n. 5
0
    def traverse_commits(self) -> Generator[Commit, None, None]:
        """
        Analyze all the specified commits (all of them by default), returning
        a generator of commits.
        """

        if isinstance(self._path_to_repo, str):
            self._path_to_repo = [self._path_to_repo]

        for path_repo in self._path_to_repo:
            # if it is a remote repo, clone it first in a temporary folder!
            if self._isremote(path_repo):
                tmp_folder = tempfile.TemporaryDirectory()
                path_repo = self._clone_remote_repos(tmp_folder.name,
                                                     path_repo)

            git_repo = GitRepository(path_repo)

            self._sanity_check_filters(git_repo)
            self._check_timezones()

            logger.info('Analyzing git repository in %s', git_repo.path)

            if self._filepath is not None:
                self._filepath_commits = git_repo.get_commits_modified_file(
                    self._filepath)

            if self._only_releases:
                self._tagged_commits = git_repo.get_tagged_commits()

            for commit in git_repo.get_list_commits(self._only_in_branch,
                                                    not self._reversed_order):
                logger.info('Commit #%s in %s from %s', commit.hash,
                            commit.committer_date, commit.author.name)

                if self._is_commit_filtered(commit):
                    logger.info('Commit #%s filtered', commit.hash)
                    continue

                yield commit
Esempio n. 6
0
def test_get_commits_modified_file_missing_file():
    gr = GitRepository('test-repos/test1/')

    commits = gr.get_commits_modified_file('non-existing-file.java')

    assert len(commits) == 0
Esempio n. 7
0
def test_get_commits_modified_file_missing_file(repo: GitRepository):
    commits = repo.get_commits_modified_file('non-existing-file.java')

    assert len(commits) == 0
Esempio n. 8
0
    def traverse_commits(self) -> Generator[Commit, None, None]:
        """
        Analyze all the specified commits (all of them by default), returning
        a generator of commits.
        """
        for path_repo in self._conf.get('path_to_repos'):
            local_path_repo = path_repo
            if self._is_remote(path_repo):
                local_path_repo = self._clone_remote_repo(
                    self._clone_folder(), path_repo)

            # Get absolute path
            local_path_repo = str(Path(local_path_repo).expanduser().resolve())

            # when multiple repos are given in input, this variable will serve as a reminder
            # of which one we are currently analyzing
            self._conf.set_value('path_to_repo', local_path_repo)

            git_repo = GitRepository(local_path_repo, self._conf)
            # saving the GitRepository object for further use
            self._conf.set_value("git_repo", git_repo)

            # checking that the filters are set correctly
            self._conf.sanity_check_filters()

            logger.info('Analyzing git repository in %s', git_repo.path)

            # Get the commits that modified the filepath. In this case, we can not use
            # git rev-list since it doesn't have the option --follow, necessary to follow
            # the renames. Hence, we manually call git log instead
            if self._conf.get('filepath') is not None:
                self._conf.set_value(
                    'filepath_commits',
                    git_repo.get_commits_modified_file(
                        self._conf.get('filepath')))

            # Gets only the commits that are tagged
            if self._conf.get('only_releases'):
                self._conf.set_value('tagged_commits',
                                     git_repo.get_tagged_commits())

            # Build the arguments to pass to git rev-list.
            rev, kwargs = self._conf.build_args()

            # Iterate over all the commits returned by git rev-list
            for commit in git_repo.get_list_commits(rev, **kwargs):
                logger.info('Commit #%s in %s from %s', commit.hash,
                            commit.committer_date, commit.author.name)

                if self._conf.is_commit_filtered(commit):
                    logger.info('Commit #%s filtered', commit.hash)
                    continue

                yield commit

            # cleaning, this is necessary since GitPython issues on memory leaks
            self._conf.set_value("git_repo", None)
            git_repo.clear()

            # delete the temporary directory if created
            if self._is_remote(path_repo) and self._cleanup is True:
                assert self._tmp_dir is not None
                try:
                    self._tmp_dir.cleanup()
                except PermissionError:
                    # on Windows, Python 3.5, 3.6, 3.7 are not able to delete
                    # git directories because of read-only files. This is now fixed
                    # in python 3.8. In this case, we need to use an
                    # onerror callback to clear the read-only bit.
                    # see https://docs.python.org/3/library/shutil.html?highlight=shutil#rmtree-example
                    def remove_readonly(func, path, _):
                        os.chmod(path, stat.S_IWRITE)
                        func(path)

                    shutil.rmtree(self._tmp_dir.name, onerror=remove_readonly)