summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG19
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.lock10
-rw-r--r--LICENSE2
-rw-r--r--app/assets/javascripts/calendar.js.coffee6
-rw-r--r--app/assets/javascripts/notes.js.coffee10
-rw-r--r--app/assets/javascripts/sidebar.js.coffee11
-rw-r--r--app/assets/stylesheets/generic/filters.scss55
-rw-r--r--app/assets/stylesheets/generic/mobile.scss7
-rw-r--r--app/assets/stylesheets/generic/selects.scss13
-rw-r--r--app/assets/stylesheets/pages/issuable.scss8
-rw-r--r--app/assets/stylesheets/pages/issues.scss38
-rw-r--r--app/assets/stylesheets/pages/projects.scss48
-rw-r--r--app/helpers/blob_helper.rb8
-rw-r--r--app/helpers/icons_helper.rb44
-rw-r--r--app/helpers/labels_helper.rb3
-rw-r--r--app/helpers/milestones_helper.rb3
-rw-r--r--app/helpers/projects_helper.rb34
-rw-r--r--app/helpers/tree_helper.rb9
-rw-r--r--app/views/groups/group_members/_new_group_member.html.haml2
-rw-r--r--app/views/projects/_home_panel.html.haml35
-rw-r--r--app/views/projects/blob/_blob.html.haml2
-rw-r--r--app/views/projects/commit/_commit_box.html.haml3
-rw-r--r--app/views/projects/commits/_head.html.haml4
-rw-r--r--app/views/projects/issues/index.html.haml10
-rw-r--r--app/views/projects/merge_requests/show/_state_widget.html.haml2
-rw-r--r--app/views/projects/repositories/_download_archive.html.haml4
-rw-r--r--app/views/projects/show.html.haml11
-rw-r--r--app/views/projects/tree/_blob_item.html.haml2
-rw-r--r--app/views/projects/tree/_submodule_item.html.haml2
-rw-r--r--app/views/projects/tree/_tree_item.html.haml2
-rw-r--r--app/views/shared/_issuable_filter.html.haml44
-rw-r--r--config/gitlab.yml.example34
-rw-r--r--config/initializers/acts_as_taggable_on_patch.rb131
-rw-r--r--doc/ssh/README.md2
-rw-r--r--docker/Dockerfile2
-rw-r--r--features/groups.feature8
-rw-r--r--features/project/star.feature2
-rw-r--r--features/steps/groups.rb26
-rw-r--r--features/steps/project/star.rb8
-rw-r--r--lib/api/projects.rb7
-rw-r--r--lib/tasks/gitlab/test.rake1
-rw-r--r--spec/helpers/icons_helper_spec.rb109
-rw-r--r--spec/models/project_services/asana_service_spec.rb (renamed from spec/models/asana_service_spec.rb)0
-rw-r--r--spec/spec_helper.rb2
-rw-r--r--spec/support/test_env.rb8
46 files changed, 437 insertions, 358 deletions
diff --git a/CHANGELOG b/CHANGELOG
index d1470c45bad..6cf459754f9 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -5,10 +5,7 @@ v 7.10.0 (unreleased)
- Set Application controller default URL options to ensure all url_for calls are consistent (Stan Hu)
- Allow HTML tags in Markdown input
- Fix code unfold not working on Compare commits page (Stan Hu)
- - Include missing events and fix save functionality in admin service template settings form (Stan Hu)
- - Fix "Import projects from" button to show the correct instructions (Stan Hu)
- Fix dots in Wiki slugs causing errors (Stan Hu)
- - Fix OAuth2 issue importing a new project from GitHub and GitLab (Stan Hu)
- Update poltergeist to version 1.6.0 to support PhantomJS 2.0 (Zeger-Jan van de Weg)
- Fix cross references when usernames, milestones, or project names contain underscores (Stan Hu)
- Disable reference creation for comments surrounded by code/preformatted blocks (Stan Hu)
@@ -17,6 +14,7 @@ v 7.10.0 (unreleased)
- extend the commit calendar to show the actual commits made on a date (Hannes Rosenรถgger)
- Fix a link in the patch update guide
- Add a service to support external wikis (Hannes Rosenรถgger)
+ - Omit the "email patches" link and fix plain diff view for merge commits
- List new commits for newly pushed branch in activity view.
- Add sidetiq gem dependency to match EE
- Add changelog, license and contribution guide links to project sidebar.
@@ -24,6 +22,7 @@ v 7.10.0 (unreleased)
- Fix alignment of navbar toggle button (Cody Mize)
- Fix checkbox rendering for nested task lists
- Identical look of selectboxes in UI
+ - Upgrade the gitlab_git gem to version 7.1.3
- Move "Import existing repository by URL" option to button.
- Improve error message when save profile has error.
- Passing the name of pushed ref to CI service (requires GitLab CI 7.9+)
@@ -37,7 +36,6 @@ v 7.10.0 (unreleased)
- Add ability to unlink connected accounts
- Replace commits calendar with faster contribution calendar that includes issues and merge requests
- Add inifinite scroll to user page activity
- - Don't show commit comment button when user is not signed in.
- Don't include system notes in issue/MR comment count.
- Don't mark merge request as updated when merge status relative to target branch changes.
- Link note avatar to user.
@@ -46,6 +44,10 @@ v 7.10.0 (unreleased)
- Refactor issue filtering
- AJAX selectbox for issue assignee and author filters
- Fix issue with missing options in issue filtering dropdown if selected one
+ - Prevent holding Control-Enter or Command-Enter from posting comment multiple times.
+ - Prevent note form from being cleared when submitting failed.
+ - Improve file icons rendering on tree (Sullivan Sรฉnรฉchal)
+ - API: Add pagination to project events
- Get issue links in notification mail to work again.
v 7.9.0
@@ -54,6 +56,15 @@ v 7.9.0
- Prevent doubling AJAX request with each commit visit via Turbolink
- Prevent unnecessary doubling of js events on import pages and user calendar
+v 7.9.1
+ - Include missing events and fix save functionality in admin service template settings form (Stan Hu)
+ - Fix "Import projects from" button to show the correct instructions (Stan Hu)
+ - Fix OAuth2 issue importing a new project from GitHub and GitLab (Stan Hu)
+ - Fix for LDAP with commas in DN
+ - Fix missing events and in admin Slack service template settings form (Stan Hu)
+ - Don't show commit comment button when user is not signed in.
+ - Downgrade gemnasium-gitlab-service gem
+
v 7.9.0
- Add HipChat integration documentation (Stan Hu)
- Update documentation for object_kind field in Webhook push and tag push Webhooks (Stan Hu)
diff --git a/Gemfile b/Gemfile
index e7f75055f3f..e767aec5053 100644
--- a/Gemfile
+++ b/Gemfile
@@ -39,7 +39,7 @@ gem "browser"
# Extracting information from a git repository
# Provide access to Gitlab::Git library
-gem "gitlab_git", '~> 7.1.2'
+gem "gitlab_git", '~> 7.1.3'
# Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.0.rc2', require: 'grack'
@@ -115,7 +115,7 @@ end
gem "state_machine"
# Issue tags
-gem "acts-as-taggable-on"
+gem 'acts-as-taggable-on', '~> 3.4'
# Background jobs
gem 'slim'
diff --git a/Gemfile.lock b/Gemfile.lock
index 7da4d3c3583..ed8663b358b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -33,8 +33,8 @@ GEM
minitest (~> 5.1)
thread_safe (~> 0.1)
tzinfo (~> 1.1)
- acts-as-taggable-on (2.4.1)
- rails (>= 3, < 5)
+ acts-as-taggable-on (3.5.0)
+ activerecord (>= 3.2, < 5)
addressable (2.3.5)
annotate (2.6.0)
activerecord (>= 2.3.0)
@@ -212,7 +212,7 @@ GEM
mime-types (~> 1.19)
gitlab_emoji (0.1.0)
gemojione (~> 2.0)
- gitlab_git (7.1.2)
+ gitlab_git (7.1.3)
activesupport (~> 4.0)
charlock_holmes (~> 0.6)
gitlab-linguist (~> 3.0)
@@ -662,7 +662,7 @@ PLATFORMS
DEPENDENCIES
RedCloth
ace-rails-ap
- acts-as-taggable-on
+ acts-as-taggable-on (~> 3.4)
addressable
annotate (~> 2.6.0.beta2)
asana (~> 0.0.6)
@@ -703,7 +703,7 @@ DEPENDENCIES
gitlab-grack (~> 2.0.0.rc2)
gitlab-linguist (~> 3.0.1)
gitlab_emoji (~> 0.1)
- gitlab_git (~> 7.1.2)
+ gitlab_git (~> 7.1.3)
gitlab_meta (= 7.0)
gitlab_omniauth-ldap (= 1.2.1)
gollum-lib (~> 4.0.2)
diff --git a/LICENSE b/LICENSE
index d11b8730bf1..d8cb29f3638 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2011-2014 GitLab B.V.
+Copyright (c) 2011-2015 GitLab B.V.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee
index 37b7ba2cc10..44d75bd694f 100644
--- a/app/assets/javascripts/calendar.js.coffee
+++ b/app/assets/javascripts/calendar.js.coffee
@@ -20,9 +20,9 @@ class @Calendar
position: "top"
legend: [
0
- 1
- 4
- 7
+ 10
+ 20
+ 30
]
legendCellPadding: 3
onClick: (date, count) ->
diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee
index c366c98cf54..6dfe10f0006 100644
--- a/app/assets/javascripts/notes.js.coffee
+++ b/app/assets/javascripts/notes.js.coffee
@@ -37,7 +37,8 @@ class @Notes
$(document).on "click", ".js-note-attachment-delete", @removeAttachment
# reset main target form after submit
- $(document).on "ajax:complete", ".js-main-target-form", @resetMainTargetForm
+ $(document).on "ajax:complete", ".js-main-target-form", @reenableTargetFormSubmitButton
+ $(document).on "ajax:success", ".js-main-target-form", @resetMainTargetForm
# update the file name when an attachment is selected
$(document).on "change", ".js-note-attachment-input", @updateFormAttachment
@@ -57,6 +58,7 @@ class @Notes
@notes_forms = '.js-main-target-form textarea, .js-discussion-note-form textarea'
# Chrome doesn't fire keypress or keyup for Command+Enter, so we need keydown.
$(document).on('keydown', @notes_forms, (e) ->
+ return if e.originalEvent.repeat
if e.keyCode == 10 || ((e.metaKey || e.ctrlKey) && e.keyCode == 13)
$(@).parents('form').submit()
)
@@ -70,6 +72,7 @@ class @Notes
$(document).off "click", ".js-note-delete"
$(document).off "click", ".js-note-attachment-delete"
$(document).off "ajax:complete", ".js-main-target-form"
+ $(document).off "ajax:success", ".js-main-target-form"
$(document).off "click", ".js-discussion-reply-button"
$(document).off "click", ".js-add-diff-note-button"
$(document).off "visibilitychange"
@@ -169,6 +172,11 @@ class @Notes
form.find(".js-note-text").data("autosave").reset()
+ reenableTargetFormSubmitButton: ->
+ form = $(".js-main-target-form")
+
+ form.find(".js-note-text").trigger "input"
+
###
Shows the main form and does some setup on it.
diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee
index 7febcba0e94..2e3f5608257 100644
--- a/app/assets/javascripts/sidebar.js.coffee
+++ b/app/assets/javascripts/sidebar.js.coffee
@@ -3,12 +3,7 @@ $(document).on("click", '.toggle-nav-collapse', (e) ->
collapsed = 'page-sidebar-collapsed'
expanded = 'page-sidebar-expanded'
- if $('.page-with-sidebar').hasClass(collapsed)
- $('.page-with-sidebar').removeClass(collapsed).addClass(expanded)
- $('.toggle-nav-collapse i').removeClass('fa-angle-right').addClass('fa-angle-left')
- $.cookie("collapsed_nav", "false", { path: '/' })
- else
- $('.page-with-sidebar').removeClass(expanded).addClass(collapsed)
- $('.toggle-nav-collapse i').removeClass('fa-angle-left').addClass('fa-angle-right')
- $.cookie("collapsed_nav", "true", { path: '/' })
+ $('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}")
+ $('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
+ $.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
)
diff --git a/app/assets/stylesheets/generic/filters.scss b/app/assets/stylesheets/generic/filters.scss
new file mode 100644
index 00000000000..bd93a79722d
--- /dev/null
+++ b/app/assets/stylesheets/generic/filters.scss
@@ -0,0 +1,55 @@
+.filter-item {
+ margin-right: 15px;
+}
+
+.issues-state-filters {
+ li.active a {
+ border-color: #DDD !important;
+
+ &, &:hover, &:active, &.active {
+ background: #f5f5f5 !important;
+ border-bottom: 1px solid #f5f5f5 !important;
+ }
+ }
+}
+
+.issues-details-filters {
+ font-size: 13px;
+ background: #f5f5f5;
+ margin: -10px 0;
+ padding: 10px 15px;
+ margin-top: -15px;
+ border-left: 1px solid #DDD;
+ border-right: 1px solid #DDD;
+
+ .btn {
+ font-size: 13px;
+ }
+}
+
+@media (min-width: 800px) {
+ .issues-filters,
+ .issues_bulk_update {
+ select, .select2-container {
+ width: 120px !important;
+ display: inline-block;
+ }
+ }
+}
+
+@media (min-width: 1200px) {
+ .issues-filters,
+ .issues_bulk_update {
+ select, .select2-container {
+ width: 150px !important;
+ display: inline-block;
+ }
+ }
+}
+
+.issues-filters,
+.issues_bulk_update {
+ .select2-container .select2-choice {
+ color: #444 !important;
+ }
+}
diff --git a/app/assets/stylesheets/generic/mobile.scss b/app/assets/stylesheets/generic/mobile.scss
index 1b0e056216f..71a1fc4493f 100644
--- a/app/assets/stylesheets/generic/mobile.scss
+++ b/app/assets/stylesheets/generic/mobile.scss
@@ -24,13 +24,6 @@
display: none !important;
}
- .project-home-panel {
- .star-fork-buttons {
- padding-top: 10px;
- padding-right: 15px;
- }
- }
-
.project-home-links {
display: none;
}
diff --git a/app/assets/stylesheets/generic/selects.scss b/app/assets/stylesheets/generic/selects.scss
index 69613608c82..d8e0dc028d1 100644
--- a/app/assets/stylesheets/generic/selects.scss
+++ b/app/assets/stylesheets/generic/selects.scss
@@ -2,20 +2,25 @@
.select2-container, .select2-container.select2-drop-above {
.select2-choice {
background: #FFF;
- border-color: #CCC;
+ border-color: #DDD;
+ height: 34px;
padding: 6px 14px;
+ font-size: 14px;
line-height: 1.42857143;
- height: auto;
+
+ @include border-radius(4px);
.select2-arrow {
background: #FFF;
- border-left: 1px solid #DDD;
+ border-left: none;
+ padding-top: 3px;
}
}
}
.select2-container-multi .select2-choices {
- @include border-radius(4px)
+ @include border-radius(4px);
+ border-color: #CCC;
}
.select2-container-multi .select2-choices .select2-search-field input {
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 13e09d5596f..a640a4e2051 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -45,11 +45,3 @@
.btn { font-size: 13px; }
}
-
-.filter-item {
- margin-right: 15px;
-
- > span {
- margin-right: 4px;
- }
-}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 55e648a568f..cd86a9be8b2 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -41,12 +41,9 @@
}
.check-all-holder {
- height: 36px;
+ line-height: 36px;
float: left;
- margin-right: 12px;
- padding: 6px 15px;
- border: 1px solid #ccc;
- @include border-radius(4px);
+ margin-right: 15px;
}
.issues_content {
@@ -59,33 +56,6 @@
}
}
-@media (min-width: 800px) {
- .issues-filters,
- .issues_bulk_update {
- select, .select2-container {
- width: 120px !important;
- display: inline-block;
- }
- }
-}
-
-@media (min-width: 1200px) {
- .issues-filters,
- .issues_bulk_update {
- select, .select2-container {
- width: 140px !important;
- display: inline-block;
- }
- }
-}
-
-.issues-filters,
-.issues_bulk_update {
- .select2-container .select2-choice {
- color: #444 !important;
- }
-}
-
.participants {
margin-bottom: 20px;
}
@@ -123,12 +93,12 @@ form.edit-issue {
}
&.closed {
- background: #F5f5f5;
+ background: #F9F9F9;
border-color: #E5E5E5;
}
&.merged {
- background: #F5f5f5;
+ background: #F9F9F9;
border-color: #E5E5E5;
}
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 6d55a5fa66e..5bd725d1222 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -49,35 +49,20 @@
@extend .clearfix;
margin-bottom: 15px;
- .project-home-desc,
- .star-fork-buttons {
+ &.project-home-row-top {
+ margin-bottom: 15px;
+ }
+
+ .project-home-desc {
font-size: 16px;
line-height: 1.3;
+ margin-right: 215px;
}
.project-home-desc {
float: left;
color: #666;
}
-
- .star-fork-buttons {
- float: right;
- min-width: 200px;
- font-weight: bold;
-
- .star-buttons, .fork-buttons {
- float: right;
- margin-left: 20px;
-
- a:hover {
- text-decoration: none;
- }
-
- .count {
- margin-left: 5px;
- }
- }
- }
}
.visibility-level-label {
@@ -87,6 +72,27 @@
color: inherit;
}
}
+
+ .project-repo-buttons {
+ margin-top: -3px;
+ position: absolute;
+ right: 0;
+ width: 260px;
+ text-align: right;
+
+ .btn {
+ font-weight: bold;
+ font-size: 14px;
+ line-height: 16px;
+
+ .count {
+ padding-left: 10px;
+ border-left: 1px solid #ccc;
+ display: inline-block;
+ margin-left: 10px;
+ }
+ }
+ }
}
.project-home-links {
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 798d62b3a09..4ea838ca447 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -61,4 +61,12 @@ module BlobHelper
'Preview changes'
end
end
+
+ # Return an image icon depending on the file mode and extension
+ #
+ # mode - File unix mode
+ # mode - File name
+ def blob_icon(mode, name)
+ icon("#{file_type_icon_class('file', mode, name)} fw")
+ end
end
diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb
index 18260f0ed4d..187e21832f0 100644
--- a/app/helpers/icons_helper.rb
+++ b/app/helpers/icons_helper.rb
@@ -36,4 +36,48 @@ module IconsHelper
def private_icon
icon('lock')
end
+
+ def file_type_icon_class(type, mode, name)
+ if type == 'folder'
+ icon_class = 'folder'
+ elsif mode == 0120000
+ icon_class = 'share'
+ else
+ # Guess which icon to choose based on file extension.
+ # If you think a file extension is missing, feel free to add it on PR
+
+ case File.extname(name).downcase
+ when '.pdf'
+ icon_class = 'file-pdf-o'
+ when '.jpg', '.jpeg', '.jif', '.jfif',
+ '.jp2', '.jpx', '.j2k', '.j2c',
+ '.png', '.gif', '.tif', '.tiff',
+ '.svg', '.ico', '.bmp'
+ icon_class = 'file-image-o'
+ when '.zip', '.zipx', '.tar', '.gz', '.bz', '.bzip',
+ '.xz', '.rar', '.7z'
+ icon_class = 'file-archive-o'
+ when '.mp3', '.wma', '.ogg', '.oga', '.wav', '.flac', '.aac'
+ icon_class = 'file-audio-o'
+ when '.mp4', '.m4p', '.m4v',
+ '.mpg', '.mp2', '.mpeg', '.mpe', '.mpv',
+ '.mpg', '.mpeg', '.m2v',
+ '.avi', '.mkv', '.flv', '.ogv', '.mov',
+ '.3gp', '.3g2'
+ icon_class = 'file-video-o'
+ when '.doc', '.dot', '.docx', '.docm', '.dotx', '.dotm', '.docb'
+ icon_class = 'file-word-o'
+ when '.xls', '.xlt', '.xlm', '.xlsx', '.xlsm', '.xltx', '.xltm',
+ '.xlsb', '.xla', '.xlam', '.xll', '.xlw'
+ icon_class = 'file-excel-o'
+ when '.ppt', '.pot', '.pps', '.pptx', '.pptm', '.potx', '.potm',
+ '.ppam', '.ppsx', '.ppsm', '.sldx', '.sldm'
+ icon_class = 'file-powerpoint-o'
+ else
+ icon_class = 'file-text-o'
+ end
+ end
+
+ icon_class
+ end
end
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index aa98ead43f1..32ef2e7ca84 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -49,7 +49,6 @@ module LabelsHelper
end
def project_labels_options(project)
- options_for_select([['Any', nil]]) +
- options_from_collection_for_select(project.labels, 'name', 'name', params[:label_name])
+ options_from_collection_for_select(project.labels, 'name', 'name', params[:label_name])
end
end
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index e1dec3ec628..282bdf744d2 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -28,7 +28,6 @@ module MilestonesHelper
Milestone.where(project_id: @projects)
end.active
- options_for_select([['Any', nil]]) +
- options_from_collection_for_select(milestones, 'id', 'title', params[:milestone_id])
+ options_from_collection_for_select(milestones, 'id', 'title', params[:milestone_id])
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 7bf51b5b8e8..e3734023be3 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -80,17 +80,17 @@ module ProjectsHelper
@project.milestones.active.order("due_date, title ASC")
end
- def link_to_toggle_star(title, starred, signed_in)
- cls = 'star-btn'
- cls << ' disabled' unless signed_in
+ def link_to_toggle_star(title, starred)
+ cls = 'star-btn btn btn-sm btn-default'
+
+ toggle_text =
+ if starred
+ ' Unstar'
+ else
+ ' Star'
+ end
toggle_html = content_tag('span', class: 'toggle') do
- toggle_text = if starred
- ' Unstar'
- else
- ' Star'
- end
-
icon('star') + toggle_text
end
@@ -106,23 +106,25 @@ module ProjectsHelper
data: { type: 'json' }
}
+ path = toggle_star_namespace_project_path(@project.namespace, @project)
content_tag 'span', class: starred ? 'turn-on' : 'turn-off' do
- link_to(
- toggle_star_namespace_project_path(@project.namespace, @project),
- link_opts
- ) do
+ link_to(path, link_opts) do
toggle_html + ' ' + count_html
end
end
end
def link_to_toggle_fork
- out = icon('code-fork')
- out << ' Fork'
- out << content_tag(:span, class: 'count') do
+ html = content_tag('span') do
+ icon('code-fork') + ' Fork'
+ end
+
+ count_html = content_tag(:span, class: 'count') do
@project.forks_count.to_s
end
+
+ html + count_html
end
private
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index bf6726574ec..6dd9b6f017c 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -34,12 +34,13 @@ module TreeHelper
end
end
- # Return an image icon depending on the file type
+ # Return an image icon depending on the file type and mode
#
# type - String type of the tree item; either 'folder' or 'file'
- def tree_icon(type)
- icon_class = type == 'folder' ? 'folder' : 'file-o'
- icon(icon_class)
+ # mode - File unix mode
+ # name - File name
+ def tree_icon(type, mode, name)
+ icon("#{file_type_icon_class(type, mode, name)} fw")
end
def tree_hex_class(content)
diff --git a/app/views/groups/group_members/_new_group_member.html.haml b/app/views/groups/group_members/_new_group_member.html.haml
index c4c29bb2e8d..a52b8197384 100644
--- a/app/views/groups/group_members/_new_group_member.html.haml
+++ b/app/views/groups/group_members/_new_group_member.html.haml
@@ -1,7 +1,7 @@
= form_for @group_member, url: group_group_members_path(@group), html: { class: 'form-horizontal users-group-form' } do |f|
.form-group
= f.label :user_ids, "People", class: 'control-label'
- .col-sm-10= users_select_tag(:user_ids, multiple: true, class: 'input-large')
+ .col-sm-10= users_select_tag(:user_ids, multiple: true, class: 'input-large', scope: :all)
.form-group
= f.label :access_level, "Group Access", class: 'control-label'
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index a295a0d6cdc..5689bdee1c6 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -2,7 +2,7 @@
.project-home-panel{:class => ("empty-project" if empty_repo)}
.project-identicon-holder
= project_icon(@project, alt: '', class: 'avatar project-avatar')
- .project-home-row
+ .project-home-row.project-home-row-top
.project-home-desc
- if @project.description.present?
= escaped_autolink(@project.description)
@@ -14,31 +14,30 @@
&ndash;
= link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)) do
= readme.name
- .star-fork-buttons
+ .project-repo-buttons
+ .inline.star.js-toggler-container{class: @show_star ? 'on' : ''}
+ - if current_user
+ = link_to_toggle_star('Star this project.', false)
+ = link_to_toggle_star('Unstar this project.', true)
+ - else
+ = link_to new_user_session_path, class: 'btn star-btn has_tooltip', title: 'You must sign in to star a project' do
+ %span
+ = icon('star')
+ Star
+ %span.count
+ = @project.star_count
- unless @project.empty_repo?
- .fork-buttons
- - if current_user && can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
+ - if current_user && can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
+ .inline.fork-buttons.prepend-left-10
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
- = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork' do
+ = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-sm btn-default' do
= link_to_toggle_fork
- else
- = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project" do
+ = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-sm btn-default' do
= link_to_toggle_fork
- .star-buttons
- %span.star.js-toggler-container{class: @show_star ? 'on' : ''}
- - if current_user
- = link_to_toggle_star('Star this project.', false, true)
- = link_to_toggle_star('Unstar this project.', true, true)
- - else
- = link_to_toggle_star('You must sign in to star a project.', false, false)
-
.project-home-row.hidden-xs
- if current_user && !empty_repo
.project-home-dropdown
= render "dropdown"
- - unless @project.empty_repo?
- - if can? current_user, :download_code, @project
- .pull-right.prepend-left-10
- = render 'projects/repositories/download_archive', split_button: true
= render "shared/clone_panel"
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index ba60bd92869..65c3ab10e02 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -22,7 +22,7 @@
%div#tree-content-holder.tree-content-holder
%article.file-holder
.file-title
- %i.fa.fa-file
+ = blob_icon blob.mode, blob.name
%strong
= blob.name
%small
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index 2579f2cac92..3f645b81397 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -10,7 +10,8 @@
Download as
%span.caret
%ul.dropdown-menu
- %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch)
+ - unless @commit.parents.length > 1
+ %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch)
%li= link_to "Plain Diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff)
= link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-primary btn-grouped" do
%span Browse Code ยป
diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml
index 83e4d24cf5f..a714f5f79e0 100644
--- a/app/views/projects/commits/_head.html.haml
+++ b/app/views/projects/commits/_head.html.haml
@@ -1,6 +1,8 @@
%ul.nav.nav-tabs
= nav_link(controller: [:commit, :commits]) do
- = link_to 'Commits', namespace_project_commits_path(@project.namespace, @project, @repository.root_ref)
+ = link_to namespace_project_commits_path(@project.namespace, @project, @repository.root_ref) do
+ Commits
+ %span.badge= number_with_precision(@repository.commit_count, precision: 0, delimiter: ',')
= nav_link(controller: :compare) do
= link_to 'Compare', namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: @ref || @repository.root_ref)
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index 210b77a6b15..d3c7ae24a75 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -15,15 +15,5 @@
= render 'shared/issuable_filter'
- .clearfix
- .issues_bulk_update.hide
- = form_tag bulk_update_namespace_project_issues_path(@project.namespace, @project), method: :post do
- = select_tag('update[state_event]', options_for_select([['Open', 'reopen'], ['Closed', 'close']]), prompt: "Status", class: 'form-control')
- = users_select_tag('update[assignee_id]', placeholder: 'Assignee', null_user: true)
- = select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone")
- = hidden_field_tag 'update[issues_ids]', []
- = hidden_field_tag :state_event, params[:state_event]
- = button_tag "Update issues", class: "btn update_selected_issues btn-save"
-
.issues-holder
= render "issues"
diff --git a/app/views/projects/merge_requests/show/_state_widget.html.haml b/app/views/projects/merge_requests/show/_state_widget.html.haml
index a4f2a890969..44bd9347f51 100644
--- a/app/views/projects/merge_requests/show/_state_widget.html.haml
+++ b/app/views/projects/merge_requests/show/_state_widget.html.haml
@@ -29,7 +29,7 @@
%h4
Merge in progress...
%p
- GitLab tries to merge it right now. During this time merge request is locked and can not be closed.
+ Merging is in progress. While merging this request is locked and cannot be closed.
- unless @commits.any?
%h4 Nothing to merge
diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml
index 26669fb00a9..1ba7a1f2060 100644
--- a/app/views/projects/repositories/_download_archive.html.haml
+++ b/app/views/projects/repositories/_download_archive.html.haml
@@ -3,10 +3,10 @@
- split_button = split_button || false
- if split_button == true
%span.btn-group{class: btn_class}
- = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn', rel: 'nofollow' do
+ = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn btn-sm', rel: 'nofollow' do
%i.fa.fa-download
%span Download zip
- %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' }
+ %a.btn-sm.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' }
%span.caret
%span.sr-only
Select Archive Format
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index cfa6f558dd6..85113ffa7e2 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -68,7 +68,7 @@
= link_to license_url(@project), class: 'btn btn-block' do
View license
- .prepend-top-10
+ .prepend-top-10.append-bottom-10
%p
%span.light Created on
#{@project.created_at.stamp('Aug 22, 2013')}
@@ -79,8 +79,16 @@
- else
#{link_to @project.owner_name, @project.owner}
+ - unless @project.empty_repo?
+ - if can? current_user, :download_code, @project
+ %hr
+ .prepend-top-10.append-bottom-10
+ = render 'projects/repositories/download_archive', split_button: true
+
+ .prepend-top-10
- @project.ci_services.each do |ci_service|
- if ci_service.active? && ci_service.respond_to?(:builds_path)
+ %hr
- if ci_service.respond_to?(:status_img_path)
= link_to ci_service.builds_path, :'data-no-turbolink' => 'data-no-turbolink' do
= image_tag ci_service.status_img_path, alt: "build status"
@@ -97,4 +105,3 @@
= readme.name
.wiki
= render_readme(readme)
-
diff --git a/app/views/projects/tree/_blob_item.html.haml b/app/views/projects/tree/_blob_item.html.haml
index b253fe896e3..02ecbade219 100644
--- a/app/views/projects/tree/_blob_item.html.haml
+++ b/app/views/projects/tree/_blob_item.html.haml
@@ -1,6 +1,6 @@
%tr{ class: "tree-item #{tree_hex_class(blob_item)}" }
%td.tree-item-file-name
- = tree_icon(type)
+ = tree_icon(type, blob_item.mode, blob_item.name)
%span.str-truncated
= link_to blob_item.name, namespace_project_blob_path(@project.namespace, @project, tree_join(@id || @commit.id, blob_item.name))
%td.tree_time_ago.cgray
diff --git a/app/views/projects/tree/_submodule_item.html.haml b/app/views/projects/tree/_submodule_item.html.haml
index 20c70cac699..2b5f671c09e 100644
--- a/app/views/projects/tree/_submodule_item.html.haml
+++ b/app/views/projects/tree/_submodule_item.html.haml
@@ -1,6 +1,6 @@
%tr{ class: "tree-item" }
%td.tree-item-file-name
- %i.fa.fa-archive
+ %i.fa.fa-archive.fa-fw
= submodule_link(submodule_item, @ref)
%td
%td.hidden-xs
diff --git a/app/views/projects/tree/_tree_item.html.haml b/app/views/projects/tree/_tree_item.html.haml
index 94342bc9b2b..e87138bf980 100644
--- a/app/views/projects/tree/_tree_item.html.haml
+++ b/app/views/projects/tree/_tree_item.html.haml
@@ -1,6 +1,6 @@
%tr{ class: "tree-item #{tree_hex_class(tree_item)}" }
%td.tree-item-file-name
- = tree_icon(type)
+ = tree_icon(type, tree_item.mode, tree_item.name)
%span.str-truncated
- path = flatten_tree(tree_item)
= link_to path, namespace_project_tree_path(@project.namespace, @project, tree_join(@id || @commit.id, path))
diff --git a/app/views/shared/_issuable_filter.html.haml b/app/views/shared/_issuable_filter.html.haml
index 686a3389bb4..f169733f2e9 100644
--- a/app/views/shared/_issuable_filter.html.haml
+++ b/app/views/shared/_issuable_filter.html.haml
@@ -14,7 +14,7 @@
%i.fa.fa-compass
All
- %div
+ .issues-details-filters
= form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_id, :label_name]), method: :get, class: 'filter-form' do
- if controller.controller_name == 'issues'
.check-all-holder
@@ -23,39 +23,33 @@
disabled: !can?(current_user, :modify_issue, @project)
.issues-other-filters
.filter-item.inline
- %span.light
- %i.fa.fa-user
- Assignee
- %strong
- = users_select_tag(:assignee_id, selected: params[:assignee_id],
- placeholder: 'Any', class: 'trigger-submit', any_user: true, null_user: true)
+ = users_select_tag(:assignee_id, selected: params[:assignee_id],
+ placeholder: 'Assignee', class: 'trigger-submit', any_user: true, null_user: true)
.filter-item.inline
- %span.light
- %i.fa.fa-user
- Author
- %strong
- = users_select_tag(:author_id, selected: params[:author_id],
- placeholder: 'Any', class: 'trigger-submit', any_user: true)
+ = users_select_tag(:author_id, selected: params[:author_id],
+ placeholder: 'Author', class: 'trigger-submit', any_user: true)
- .filter-item.inline
- %span.light
- %i.fa.fa-clock-o
- Milestone
- %strong
- = select_tag('milestone_id', projects_milestones_options, class: "select2 trigger-submit")
+ .filter-item.inline.milestone-filter
+ = select_tag('milestone_id', projects_milestones_options, class: "select2 trigger-submit", prompt: 'Milestone')
- if @project
- .filter-item.inline
- %span.light
- %i.fa.fa-tag
- Label
- %strong
- = select_tag('label_name', project_labels_options(@project), class: "select2 trigger-submit")
+ .filter-item.inline.labels-filter
+ = select_tag('label_name', project_labels_options(@project), class: "select2 trigger-submit", prompt: 'Label')
.pull-right
= render 'shared/sort_dropdown'
+ - if controller.controller_name == 'issues'
+ .issues_bulk_update.hide
+ = form_tag bulk_update_namespace_project_issues_path(@project.namespace, @project), method: :post do
+ = select_tag('update[state_event]', options_for_select([['Open', 'reopen'], ['Closed', 'close']]), prompt: "Status", class: 'form-control')
+ = users_select_tag('update[assignee_id]', placeholder: 'Assignee', null_user: true)
+ = select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone")
+ = hidden_field_tag 'update[issues_ids]', []
+ = hidden_field_tag :state_event, params[:state_event]
+ = button_tag "Update issues", class: "btn update_selected_issues btn-save"
+
:coffeescript
new UsersSelect()
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index c4a0fefb7ab..3f1ca34a667 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -2,6 +2,11 @@
# GitLab application config file #
# # # # # # # # # # # # # # # # # #
#
+########################### NOTE #####################################
+# This file should not receive new settings. All configuration options #
+# are being moved to ApplicationSetting model! #
+########################################################################
+#
# How to use:
# 1. Copy file as gitlab.yml
# 2. Update gitlab -> host with your fully qualified domain name
@@ -81,35 +86,6 @@ production: &base
# The default is 'tmp/repositories' relative to the root of the Rails app.
# repository_downloads_path: tmp/repositories
- ## External issues trackers
- issues_tracker:
- # redmine:
- # title: "Redmine"
- # ## If not nil, link 'Issues' on project page will be replaced with this
- # ## Use placeholders:
- # ## :project_id - GitLab project identifier
- # ## :issues_tracker_id - Project Name or Id in external issue tracker
- # project_url: "http://redmine.sample/projects/:issues_tracker_id"
- #
- # ## If not nil, links from /#\d/ entities from commit messages will replaced with this
- # ## Use placeholders:
- # ## :project_id - GitLab project identifier
- # ## :issues_tracker_id - Project Name or Id in external issue tracker
- # ## :id - Issue id (from commit messages)
- # issues_url: "http://redmine.sample/issues/:id"
- #
- # ## If not nil, links to creating new issues will be replaced with this
- # ## Use placeholders:
- # ## :project_id - GitLab project identifier
- # ## :issues_tracker_id - Project Name or Id in external issue tracker
- # new_issue_url: "http://redmine.sample/projects/:issues_tracker_id/issues/new"
- #
- # jira:
- # title: "Atlassian Jira"
- # project_url: "http://jira.sample/issues/?jql=project=:issues_tracker_id"
- # issues_url: "http://jira.sample/browse/:id"
- # new_issue_url: "http://jira.sample/secure/CreateIssue.jspa"
-
## Gravatar
## For Libravatar see: http://doc.gitlab.com/ce/customization/libravatar.html
gravatar:
diff --git a/config/initializers/acts_as_taggable_on_patch.rb b/config/initializers/acts_as_taggable_on_patch.rb
deleted file mode 100644
index 0d535cb5cac..00000000000
--- a/config/initializers/acts_as_taggable_on_patch.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-# This is a patch to address the issue in https://github.com/mbleigh/acts-as-taggable-on/issues/427 caused by
-# https://github.com/rails/rails/commit/31a43ebc107fbd50e7e62567e5208a05909ec76c
-# gem 'acts-as-taggable-on' has the fix included https://github.com/mbleigh/acts-as-taggable-on/commit/89bbed3864a9252276fb8dd7d535fce280454b90
-# but not in the currently used version of gem ('2.4.1')
-# With replacement of 'acts-as-taggable-on' gem this file will become obsolete
-
-module ActsAsTaggableOn::Taggable
- module Core
- module ClassMethods
- def tagged_with(tags, options = {})
- tag_list = ActsAsTaggableOn::TagList.from(tags)
- empty_result = where("1 = 0")
-
- return empty_result if tag_list.empty?
-
- joins = []
- conditions = []
- having = []
- select_clause = []
-
- context = options.delete(:on)
- owned_by = options.delete(:owned_by)
- alias_base_name = undecorated_table_name.gsub('.','_')
- quote = ActsAsTaggableOn::Tag.using_postgresql? ? '"' : ''
-
- if options.delete(:exclude)
- if options.delete(:wild)
- tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ? ESCAPE '!'", "%#{escape_like(t)}%"]) }.join(" OR ")
- else
- tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ?", t]) }.join(" OR ")
- end
-
- conditions << "#{table_name}.#{primary_key} NOT IN (SELECT #{ActsAsTaggableOn::Tagging.table_name}.taggable_id FROM #{ActsAsTaggableOn::Tagging.table_name} JOIN #{ActsAsTaggableOn::Tag.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key} AND (#{tags_conditions}) WHERE #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name, nil)})"
-
- if owned_by
- joins << "JOIN #{ActsAsTaggableOn::Tagging.table_name}" +
- " ON #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
- " AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name, nil)}" +
- " AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_id = #{owned_by.id}" +
- " AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_type = #{quote_value(owned_by.class.base_class.to_s, nil)}"
- end
-
- elsif options.delete(:any)
- # get tags, drop out if nothing returned (we need at least one)
- tags =
- if options.delete(:wild)
- ActsAsTaggableOn::Tag.named_like_any(tag_list)
- else
- ActsAsTaggableOn::Tag.named_any(tag_list)
- end
-
- return empty_result unless tags.length > 0
-
- # setup taggings alias so we can chain, ex: items_locations_taggings_awesome_cool_123
- # avoid ambiguous column name
- taggings_context = context ? "_#{context}" : ''
-
- taggings_alias = adjust_taggings_alias(
- "#{alias_base_name[0..4]}#{taggings_context[0..6]}_taggings_#{sha_prefix(tags.map(&:name).join('_'))}"
- )
-
- tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
- " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
- " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}"
- tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
-
- # don't need to sanitize sql, map all ids and join with OR logic
- conditions << tags.map { |t| "#{taggings_alias}.tag_id = #{t.id}" }.join(" OR ")
- select_clause = "DISTINCT #{table_name}.*" unless context and tag_types.one?
-
- if owned_by
- tagging_join << " AND " +
- sanitize_sql([
- "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
- owned_by.id,
- owned_by.class.base_class.to_s
- ])
- end
-
- joins << tagging_join
- else
- tags = ActsAsTaggableOn::Tag.named_any(tag_list)
-
- return empty_result unless tags.length == tag_list.length
-
- tags.each do |tag|
- taggings_alias = adjust_taggings_alias("#{alias_base_name[0..11]}_taggings_#{sha_prefix(tag.name)}")
- tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
- " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
- " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}" +
- " AND #{taggings_alias}.tag_id = #{tag.id}"
-
- tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
-
- if owned_by
- tagging_join << " AND " +
- sanitize_sql([
- "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
- owned_by.id,
- owned_by.class.base_class.to_s
- ])
- end
-
- joins << tagging_join
- end
- end
-
- taggings_alias, tags_alias = adjust_taggings_alias("#{alias_base_name}_taggings_group"), "#{alias_base_name}_tags_group"
-
- if options.delete(:match_all)
- joins << "LEFT OUTER JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
- " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
- " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}"
-
-
- group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(self) : "#{table_name}.#{primary_key}"
- group = group_columns
- having = "COUNT(#{taggings_alias}.taggable_id) = #{tags.size}"
- end
-
- select(select_clause) \
- .joins(joins.join(" ")) \
- .where(conditions.join(" AND ")) \
- .group(group) \
- .having(having) \
- .order(options[:order]) \
- .readonly(false)
- end
- end
- end
-end
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index 66941521c2e..0acb15896d3 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -68,6 +68,6 @@ You can't add the same deploy key twice with the 'New Deploy Key' option.
If you want to add the same key to another project, please enable it in the
list that says 'Deploy keys from projects available to you'. All the deploy
keys of all the projects you have access to are available. This project
-access can happen through being a direct member of the projecti, or through
+access can happen through being a direct member of the project, or through
a group. See `def accessible_deploy_keys` in `app/models/user.rb` for more
information.
diff --git a/docker/Dockerfile b/docker/Dockerfile
index b228a66832a..f0a8b9f53df 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -11,7 +11,7 @@ RUN apt-get update -q \
# If the Omnibus package version below is outdated please contribute a merge request to update it.
# If you run GitLab Enterprise Edition point it to a location where you have downloaded it.
RUN TMP_FILE=$(mktemp); \
- wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.9.0-omnibus.2-1_amd64.deb \
+ wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.9.1-omnibus.1-1_amd64.deb \
&& dpkg -i $TMP_FILE \
&& rm -f $TMP_FILE
diff --git a/features/groups.feature b/features/groups.feature
index 05546e0d6ef..65d06a0daf9 100644
--- a/features/groups.feature
+++ b/features/groups.feature
@@ -47,6 +47,14 @@ Feature: Groups
Then I should not see group "Owned" avatar
And I should not see the "Remove avatar" button
+ @javascript
+ Scenario: Add user to group
+ Given gitlab user "Mike"
+ When I visit group "Owned" members page
+ And I click link "Add members"
+ When I select "Mike" as "Reporter"
+ Then I should see "Mike" in team list as "Reporter"
+
# Leave
@javascript
diff --git a/features/project/star.feature b/features/project/star.feature
index 3322f891805..a45f9c470ea 100644
--- a/features/project/star.feature
+++ b/features/project/star.feature
@@ -13,7 +13,7 @@ Feature: Project Star
Given public project "Community"
And I visit project "Community" page
When I click on the star toggle button
- Then The project has 0 stars
+ Then I redirected to sign in page
@javascript
Scenario: Signed in users can toggle star
diff --git a/features/steps/groups.rb b/features/steps/groups.rb
index 91921f5e21c..ec5213e4b93 100644
--- a/features/steps/groups.rb
+++ b/features/steps/groups.rb
@@ -5,6 +5,32 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
include SharedUser
include Select2Helper
+ step 'gitlab user "Mike"' do
+ create(:user, name: "Mike")
+ end
+
+ step 'I click link "Add members"' do
+ find(:css, 'button.btn-new').click
+ end
+
+ step 'I select "Mike" as "Reporter"' do
+ user = User.find_by(name: "Mike")
+
+ within ".users-group-form" do
+ select2(user.id, from: "#user_ids", multiple: true)
+ select "Reporter", from: "access_level"
+ end
+
+ click_button "Add users to group"
+ end
+
+ step 'I should see "Mike" in team list as "Reporter"' do
+ within '.well-list' do
+ page.should have_content('Mike')
+ page.should have_content('Reporter')
+ end
+ end
+
step 'I should see group "Owned" projects list' do
Group.find_by(name: "Owned").projects.each do |project|
page.should have_link project.name
diff --git a/features/steps/project/star.rb b/features/steps/project/star.rb
index ae2e4c7a201..50cdfd73c34 100644
--- a/features/steps/project/star.rb
+++ b/features/steps/project/star.rb
@@ -22,12 +22,16 @@ class Spinach::Features::ProjectStar < Spinach::FeatureSteps
# Requires @javascript
step "I click on the star toggle button" do
- find(".star .toggle", visible: true).click
+ find(".star-btn", visible: true).click
+ end
+
+ step 'I redirected to sign in page' do
+ current_path.should == new_user_session_path
end
protected
def has_n_stars(n)
- expect(page).to have_css(".star .count", text: /^#{n}$/, visible: true)
+ expect(page).to have_css(".star-btn .count", text: n, visible: true)
end
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 83f65eec6cc..e3fff79d68f 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -88,17 +88,14 @@ module API
present user_project, with: Entities::ProjectWithAccess, user: current_user
end
- # Get a single project events
+ # Get events for a single project
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# GET /projects/:id/events
get ":id/events" do
- limit = (params[:per_page] || 20).to_i
- offset = (params[:page] || 0).to_i * limit
- events = user_project.events.recent.limit(limit).offset(offset)
-
+ events = paginate user_project.events.recent
present events, with: Entities::Event
end
diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake
index b4076f8238f..b4c0ae3ff79 100644
--- a/lib/tasks/gitlab/test.rake
+++ b/lib/tasks/gitlab/test.rake
@@ -2,6 +2,7 @@ namespace :gitlab do
desc "GITLAB | Run all tests"
task :test do
cmds = [
+ %W(rake brakeman),
%W(rake rubocop),
%W(rake spinach),
%W(rake spec),
diff --git a/spec/helpers/icons_helper_spec.rb b/spec/helpers/icons_helper_spec.rb
new file mode 100644
index 00000000000..0b1cf07b7b0
--- /dev/null
+++ b/spec/helpers/icons_helper_spec.rb
@@ -0,0 +1,109 @@
+require 'spec_helper'
+
+describe IconsHelper do
+ describe 'file_type_icon_class' do
+ it 'returns folder class' do
+ expect(file_type_icon_class('folder', 0, 'folder_name')).to eq 'folder'
+ end
+
+ it 'returns share class' do
+ expect(file_type_icon_class('file', 0120000, 'link')).to eq 'share'
+ end
+
+ it 'returns file-pdf-o class with .pdf' do
+ expect(file_type_icon_class('file', 0, 'filename.pdf')).to eq 'file-pdf-o'
+ end
+
+ it 'returns file-image-o class with .jpg' do
+ expect(file_type_icon_class('file', 0, 'filename.jpg')).to eq 'file-image-o'
+ end
+
+ it 'returns file-image-o class with .JPG' do
+ expect(file_type_icon_class('file', 0, 'filename.JPG')).to eq 'file-image-o'
+ end
+
+ it 'returns file-image-o class with .png' do
+ expect(file_type_icon_class('file', 0, 'filename.png')).to eq 'file-image-o'
+ end
+
+ it 'returns file-archive-o class with .tar' do
+ expect(file_type_icon_class('file', 0, 'filename.tar')).to eq 'file-archive-o'
+ end
+
+ it 'returns file-archive-o class with .TAR' do
+ expect(file_type_icon_class('file', 0, 'filename.TAR')).to eq 'file-archive-o'
+ end
+
+ it 'returns file-archive-o class with .tar.gz' do
+ expect(file_type_icon_class('file', 0, 'filename.tar.gz')).to eq 'file-archive-o'
+ end
+
+ it 'returns file-audio-o class with .mp3' do
+ expect(file_type_icon_class('file', 0, 'filename.mp3')).to eq 'file-audio-o'
+ end
+
+ it 'returns file-audio-o class with .MP3' do
+ expect(file_type_icon_class('file', 0, 'filename.MP3')).to eq 'file-audio-o'
+ end
+
+ it 'returns file-audio-o class with .wav' do
+ expect(file_type_icon_class('file', 0, 'filename.wav')).to eq 'file-audio-o'
+ end
+
+ it 'returns file-video-o class with .avi' do
+ expect(file_type_icon_class('file', 0, 'filename.avi')).to eq 'file-video-o'
+ end
+
+ it 'returns file-video-o class with .AVI' do
+ expect(file_type_icon_class('file', 0, 'filename.AVI')).to eq 'file-video-o'
+ end
+
+ it 'returns file-video-o class with .mp4' do
+ expect(file_type_icon_class('file', 0, 'filename.mp4')).to eq 'file-video-o'
+ end
+
+ it 'returns file-word-o class with .doc' do
+ expect(file_type_icon_class('file', 0, 'filename.doc')).to eq 'file-word-o'
+ end
+
+ it 'returns file-word-o class with .DOC' do
+ expect(file_type_icon_class('file', 0, 'filename.DOC')).to eq 'file-word-o'
+ end
+
+ it 'returns file-word-o class with .docx' do
+ expect(file_type_icon_class('file', 0, 'filename.docx')).to eq 'file-word-o'
+ end
+
+ it 'returns file-excel-o class with .xls' do
+ expect(file_type_icon_class('file', 0, 'filename.xls')).to eq 'file-excel-o'
+ end
+
+ it 'returns file-excel-o class with .XLS' do
+ expect(file_type_icon_class('file', 0, 'filename.XLS')).to eq 'file-excel-o'
+ end
+
+ it 'returns file-excel-o class with .xlsx' do
+ expect(file_type_icon_class('file', 0, 'filename.xlsx')).to eq 'file-excel-o'
+ end
+
+ it 'returns file-excel-o class with .ppt' do
+ expect(file_type_icon_class('file', 0, 'filename.ppt')).to eq 'file-powerpoint-o'
+ end
+
+ it 'returns file-excel-o class with .PPT' do
+ expect(file_type_icon_class('file', 0, 'filename.PPT')).to eq 'file-powerpoint-o'
+ end
+
+ it 'returns file-excel-o class with .pptx' do
+ expect(file_type_icon_class('file', 0, 'filename.pptx')).to eq 'file-powerpoint-o'
+ end
+
+ it 'returns file-text-o class with .unknow' do
+ expect(file_type_icon_class('file', 0, 'filename.unknow')).to eq 'file-text-o'
+ end
+
+ it 'returns file-text-o class with no extension' do
+ expect(file_type_icon_class('file', 0, 'CHANGELOG')).to eq 'file-text-o'
+ end
+ end
+end
diff --git a/spec/models/asana_service_spec.rb b/spec/models/project_services/asana_service_spec.rb
index 13c8d54a2af..13c8d54a2af 100644
--- a/spec/models/asana_service_spec.rb
+++ b/spec/models/project_services/asana_service_spec.rb
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index eaec2198dc8..53ccaa4fd67 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -44,3 +44,5 @@ RSpec.configure do |config|
TestEnv.init
end
end
+
+ActiveRecord::Migration.maintain_test_schema!
diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb
index f869488d8d8..44d70e741b2 100644
--- a/spec/support/test_env.rb
+++ b/spec/support/test_env.rb
@@ -85,7 +85,7 @@ module TestEnv
end
# We must copy bare repositories because we will push to them.
- system(*%W(git clone -q --bare #{factory_repo_path} #{factory_repo_path_bare}))
+ system(git_env, *%W(git clone -q --bare #{factory_repo_path} #{factory_repo_path_bare}))
end
def copy_repo(project)
@@ -113,4 +113,10 @@ module TestEnv
def factory_repo_name
'gitlab-test'
end
+
+ # Prevent developer git configurations from being persisted to test
+ # repositories
+ def git_env
+ {'GIT_TEMPLATE_DIR' => ''}
+ end
end