diff --git a/README.md b/README.md index 2a0d3d4f..f9c8d61b 100644 --- a/README.md +++ b/README.md @@ -224,6 +224,9 @@ COMP_EXECUTABLES = [ ('myexe', 'L'), ] ``` +* `COMPARISON_COMMIT_TAGS: Defines a list of tags to display on the comparison page. This comes + handy when there are a lot of tags. It defaults to ``None`` which means display all the available + tags. ### VCS Provider Specific Settings diff --git a/codespeed/settings.py b/codespeed/settings.py index 916c4cbd..5290a15e 100644 --- a/codespeed/settings.py +++ b/codespeed/settings.py @@ -78,6 +78,13 @@ # ('myexe', '21df2423ra'), # ('myexe', 'L'),] +COMPARISON_COMMIT_TAGS = None # List of tag names which should be included in the executables list + # on the comparision page. + # This comes handy where project contains a lot of tags, but you only want + # to list subset of them on the comparison page. + # If this value is set to None (default value), all the available tags will + # be included. + TIMELINE_EXECUTABLE_NAME_MAX_LEN = 22 # Maximum length of the executable name used in the # Changes and Timeline view. If the name is longer, the name # will be truncated and "..." will be added at the end. diff --git a/codespeed/tests/test_views_data.py b/codespeed/tests/test_views_data.py index 6a037997..3bc5f6c7 100644 --- a/codespeed/tests/test_views_data.py +++ b/codespeed/tests/test_views_data.py @@ -61,7 +61,15 @@ def setUp(self): self.revision_1_custom = Revision.objects.create( branch=self.branch_custom, commitid='1') - def test_get_comparisionexes_master_default_branch(self): + def _insert_mock_revision_objects(self): + self.rev_v4 = Revision.objects.create( + branch=self.branch_master, commitid='4', tag='v4.0.0') + self.rev_v5 = Revision.objects.create( + branch=self.branch_master, commitid='5', tag='v5.0.0') + self.rev_v6 = Revision.objects.create( + branch=self.branch_master, commitid='6', tag='v6.0.0') + + def test_get_comparisonexes_master_default_branch(self): # Standard "master" default branch is used self.project.default_branch = 'master' self.project.save() @@ -100,7 +108,7 @@ def test_get_comparisionexes_master_default_branch(self): self.assertEqual(exe_keys[0], '1+L+master') self.assertEqual(exe_keys[1], '2+L+master') - def test_get_comparisionexes_custom_default_branch(self): + def test_get_comparisonexes_custom_default_branch(self): # Custom default branch is used self.project.default_branch = 'custom' self.project.save() @@ -141,7 +149,7 @@ def test_get_comparisionexes_custom_default_branch(self): self.assertEqual(exe_keys[2], '1+L+custom') self.assertEqual(exe_keys[3], '2+L+custom') - def test_get_comparisionexes_branch_filtering(self): + def test_get_comparisonexes_branch_filtering(self): # branch1 and branch3 have display_on_comparison_page flag set to False # so they shouldn't be included in the result branch1 = Branch.objects.create(name='branch1', project=self.project, @@ -173,6 +181,82 @@ def test_get_comparisionexes_branch_filtering(self): for index, exe_key in enumerate(expected_exe_keys): self.assertEqual(executables[self.project][index]['key'], exe_key) + def test_get_comparisonexes_tag_name_filtering_no_filter_specified(self): + # Insert some mock revisions with tags + self._insert_mock_revision_objects() + + # No COMPARISON_TAGS filters specified, all the tags should be included + executables, exe_keys = getcomparisonexes() + self.assertEqual(len(executables), 1) + self.assertEqual(len(executables[self.project]), 2 * 2 + 2 * 3) + self.assertEqual(len(exe_keys), 2 * 2 + 2 * 3) + + self.assertExecutablesListContainsRevision(executables[self.project], + self.rev_v4) + self.assertExecutablesListContainsRevision(executables[self.project], + self.rev_v5) + self.assertExecutablesListContainsRevision(executables[self.project], + self.rev_v6) + + def test_get_comparisonexes_tag_name_filtering_single_tag_specified(self): + # Insert some mock revisions with tags + self._insert_mock_revision_objects() + + # Only a single tag should be included + with override_settings(COMPARISON_COMMIT_TAGS=['v4.0.0']): + executables, exe_keys = getcomparisonexes() + self.assertEqual(len(executables), 1) + self.assertEqual(len(executables[self.project]), 2 * 2 + 2 * 1) + self.assertEqual(len(exe_keys), 2 * 2 + 2 * 1) + + self.assertExecutablesListContainsRevision( + executables[self.project], self.rev_v4) + self.assertExecutablesListDoesntContainRevision( + executables[self.project], self.rev_v5) + self.assertExecutablesListDoesntContainRevision( + executables[self.project], self.rev_v6) + + def test_get_comparisonexes_tag_name_filtering_empty_list_specified(self): + # Insert some mock revisions with tags + self._insert_mock_revision_objects() + + # No tags should be included + with override_settings(COMPARISON_COMMIT_TAGS=[]): + executables, exe_keys = getcomparisonexes() + self.assertEqual(len(executables), 1) + self.assertEqual(len(executables[self.project]), 2 * 2) + self.assertEqual(len(exe_keys), 2 * 2) + + self.assertExecutablesListDoesntContainRevision( + executables[self.project], self.rev_v4) + self.assertExecutablesListDoesntContainRevision( + executables[self.project], self.rev_v5) + self.assertExecutablesListDoesntContainRevision( + executables[self.project], self.rev_v6) + + def assertExecutablesListContainsRevision(self, executables, revision): + found = self._executable_list_contains_revision(executables=executables, + revision=revision) + + if not found: + self.assertFalse("Didn't find revision \"%s\" in executable list \"%s\"" % + (str(revision), str(executables))) + + def assertExecutablesListDoesntContainRevision(self, executables, revision): + found = self._executable_list_contains_revision(executables=executables, + revision=revision) + + if found: + self.assertFalse("Found revision \"%s\", but didn't expect it" % + (str(revision))) + + def _executable_list_contains_revision(self, executables, revision): + for executable in executables: + if executable['revision'] == revision: + return True + + return False + class UtilityFunctionsTestCase(TestCase): @override_settings(TIMELINE_EXECUTABLE_NAME_MAX_LEN=22) @@ -186,7 +270,7 @@ def test_get_sanitized_executable_name_for_timeline_view(self): self.assertEqual(name, 'a' * 22 + '...') @override_settings(COMPARISON_EXECUTABLE_NAME_MAX_LEN=20) - def test_get_sanitized_executable_name_for_comparision_view(self): + def test_get_sanitized_executable_name_for_comparison_view(self): executable = Executable(name='b' * 20) name = get_sanitized_executable_name_for_comparison_view(executable) self.assertEqual(name, 'b' * 20) diff --git a/codespeed/views_data.py b/codespeed/views_data.py index 6b4210be..583f5457 100644 --- a/codespeed/views_data.py +++ b/codespeed/views_data.py @@ -49,7 +49,12 @@ def get_default_environment(enviros, data, multi=False): return defaultenviros[0] -def getbaselineexecutables(): +def getbaselineexecutables(include_tags=None): + """ + :param include_tags: A list of tags to include in the result. If set to + None,, it will include all the available tags. + :type include_tags: ``list`` + """ baseline = [{ 'key': "none", 'name': "None", @@ -57,7 +62,14 @@ def getbaselineexecutables(): 'revision': "none", }] executables = Executable.objects.select_related('project') - revs = Revision.objects.exclude(tag="").select_related('branch__project') + + if include_tags is not None: + revs = Revision.objects.filter(tag__in=include_tags) + else: + revs = Revision.objects.exclude(tag="") + + revs = revs.select_related('branch__project') + for rev in revs: # Add executables that correspond to each tagged revision. for exe in [e for e in executables if e.project == rev.branch.project]: @@ -107,9 +119,12 @@ def getdefaultexecutable(): def getcomparisonexes(): + comparison_commit_tags = getattr(settings, 'COMPARISON_COMMIT_TAGS', None) + all_executables = {} exekeys = [] - baselines = getbaselineexecutables() + baselines = getbaselineexecutables(include_tags=comparison_commit_tags) + for proj in Project.objects.all(): executables = [] executablekeys = [] @@ -281,7 +296,7 @@ def get_sanitized_executable_name_for_timeline_view(executable): def get_sanitized_executable_name_for_comparison_view(executable): """ Return sanitized executable name which is used in the sidebar in the - comparision view. + comparison view. If the name is longer than settings.COMPARISON_EXECUTABLE_NAME_MAX_LEN, the name will be truncated to that length and "..." appended to it.