Mercurial > kallithea
changeset 7142:3dbb625d5f9c
vcs: introduce 'branches' attribute on changesets, making it possible for Git to show multiple branches for a changeset
Mercurial changesets will always have have exactly one branch (which might be
"default"). The VCS data model was the same.
Git allows for a changeset to have 0 or more branches ... and possibly one of
them as active. The right data model is thus to have an enumerable of branches.
We thus add a 'branches' attribute and use it where applicable.
The existing 'branch' attribute used some heuristics to decide which branch use
as "the" branch ... and in some places code (and tests) rely on that. We thus
keep that old method, knowing that some of its uses probably should move to
'branches'.
The code for retrieving Git branches is based on work by Dominik Ruf.
author | Mads Kiilerich <mads@kiilerich.com> |
---|---|
date | Mon, 12 Feb 2018 02:38:02 +0100 |
parents | f200ce5efce6 |
children | dc7e37ec3dfd |
files | kallithea/controllers/feed.py kallithea/controllers/files.py kallithea/controllers/pullrequests.py kallithea/lib/vcs/backends/base.py kallithea/lib/vcs/backends/git/changeset.py kallithea/lib/vcs/backends/hg/changeset.py kallithea/templates/changelog/changelog_table.html kallithea/templates/changeset/changeset.html kallithea/templates/changeset/changeset_range.html kallithea/tests/vcs/test_branches.py kallithea/tests/vcs/test_changesets.py kallithea/tests/vcs/test_git.py kallithea/tests/vcs/test_hg.py |
diffstat | 13 files changed, 48 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/kallithea/controllers/feed.py Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/controllers/feed.py Mon Feb 12 02:38:02 2018 +0100 @@ -63,8 +63,8 @@ desc_msg = [(_('%s committed on %s') % (h.person(cs.author), h.fmt_date(cs.date))) + '<br/>'] # branches, tags, bookmarks - if cs.branch: - desc_msg.append('branch: %s<br/>' % cs.branch) + for branch in cs.branches: + desc_msg.append('branch: %s<br/>' % branch) for book in cs.bookmarks: desc_msg.append('bookmark: %s<br/>' % book) for tag in cs.tags:
--- a/kallithea/controllers/files.py Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/controllers/files.py Mon Feb 12 02:38:02 2018 +0100 @@ -189,7 +189,7 @@ # TODO: tags and bookmarks? c.revision_options = [(c.changeset.raw_id, - _('%s at %s') % (c.changeset.branch, h.short_id(c.changeset.raw_id)))] + \ + _('%s at %s') % (b, h.short_id(c.changeset.raw_id))) for b in c.changeset.branches] + \ [(n, b) for b, n in c.db_repo_scm_instance.branches.items()] if c.db_repo_scm_instance.closed_branches: prefix = _('(closed)') + ' ' @@ -755,7 +755,7 @@ branches_group = ([], _("Branches")) tags_group = ([], _("Tags")) for chs in changesets: - #_branch = '(%s)' % chs.branch if (cs.repository.alias == 'hg') else '' + # TODO: loop over chs.branches ... but that will not give all the bogus None branches for Git ... _branch = chs.branch n_desc = '%s (%s)' % (h.show_id(chs), _branch) changesets_group[0].append((chs.raw_id, n_desc,))
--- a/kallithea/controllers/pullrequests.py Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/controllers/pullrequests.py Mon Feb 12 02:38:02 2018 +0100 @@ -102,11 +102,11 @@ for i in repo._repo.revs( "sort(parents(branch(id(%s)) and merge()) - branch(id(%s)), -rev)", branch_rev, branch_rev): - abranch = repo.get_changeset(i).branch - if abranch not in peerbranches: - n = 'branch:%s:%s' % (abranch, repo.get_changeset(abranch).raw_id) - peers.append((n, abranch)) - peerbranches.add(abranch) + for abranch in repo.get_changeset(i).branches: + if abranch not in peerbranches: + n = 'branch:%s:%s' % (abranch, repo.get_changeset(abranch).raw_id) + peers.append((n, abranch)) + peerbranches.add(abranch) selected = None tiprev = repo.tags.get('tip')
--- a/kallithea/lib/vcs/backends/base.py Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/lib/vcs/backends/base.py Mon Feb 12 02:38:02 2018 +0100 @@ -1038,6 +1038,11 @@ return get_backend(self.alias).DEFAULT_BRANCH_NAME @LazyProperty + def branches(self): + from kallithea.lib.vcs.backends import get_backend + return [get_backend(self.alias).DEFAULT_BRANCH_NAME] + + @LazyProperty def short_id(self): return self.raw_id[:12]
--- a/kallithea/lib/vcs/backends/git/changeset.py Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/lib/vcs/backends/git/changeset.py Mon Feb 12 02:38:02 2018 +0100 @@ -91,13 +91,19 @@ @LazyProperty def branch(self): - + # Note: This function will return one branch name for the changeset - + # that might not make sense in Git where branches() is a better match + # for the basic model heads = self.repository._heads(reverse=False) - ref = heads.get(self.raw_id) if ref: return safe_unicode(ref) + @LazyProperty + def branches(self): + heads = self.repository._heads(reverse=True) + return [b for b in heads if heads[b] == self.raw_id] # FIXME: Inefficient ... and returning None! + def _fix_path(self, path): """ Paths are stored without trailing slash so we need to get rid off it if
--- a/kallithea/lib/vcs/backends/hg/changeset.py Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/lib/vcs/backends/hg/changeset.py Mon Feb 12 02:38:02 2018 +0100 @@ -41,6 +41,10 @@ return safe_unicode(self._ctx.branch()) @LazyProperty + def branches(self): + return [safe_unicode(self._ctx.branch())] + + @LazyProperty def closesbranch(self): return self._ctx.closesbranch()
--- a/kallithea/templates/changelog/changelog_table.html Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/templates/changelog/changelog_table.html Mon Feb 12 02:38:02 2018 +0100 @@ -97,8 +97,10 @@ %if cs.phase: <span class="label label-phase" title="Phase">${cs.phase}</span> %endif - %if show_branch and cs.branch: - <span class="label label-branch" title="${_('Branch %s' % cs.branch)}">${h.link_to(cs.branch,h.url('changelog_home',repo_name=repo_name,branch=cs.branch))}</span> + %if show_branch: + %for branch in cs.branches: + <span class="label label-branch" title="${_('Branch %s' % branch)}">${h.link_to(branch,h.url('changelog_home',repo_name=repo_name,branch=branch))}</span> + %endfor %endif </div> </div>
--- a/kallithea/templates/changeset/changeset.html Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/templates/changeset/changeset.html Mon Feb 12 02:38:02 2018 +0100 @@ -68,9 +68,9 @@ <span class="label label-tag" title="${_('Tag %s') % tag}">${h.link_to(tag,h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span> %endfor - %if c.changeset.branch: - <span class="label label-branch" title="${_('Branch %s') % c.changeset.branch}">${h.link_to(c.changeset.branch,h.url('changelog_home',repo_name=c.repo_name,branch=c.changeset.branch))}</span> - %endif + %for branch in c.changeset.branches: + <span class="label label-branch" title="${_('Branch %s') % branch}">${h.link_to(branch,h.url('changelog_home',repo_name=c.repo_name,branch=branch))}</span> + %endfor </span> <div class="changes">
--- a/kallithea/templates/changeset/changeset_range.html Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/templates/changeset/changeset_range.html Mon Feb 12 02:38:02 2018 +0100 @@ -90,11 +90,11 @@ <span class="label label-tag" title="${_('Tag %s') % tag}"> ${h.link_to(tag,h.url('changeset_home',repo_name=c.cs_repo.repo_name,revision=cs.raw_id))}</span> %endfor - %if cs.branch: - <span class="label label-branch" title="${_('Branch %s') % cs.branch}"> - ${h.link_to(cs.branch,h.url('changeset_home',repo_name=c.cs_repo.repo_name,revision=cs.raw_id))} - </span> - %endif + %for branch in cs.branches: + <span class="label label-branch" title="${_('Branch %s') % branch}"> + ${h.link_to(branch,h.url('changeset_home',repo_name=c.cs_repo.repo_name,revision=cs.raw_id))} + </span> + %endfor </span> </div> </div>
--- a/kallithea/tests/vcs/test_branches.py Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/tests/vcs/test_branches.py Mon Feb 12 02:38:02 2018 +0100 @@ -53,6 +53,7 @@ ) assert 'foobar' in self.repo.branches assert foobar_tip.branch == 'foobar' + assert foobar_tip.branches == ['foobar'] def test_new_head(self): tip = self.repo.get_changeset() @@ -81,6 +82,7 @@ ) assert newest_tip.branch == self.backend_class.DEFAULT_BRANCH_NAME + assert newest_tip.branches == [self.backend_class.DEFAULT_BRANCH_NAME] def test_branch_with_slash_in_name(self): self.imc.add(vcs.nodes.FileNode('extrafile', content='Some data\n'))
--- a/kallithea/tests/vcs/test_changesets.py Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/tests/vcs/test_changesets.py Mon Feb 12 02:38:02 2018 +0100 @@ -78,6 +78,7 @@ ) assert 'foobar' in self.repo.branches assert foobar_tip.branch == 'foobar' + assert foobar_tip.branches == ['foobar'] # 'foobar' should be the only branch that contains the new commit branch_tips = self.repo.branches.values() assert branch_tips.count(str(foobar_tip.raw_id)) == 1 @@ -109,6 +110,7 @@ ) assert newest_tip.branch == self.backend_class.DEFAULT_BRANCH_NAME + assert newest_tip.branches == [self.backend_class.DEFAULT_BRANCH_NAME] def test_get_changesets_respects_branch_name(self): tip = self.repo.get_changeset()
--- a/kallithea/tests/vcs/test_git.py Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/tests/vcs/test_git.py Mon Feb 12 02:38:02 2018 +0100 @@ -309,16 +309,19 @@ rev0 = self.repo.revisions[0] chset0 = self.repo.get_changeset(rev0) assert chset0.branch is None # should be 'master'? + assert chset0.branches == [] # should be 'master'? assert chset0.tags == [] rev10 = self.repo.revisions[10] chset10 = self.repo.get_changeset(rev10) assert chset10.branch is None # should be 'master'? + assert chset10.branches == [] # should be 'master'? assert chset10.tags == [] rev44 = self.repo.revisions[44] chset44 = self.repo.get_changeset(rev44) assert chset44.branch is None # should be 'web-branch'? + assert chset44.branches == [] # should be 'web-branch'? tip = self.repo.get_changeset('tip') assert 'tip' not in tip.tags # it should be?
--- a/kallithea/tests/vcs/test_hg.py Sun Jan 28 00:16:18 2018 +0100 +++ b/kallithea/tests/vcs/test_hg.py Mon Feb 12 02:38:02 2018 +0100 @@ -320,14 +320,17 @@ def test_branch_and_tags(self): chset0 = self.repo.get_changeset(0) assert chset0.branch == 'default' + assert chset0.branches == ['default'] assert chset0.tags == [] chset10 = self.repo.get_changeset(10) assert chset10.branch == 'default' + assert chset10.branches == ['default'] assert chset10.tags == [] chset44 = self.repo.get_changeset(44) assert chset44.branch == 'web' + assert chset44.branches == ['web'] tip = self.repo.get_changeset('tip') assert 'tip' in tip.tags