Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6e682c8

Browse files
committed
start working on using git filters. major changes need to be done for this
1 parent 293b02c commit 6e682c8

6 files changed

Lines changed: 70 additions & 51 deletions

File tree

.github/workflows/continuous-integration-workflow.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,5 @@ jobs:
4545
if: matrix.os == 'ubuntu-latest' || matrix.os == 'macOS-latest'
4646
uses: codecov/codecov-action@v1
4747
with:
48-
token: ${{ secrets.CODECOV_TOKEN }}
4948
file: ./coverage.xml
5049
yml: .codecov.yml
51-
fail_ci_if_error: true

.pylintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ indent-after-paren=4
244244
indent-string=' '
245245

246246
# Maximum number of characters on a single line.
247-
max-line-length=79
247+
max-line-length=150
248248

249249
# Maximum number of lines in a module.
250250
max-module-lines=1000

pydriller/git_repository.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,20 @@ def get_head(self) -> Commit:
121121
head_commit = self.repo.head.commit
122122
return Commit(head_commit, self._conf)
123123

124-
def get_list_commits(self, branch: str = None,
125-
reverse_order: bool = True) \
126-
-> Generator[Commit, None, None]:
124+
def get_list_commits(self, args: List = None) -> Generator[Commit, None, None]:
127125
"""
128126
Return a generator of commits of all the commits in the repo.
129127
130128
:return: Generator[Commit], the generator of all the commits in the
131129
repo
132130
"""
133-
for commit in self.repo.iter_commits(branch, reverse=reverse_order):
131+
# With no arguments, just analyze all the commits until the HEAD,
132+
# in reverse order
133+
if args is None or not args:
134+
args = [self.repo.head.commit.hexsha, '--reverse']
135+
136+
print(args)
137+
for commit in self.repo.iter_commits(args):
134138
yield self.get_commit_from_gitpython(commit)
135139

136140
def get_commit(self, commit_id: str) -> Commit:

pydriller/repository_mining.py

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,11 @@ def traverse_commits(self) -> Generator[Commit, None, None]:
139139
if self._conf.get('clone_repo_to'):
140140
clone_folder = str(Path(self._conf.get('clone_repo_to')))
141141
if not os.path.isdir(clone_folder):
142-
raise Exception("Not a directory: " \
143-
"{0}".format(clone_folder))
144-
path_repo = self._clone_remote_repos(clone_folder,
145-
path_repo)
142+
raise Exception("Not a directory: {0}".format(clone_folder))
143+
path_repo = self._clone_remote_repos(clone_folder, path_repo)
146144
else:
147145
tmp_folder = tempfile.TemporaryDirectory()
148-
path_repo = self._clone_remote_repos(tmp_folder.name,
149-
path_repo)
146+
path_repo = self._clone_remote_repos(tmp_folder.name, path_repo)
150147

151148
git_repo = GitRepository(path_repo, self._conf)
152149
self._conf.set_value("git_repo", git_repo)
@@ -155,19 +152,15 @@ def traverse_commits(self) -> Generator[Commit, None, None]:
155152
logger.info('Analyzing git repository in %s', git_repo.path)
156153

157154
if self._conf.get('filepath') is not None:
158-
self._conf.set_value('filepath_commits',
159-
git_repo.get_commits_modified_file(
160-
self._conf.get('filepath')))
155+
self._conf.set_value('filepath_commits', git_repo.get_commits_modified_file(self._conf.get('filepath')))
161156

162157
if self._conf.get('only_releases'):
163-
self._conf.set_value('tagged_commits',
164-
git_repo.get_tagged_commits())
165-
166-
for commit in git_repo.get_list_commits(self._conf.get(
167-
'only_in_branch'), not self._conf.get('reversed_order')):
168-
logger.info('Commit #%s in %s from %s', commit.hash,
169-
commit.committer_date,
170-
commit.author.name)
158+
self._conf.set_value('tagged_commits', git_repo.get_tagged_commits())
159+
160+
args = self._conf.build_args()
161+
162+
for commit in git_repo.get_list_commits(args):
163+
logger.info('Commit #%s in %s from %s', commit.hash, commit.committer_date, commit.author.name)
171164

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

