Index: app/helpers/repositories_helper.rb =================================================================== --- app/helpers/repositories_helper.rb (revision 22112) +++ app/helpers/repositories_helper.rb (working copy) @@ -326,4 +326,59 @@ end max_space end + + def has_branch_detail? + @repository.scm.respond_to? :branch_contains + end + + def insert_branches_detail(html) + return html unless has_branch_detail? + substring = '' + location = html.index(substring).to_i + substring.length + html.insert(location, branches_html) + end + + def branches_html + content_tag(:li) do + content = content_tag(:strong, "#{l(:label_branch)}") + content << " " + content << "#{@repository.identifier}@ " + content << links_to_branches.join(', ').html_safe + end + end + + def links_to_branches + return [] unless has_branch_detail? + branch_groups.map { |name, branches| branches_link(name, branches) } + end + + def branches_link(name, branches) + return branch_link(branches.first) if branches.length == 1 + link = link_to("[#{name}...]", 'javascript:;', class: 'scm-branch-group').html_safe + content_tag(:span, class: 'scm-branch-hide') do + link << content_tag(:span, class: 'scm-branches') do + branches.map { |branch| branch_link(branch) }.join(', ').html_safe + end + end + end + + def branch_link(branch) + link_to(branch, {:controller => 'repositories', + :action => 'show', + :id => @repository.project, + :repository_id => @repository.identifier, + :path => to_path_param(@path), + :rev => branch}).html_safe + end + + def branch_groups + @repository.scm.branch_contains(@rev).group_by do |branch| + branch.downcase + .gsub(/^\d+/, '#####') + .split(/[\-\._]/) + .first + end.sort_by { |name, branches| [branches.length, name] } + end + + end Index: app/views/issues/tabs/_changesets.html.erb =================================================================== --- app/views/issues/tabs/_changesets.html.erb (revision 22112) +++ app/views/issues/tabs/_changesets.html.erb (working copy) @@ -7,6 +7,9 @@

<%= "#{changeset.project.name} - " unless changeset.project == project %> + <%= if Setting.display_repository_base_name? + changeset.repository.url.split('/').last.sub('.git','') + ': ' + end %> <%= link_to_revision(changeset, changeset.repository, :text => "#{l(:label_revision)} #{changeset.format_identifier}") %> <% if changeset.filechanges.any? && User.current.allowed_to?(:browse_repository, changeset.project) %> @@ -17,6 +20,12 @@ :repository_id => changeset.repository.identifier_param, :path => "", :rev => changeset.identifier) %>) + <% if Setting.display_under_associated_revisions? && changeset.scmid.present? + @repository = changeset.repository + @rev = changeset.identifier + %> + (<%= l(:label_branches) %>: <%= links_to_branches.join(', ').html_safe %>) + <% end %> <% end %>

