Skip to content

Commit

Permalink
feat: Add -F,--filter-commits to filter by revision-range
Browse files Browse the repository at this point in the history
This feature adds support for filtering the commits that will be used by git-changelog.

Issue #63: #63
Issue #16: #16
PR #64: #64
Co-authored-by: Timothée Mazzucotelli <[email protected]>
  • Loading branch information
pedro-psb authored Nov 4, 2023
1 parent 816e662 commit e016965
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 2 deletions.
25 changes: 24 additions & 1 deletion docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,29 @@ Templates are single files written using the [Jinja][jinja] templating engine.
You can get inspiration from
[the source of our built-in templates](https://github.com/pawamoy/git-changelog/tree/master/src/git_changelog/templates).

## Filter commits

Sometimes it may be useful to use a limited set of commits, for example, if your
project has migrated to semver recently and you want to ignore old non-conventional commits.

This is possible through the option `-F`, `--filter-commits`, which takes a
*revision-range* to select the commits that will be used in the changelog.
This option will pass the [revision-range](https://git-scm.com/docs/git-log#
Documentation/git-log.txt-ltrevision-rangegt) to `git log`, so it will follow
the rules defined by Git.

For example, to use commits from tag `0.5.0` up to latest:

```bash
git-changelog --filter-commits "0.5.0.."
```

Or using the commit hash:

```bash
git-changelog --filter-commits "2c0dbb8.."
```

## Understand the relationship with SemVer

[Semver][semver], or Semantic Versioning, helps users of tools and libraries
Expand Down Expand Up @@ -438,7 +461,6 @@ Other options can be used to help *git-changelog* retrieving
the latest entry from your changelog: `--version-regex`
and `--marker-line`.


## Configuration files

Project-wise, permanent configuration of *git-changelog* is possible.
Expand Down Expand Up @@ -475,6 +497,7 @@ for most of the command line options:
bump = "auto"
convention = "basic"
in-place = false
filter-commits = "0.5.0.."
marker-line = "<!-- insertion marker -->"
output = "output.log"
parse-refs = false
Expand Down
14 changes: 13 additions & 1 deletion src/git_changelog/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import os
import sys
import warnings
from subprocess import check_output
from subprocess import CalledProcessError, check_output
from typing import TYPE_CHECKING, ClassVar, Literal, Type, Union
from urllib.parse import urlsplit, urlunsplit

Expand Down Expand Up @@ -170,6 +170,7 @@ def __init__(
sections: list[str] | None = None,
bump_latest: bool = False,
bump: str | None = None,
filter_commits: str | None = None,
):
"""Initialization method.
Expand All @@ -182,10 +183,12 @@ def __init__(
sections: The sections to render (features, bug fixes, etc.).
bump_latest: Deprecated, use `bump="auto"` instead. Whether to try and bump latest version to guess new one.
bump: Whether to try and bump to a given version.
filter_commits: The Git revision-range used to filter commits in git-log (e.g: `v1.0.1..`).
"""
self.repository: str | Path = repository
self.parse_provider_refs: bool = parse_provider_refs
self.parse_trailers: bool = parse_trailers
self.filter_commits: str | None = filter_commits

# set provider
if not isinstance(provider, ProviderRefParser):
Expand Down Expand Up @@ -292,6 +295,15 @@ def get_log(self) -> str:
Returns:
The output of the `git log` command, with a particular format.
"""
if self.filter_commits:
try:
return self.run_git("log", "--date=unix", "--format=" + self.FORMAT, self.filter_commits)
except CalledProcessError as e:
raise ValueError(
f"An error ocurred. Maybe the provided git-log revision-range is not valid: '{self.filter_commits}'",
) from e

# No revision-range provided. Call normally
return self.run_git("log", "--date=unix", "--format=" + self.FORMAT)

def parse_commits(self) -> list[Commit]:
Expand Down
11 changes: 11 additions & 0 deletions src/git_changelog/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"bump": None,
"bump_latest": None,
"convention": "basic",
"filter_commits": None,
"in_place": False,
"input": DEFAULT_CHANGELOG_FILE,
"marker_line": DEFAULT_MARKER_LINE,
Expand Down Expand Up @@ -305,6 +306,13 @@ def get_parser() -> argparse.ArgumentParser:
dest="omit_empty_versions",
help="Omit empty versions from the output. Default: unset (false).",
)
parser.add_argument(
"-F",
"--filter-commits",
action="store",
dest="filter_commits",
help="The Git revision-range filter to use (e.g. 'v1.2.0..'). Default: no filter",
)
parser.add_argument(
"-V",
"--version",
Expand Down Expand Up @@ -457,6 +465,7 @@ def build_and_render(
omit_empty_versions: bool = False, # noqa: FBT001,FBT002
provider: str | None = None,
bump: str | None = None,
filter_commits: str | None = None,
) -> tuple[Changelog, str]:
"""Build a changelog and render it.
Expand All @@ -479,6 +488,7 @@ def build_and_render(
omit_empty_versions: Whether to omit empty versions from the output.
provider: Provider class used by this repository.
bump: Whether to try and bump to a given version.
filter_commits: The Git revision-range used to filter commits in git-log.
Raises:
ValueError: When some arguments are incompatible or missing.
Expand Down Expand Up @@ -521,6 +531,7 @@ def build_and_render(
parse_trailers=parse_trailers,
sections=sections,
bump=bump,
filter_commits=filter_commits,
)

# remove empty versions from changelog data
Expand Down
25 changes: 25 additions & 0 deletions tests/test_end_to_end.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,28 @@ def test_removing_credentials_from_remotes(repo: Path) -> None:
changelog = Changelog(repo)
assert creds not in changelog.remote_url
assert urlunsplit(urlsplit(changelog.remote_url)) == changelog.remote_url


def test_filter_commits_option(repo: Path) -> None:
"""Filter commit by revision-range argument.
Parameters:
repo: Temporary Git repository (fixture).
"""
git = partial(_git, "-C", str(repo))
is_tag_with_v = git("tag").split("\n")[0].startswith("v")

range = "1.0.0.."
expected = ["", "1.1.0"]
if is_tag_with_v:
range = "v1.0.0.."
expected = ["", "v1.1.0"]

changelog = Changelog(repo, filter_commits=range)
taglist = [version.tag for version in changelog.versions_list]

assert taglist == expected

err_msg = "Maybe the provided git-log revision-range is not valid"
with pytest.raises(ValueError, match=err_msg):
changelog = Changelog(repo, filter_commits="invalid")

0 comments on commit e016965

Please sign in to comment.