Skip to content

Add ignored commits feature #114

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ You can customize the plugin by setting options in `mkdocs.yml`. For example:
- index.md
enabled: true
strict: true
ignored_commits_file: .git-blame-ignore-revs
```

## `type`
Expand Down Expand Up @@ -147,3 +148,18 @@ Default is `true`. When enabled, the logs will show warnings when something is w
- git-revision-date-localized:
strict: true
```

## `ignored_commits_file`

Default is `None`. When specified, contains a file that contains a list of commit hashes to ignore
when determining the most recent updated time. The format of the file is the same as the format of
git `blame.ignoreRevsFile`. This can be useful to ignore formatting updates or other mass changes to the documents.


=== ":octicons-file-code-16: mkdocs.yml"

```yaml
plugins:
- git-revision-date-localized:
ignored_commits_file: .git-blame-ignore-revs
```
1 change: 1 addition & 0 deletions mkdocs_git_revision_date_localized_plugin/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class GitRevisionDateLocalizedPlugin(BasePlugin):
("enable_creation_date", config_options.Type(bool, default=False)),
("enabled", config_options.Type(bool, default=True)),
("strict", config_options.Type(bool, default=True)),
("ignored_commits_file", config_options.Type(str, default=None)),
)

def on_config(self, config: config_options.Config, **kwargs) -> Dict[str, Any]:
Expand Down
41 changes: 36 additions & 5 deletions mkdocs_git_revision_date_localized_plugin/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
NoSuchPathError,
)

from typing import Any, Dict
from typing import Any, Dict, List

logger = logging.getLogger("mkdocs.plugins")

Expand All @@ -32,6 +32,9 @@ def __init__(self, config={}):
self.config = config
self.repo_cache = {}

ignore_commits_file = self.config.get("ignored_commits_file")
self.ignored_commits = self.parse_git_ignore_revs(ignore_commits_file) if ignore_commits_file else []

