Skip to content
Open
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
45 changes: 43 additions & 2 deletions docs/using.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,23 @@ will accept. See `the man page`_ for details.

Sphinx will output a warning if you specify both.

Filter Revisons to Matching Only Certain Files Based on Filenames
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Filter Revisions to Match Only a Single Directory or File
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you only want to see the changelog regarding to a certain directory or file
you can use the ``:path:`` argument with ``git_changelog``.
``:path:`` expects a path to the directory or file you want to filter on, either
as an absolute path or as a relative path from the working directory. So::

.. git_changelog::
:path: doc/

will show all commits that modified files in the ``doc/`` directory.


Filter Revisions to Matching Only Certain Files Based on Filenames
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you only want to see the changelog regarding certain files (eg. for devops
reasons you need to have both SaSS and CSS in your repository or you only want
Expand Down Expand Up @@ -158,6 +173,32 @@ for example:
:detailed-message-strong: False


Hiding merge commits
~~~~~~~~~~~~~~~~~~~~

If you want to hide merge commits from the changelog,
then you can add the ``:no_merges:`` argument. So::

.. git_changelog::
:no_merges:

will hide all commits that have more than one parent.


Showing only the first parent commits
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you want the changelog to only display the first parents of commits
(e.g. your main branch has been merged into a lot and you don't want to
see the individual commits that came from other branches), then you can
add the ``:first_parent:`` argument. So::

.. git_changelog::
:first_parent:

will only show the first parent of merge commits.


git_commit_detail Directive
---------------------------

Expand Down
17 changes: 13 additions & 4 deletions sphinx_git/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ class GitChangelog(GitDirectiveBase):
'hide_date': bool,
'hide_details': bool,
'repo-dir': six.text_type,
'path': directives.path,
'first_parent': bool,
'no_merges': bool,
}

def run(self):
Expand All @@ -138,10 +141,16 @@ def _commits_to_display(self):
return commits

def _filter_commits(self, repo):
if 'rev-list' in self.options:
commits = repo.iter_commits(rev=self.options['rev-list'])
else:
commits = repo.iter_commits()
first_parent = 'first_parent' in self.options
no_merges = 'no_merges' in self.options

commits = repo.iter_commits(
rev=self.options.get('rev-list', None),
paths=self.options.get('path', ''),
first_parent=first_parent,
no_merges=no_merges,
)
if 'rev-list' not in self.options:
revisions_to_display = self.options.get('revisions', 10)
commits = list(commits)[:revisions_to_display]
if 'filename_filter' in self.options:
Expand Down
82 changes: 82 additions & 0 deletions tests/test_git_changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,88 @@ def test_single_commit_message_hide_date(self):
assert_not_in(' at ', par_children[1].text)
assert_in(' by ', par_children[1].text)

def test_path_filter(self):
self.repo.index.commit('initial')
dirnames = ['dir1', 'dir2']
for dirname in dirnames:
full_dir_path = os.path.join(self.repo.working_tree_dir, dirname)
os.mkdir(full_dir_path)
full_file_path = os.path.join(full_dir_path, 'test.txt')
f = open(full_file_path, 'w+')
f.close()
self.repo.index.add([full_file_path])
self.repo.index.commit('commit to file in {}'.format(dirname))
self.repo.index.commit('commit without file in a specific directory')

dirname_ut = dirnames[0]
self.changelog.options.update({'path': "{}/".format(dirname_ut)})
nodes = self.changelog.run()
assert_equal(1, len(nodes))
list_markup = BeautifulSoup(str(nodes[0]), features='xml')
assert_equal(1, len(list_markup.findAll('bullet_list')))

bullet_list = list_markup.bullet_list
assert_equal(1, len(bullet_list.findAll('list_item')), nodes)

item = list_markup.bullet_list.list_item
children = list(item.childGenerator())
assert_equal(1, len(children))
par_children = list(item.paragraph.childGenerator())
assert_equal(5, len(par_children))
assert_equal('commit to file in {}'.format(dirname_ut),
par_children[0].text)

def _merge_test_setup(self):
self.repo.index.commit('initial')
original_branch = self.repo.active_branch

# Create a new branch and add a commit to it
new_branch = self.repo.create_head('newbranch')
new_branch.checkout()
file_path = os.path.join(self.repo.working_tree_dir, 'test.txt')
f = open(file_path, 'w+')
f.close()
self.repo.index.add([file_path])
self.repo.index.commit('regular commit')

# Merge the new branch into the original branch
original_branch.checkout()
base = self.repo.merge_base(original_branch, new_branch)
self.repo.index.merge_tree(new_branch, base=base)
parent_commits = (original_branch.commit, new_branch.commit)
self.repo.index.commit('merge commit', parent_commits=parent_commits)

def test_merge_commit_show_first_parent_only(self):
self._merge_test_setup()

self.changelog.options.update({'first_parent': True})
nodes = self.changelog.run()
assert_equal(1, len(nodes))
list_markup = BeautifulSoup(str(nodes[0]), features='xml')
assert_equal(1, len(list_markup.findAll('bullet_list')))
bullet_list = list_markup.bullet_list
# Expect the initial commit & the merge commit
assert_equal(2, len(bullet_list.findAll('list_item')))
# Verify the regular commit is not in the changelog
for child in bullet_list.childGenerator():
assert_not_in('regular commit', child.text)

def test_merge_commit_show_no_merges(self):
self._merge_test_setup()

# Test git changelog
self.changelog.options.update({'no_merges': True})
nodes = self.changelog.run()
assert_equal(1, len(nodes))
list_markup = BeautifulSoup(str(nodes[0]), features='xml')
assert_equal(1, len(list_markup.findAll('bullet_list')))
bullet_list = list_markup.bullet_list
# Expect the initial commit & the regular commit
assert_equal(2, len(bullet_list.findAll('list_item')))
# Verify the merge commit is not in the changelog
for child in bullet_list.childGenerator():
assert_not_in('merge commit', child.text)


class TestWithOtherRepository(TestWithRepository):
"""
Expand Down