Index: app/views/repositories/_changeset.html.erb =================================================================== --- app/views/repositories/_changeset.html.erb (revision 22112) +++ app/views/repositories/_changeset.html.erb (working copy) @@ -20,6 +20,13 @@ }.join(", ").html_safe %> <% end %> + <% if !Setting.display_under_single_revision? %> +
  • + <%= l(:label_branches) %> + <%= links_to_branches.join(', ').html_safe %> +
  • + <% end %> + <% if @changeset.children.present? %>
  • <%= l(:label_child_revision) %> Index: app/views/settings/_issues.html.erb =================================================================== --- app/views/settings/_issues.html.erb (revision 22112) +++ app/views/settings/_issues.html.erb (working copy) @@ -24,8 +24,19 @@

    <%= setting_text_field :gantt_items_limit, :size => 6 %>

    <%= setting_text_field :gantt_months_limit, :size => 6 %>

    +
  • +
    + <%= l(:label_display_revision_branches) %> +
    +

    <%= setting_check_box :display_under_single_revision %>

    +

    <%= setting_check_box :display_under_associated_revisions %>

    + +

    <%= setting_check_box :display_repository_base_name %>

    +
    +
    +
    <%= l(:label_parent_task_attributes) %>
    Index: config/locales/de.yml =================================================================== --- config/locales/de.yml (revision 22112) +++ config/locales/de.yml (working copy) @@ -461,6 +461,7 @@ label_board_sticky: Wichtig (immer oben) label_boolean: Boolean label_branch: Zweig + label_branches: Zweige label_browse: Codebrowser label_bulk_edit_selected_issues: Alle ausgewählten Tickets bearbeiten label_bulk_edit_selected_time_entries: Ausgewählte Zeitaufwände bearbeiten @@ -1005,6 +1006,9 @@ setting_default_projects_tracker_ids: Standardmäßig aktivierte Tracker für neue Projekte setting_diff_max_lines_displayed: Maximale Anzahl anzuzeigender Diff-Zeilen setting_display_subprojects_issues: Tickets von Unterprojekten im Hauptprojekt anzeigen + setting_display_under_single_revision: Unterschiede bei Revision anzeigen + setting_display_under_associated_revisions: Bei zugehörigen Revisionen anzeigen + setting_display_repository_base_name: Name des zugehörigen Repository anzeigen setting_emails_footer: E-Mail-Fußzeile setting_emails_header: E-Mail-Kopfzeile setting_enabled_scm: Aktivierte Versionskontrollsysteme @@ -1303,6 +1307,7 @@ label_ends_with: endet mit label_issue_fixed_version_updated: Zielversion aktualisiert setting_project_list_defaults: Voreinstellungen Projektliste + label_display_revision_branches: Zweige zur Revision anzeigen label_display_type: Ergebnisse anzeigen als label_display_type_list: Liste label_display_type_board: Karte Index: config/locales/en.yml =================================================================== --- config/locales/en.yml (revision 22112) +++ config/locales/en.yml (working copy) @@ -443,6 +443,9 @@ setting_time_format: Time format setting_timespan_format: Time span format setting_cross_project_issue_relations: Allow cross-project issue relations + setting_display_under_single_revision: Display revision under Single Revision + setting_display_under_associated_revisions: Display revision under Associated Revisions + setting_display_repository_base_name: Display basename of associated repository setting_cross_project_subtasks: Allow cross-project subtasks setting_issue_list_default_columns: Issues list defaults setting_repositories_encodings: Attachments and repositories encodings @@ -823,6 +826,7 @@ label_repository_plural: Repositories label_browse: Browse label_branch: Branch + label_branches: Branches label_tag: Tag label_revision: Revision label_revision_plural: Revisions @@ -947,6 +951,7 @@ label_registration_manual_activation: manual account activation label_registration_automatic_activation: automatic account activation label_display_per_page: "Per page: %{value}" + label_display_revision_branches: Show branches for revision label_age: Age label_change_properties: Change properties label_general: General Index: config/settings.yml =================================================================== --- config/settings.yml (revision 22112) +++ config/settings.yml (working copy) @@ -226,8 +226,14 @@ issue_list_default_totals: serialized: true default: [] +display_under_single_revision: + default: true +display_under_associated_revisions: + default: true display_subprojects_issues: default: 1 +display_repository_base_name: + default: true time_entry_list_defaults: serialized: true default: Index: lib/redmine/scm/adapters/git_adapter.rb =================================================================== --- lib/redmine/scm/adapters/git_adapter.rb (revision 22112) +++ lib/redmine/scm/adapters/git_adapter.rb (working copy) @@ -98,6 +98,19 @@ rescue ScmCommandAborted nil end + + def branch_contains(hash) + cleaned_hash = hash.sub(/[^\w]/, '') + cmd_args = ['branch', '--contains', cleaned_hash] + begin + branches = git_cmd(cmd_args) do |io| + io.readlines.sort!.map{|t| t.strip.gsub(/\* ?/, '')} + end + rescue ScmCommandAborted + branches = Array.new + end + branches.uniq + end def tags return @tags if @tags Index: public/javascripts/repository_navigation.js =================================================================== --- public/javascripts/repository_navigation.js (revision 22112) +++ public/javascripts/repository_navigation.js (working copy) @@ -33,4 +33,8 @@ $('#branch,#tag').removeAttr('disabled'); } }); + + $('a.scm-branch-group').on('click', function() { + $(this).parent().removeClass('scm-branch-hide'); + }); }) Index: public/stylesheets/scm.css =================================================================== --- public/stylesheets/scm.css (revision 22112) +++ public/stylesheets/scm.css (working copy) @@ -126,3 +126,6 @@ .breadcrumbs>.separator::before, .breadcrumbs>.separator::after { content: " "; } + +.scm-branch-group, .scm-branch-hide > .scm-branches { display: none; } +.scm-branch-hide > .scm-branch-group { display: inline; }