pydriller/utils/conf.py

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def sanity_check_filters(self):
6969
Check if the values passed by the user are correct.
7070
7171
"""
72+
self._check_correct_filters_order()
7273
self.check_starting_commit()
7374
self.check_ending_commit()
7475
self._check_timezones()
@@ -83,8 +84,6 @@ def sanity_check_filters(self):
8384
self.set_value("to_commit", None)
8485
self.set_value("single", single)
8586

86-
self._check_correct_filters_order()
87-
8887
if self.get('single') is not None:
8988
if any([self.get('since'),
9089
self.get('to'),
@@ -113,9 +112,7 @@ def _check_correct_filters_order(self):
113112
self.get('git_repo').get_commit(self.get('from_commit')),
114113
self.get('git_repo').get_commit(self.get('to_commit')))
115114

116-
if self.get('reversed_order') and chronological_order:
117-
self._swap_commit_fiters()
118-
elif not self.get('reversed_order') and not chronological_order:
115+
if not chronological_order:
119116
self._swap_commit_fiters()
120117

121118
def _swap_commit_fiters(self):
@@ -140,12 +137,17 @@ def check_starting_commit(self):
140137
raise Exception('You can only specify one between since, '
141138
'from_tag and from_commit')
142139
if self.get('from_tag') is not None:
143-
self.set_value('from_commit', self.get(
144-
"git_repo").get_commit_from_tag(self.get('from_tag')).hash)
140+
self.set_value('from_commit', self.get("git_repo").get_commit_from_tag(self.get('from_tag')).hash)
145141
if self.get('from_commit'):
146142
try:
147-
self.set_value('from_commit', self.get("git_repo").get_commit(
148-
self.get('from_commit')).hash)
143+
commit = self.get("git_repo").get_commit(self.get('from_commit'))
144+
if len(commit.parents) == 0:
145+
self.set_value('from_commit', [commit.hash])
146+
elif len(commit.parents) == 1:
147+
self.set_value('from_commit', ['^' + commit.hash + '^'])
148+
else:
149+
commits = ['^' + x for x in commit.parents]
150+
self.set_value('from_commit', commits)
149151
except Exception:
150152
raise Exception("The commit {} defined in the 'from_tag' "
151153
"or 'from_commit' filter does "
@@ -165,8 +167,8 @@ def check_ending_commit(self):
165167
"git_repo").get_commit_from_tag(self.get('to_tag')).hash)
166168
if self.get('to_commit'):
167169
try:
168-
self.set_value('to_commit', self.get("git_repo").get_commit(
169-
self.get('to_commit')).hash)
170+
commit = self.get("git_repo").get_commit(self.get('to_commit'))
171+
self.set_value('to_commit', commit.hash)
170172
except Exception:
171173
raise Exception("The commit {} defined in the 'to_tag' "
172174
"or 'to_commit' filter does "
@@ -182,6 +184,37 @@ def only_one_filter(arr):
182184
"""
183185
return len([x for x in arr if x is not None]) <= 1
184186

187+
def build_args(self):
188+
from_commit = self.get('from_commit')
189+
to_commit = self.get('to_commit')
190+
branch = self.get('only_in_branch')
191+
192+
args = []
193+
194+
if from_commit is not None or to_commit is not None:
195+
if from_commit is not None and to_commit is not None:
196+
args.extend(from_commit)
197+
args.append(to_commit)
198+
elif from_commit is not None:
199+
args.extend(from_commit)
200+
args.append('HEAD')
201+
else:
202+
args.append(to_commit)
203+
else:
204+
args.append('HEAD')
205+
206+
if branch is not None:
207+
args.append(branch)
208+
209+
if self.get('only_no_merge'):
210+
args.append('--no-merges')
211+
212+
if not self.get('reversed_order'):
213+
args.append('--reverse')
214+
215+
print(f'Returning args: {args}')
216+
return args
217+
185218
def is_commit_filtered(self, commit: Commit):
186219
# pylint: disable=too-many-branches,too-many-return-statements
187220
"""
@@ -201,22 +234,6 @@ def is_commit_filtered(self, commit: Commit):
201234
(self.get('to') is not None and
202235
commit.committer_date > self.get('to')):
203236
return True
204-
if self.get('from_commit') is not None and \
205-
self.get('from_commit') == commit.hash:
206-
self.set_value('from_commit_started', True)
207-
return False
208-
if self.get('from_commit') is not None and \
209-
self.get('from_commit') != commit.hash and \
210-
self.get('from_commit_started') is None:
211-
return True
212-
if self.get('to_commit') is not None and \
213-
self.get('to_commit') != commit.hash and \
214-
self.get('to_commit_reached') is not None:
215-
return True
216-
if self.get('to_commit') is not None and \
217-
self.get('to_commit') == commit.hash:
218-
self.set_value('to_commit_reached', True)
219-
return False
220237
if self.get('only_modifications_with_file_types') is not None:
221238
if not self._has_modification_with_file_type(commit):
222239
logger.debug('Commit filtered for modification types')

tests/integration/test_ranges.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ def test_from_and_to_commit(repository_mining_cc, expected_commits):
138138
assert len(repository_mining_cc) == expected_commits
139139

140140

141+
def test_from_and_to_commit_with_merge_commit():
142+
commits = RepositoryMining('test-repos/pydriller',
143+
from_commit="015f7144641a418f6a9fae4d024286ec17fd7ce8",
144+
to_commit="01d2f2fbeb6980cc5568825d008017ca8ca767d6").traverse_commits()
145+
assert len(list(commits)) == 3
146+
147+
141148
# FROM AND TO TAG
142149
@pytest.mark.parametrize('to_tag,expected_commits', [
143150
('v1.4', 3),

0 commit comments

Comments
 (0)