Repository: ishepard/pydriller (python)

Issue:
Newly created files have really high churn
Hi, this might not really be a feature request, as me asking for some tips. 

So i'm trying to calculate churn for all files in a repo, and I found the wonder full codechurn metri. Really nice!!.

I then made this little script to calculate churn for all files (in a arbitrarily long period of time) and print all files in the repo sorted by highest churn first:


```
from datetime import datetime
myrepo = "/home/ask/Git/tweeda"

from pydriller.metrics.process.code_churn import CodeChurn

metric = CodeChurn(path_to_repo = myrepo, since=datetime(2018, 1, 1), to=datetime(2020, 10, 10))

fileamount = metric.count()

for c in sorted(fileamount, key=fileamount.get, reverse=True):
    print(c)
```

This is super nice, but there is one thing however.

It looks like that when a file is added, then all the lines inside of it counts towards the churn for that file.
In my repo, I have some really big files that have just been added in one single commit, and then not really changed after that. This means that these files rank really highly in terms of churn, even though they havent been changed that many times. This does seem a little bit misleading

Is there any way that I can circumvent this "issue"?


Pull request:
Closes #169
 Added flag **ignore_added_files** to not count churns when files are created.

Patch:
diff --git a/pydriller/metrics/process/code_churn.py b/pydriller/metrics/process/code_churn.py
index dfdde34..f350d9d 100644
--- a/pydriller/metrics/process/code_churn.py
+++ b/pydriller/metrics/process/code_churn.py
@@ -23,9 +23,14 @@ class CodeChurn(ProcessMetric):
                  since=None,
                  to=None,
                  from_commit: str = None,
-                 to_commit: str = None):
+                 to_commit: str = None,
+                 ignore_added_files=False):
+        """
+        :ignore_added_files: if True, do not count churns for files when created
+        """
 
         super().__init__(path_to_repo, since=since, to=to, from_commit=from_commit, to_commit=to_commit)
+        self.ignore_added_files = ignore_added_files
         self._initialize()
 
     def _initialize(self):
@@ -42,6 +47,9 @@ class CodeChurn(ProcessMetric):
                 if modified_file.change_type == ModificationType.RENAME:
                     renamed_files[modified_file.old_path] = filepath
 
+                if self.ignore_added_files and modified_file.change_type == ModificationType.ADD:
+                    continue
+
                 churn = modified_file.added_lines - modified_file.deleted_lines
                 self.files.setdefault(filepath, []).append(churn)
 


Test patch:
diff --git a/tests/metrics/process/test_code_churn.py b/tests/metrics/process/test_code_churn.py
index 2a70234..6bff44b 100644
--- a/tests/metrics/process/test_code_churn.py
+++ b/tests/metrics/process/test_code_churn.py
@@ -45,3 +45,29 @@ def test_with_dates(path_to_repo, filepath, since, to, expected_count, expected_
     assert actual_count[filepath] == expected_count
     assert actual_max[filepath] == expected_max
     assert actual_avg[filepath] == expected_avg
+
+
+def test_without_flag():
+    metric = CodeChurn(path_to_repo='test-repos/pydriller',
+                       from_commit='ab36bf45859a210b0eae14e17683f31d19eea041',
+                       to_commit='fdf671856b260aca058e6595a96a7a0fba05454b',
+                       ignore_added_files=False)
+
+    code_churns = metric.count()
+
+    assert len(code_churns) == 18
+    assert str(Path('domain/__init__.py')) in code_churns
+    assert code_churns[str(Path('domain/commit.py'))] == 34
+
+
+def test_with_flag():
+    metric = CodeChurn(path_to_repo='test-repos/pydriller',
+                       from_commit='ab36bf45859a210b0eae14e17683f31d19eea041',
+                       to_commit='fdf671856b260aca058e6595a96a7a0fba05454b',
+                       ignore_added_files=True)
+
+    code_churns = metric.count()
+
+    assert len(code_churns) == 7
+    assert str(Path('domain/__init__.py')) not in code_churns
+    assert code_churns[str(Path('domain/commit.py'))] == 0