def _get_repo(self, path: str) -> Git:
if not os.path.isdir(path):
path = os.path.dirname(path)
Expand Down Expand Up @@ -117,6 +120,7 @@ def get_git_commit_timestamp(
realpath = os.path.realpath(path)
git = self._get_repo(realpath)

# Ignored commits are only considered for the most recent update, not for creation
if is_first_commit:
# diff_filter="A" will select the commit that created the file
commit_timestamp = git.log(
Expand All @@ -128,10 +132,21 @@ def get_git_commit_timestamp(
if commit_timestamp != "":
commit_timestamp = commit_timestamp.split()[-1]
else:
# Latest commit touching a specific file
commit_timestamp = git.log(
realpath, date="unix", format="%at", n=1, no_show_signature=True
)
# Retrieve the history for the file in the format <hash> <timestamp>
# The maximum number of commits we will ever need to examine is 1 more than the number of ignored commits.
lines = git.log(
realpath, date="unix", format="%H %at", n=len(self.ignored_commits)+1, no_show_signature=True,
).split("\n")
# process the commits for the file in reverse-chronological order. Ignore any commit that is on the
# ignored list. If the line is empty, we've reached the end and need to use the fallback behavior
for line in lines:
if not line:
commit_timestamp = ""
break
commit, commit_timestamp = line.split(" ")
if not any(commit.startswith(x) for x in self.ignored_commits):
break

except (InvalidGitRepositoryError, NoSuchPathError) as err:
if self.config.get('fallback_to_build_date'):
log(
Expand Down Expand Up @@ -224,3 +239,19 @@ def add_spans(date_formats: Dict[str, str]) -> Dict[str, str]:
% (date_type, date_string)
)
return date_formats

@staticmethod
def parse_git_ignore_revs(filename: str) -> List[str]:
"""
Parses a file that is the same format as git's blame.ignoreRevsFile and return the list of commit hashes.

Whitespace, blanklines and comments starting with # are all ignored.
"""
result = []
with open(filename, "rt") as f:
for line in f:
line = line.split("#", 1)[0].strip()
if not line:
continue
result.append(line)
return result
8 changes: 8 additions & 0 deletions tests/fixtures/basic_project/mkdocs_ignored_commits.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
site_name: test gitrevisiondatelocalized_plugin
use_directory_urls: true

plugins:
- search
- git-revision-date-localized:
enable_creation_date: True
ignored_commits_file: ignored-commits.txt
45 changes: 42 additions & 3 deletions tests/test_builds.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,15 @@ def setup_commit_history(testproject_path):
repo.git.commit(message="add homepage", author=author, date="1500854705") # Mon Jul 24 2017 00:05:05 GMT+0000

file_name = os.path.join(testproject_path, "docs/page_with_tag.md")
with open(file_name, "a") as the_file:
the_file.write("test\n")
repo.git.add("docs/page_with_tag.md")
repo.git.commit(message="update homepage #1", author=author, date="1525475836") # Fri May 04 2018 23:17:16 GMT+0000

with open(file_name, "a") as the_file:
the_file.write("awa\n")
repo.git.add("docs/page_with_tag.md")
repo.git.commit(message="update homepage", author=author, date="1642911026") # Sun Jan 23 2022 04:10:26 GMT+0000
repo.git.commit(message="update homepage #2", author=author, date="1642911026") # Sun Jan 23 2022 04:10:26 GMT+0000

if os.path.exists("docs/page_with_renamed.md"):
bf_file_name = os.path.join(testproject_path, "docs/page_with_renamed.md")
Expand Down Expand Up @@ -382,10 +387,10 @@ def test_tags_are_replaced(tmp_path, mkdocs_file):
pytest.skip("Not necessary to test the JS library")

# Make sure count_commits() works
# We created 10 commits in setup_commit_history()
# We created 11 commits in setup_commit_history()
with working_directory(testproject_path):
u = Util()
assert commit_count(u._get_repo("docs/page_with_tag.md")) == 10
assert commit_count(u._get_repo("docs/page_with_tag.md")) == 11


# the revision date was in 'setup_commit_history' was set to 1642911026 (Sun Jan 23 2022 04:10:26 GMT+0000)
Expand Down Expand Up @@ -672,3 +677,37 @@ def test_mkdocs_genfiles_plugin(tmp_path):
validate_build(
testproject_path, plugin_config
)


def test_ignored_commits(tmp_path):
testproject_path = setup_clean_mkdocs_folder(
"tests/fixtures/basic_project/mkdocs_ignored_commits.yml", tmp_path
)
repo = setup_commit_history(testproject_path)

# First test that the middle commit doesn't show up by default
# January 23, 2022 is the date of the most recent commit
with open(str(testproject_path / "ignored-commits.txt"), "wt") as fp:
fp.write("")

result = build_docs_setup(testproject_path)
assert result.exit_code == 0

page_with_tag = testproject_path / "site/page_with_tag/index.html"
contents = page_with_tag.read_text(encoding="utf8")
assert "January 23, 2022" in contents

# Now mark the most recent change to page_with_tag as ignored
# May 4, 2018 is the date of the second most recent commit
hash = repo.git.log("docs/page_with_tag.md", format="%H", n=1)

with open(str(testproject_path / "ignored-commits.txt"), "wt") as fp:
fp.write(hash)

# should not raise warning
result = build_docs_setup(testproject_path)
assert result.exit_code == 0

page_with_tag = testproject_path / "site/page_with_tag/index.html"
contents = page_with_tag.read_text(encoding="utf8")
assert "May 4, 2018" in contents
16 changes: 16 additions & 0 deletions tests/test_parse_git_ignore_revs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from mkdocs_git_revision_date_localized_plugin.util import Util
import pytest
import tempfile

TEST_PARAMS = [
(b"abc123\n", ["abc123"]),
(b"abc123 # comments are ignored\n", ["abc123"]),
(b"\n\n\n\n\nabc123\n\n\n\n\n", ["abc123"]),
]

@pytest.mark.parametrize("test_input,expected", TEST_PARAMS)
def test_parse_git_ignore_revs(test_input, expected):
with tempfile.NamedTemporaryFile() as fp:
fp.write(test_input)
fp.flush()
assert Util.parse_git_ignore_revs(fp.name) == expected