Commit 29611a24 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq

Conflicts:
	GITLAB_SHELL_VERSION
	VERSION
	lib/api/entities.rb
	lib/api/groups.rb
parents c847e6a6 5555c4d9
v 7.9.0 (unreleased)
- Fix broken access control for note attachments (Hannes Rosenögger)
v 7.8.0 (unreleased) v 7.8.0 (unreleased)
- Replace highlight.js with rouge-fork rugments (Stefan Tatschner) - Replace highlight.js with rouge-fork rugments (Stefan Tatschner)
- Make project search case insensitive (Hannes Rosenögger) - Make project search case insensitive (Hannes Rosenögger)
...@@ -56,6 +59,10 @@ v 7.8.0 (unreleased) ...@@ -56,6 +59,10 @@ v 7.8.0 (unreleased)
- Show users button to share their newly created public or internal projects on twitter - Show users button to share their newly created public or internal projects on twitter
- Add quick help links to the GitLab pricing and feature comparison pages. - Add quick help links to the GitLab pricing and feature comparison pages.
- Fix duplicate authorized applications in user profile and incorrect application client count in admin area. - Fix duplicate authorized applications in user profile and incorrect application client count in admin area.
- Make sure Markdown previews always use the same styling as the eventual destination.
- Remove deprecated Group#owner_id from API
- Show projects user contributed to on user page. Show stars near project on user page.
- Improve database performance for GitLab
v 7.7.2 v 7.7.2
- Update GitLab Shell to version 2.4.2 that fixes a bug when developers can push to protected branch - Update GitLab Shell to version 2.4.2 that fixes a bug when developers can push to protected branch
......
...@@ -71,7 +71,7 @@ Thanks for the issue report. Please reformat your issue to conform to the issue ...@@ -71,7 +71,7 @@ Thanks for the issue report. Please reformat your issue to conform to the issue
### Feature requests ### Feature requests
Thank you for your interest in improving GitLab. We don't use the issue tracker for feature requests. Things that are wrong but are not a regression compared to older versions of GitLab are considered feature requests and not issues. Please use the [feature request forum](http://feedback.gitlab.com/) for this purpose or create a merge request implementing this feature. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information. Thank you for your interest in improving GitLab. We don't use the issue tracker for feature requests. Things that are wrong but are not a regression compared to older versions of GitLab are considered feature requests and not issues. Please use the \[feature request forum\]\(http://feedback.gitlab.com/) for this purpose or create a merge request implementing this feature. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information.
### Issue report for old version ### Issue report for old version
......
7.8.0.pre-ee 7.9.0.pre-ee
...@@ -15,3 +15,9 @@ class @Issue ...@@ -15,3 +15,9 @@ class @Issue
"issue" "issue"
updateTaskState updateTaskState
) )
$('.issuable-affix').affix offset:
top: ->
@top = $('.issue-details').outerHeight(true) + 25
bottom: ->
@bottom = $('.footer').outerHeight(true)
...@@ -20,6 +20,12 @@ class @MergeRequest ...@@ -20,6 +20,12 @@ class @MergeRequest
if $("a.btn-close").length if $("a.btn-close").length
$("li.task-list-item input:checkbox").prop("disabled", false) $("li.task-list-item input:checkbox").prop("disabled", false)
$('.issuable-affix').affix offset:
top: ->
@top = $('.merge-request-details').outerHeight(true) + 70
bottom: ->
@bottom = $('.footer').outerHeight(true)
# Local jQuery finder # Local jQuery finder
$: (selector) -> $: (selector) ->
this.$el.find(selector) this.$el.find(selector)
......
...@@ -272,7 +272,7 @@ class @Notes ...@@ -272,7 +272,7 @@ class @Notes
note_li = $(".note-row-" + note.id) note_li = $(".note-row-" + note.id)
note_li.replaceWith(note.html) note_li.replaceWith(note.html)
note_li.find('.note-edit-form').hide() note_li.find('.note-edit-form').hide()
note_li.find('.note-text').show() note_li.find('.note-body > .note-text').show()
### ###
Called in response to clicking the edit note link Called in response to clicking the edit note link
...@@ -284,7 +284,7 @@ class @Notes ...@@ -284,7 +284,7 @@ class @Notes
showEditForm: (e) -> showEditForm: (e) ->
e.preventDefault() e.preventDefault()
note = $(this).closest(".note") note = $(this).closest(".note")
note.find(".note-text").hide() note.find(".note-body > .note-text").hide()
note.find(".note-header").hide() note.find(".note-header").hide()
base_form = note.find(".note-edit-form") base_form = note.find(".note-edit-form")
form = base_form.clone().insertAfter(base_form) form = base_form.clone().insertAfter(base_form)
...@@ -311,7 +311,7 @@ class @Notes ...@@ -311,7 +311,7 @@ class @Notes
cancelEdit: (e) -> cancelEdit: (e) ->
e.preventDefault() e.preventDefault()
note = $(this).closest(".note") note = $(this).closest(".note")
note.find(".note-text").show() note.find(".note-body > .note-text").show()
note.find(".note-header").show() note.find(".note-header").show()
note.find(".current-note-edit-form").remove() note.find(".current-note-edit-form").remove()
...@@ -345,7 +345,7 @@ class @Notes ...@@ -345,7 +345,7 @@ class @Notes
removeAttachment: -> removeAttachment: ->
note = $(this).closest(".note") note = $(this).closest(".note")
note.find(".note-attachment").remove() note.find(".note-attachment").remove()
note.find(".note-text").show() note.find(".note-body > .note-text").show()
note.find(".js-note-attachment-delete").hide() note.find(".js-note-attachment-delete").hide()
note.find(".note-edit-form").hide() note.find(".note-edit-form").hide()
......
...@@ -120,6 +120,15 @@ ...@@ -120,6 +120,15 @@
} }
} }
.dash-new-group {
background: $bg_success;
border: 1px solid $border_success;
a {
color: #FFF;
}
}
.dash-list .str-truncated { .dash-list .str-truncated {
max-width: 72%; max-width: 72%;
} }
@media (max-width: $screen-sm-max) {
.issuable-affix {
margin-top: 20px;
}
}
@media (max-width: $screen-md-max) {
.issuable-affix {
position: static;
}
}
@media (min-width: $screen-md-max) {
.issuable-affix {
&.affix-top {
position: static;
}
&.affix {
position: fixed;
top: 70px;
width: 220px;
}
}
}
...@@ -94,8 +94,15 @@ ...@@ -94,8 +94,15 @@
} }
} }
.issue-show-labels .color-label { .issue-show-labels {
padding: 6px 10px; a {
margin-right: 5px;
margin-bottom: 5px;
display: inline-block;
.color-label {
padding: 6px 10px;
}
}
} }
form.edit-issue { form.edit-issue {
......
...@@ -185,6 +185,13 @@ ...@@ -185,6 +185,13 @@
} }
} }
.merge-request-show-labels .label { .merge-request-show-labels {
padding: 6px 10px; a {
margin-right: 5px;
margin-bottom: 5px;
display: inline-block;
.color-label {
padding: 6px 10px;
}
}
} }
...@@ -12,11 +12,7 @@ class DashboardController < ApplicationController ...@@ -12,11 +12,7 @@ class DashboardController < ApplicationController
@groups = current_user.authorized_groups.order_name_asc @groups = current_user.authorized_groups.order_name_asc
@has_authorized_projects = @projects.count > 0 @has_authorized_projects = @projects.count > 0
@projects_count = @projects.count @projects_count = @projects.count
@projects = @projects.limit(@projects_limit) @projects = @projects.includes(:namespace).limit(@projects_limit)
@events = Event.in_projects(current_user.authorized_projects.pluck(:id))
@events = @event_filter.apply_filter(@events)
@events = @events.limit(20).offset(params[:offset] || 0)
@last_push = current_user.recent_push @last_push = current_user.recent_push
...@@ -24,8 +20,16 @@ class DashboardController < ApplicationController ...@@ -24,8 +20,16 @@ class DashboardController < ApplicationController
respond_to do |format| respond_to do |format|
format.html format.html
format.json { pager_json("events/_events", @events.count) }
format.atom { render layout: false } format.json do
load_events
pager_json("events/_events", @events.count)
end
format.atom do
load_events
render layout: false
end
end end
end end
...@@ -74,4 +78,10 @@ class DashboardController < ApplicationController ...@@ -74,4 +78,10 @@ class DashboardController < ApplicationController
def load_projects def load_projects
@projects = current_user.authorized_projects.sorted_by_activity.non_archived @projects = current_user.authorized_projects.sorted_by_activity.non_archived
end end
def load_events
@events = Event.in_projects(current_user.authorized_projects.pluck(:id))
@events = @event_filter.apply_filter(@events).with_associations
@events = @events.limit(20).offset(params[:offset] || 0)
end
end end
...@@ -18,7 +18,7 @@ class Explore::ProjectsController < ApplicationController ...@@ -18,7 +18,7 @@ class Explore::ProjectsController < ApplicationController
def starred def starred
@starred_projects = ProjectsFinder.new.execute(current_user) @starred_projects = ProjectsFinder.new.execute(current_user)
@starred_projects = @starred_projects.order('star_count DESC') @starred_projects = @starred_projects.reorder('star_count DESC')
@starred_projects = @starred_projects.page(params[:page]).per(10) @starred_projects = @starred_projects.page(params[:page]).per(10)
end end
end end
...@@ -5,8 +5,11 @@ class FilesController < ApplicationController ...@@ -5,8 +5,11 @@ class FilesController < ApplicationController
if uploader.file_storage? if uploader.file_storage?
if can?(current_user, :read_project, note.project) if can?(current_user, :read_project, note.project)
# Replace old notes location in /public with the new one in / and send the file
path = uploader.file.path.gsub("#{Rails.root}/public", Rails.root.to_s)
disposition = uploader.image? ? 'inline' : 'attachment' disposition = uploader.image? ? 'inline' : 'attachment'
send_file uploader.file.path, disposition: disposition send_file path, disposition: disposition
else else
not_found! not_found!
end end
......
...@@ -10,11 +10,11 @@ class GroupsController < ApplicationController ...@@ -10,11 +10,11 @@ class GroupsController < ApplicationController
# Load group projects # Load group projects
before_filter :load_projects, except: [:new, :create, :projects, :edit, :update] before_filter :load_projects, except: [:new, :create, :projects, :edit, :update]
before_filter :event_filter, only: :show
before_filter :set_title, only: [:new, :create]
layout :determine_layout layout :determine_layout
before_filter :set_title, only: [:new, :create]
def new def new
@group = Group.new @group = Group.new
end end
...@@ -32,17 +32,23 @@ class GroupsController < ApplicationController ...@@ -32,17 +32,23 @@ class GroupsController < ApplicationController
end end
def show def show
@events = Event.in_projects(project_ids)
@events = event_filter.apply_filter(@events)
@events = @events.limit(20).offset(params[:offset] || 0)
@last_push = current_user.recent_push if current_user @last_push = current_user.recent_push if current_user
@projects = @projects.includes(:namespace)
@shared_projects = @group.shared_projects @shared_projects = @group.shared_projects
respond_to do |format| respond_to do |format|
format.html format.html
format.json { pager_json("events/_events", @events.count) }
format.atom { render layout: false } format.json do
load_events
pager_json("events/_events", @events.count)
end
format.atom do
load_events
render layout: false
end
end end
end end
...@@ -151,4 +157,10 @@ class GroupsController < ApplicationController ...@@ -151,4 +157,10 @@ class GroupsController < ApplicationController
def group_params def group_params
params.require(:group).permit(:name, :description, :path, :avatar, :membership_lock) params.require(:group).permit(:name, :description, :path, :avatar, :membership_lock)
end end
def load_events
@events = Event.in_projects(project_ids)
@events = event_filter.apply_filter(@events).with_associations
@events = @events.limit(20).offset(params[:offset] || 0)
end
end end
...@@ -5,9 +5,10 @@ class ProjectsController < ApplicationController ...@@ -5,9 +5,10 @@ class ProjectsController < ApplicationController
# Authorize # Authorize
before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive] before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive]
before_filter :set_title, only: [:new, :create]
before_filter :event_filter, only: :show
layout 'navless', only: [:new, :create, :fork] layout 'navless', only: [:new, :create, :fork]
before_filter :set_title, only: [:new, :create]
def new def new
@project = Project.new @project = Project.new
...@@ -56,9 +57,6 @@ class ProjectsController < ApplicationController ...@@ -56,9 +57,6 @@ class ProjectsController < ApplicationController
end end
limit = (params[:limit] || 20).to_i limit = (params[:limit] || 20).to_i
@events = @project.events.recent
@events = event_filter.apply_filter(@events)
@events = @events.limit(limit).offset(params[:offset] || 0)
@show_star = !(current_user && current_user.starred?(@project)) @show_star = !(current_user && current_user.starred?(@project))
...@@ -76,7 +74,12 @@ class ProjectsController < ApplicationController ...@@ -76,7 +74,12 @@ class ProjectsController < ApplicationController
end end
end end
format.json { pager_json('events/_events', @events.count) } format.json do
@events = @project.events.recent
@events = event_filter.apply_filter(@events).with_associations
@events = @events.limit(limit).offset(params[:offset] || 0)
pager_json('events/_events', @events.count)
end
end end
end end
......
...@@ -4,19 +4,20 @@ class UsersController < ApplicationController ...@@ -4,19 +4,20 @@ class UsersController < ApplicationController
layout :determine_layout layout :determine_layout
def show def show
# Projects user can view @contributed_projects = Project.
visible_projects = ProjectsFinder.new.execute(current_user) where(id: authorized_projects_ids & @user.contributed_projects_ids).
authorized_projects_ids = visible_projects.pluck(:id) in_group_namespace.includes(:namespace)
@projects = @user.personal_projects. @projects = @user.personal_projects.
where(id: authorized_projects_ids) where(id: authorized_projects_ids).includes(:namespace)
# Collect only groups common for both users # Collect only groups common for both users
@groups = @user.groups & GroupsFinder.new.execute(current_user) @groups = @user.groups & GroupsFinder.new.execute(current_user)
# Get user activity feed for projects common for both users # Get user activity feed for projects common for both users
@events = @user.recent_events. @events = @user.recent_events.
where(project_id: authorized_projects_ids).limit(30) where(project_id: authorized_projects_ids).
with_associations.limit(30)
@title = @user.name @title = @user.name
@title_url = user_path(@user) @title_url = user_path(@user)
...@@ -28,8 +29,8 @@ class UsersController < ApplicationController ...@@ -28,8 +29,8 @@ class UsersController < ApplicationController
end end
def calendar def calendar
visible_projects = ProjectsFinder.new.execute(current_user) projects = Project.where(id: authorized_projects_ids & @user.contributed_projects_ids)
calendar = Gitlab::CommitsCalendar.new(visible_projects, @user) calendar = Gitlab::CommitsCalendar.new(projects, @user)
@timestamps = calendar.timestamps @timestamps = calendar.timestamps
@starting_year = calendar.starting_year @starting_year = calendar.starting_year
@starting_month = calendar.starting_month @starting_month = calendar.starting_month
...@@ -54,4 +55,10 @@ class UsersController < ApplicationController ...@@ -54,4 +55,10 @@ class UsersController < ApplicationController
return authenticate_user! return authenticate_user!
end end
end end
def authorized_projects_ids
# Projects user can view
@authorized_projects_ids ||=
ProjectsFinder.new.execute(current_user).pluck(:id)
end
end end
...@@ -51,7 +51,13 @@ module ApplicationHelper ...@@ -51,7 +51,13 @@ module ApplicationHelper
end end
def project_icon(project_id, options = {}) def project_icon(project_id, options = {})
project = Project.find_with_namespace(project_id) project =
if project_id.is_a?(Project)
project = project_id
else
Project.find_with_namespace(project_id)
end
if project.avatar.present? if project.avatar.present?
image_tag project.avatar.url, options image_tag project.avatar.url, options
elsif project.avatar_in_git elsif project.avatar_in_git
......
...@@ -17,7 +17,7 @@ module BlobHelper ...@@ -17,7 +17,7 @@ module BlobHelper
end end
def no_highlight_files def no_highlight_files
%w(credits changelog copying copyright license authors) %w(credits changelog news copying copyright license authors)
end end
def edit_blob_link(project, ref, path, options = {}) def edit_blob_link(project, ref, path, options = {})
......
...@@ -110,7 +110,7 @@ module GitlabMarkdownHelper ...@@ -110,7 +110,7 @@ module GitlabMarkdownHelper
end end
def link_to_ignore?(link) def link_to_ignore?(link)
if link =~ /\#\w+/ if link =~ /\A\#\w+/
# ignore anchors like <a href="#my-header"> # ignore anchors like <a href="#my-header">
true true
else else
...@@ -122,10 +122,11 @@ module GitlabMarkdownHelper ...@@ -122,10 +122,11 @@ module GitlabMarkdownHelper
["http://","https://", "ftp://", "mailto:"] ["http://","https://", "ftp://", "mailto:"]
end end
def rebuild_path(path) def rebuild_path(file_path)
path.gsub!(/(#.*)/, "") file_path = file_path.dup
file_path.gsub!(/(#.*)/, "")
id = $1 || "" id = $1 || ""
file_path = relative_file_path(path) file_path = relative_file_path(file_path)
file_path = sanitize_slashes(file_path) file_path = sanitize_slashes(file_path)
[ [
......
...@@ -47,6 +47,7 @@ class Event < ActiveRecord::Base ...@@ -47,6 +47,7 @@ class Event < ActiveRecord::Base
scope :recent, -> { order("created_at DESC") } scope :recent, -> { order("created_at DESC") }
scope :code_push, -> { where(action: PUSHED) } scope :code_push, -> { where(action: PUSHED) }
scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent } scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent }
scope :with_associations, -> { includes(project: :namespace) }
class << self class << self
def reset_event_cache_for(target) def reset_event_cache_for(target)
......
...@@ -26,7 +26,7 @@ class Group < Namespace ...@@ -26,7 +26,7 @@ class Group < Namespace
validate :avatar_type, if: ->(user) { user.avatar_changed? } validate :avatar_type, if: ->(user) { user.avatar_changed? }
validates :avatar, file_size: { maximum: 200.kilobytes.to_i } validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
mount_uploader :avatar, AttachmentUploader mount_uploader :avatar, AvatarUploader
after_create :post_create_hook after_create :post_create_hook
after_destroy :post_destroy_hook after_destroy :post_destroy_hook
......
...@@ -145,7 +145,7 @@ class Project < ActiveRecord::Base ...@@ -145,7 +145,7 @@ class Project < ActiveRecord::Base
if: ->(project) { project.avatar && project.avatar_changed? } if: ->(project) { project.avatar && project.avatar_changed? }
validates :avatar, file_size: { maximum: 200.kilobytes.to_i } validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
mount_uploader :avatar, AttachmentUploader mount_uploader :avatar, AvatarUploader
# Scopes # Scopes
scope :sorted_by_activity, -> { reorder(last_activity_at: :desc) } scope :sorted_by_activity, -> { reorder(last_activity_at: :desc) }
......
...@@ -177,7 +177,7 @@ class User < ActiveRecord::Base ...@@ -177,7 +177,7 @@ class User < ActiveRecord::Base
end end
end end
mount_uploader :avatar, AttachmentUploader mount_uploader :avatar, AvatarUploader
# Scopes # Scopes
scope :admins, -> { where(admin: true) } scope :admins, -> { where(admin: true) }
...@@ -623,4 +623,13 @@ class User < ActiveRecord::Base ...@@ -623,4 +623,13 @@ class User < ActiveRecord::Base
def oauth_authorized_tokens def oauth_authorized_tokens
Doorkeeper::AccessToken.where(resource_owner_id: self.id, revoked_at: nil) Doorkeeper::AccessToken.where(resource_owner_id: self.id, revoked_at: nil)
end end
def contributed_projects_ids
Event.where(author_id: self).
where("created_at > ?", Time.now - 1.year).
code_push.
reorder(project_id: :desc).
select('DISTINCT(project_id)').
map(&:project_id)
end
end end
...@@ -3,10 +3,8 @@ ...@@ -3,10 +3,8 @@
class AttachmentUploader < CarrierWave::Uploader::Base class AttachmentUploader < CarrierWave::Uploader::Base
storage :file storage :file
after :store, :reset_events_cache
def store_dir def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" "#{Rails.root}/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end end
def image? def image?
...@@ -29,8 +27,4 @@ class AttachmentUploader < CarrierWave::Uploader::Base ...@@ -29,8 +27,4 @@ class AttachmentUploader < CarrierWave::Uploader::Base
def file_storage? def file_storage?
self.class.storage == CarrierWave::Storage::File self.class.storage == CarrierWave::Storage::File
end end
def reset_events_cache(file)
model.reset_events_cache if model.is_a?(User)
end
end end
# encoding: utf-8
class AvatarUploader < CarrierWave::Uploader::Base
storage :file
after :store, :reset_events_cache
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def image?
img_ext = %w(png jpg jpeg gif bmp tiff)
if file.respond_to?(:extension)
img_ext.include?(file.extension.downcase)
else
# Not all CarrierWave storages respond to :extension
ext = file.path.split('.').last.downcase
img_ext.include?(ext)
end
rescue
false
end
def file_storage?
self.class.storage == CarrierWave::Storage::File
end
def reset_events_cache(file)
model.reset_events_cache if model.is_a?(User)
end
end
= render "events/event_last_push", event: @last_push = render "events/event_last_push", event: @last_push
= render 'shared/event_filter' = render 'shared/event_filter'
.content_list
- if @events.any?
.content_list
- else
.nothing-here-block Projects activity will be displayed here
= spinner = spinner
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
.input-group .input-group
= search_field_tag :filter_group, nil, placeholder: 'Filter by name', class: 'dash-filter form-control' = search_field_tag :filter_group, nil, placeholder: 'Filter by name', class: 'dash-filter form-control'
- if current_user.can_create_group? - if current_user.can_create_group?
.input-group-addon .input-group-addon.dash-new-group
= link_to new_group_path, class: "" do = link_to new_group_path, class: "" do
%strong New group %strong New group
%ul.well-list.dash-list %ul.well-list.dash-list
......
= link_to project_path(project), class: dom_class(project) do = link_to project_path(project), class: dom_class(project) do
.dash-project-avatar .dash-project-avatar
= project_icon(project.to_param, alt: '', class: 'avatar project-avatar s40') = project_icon(project, alt: '', class: 'avatar project-avatar s40')
.dash-project-access-icon .dash-project-access-icon
= visibility_level_icon(project.visibility_level) = visibility_level_icon(project.visibility_level)
%span.str-truncated %span.str-truncated
......
...@@ -3,11 +3,9 @@ ...@@ -3,11 +3,9 @@
.project-access-icon .project-access-icon
= visibility_level_icon(project.visibility_level) = visibility_level_icon(project.visibility_level)
= link_to project.name_with_namespace, project = link_to project.name_with_namespace, project
%span.pull-right
- if current_page?(starred_explore_projects_path) %i.fa.fa-star
%strong.pull-right = project.star_count
%i.fa.fa-star
= pluralize project.star_count, 'star'
.project-info .project-info
- if project.description.present? - if project.description.present?
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
%li.project-row %li.project-row
= link_to project_path(project), class: dom_class(project) do = link_to project_path(project), class: dom_class(project) do
.dash-project-avatar .dash-project-avatar
= project_icon(project.to_param, alt: '', class: 'avatar s40') = project_icon(project, alt: '', class: 'avatar s40')
.dash-project-access-icon .dash-project-access-icon
= visibility_level_icon(project.visibility_level) = visibility_level_icon(project.visibility_level)
%span.str-truncated %span.str-truncated
......
...@@ -13,10 +13,7 @@ ...@@ -13,10 +13,7 @@
- if current_user - if current_user
= render "events/event_last_push", event: @last_push = render "events/event_last_push", event: @last_push
= render 'shared/event_filter' = render 'shared/event_filter'
- if @events.any? .content_list
.content_list
- else
.nothing-here-block Project activity will be displayed here
= spinner = spinner
%aside.side.col-md-4 %aside.side.col-md-4
= render "projects", projects: @projects = render "projects", projects: @projects
......
- empty_repo = @project.empty_repo? - empty_repo = @project.empty_repo?
.project-home-panel{:class => ("empty-project" if empty_repo)} .project-home-panel{:class => ("empty-project" if empty_repo)}
.project-identicon-holder .project-identicon-holder
= project_icon(@project.to_param, alt: '', class: 'avatar project-avatar') = project_icon(@project, alt: '', class: 'avatar project-avatar')
.project-home-row .project-home-row
.project-home-desc .project-home-desc
- if @project.description.present? - if @project.description.present?
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
= f.label :description, 'Description', class: 'control-label' = f.label :description, 'Description', class: 'control-label'
.col-sm-10 .col-sm-10
= render layout: 'projects/md_preview' do = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do
= render 'projects/zen', f: f, attr: :description, = render 'projects/zen', f: f, attr: :description,
classes: 'description form-control' classes: 'description form-control'
.col-sm-12.hint .col-sm-12.hint
......
...@@ -10,4 +10,4 @@ ...@@ -10,4 +10,4 @@
.md-write-holder .md-write-holder
= yield = yield
.md-preview-holder.hide .md-preview-holder.hide
.js-md-preview .js-md-preview{class: (preview_class if defined?(preview_class))}
...@@ -14,24 +14,24 @@ ...@@ -14,24 +14,24 @@
.voting_notes#notes= render "projects/notes/notes_with_form" .voting_notes#notes= render "projects/notes/notes_with_form"
.col-md-3 .col-md-3
%div .issuable-affix
.clearfix .clearfix
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'} %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
= cross_project_reference(@project, @issue) = cross_project_reference(@project, @issue)
%hr
.context
%cite.cgray
= render partial: 'issue_context', locals: { issue: @issue }
%hr
.clearfix
.votes-holder
%h6 Votes
#votes= render 'votes/votes_block', votable: @issue
- if @issue.labels.any?
%hr %hr
%h6 Labels .context
.issue-show-labels %cite.cgray
- @issue.labels.each do |label| = render partial: 'issue_context', locals: { issue: @issue }
= link_to project_issues_path(@project, label_name: label.name) do %hr
%p= render_colored_label(label) .clearfix
.votes-holder
%h6 Votes
#votes= render 'votes/votes_block', votable: @issue
- if @issue.labels.any?
%hr
%h6 Labels
.issue-show-labels
- @issue.labels.each do |label|
= link_to project_issues_path(@project, label_name: label.name) do
= render_colored_label(label)
%h4.page-title .issue
.issue-box{ class: issue_box_class(@issue) } .issue-details
- if @issue.closed? %h4.page-title
Closed .issue-box{ class: issue_box_class(@issue) }
- else - if @issue.closed?
Open Closed
Issue ##{@issue.iid} - else
%small.creator Open
&middot; created by #{link_to_member(@project, @issue.author)} #{issue_timestamp(@issue)} Issue ##{@issue.iid}
%small.creator
&middot; created by #{link_to_member(@project, @issue.author)} #{issue_timestamp(@issue)}
.pull-right .pull-right
- if can?(current_user, :write_issue, @project) - if can?(current_user, :write_issue, @project)
= link_to new_project_issue_path(@project), class: "btn btn-grouped new-issue-link", title: "New Issue", id: "new_issue_link" do = link_to new_project_issue_path(@project), class: "btn btn-grouped new-issue-link", title: "New Issue", id: "new_issue_link" do
%i.fa.fa-plus %i.fa.fa-plus
New Issue New Issue
- if can?(current_user, :modify_issue, @issue) - if can?(current_user, :modify_issue, @issue)
- if @issue.closed? - if @issue.closed?
= link_to 'Reopen', project_issue_path(@project, @issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-grouped btn-reopen" = link_to 'Reopen', project_issue_path(@project, @issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-grouped btn-reopen"
- else - else
= link_to 'Close', project_issue_path(@project, @issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close", title: "Close Issue" = link_to 'Close', project_issue_path(@project, @issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close", title: "Close Issue"
= link_to edit_project_issue_path(@project, @issue), class: "btn btn-grouped issuable-edit" do = link_to edit_project_issue_path(@project, @issue), class: "btn btn-grouped issuable-edit" do
%i.fa.fa-pencil-square-o %i.fa.fa-pencil-square-o
Edit Edit
%hr %hr
%h3.issue-title %h3.issue-title
= gfm escape_once(@issue.title) = gfm escape_once(@issue.title)
%div %div
- if @issue.description.present? - if @issue.description.present?
.description .description
.wiki .wiki
= preserve do = preserve do
= markdown(@issue.description, parse_tasks: true) = markdown(@issue.description, parse_tasks: true)
%hr %hr
= render "projects/issues/discussion" .issue-discussion
= render "projects/issues/discussion"
...@@ -10,22 +10,23 @@ ...@@ -10,22 +10,23 @@
= render "projects/merge_requests/show/participants" = render "projects/merge_requests/show/participants"
= render "projects/notes/notes_with_form" = render "projects/notes/notes_with_form"
.col-md-3 .col-md-3
.clearfix .issuable-affix
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'} .clearfix
= cross_project_reference(@project, @merge_request) %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
%hr = cross_project_reference(@project, @merge_request)
.context %hr
%cite.cgray .context
= render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request } %cite.cgray
%hr = render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request }
.votes-holder
%h6 Votes
#votes= render 'votes/votes_block', votable: @merge_request
- if @merge_request.labels.any?
%hr %hr
%h6 Labels .votes-holder
.merge-request-show-labels %h6 Votes
- @merge_request.labels.each do |label| #votes= render 'votes/votes_block', votable: @merge_request
= link_to project_merge_requests_path(@project, label_name: label.name) do
%p= render_colored_label(label) - if @merge_request.labels.any?
%hr
%h6 Labels
.merge-request-show-labels
- @merge_request.labels.each do |label|
= link_to project_merge_requests_path(@project, label_name: label.name) do
= render_colored_label(label)
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
- if merge_request.assignee - if merge_request.assignee
assigned to #{link_to_member(merge_request.source_project, merge_request.assignee)} assigned to #{link_to_member(merge_request.source_project, merge_request.assignee)}
- else - else
Work In Progress Unassigned
- if merge_request.votes_count > 0 - if merge_request.votes_count > 0
= render 'votes/votes_inline', votable: merge_request = render 'votes/votes_inline', votable: merge_request
- if merge_request.notes.any? - if merge_request.notes.any?
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
.form-group.issuable-description .form-group.issuable-description
= f.label :description, 'Description', class: 'control-label' = f.label :description, 'Description', class: 'control-label'
.col-sm-10 .col-sm-10
= render layout: 'projects/md_preview' do = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do
= render 'projects/zen', f: f, attr: :description, classes: 'description form-control' = render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
.col-sm-12-hint .col-sm-12-hint
......
.merge-request{'data-url' => project_merge_request_path(@project, @merge_request)} .merge-request{'data-url' => project_merge_request_path(@project, @merge_request)}
= render "projects/merge_requests/show/mr_title" .merge-request-details
%hr = render "projects/merge_requests/show/mr_title"
= render "projects/merge_requests/show/mr_box" %hr
%hr = render "projects/merge_requests/show/mr_box"
.append-bottom-20 %hr
.slead .append-bottom-20
%span From .slead
- if @merge_request.for_fork? %span From
%strong.label-branch< - if @merge_request.for_fork?
- if @merge_request.source_project %strong.label-branch<
= link_to @merge_request.source_project_namespace, project_path(@merge_request.source_project) - if @merge_request.source_project
- else = link_to @merge_request.source_project_namespace, project_path(@merge_request.source_project)
\ #{@merge_request.source_project_namespace} - else
\:#{@merge_request.source_branch} \ #{@merge_request.source_project_namespace}
%span into \:#{@merge_request.source_branch}
%strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch} %span into
- else %strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch}
%strong.label-branch #{@merge_request.source_branch} - else
%span into %strong.label-branch #{@merge_request.source_branch}
%strong.label-branch #{@merge_request.target_branch} %span into
- if @merge_request.open? %strong.label-branch #{@merge_request.target_branch}
%span.pull-right - if @merge_request.open?
.btn-group %span.pull-right
%a.btn.dropdown-toggle{ data: {toggle: :dropdown} } .btn-group
%i.fa.fa-download %a.btn.dropdown-toggle{ data: {toggle: :dropdown} }
Download as %i.fa.fa-download
%span.caret Download as
%ul.dropdown-menu %span.caret
%li= link_to "Email Patches", project_merge_request_path(@project, @merge_request, format: :patch) %ul.dropdown-menu
%li= link_to "Plain Diff", project_merge_request_path(@project, @merge_request, format: :diff) %li= link_to "Email Patches", project_merge_request_path(@project, @merge_request, format: :patch)
%li= link_to "Plain Diff", project_merge_request_path(@project, @merge_request, format: :diff)
= render "projects/merge_requests/show/how_to_merge" = render "projects/merge_requests/show/how_to_merge"
= render "projects/merge_requests/show/state_widget" = render "projects/merge_requests/show/state_widget"
- if @commits.present? - if @commits.present?
%ul.nav.nav-tabs.merge-request-tabs %ul.nav.nav-tabs.merge-request-tabs
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
.form-group.milestone-description .form-group.milestone-description
= f.label :description, "Description", class: "control-label" = f.label :description, "Description", class: "control-label"
.col-sm-10 .col-sm-10
= render layout: 'projects/md_preview' do = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do
= render 'projects/zen', f: f, attr: :description, classes: 'description form-control' = render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
.hint .hint
.pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
%i.fa.fa-github %i.fa.fa-github
Import projects from GitHub Import projects from GitHub
= render 'github_import_modal' = render 'github_import_modal'
.project-import.form-group .project-import.form-group
.col-sm-2 .col-sm-2
.col-sm-10 .col-sm-10
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
= link_to status_import_gitlab_path do = link_to status_import_gitlab_path do
%i.fa.fa-heart %i.fa.fa-heart
Import projects from GitLab.com Import projects from GitLab.com
- else - elsif request.host != 'gitlab.com'
= link_to '#', class: 'how_to_import_link light' do = link_to '#', class: 'how_to_import_link light' do
%i.fa.fa-heart %i.fa.fa-heart
Import projects from GitLab.com Import projects from GitLab.com
...@@ -99,4 +99,4 @@ ...@@ -99,4 +99,4 @@
e.preventDefault() e.preventDefault()
import_modal = $(this).parent().find(".modal").show() import_modal = $(this).parent().find(".modal").show()
$('.modal-header .close').bind 'click', -> $('.modal-header .close').bind 'click', ->
$(".modal").hide() $(".modal").hide()
\ No newline at end of file
.note-edit-form .note-edit-form
= form_for note, url: project_note_path(@project, note), method: :put, remote: true, authenticity_token: true do |f| = form_for note, url: project_note_path(@project, note), method: :put, remote: true, authenticity_token: true do |f|
= render layout: 'projects/md_preview' do = render layout: 'projects/md_preview', locals: { preview_class: "note-text" } do
= render 'projects/zen', f: f, attr: :note, = render 'projects/zen', f: f, attr: :note,
classes: 'note_text js-note-text' classes: 'note_text js-note-text'
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
= f.hidden_field :noteable_id = f.hidden_field :noteable_id
= f.hidden_field :noteable_type = f.hidden_field :noteable_type
= render layout: 'projects/md_preview' do = render layout: 'projects/md_preview', locals: { preview_class: "note-text" } do
= render 'projects/zen', f: f, attr: :note, = render 'projects/zen', f: f, attr: :note,
classes: 'note_text js-note-text' classes: 'note_text js-note-text'
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
.form-group.wiki-content .form-group.wiki-content
= f.label :content, class: 'control-label' = f.label :content, class: 'control-label'
.col-sm-10 .col-sm-10
= render layout: 'projects/md_preview' do = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do
= render 'projects/zen', f: f, attr: :content, classes: 'description form-control' = render 'projects/zen', f: f, attr: :content, classes: 'description form-control'
.col-sm-12.hint .col-sm-12.hint
.pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'} .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}
......
...@@ -7,4 +7,5 @@ ...@@ -7,4 +7,5 @@
= link_to "#L#{i}", id: "L#{i}", rel: "#L#{i}" do = link_to "#L#{i}", id: "L#{i}", rel: "#L#{i}" do
%i.fa.fa-link %i.fa.fa-link
= i = i
= highlight(blob.name, blob.data) :preserve
#{highlight(blob.name, blob.data)}
.panel.panel-default - if @contributed_projects.present?
.panel-heading Personal projects .panel.panel-default
%ul.well-list .panel-heading Projects contributed to
- projects.each do |project| %ul.well-list
%li - @contributed_projects.sort_by(&:star_count).reverse.each do |project|
= link_to_project project %li
= link_to_project project
%span.pull-right.light
%i.fa.fa-star
= project.star_count
- if @projects.present?
.panel.panel-default
.panel-heading Personal projects
%ul.well-list
- @projects.sort_by(&:star_count).reverse.each do |project|
%li
= link_to_project project
%span.pull-right.light
%i.fa.fa-star
= project.star_count
%h4 Calendar %h4 Commits calendar
#cal-heatmap.calendar #cal-heatmap.calendar
:javascript :javascript
new calendar( new calendar(
......
...@@ -35,9 +35,7 @@ ...@@ -35,9 +35,7 @@
= render @events = render @events
.col-md-4 .col-md-4
= render 'profile', user: @user = render 'profile', user: @user
- if @projects.present? = render 'projects'
= render 'projects', projects: @projects
:coffeescript :coffeescript
$ -> $ ->
......
...@@ -3,6 +3,7 @@ Gitlab::Seeder.quiet do ...@@ -3,6 +3,7 @@ Gitlab::Seeder.quiet do
s.id = 1 s.id = 1
s.name = 'Administrator' s.name = 'Administrator'
s.email = 'admin@example.com' s.email = 'admin@example.com'
s.notification_email = 'admin@example.com'
s.username = 'root' s.username = 'root'
s.password = '5iveL!fe' s.password = '5iveL!fe'
s.admin = true s.admin = true
......
class MoveNoteFolder < ActiveRecord::Migration
def up
system(
"if [ -d '#{Rails.root}/public/uploads/note' ];
then mv #{Rails.root}/public/uploads/note #{Rails.root}/uploads/note;
echo 'note folder has been moved successfully';
else
echo 'note folder has already been moved or does not exist yet. Nothing to do here.'; fi")
end
def down
system(
"if [ -d '#{Rails.root}/uploads/note' ];
then mv #{Rails.root}/uploads/note #{Rails.root}/public/uploads/note;
echo 'note folder has been moved successfully';
else
echo 'note folder has already been moved or does not exist yet. Nothing to do here.'; fi")
end
end
...@@ -14,7 +14,6 @@ GET /groups ...@@ -14,7 +14,6 @@ GET /groups
"id": 1, "id": 1,
"name": "Foobar Group", "name": "Foobar Group",
"path": "foo-bar", "path": "foo-bar",
"owner_id": 18,
"description": "An interesting group" "description": "An interesting group"
} }
] ]
...@@ -87,7 +86,6 @@ GET /groups?search=foobar ...@@ -87,7 +86,6 @@ GET /groups?search=foobar
"id": 1, "id": 1,
"name": "Foobar Group", "name": "Foobar Group",
"path": "foo-bar", "path": "foo-bar",
"owner_id": 18,
"description": "An interesting group" "description": "An interesting group"
} }
] ]
......
...@@ -148,7 +148,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -148,7 +148,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
end end
step 'I should see new group "Owned" avatar' do step 'I should see new group "Owned" avatar' do
Group.find_by(name: "Owned").avatar.should be_instance_of AttachmentUploader Group.find_by(name: "Owned").avatar.should be_instance_of AvatarUploader
Group.find_by(name: "Owned").avatar.url.should == "/uploads/group/avatar/#{ Group.find_by(name:"Owned").id }/gitlab_logo.png" Group.find_by(name: "Owned").avatar.url.should == "/uploads/group/avatar/#{ Group.find_by(name:"Owned").id }/gitlab_logo.png"
end end
......
...@@ -29,7 +29,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps ...@@ -29,7 +29,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
end end
step 'I should see new avatar' do step 'I should see new avatar' do
@user.avatar.should be_instance_of AttachmentUploader @user.avatar.should be_instance_of AvatarUploader
@user.avatar.url.should == "/uploads/user/avatar/#{ @user.id }/gitlab_logo.png" @user.avatar.url.should == "/uploads/user/avatar/#{ @user.id }/gitlab_logo.png"
end end
......
...@@ -253,7 +253,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps ...@@ -253,7 +253,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end end
step 'I should still see a comment like "Line is correct" in the first file' do step 'I should still see a comment like "Line is correct" in the first file' do
within '.files [id^=diff]:nth-child(1) .note-text' do within '.files [id^=diff]:nth-child(1) .note-body > .note-text' do
page.should have_visible_content "Line is correct" page.should have_visible_content "Line is correct"
end end
end end
...@@ -281,7 +281,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps ...@@ -281,7 +281,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end end
step 'I should see comments on the side-by-side diff page' do step 'I should see comments on the side-by-side diff page' do
within '.files [id^=diff]:nth-child(1) .parallel .note-text' do within '.files [id^=diff]:nth-child(1) .parallel .note-body > .note-text' do
page.should have_visible_content "Line is correct" page.should have_visible_content "Line is correct"
end end
end end
......
...@@ -38,7 +38,7 @@ class Spinach::Features::Project < Spinach::FeatureSteps ...@@ -38,7 +38,7 @@ class Spinach::Features::Project < Spinach::FeatureSteps
end end
step 'I should see new project avatar' do step 'I should see new project avatar' do
@project.avatar.should be_instance_of AttachmentUploader @project.avatar.should be_instance_of AvatarUploader
url = @project.avatar.url url = @project.avatar.url
url.should == "/uploads/project/avatar/#{ @project.id }/gitlab_logo.png" url.should == "/uploads/project/avatar/#{ @project.id }/gitlab_logo.png"
end end
......
...@@ -116,7 +116,7 @@ module SharedNote ...@@ -116,7 +116,7 @@ module SharedNote
end end
step 'The comment with the header should not have an ID' do step 'The comment with the header should not have an ID' do
within(".note-text") do within(".note-body > .note-text") do
page.should have_content("Comment with a header") page.should have_content("Comment with a header")
page.should_not have_css("#comment-with-a-header") page.should_not have_css("#comment-with-a-header")
end end
......
...@@ -70,7 +70,7 @@ module API ...@@ -70,7 +70,7 @@ module API
end end
class Group < Grape::Entity class Group < Grape::Entity
expose :id, :name, :path, :owner_id, :ldap_cn, :ldap_access, :description expose :id, :name, :path, :ldap_cn, :ldap_access, :description
expose :ldap_group_links, if: ->(group, _) { group.ldap_group_links.any? } do |group, _| expose :ldap_group_links, if: ->(group, _) { group.ldap_group_links.any? } do |group, _|
group.ldap_group_links.map do |group_link| group.ldap_group_links.map do |group_link|
group_link.slice(:cn, :group_access) group_link.slice(:cn, :group_access)
......
...@@ -33,7 +33,6 @@ module API ...@@ -33,7 +33,6 @@ module API
attrs = attributes_for_keys [:name, :path, :description] attrs = attributes_for_keys [:name, :path, :description]
@group = Group.new(attrs) @group = Group.new(attrs)
@group.owner = current_user
if @group.save if @group.save
# NOTE: add backwards compatibility for single ldap link # NOTE: add backwards compatibility for single ldap link
...@@ -44,6 +43,8 @@ module API ...@@ -44,6 +43,8 @@ module API
group_access: ldap_attrs[:ldap_access] group_access: ldap_attrs[:ldap_access]
}) })
end end
@group.add_owner(current_user)
present @group, with: Entities::Group present @group, with: Entities::Group
else else
render_api_error!("Failed to save group #{@group.errors.messages}", 400) render_api_error!("Failed to save group #{@group.errors.messages}", 400)
......
...@@ -83,7 +83,7 @@ module API ...@@ -83,7 +83,7 @@ module API
end end
def authenticate_by_gitlab_shell_token! def authenticate_by_gitlab_shell_token!
unauthorized! unless secret_token == params['secret_token'] unauthorized! unless secret_token == params['secret_token'].try(:chomp)
end end
def authenticated_as_admin! def authenticated_as_admin!
...@@ -236,7 +236,7 @@ module API ...@@ -236,7 +236,7 @@ module API
end end
def secret_token def secret_token
File.read(Rails.root.join('.gitlab_shell_secret')) File.read(Rails.root.join('.gitlab_shell_secret')).chomp
end end
def handle_member_errors(errors) def handle_member_errors(errors)
......
...@@ -74,7 +74,7 @@ module API ...@@ -74,7 +74,7 @@ module API
if message = BroadcastMessage.current if message = BroadcastMessage.current
present message, with: Entities::BroadcastMessage present message, with: Entities::BroadcastMessage
else else
not_found! {}
end end
end end
end end
......
module Backup module Backup
class Manager class Manager
BACKUP_CONTENTS = %w{repositories/ db/ uploads/ backup_information.yml} BACKUP_CONTENTS = %w{repositories/ db/ public/ uploads/ backup_information.yml}
def pack def pack
# saving additional informations # saving additional informations
......
module Backup module Backup
class Uploads class Uploads
attr_reader :app_uploads_dir, :backup_uploads_dir, :backup_dir attr_reader :app_public_uploads_dir, :app_private_uploads_dir, :backup_public_uploads_dir,
:backup_private_uploads_dir, :backup_dir, :backup_public_dir
def initialize def initialize
@app_uploads_dir = File.realpath(Rails.root.join('public', 'uploads')) @app_public_uploads_dir = File.realpath(Rails.root.join('public', 'uploads'))
@app_private_uploads_dir = File.realpath(Rails.root.join('uploads'))
@backup_dir = Gitlab.config.backup.path @backup_dir = Gitlab.config.backup.path
@backup_uploads_dir = File.join(Gitlab.config.backup.path, 'uploads') @backup_public_dir = File.join(backup_dir, 'public')
@backup_public_uploads_dir = File.join(backup_dir, 'public', 'uploads')
@backup_private_uploads_dir = File.join(backup_dir, 'uploads')
end end
# Copy uploads from public/uploads to backup/uploads # Copy uploads from public/uploads to backup/public/uploads and from /uploads to backup/uploads
def dump def dump
FileUtils.mkdir_p(backup_uploads_dir) FileUtils.mkdir_p(backup_public_uploads_dir)
FileUtils.cp_r(app_uploads_dir, backup_dir) FileUtils.cp_r(app_public_uploads_dir, backup_public_dir)
FileUtils.mkdir_p(backup_private_uploads_dir)
FileUtils.cp_r(app_private_uploads_dir, backup_dir)
end end
def restore def restore
backup_existing_uploads_dir backup_existing_public_uploads_dir
backup_existing_private_uploads_dir
FileUtils.cp_r(backup_uploads_dir, app_uploads_dir) FileUtils.cp_r(backup_public_uploads_dir, app_public_uploads_dir)
FileUtils.cp_r(backup_private_uploads_dir, app_private_uploads_dir)
end end
def backup_existing_uploads_dir def backup_existing_public_uploads_dir
timestamped_uploads_path = File.join(app_uploads_dir, '..', "uploads.#{Time.now.to_i}") timestamped_public_uploads_path = File.join(app_public_uploads_dir, '..', "uploads.#{Time.now.to_i}")
if File.exists?(app_uploads_dir) if File.exists?(app_public_uploads_dir)
FileUtils.mv(app_uploads_dir, timestamped_uploads_path) FileUtils.mv(app_public_uploads_dir, timestamped_public_uploads_path)
end
end
def backup_existing_private_uploads_dir
timestamped_private_uploads_path = File.join(app_private_uploads_dir, '..', "uploads.#{Time.now.to_i}")
if File.exists?(app_private_uploads_dir)
FileUtils.mv(app_private_uploads_dir, timestamped_private_uploads_path)
end end
end end
end end
......
module Gitlab module Gitlab
module CurrentSettings module CurrentSettings
def current_application_settings def current_application_settings
if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('application_settings') key = :current_application_settings
ApplicationSetting.current ||
ApplicationSetting.create_from_defaults RequestStore.store[key] ||= begin
else if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('application_settings')
fake_application_settings RequestStore.store[:current_application_settings] =
(ApplicationSetting.current || ApplicationSetting.create_from_defaults)
else
fake_application_settings
end
end end
end end
......
...@@ -7,6 +7,8 @@ module Gitlab ...@@ -7,6 +7,8 @@ module Gitlab
attr_reader :params, :project, :git_cmd, :user attr_reader :params, :project, :git_cmd, :user
def self.can_push_to_branch?(user, project, ref) def self.can_push_to_branch?(user, project, ref)
return false unless user
if project.protected_branch?(ref) && if project.protected_branch?(ref) &&
!(project.developers_can_push_to_protected_branch?(ref) && project.team.developer?(user)) !(project.developers_can_push_to_protected_branch?(ref) && project.team.developer?(user))
user.can?(:push_code_to_protected_branches, project) user.can?(:push_code_to_protected_branches, project)
......
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnp2mUaLBoHFX127ysonX
OihiGpI4098eFfH1iAxpKHIof0vs0jFF05IUScNXJZ1U3w8G1U/unY/wGGa3NzAb
ZfDd22eOF6X2Gfiey6U4w9dFf0/UT5x1bphlpX357yh4O9oWWuNaWD062DTbOOsJ
U6UW2U/sZAu/QScys0Nw+gJ58t93hb4jFq+nO5IAQc6g4S8ek5YvIXOshFEpF2in
ZLbSYowx92+9GzfjvdQ7fk0Q2ssg0zfScVa6FY8n019osz0SC3wcSd/qicdfecpu
7oycpd9YDqk4lufE1qVMOsgE8OO4KXMrByz2f+T0p/bH9zdBa5HYylf1T7i60hIL
kQIDAQAB
-----END PUBLIC KEY-----
...@@ -81,7 +81,7 @@ describe 'Comments' do ...@@ -81,7 +81,7 @@ describe 'Comments' do
within("#note_#{note.id}") do within("#note_#{note.id}") do
expect(find('.current-note-edit-form', visible: true)).to be_visible expect(find('.current-note-edit-form', visible: true)).to be_visible
expect(find('.note-edit-form', visible: true)).to be_visible expect(find('.note-edit-form', visible: true)).to be_visible
expect(find(:css, '.note-text', visible: false)).not_to be_visible expect(find(:css, '.note-body > .note-text', visible: false)).not_to be_visible
end end
end end
......
...@@ -633,7 +633,7 @@ describe GitlabMarkdownHelper do ...@@ -633,7 +633,7 @@ describe GitlabMarkdownHelper do
it "should leave code blocks untouched" do it "should leave code blocks untouched" do
allow(helper).to receive(:user_color_scheme_class).and_return(:white) allow(helper).to receive(:user_color_scheme_class).and_return(:white)
target_html = "<pre class=\"code highlight white plaintext\"><code>some code from $40\nhere too\n</code></pre>\n" target_html = "<pre class=\"code highlight white plaintext\"><code>some code from $#{snippet.id}\nhere too\n</code></pre>\n"
expect(helper.markdown("\n some code from $#{snippet.id}\n here too\n")). expect(helper.markdown("\n some code from $#{snippet.id}\n here too\n")).
to eq(target_html) to eq(target_html)
...@@ -687,6 +687,18 @@ describe GitlabMarkdownHelper do ...@@ -687,6 +687,18 @@ describe GitlabMarkdownHelper do
expect(markdown(actual)).to match(expected) expect(markdown(actual)).to match(expected)
end end
it "should handle relative urls for a file in master with an anchor" do
actual = "[GitLab API doc](doc/api/README.md#section)\n"
expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md#section\">GitLab API doc</a></p>\n"
expect(markdown(actual)).to match(expected)
end
it "should not handle relative urls for the current file with an anchor" do
actual = "[GitLab API doc](#section)\n"
expected = "<p><a href=\"#section\">GitLab API doc</a></p>\n"
expect(markdown(actual)).to match(expected)
end
it "should handle relative urls for a directory in master" do it "should handle relative urls for a directory in master" do
actual = "[GitLab API doc](doc/api)\n" actual = "[GitLab API doc](doc/api)\n"
expected = "<p><a href=\"/#{project.path_with_namespace}/tree/#{@ref}/doc/api\">GitLab API doc</a></p>\n" expected = "<p><a href=\"/#{project.path_with_namespace}/tree/#{@ref}/doc/api\">GitLab API doc</a></p>\n"
......
...@@ -32,7 +32,8 @@ describe API::API, api: true do ...@@ -32,7 +32,8 @@ describe API::API, api: true do
it do it do
get api("/internal/broadcast_message"), secret_token: secret_token get api("/internal/broadcast_message"), secret_token: secret_token
expect(response.status).to eq(404) expect(response.status).to eq(200)
expect(json_response).to be_empty
end end
end end
end end
......
...@@ -22,16 +22,7 @@ module TestEnv ...@@ -22,16 +22,7 @@ module TestEnv
# Disable mailer for spinach tests # Disable mailer for spinach tests
disable_mailer if opts[:mailer] == false disable_mailer if opts[:mailer] == false
# Clean /tmp/tests clean_test_path
tmp_test_path = Rails.root.join('tmp', 'tests')
if File.directory?(tmp_test_path)
Dir.entries(tmp_test_path).each do |entry|
unless ['.', '..', 'gitlab-shell', factory_repo_name].include?(entry)
FileUtils.rm_r(File.join(tmp_test_path, entry))
end
end
end
FileUtils.mkdir_p(repos_path) FileUtils.mkdir_p(repos_path)
...@@ -50,15 +41,30 @@ module TestEnv ...@@ -50,15 +41,30 @@ module TestEnv
allow_any_instance_of(NotificationService).to receive(:mailer).and_call_original allow_any_instance_of(NotificationService).to receive(:mailer).and_call_original
end end
# Clean /tmp/tests
#
# Keeps gitlab-shell and gitlab-test
def clean_test_path
tmp_test_path = Rails.root.join('tmp', 'tests', '**')
Dir[tmp_test_path].each do |entry|
unless File.basename(entry) =~ /\Agitlab-(shell|test)\z/
FileUtils.rm_rf(entry)
end
end
end
def setup_gitlab_shell def setup_gitlab_shell
`rake gitlab:shell:install` unless File.directory?(Rails.root.join(*%w(tmp tests gitlab-shell)))
`rake gitlab:shell:install`
end
end end
def setup_factory_repo def setup_factory_repo
clone_url = "https://gitlab.com/gitlab-org/#{factory_repo_name}.git" clone_url = "https://gitlab.com/gitlab-org/#{factory_repo_name}.git"
unless File.directory?(factory_repo_path) unless File.directory?(factory_repo_path)
system(*%W(git clone #{clone_url} #{factory_repo_path})) system(*%W(git clone -q #{clone_url} #{factory_repo_path}))
end end
Dir.chdir(factory_repo_path) do Dir.chdir(factory_repo_path) do
...@@ -79,7 +85,7 @@ module TestEnv ...@@ -79,7 +85,7 @@ module TestEnv
end end
# We must copy bare repositories because we will push to them. # We must copy bare repositories because we will push to them.
system(*%W(git clone --bare #{factory_repo_path} #{factory_repo_path_bare})) system(*%W(git clone -q --bare #{factory_repo_path} #{factory_repo_path_bare}))
end end
def copy_repo(project) def copy_repo(project)
...@@ -101,7 +107,7 @@ module TestEnv ...@@ -101,7 +107,7 @@ module TestEnv
end end
def factory_repo_path_bare def factory_repo_path_bare
factory_repo_path.to_s + '_bare' "#{factory_repo_path}_bare"
end end
def factory_repo_name def factory_repo_name
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment