Commit 9e9ce95d authored by Vinnie Okada's avatar Vinnie Okada

Merge branch 'master' into rails-4.1.9

Conflicts:
	app/views/dashboard/_project.html.haml
	app/views/events/event/_common.html.haml
	app/views/explore/projects/_project.html.haml
	app/views/groups/_projects.html.haml
	app/views/projects/_home_panel.html.haml
	app/views/projects/_issues_nav.html.haml
	app/views/projects/issues/_discussion.html.haml
	app/views/projects/issues/_issues.html.haml
	app/views/projects/issues/show.html.haml
	app/views/projects/merge_requests/_discussion.html.haml
	app/views/projects/merge_requests/_show.html.haml
	app/views/projects/milestones/index.html.haml
	app/views/projects/notes/_edit_form.html.haml
	app/views/shared/_issuable_filter.html.haml
parents 76aad9b7 de040ffa
v 7.9.0 (unreleased)
- Fix broken access control for note attachments (Hannes Rosenögger)
v 7.8.0 (unreleased)
- Replace highlight.js with rouge-fork rugments (Stefan Tatschner)
- Make project search case insensitive (Hannes Rosenögger)
......@@ -10,7 +13,7 @@ v 7.8.0 (unreleased)
- View note image attachments in new tab when clicked instead of downloading them
- Improve sorting logic in UI and API. Explicitly define what sorting method is used by default
- Allow more variations for commit messages closing issues (Julien Bianchi and Hannes Rosenögger)
- Fix overflow at sidebar when have several itens
- Fix overflow at sidebar when have several items
- Add notes for label changes in issue and merge requests
- Show tags in commit view (Hannes Rosenögger)
- Only count a user's vote once on a merge request or issue (Michael Clarke)
......@@ -54,6 +57,13 @@ v 7.8.0 (unreleased)
- Link head panel titles to relevant root page.
- Allow users that signed up via OAuth to set their password in order to use Git over HTTP(S).
- Upgrade Rails gem to version 4.1.9.
- 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.
- 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
- Update GitLab Shell to version 2.4.2 that fixes a bug when developers can push to protected branch
......
......@@ -47,6 +47,9 @@ GEM
astrolabe (1.3.0)
parser (>= 2.2.0.pre.3, < 3.0)
attr_required (1.0.0)
autoprefixer-rails (5.1.6)
execjs
json
awesome_print (1.2.0)
axiom-types (0.0.5)
descendants_tracker (~> 0.0.1)
......@@ -57,8 +60,9 @@ GEM
erubis (>= 2.6.6)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
bootstrap-sass (3.0.3.0)
sass (~> 3.2)
bootstrap-sass (3.3.3)
autoprefixer-rails (>= 5.0.0.1)
sass (>= 3.2.19)
browser (0.7.2)
builder (3.2.2)
cal-heatmap-rails (0.0.1)
......
......@@ -71,7 +71,7 @@ Thanks for the issue report. Please reformat your issue to conform to the issue
### 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
......
......@@ -60,7 +60,7 @@ Please see the [requirements documentation](doc/install/requirements.md) for sys
## Installation
The recommended way to install GitLab is using the provided [Omnibus packages](https://about.gitlab.com/downloads/). Compared to a manual installation, this is faster and less error prone. Just select your operating system, download the respective package (Debian or RPM) and install it using the system's package manager.
The recommended way to install GitLab is using the provided [Omnibus packages](https://about.gitlab.com/downloads/). Compared to an installation from source, this is faster and less error prone. Just select your operating system, download the respective package (Debian or RPM) and install it using the system's package manager.
There are various other options to install GitLab, please refer to the [installation page on the GitLab website](https://about.gitlab.com/installation/) for more information.
......@@ -76,7 +76,7 @@ Since 2011 a minor or major version of GitLab is released on the 22nd of every m
## Upgrading
For updating the Omnibus installation please see the [update documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md). For manual installations there is an [upgrader script](doc/update/upgrader.md) and there are [upgrade guides](doc/update) detailing all necessary commands to migrate to the next version.
For updating the Omnibus installation please see the [update documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md). For installations from source there is an [upgrader script](doc/update/upgrader.md) and there are [upgrade guides](doc/update) detailing all necessary commands to migrate to the next version.
## Install a development environment
......
7.8.0.pre
7.9.0.pre
......@@ -15,3 +15,9 @@ class @Issue
"issue"
updateTaskState
)
$('.issuable-affix').affix offset:
top: ->
@top = $('.issue-details').outerHeight(true) + 25
bottom: ->
@bottom = $('.footer').outerHeight(true)
......@@ -15,7 +15,7 @@
$(this).html totalIssues + 1
else
$(this).html totalIssues - 1
$("body").on "click", ".issues-filters .dropdown-menu a", ->
$("body").on "click", ".issues-other-filters .dropdown-menu a", ->
$('.issues-list').block(
message: null,
overlayCSS:
......@@ -77,9 +77,9 @@
ids.push $(value).attr("data-id")
$("#update_issues_ids").val ids
$(".issues-filters").hide()
$(".issues-other-filters").hide()
$(".issues_bulk_update").show()
else
$("#update_issues_ids").val []
$(".issues_bulk_update").hide()
$(".issues-filters").show()
$(".issues-other-filters").show()
......@@ -20,6 +20,12 @@ class @MergeRequest
if $("a.btn-close").length
$("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
$: (selector) ->
this.$el.find(selector)
......
......@@ -77,7 +77,7 @@ class @Notes
$(document).off "click", ".js-discussion-reply-button"
$(document).off "click", ".js-add-diff-note-button"
$(document).off "visibilitychange"
$(document).off "keypress", @notes_forms
$(document).off "keydown", @notes_forms
$(document).off "keyup", ".js-note-text"
$(document).off "click", ".js-note-target-reopen"
$(document).off "click", ".js-note-target-close"
......@@ -272,7 +272,7 @@ class @Notes
note_li = $(".note-row-" + note.id)
note_li.replaceWith(note.html)
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
......@@ -284,7 +284,7 @@ class @Notes
showEditForm: (e) ->
e.preventDefault()
note = $(this).closest(".note")
note.find(".note-text").hide()
note.find(".note-body > .note-text").hide()
note.find(".note-header").hide()
base_form = note.find(".note-edit-form")
form = base_form.clone().insertAfter(base_form)
......@@ -311,7 +311,7 @@ class @Notes
cancelEdit: (e) ->
e.preventDefault()
note = $(this).closest(".note")
note.find(".note-text").show()
note.find(".note-body > .note-text").show()
note.find(".note-header").show()
note.find(".current-note-edit-form").remove()
......@@ -345,7 +345,7 @@ class @Notes
removeAttachment: ->
note = $(this).closest(".note")
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(".note-edit-form").hide()
......
......@@ -17,6 +17,10 @@ h3.page-title {
font-size: 22px;
}
h4.page-title {
margin-top: 0px;
}
h6 {
color: #888;
text-transform: uppercase;
......@@ -131,4 +135,4 @@ textarea.js-gfm-input {
.strikethrough {
text-decoration: line-through;
}
\ No newline at end of file
}
......@@ -12,6 +12,7 @@
border-left: 1px solid #666;
}
// highlight line via anchor
pre.hll {
background-color: #fff !important;
}
......
......@@ -12,6 +12,11 @@
border-left: 1px solid #555;
}
// highlight line via anchor
pre.hll {
background-color: #49483e !important;
}
.hll { background-color: #49483e }
.c { color: #75715e } /* Comment */
.err { color: #960050; background-color: #1e0010 } /* Error */
......
......@@ -12,6 +12,11 @@
border-left: 1px solid #113b46;
}
// highlight line via anchor
pre.hll {
background-color: #073642 !important;
}
/* Solarized Dark
For use with Jekyll and Pygments
......
......@@ -12,6 +12,11 @@
border-left: 1px solid #c5d0d4;
}
// highlight line via anchor
pre.hll {
background-color: #eee8d5 !important;
}
/* Solarized Light
For use with Jekyll and Pygments
......
......@@ -12,6 +12,11 @@
border-left: 1px solid #bbb;
}
// highlight line via anchor
pre.hll {
background-color: #f8eec7 !important;
}
.hll { background-color: #f8f8f8 }
.c { color: #999988; font-style: italic; }
.err { color: #a61717; background-color: #e3d2d2; }
......
......@@ -120,6 +120,15 @@
}
}
.dash-new-group {
background: $bg_success;
border: 1px solid $border_success;
a {
color: #FFF;
}
}
.dash-list .str-truncated {
max-width: 72%;
}
......@@ -64,6 +64,10 @@
.md {
font-size: 13px;
iframe.twitter-share-button {
vertical-align: bottom;
}
}
pre {
......
@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 @@
}
}
.issue-show-labels .color-label {
padding: 6px 10px;
.issue-show-labels {
a {
margin-right: 5px;
margin-bottom: 5px;
display: inline-block;
.color-label {
padding: 6px 10px;
}
}
}
form.edit-issue {
......
......@@ -24,6 +24,7 @@
.accept-control {
display: inline-block;
margin: 0;
margin-left: 20px;
padding: 10px 0;
line-height: 20px;
......@@ -31,6 +32,7 @@
.remove_source_checkbox {
margin: 0;
font-weight: bold;
}
}
}
......@@ -185,6 +187,13 @@
}
}
.merge-request-show-labels .label {
padding: 6px 10px;
.merge-request-show-labels {
a {
margin-right: 5px;
margin-bottom: 5px;
display: inline-block;
.color-label {
padding: 6px 10px;
}
}
}
......@@ -40,12 +40,16 @@
.nav-sidebar li {
&.active a {
color: #111;
background: #EEE;
color: #333;
background: #FFF;
font-weight: bold;
border: 1px solid #EEE;
border-right: 1px solid transparent;
border-left: 3px solid $style_color;
&.no-highlight {
background: none;
border: none;
}
i {
......@@ -65,7 +69,7 @@
color: #555;
display: block;
text-decoration: none;
padding: 6px 15px;
padding: 8px 15px;
font-size: 13px;
line-height: 20px;
text-shadow: 0 1px 2px #FFF;
......@@ -133,7 +137,7 @@
li a {
padding-left: 18px;
font-size: 14px;
padding: 10px 15px;
padding: 8px 15px;
text-align: center;
& > span {
......
......@@ -26,6 +26,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:signup_enabled,
:signin_enabled,
:gravatar_enabled,
:twitter_sharing_enabled,
:sign_in_text,
:home_page_url
)
......
......@@ -12,11 +12,7 @@ class DashboardController < ApplicationController
@groups = current_user.authorized_groups.order_name_asc
@has_authorized_projects = @projects.count > 0
@projects_count = @projects.count
@projects = @projects.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)
@projects = @projects.includes(:namespace).limit(@projects_limit)
@last_push = current_user.recent_push
......@@ -24,8 +20,16 @@ class DashboardController < ApplicationController
respond_to do |format|
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
......@@ -74,4 +78,10 @@ class DashboardController < ApplicationController
def load_projects
@projects = current_user.authorized_projects.sorted_by_activity.non_archived
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
......@@ -18,7 +18,7 @@ class Explore::ProjectsController < ApplicationController
def starred
@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)
end
end
......@@ -10,11 +10,11 @@ class GroupsController < ApplicationController
# Load group projects
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
before_filter :set_title, only: [:new, :create]
def new
@group = Group.new
end
......@@ -32,15 +32,21 @@ class GroupsController < ApplicationController
end
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
@projects = @projects.includes(:namespace)
respond_to do |format|
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
......@@ -149,4 +155,10 @@ class GroupsController < ApplicationController
def group_params
params.require(:group).permit(:name, :description, :path, :avatar)
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
......@@ -16,6 +16,7 @@ class ProfilesController < ApplicationController
def applications
@applications = current_user.oauth_applications
@authorized_tokens = current_user.oauth_authorized_tokens
@authorized_apps = @authorized_tokens.map(&:application).uniq
end
def update
......
......@@ -27,7 +27,7 @@ class Projects::TagsController < Projects::ApplicationController
tag = @repository.find_tag(params[:id])
if tag && @repository.rm_tag(tag.name)
Event.create_ref_event(@project, current_user, tag, 'rm', 'refs/tags')
EventCreateService.new.push_ref(@project, current_user, tag, 'rm', 'refs/tags')
end
respond_to do |format|
......
......@@ -5,9 +5,10 @@ class ProjectsController < ApplicationController
# Authorize
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]
before_filter :set_title, only: [:new, :create]
def new
@project = Project.new
......@@ -65,9 +66,6 @@ class ProjectsController < ApplicationController
end
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))
......@@ -85,7 +83,12 @@ class ProjectsController < ApplicationController
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
......
......@@ -4,19 +4,20 @@ class UsersController < ApplicationController
layout :determine_layout
def show
# Projects user can view
visible_projects = ProjectsFinder.new.execute(current_user)
authorized_projects_ids = visible_projects.pluck(:id)
@contributed_projects = Project.
where(id: authorized_projects_ids & @user.contributed_projects_ids).
in_group_namespace.includes(:namespace)
@projects = @user.personal_projects.
where(id: authorized_projects_ids)
where(id: authorized_projects_ids).includes(:namespace)
# Collect only groups common for both users
@groups = @user.groups & GroupsFinder.new.execute(current_user)
# Get user activity feed for projects common for both users
@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_url = user_path(@user)
......@@ -28,8 +29,8 @@ class UsersController < ApplicationController
end
def calendar
visible_projects = ProjectsFinder.new.execute(current_user)
calendar = Gitlab::CommitsCalendar.new(visible_projects, @user)
projects = Project.where(id: authorized_projects_ids & @user.contributed_projects_ids)
calendar = Gitlab::CommitsCalendar.new(projects, @user)
@timestamps = calendar.timestamps
@starting_year = calendar.starting_year
@starting_month = calendar.starting_month
......@@ -54,4 +55,10 @@ class UsersController < ApplicationController
return authenticate_user!
end
end
def authorized_projects_ids
# Projects user can view
@authorized_projects_ids ||=
ProjectsFinder.new.execute(current_user).pluck(:id)
end
end
......@@ -8,7 +8,7 @@ class TrendingProjectsFinder
# for period of time - ex. month
projects.joins(:notes).where('notes.created_at > ?', start_date).
select("projects.*, count(notes.id) as ncount").
group("projects.id").order("ncount DESC")
group("projects.id").reorder("ncount DESC")
end
private
......
......@@ -51,7 +51,13 @@ module ApplicationHelper
end
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?
image_tag project.avatar.url, options
elsif project.avatar_in_git
......
......@@ -3,6 +3,10 @@ module ApplicationSettingsHelper
current_application_settings.gravatar_enabled?
end
def twitter_sharing_enabled?
current_application_settings.twitter_sharing_enabled?
end
def signup_enabled?
current_application_settings.signup_enabled?
end
......
......@@ -17,7 +17,7 @@ module BlobHelper
end
def no_highlight_files
%w(credits changelog copying copyright license authors)
%w(credits changelog news copying copyright license authors)
end
def edit_blob_link(project, ref, path, options = {})
......
......@@ -10,11 +10,15 @@ module EventsHelper
end
def event_action_name(event)
target = if event.target_type
event.target_type.titleize.downcase
else
'project'
end
target = if event.target_type
if event.note?
event.note_target_type
else
event.target_type.titleize.downcase
end
else
'project'
end
[event.action_name, target].join(" ")
end
......@@ -42,21 +46,30 @@ module EventsHelper
end
def event_feed_title(event)
if event.issue?
"#{event.author_name} #{event.action_name} issue ##{event.target_iid}: #{event.issue_title} at #{event.project_name}"
elsif event.merge_request?
"#{event.author_name} #{event.action_name} MR ##{event.target_iid}: #{event.merge_request_title} at #{event.project_name}"
elsif event.push?
"#{event.author_name} #{event.push_action_name} #{event.ref_type} #{event.ref_name} at #{event.project_name}"
elsif event.membership_changed?
"#{event.author_name} #{event.action_name} #{event.project_name}"
elsif event.note? && event.note_commit?
"#{event.author_name} commented on #{event.note_target_type} #{event.note_short_commit_id} at #{event.project_name}"
elsif event.note?
"#{event.author_name} commented on #{event.note_target_type} ##{truncate event.note_target_iid} at #{event.project_name}"
else
""
words = []
words << event.author_name
words << event_action_name(event)
if event.push?
words << event.ref_type
words << event.ref_name
words << "at"
elsif event.commented?
if event.note_commit?
words << event.note_short_commit_id
else
words << "##{truncate event.note_target_iid}"
end
words << "at"
elsif event.target
words << "##{event.target_iid}:"
words << event.target.title if event.target.respond_to?(:title)
words << "at"
end
words << event.project_name
words.join(" ")
end
def event_feed_url(event)
......@@ -106,8 +119,6 @@ module EventsHelper
render "events/event_push", event: event
elsif event.merge_request?
render "events/event_merge_request", merge_request: event.merge_request
elsif event.push?
render "events/event_push", event: event
elsif event.note?
render "events/event_note", note: event.note
end
......
......@@ -110,7 +110,7 @@ module GitlabMarkdownHelper
end
def link_to_ignore?(link)
if link =~ /\#\w+/
if link =~ /\A\#\w+/
# ignore anchors like <a href="#my-header">
true
else
......@@ -122,10 +122,11 @@ module GitlabMarkdownHelper
["http://","https://", "ftp://", "mailto:"]
end
def rebuild_path(path)
path.gsub!(/(#.*)/, "")
def rebuild_path(file_path)
file_path = file_path.dup
file_path.gsub!(/(#.*)/, "")
id = $1 || ""
file_path = relative_file_path(path)
file_path = relative_file_path(file_path)
file_path = sanitize_slashes(file_path)
[
......
......@@ -8,6 +8,7 @@
# signup_enabled :boolean
# signin_enabled :boolean
# gravatar_enabled :boolean
# twitter_sharing_enabled :boolean
# sign_in_text :text
# created_at :datetime
# updated_at :datetime
......@@ -30,6 +31,7 @@ class ApplicationSetting < ActiveRecord::Base
default_branch_protection: Settings.gitlab['default_branch_protection'],
signup_enabled: Settings.gitlab['signup_enabled'],
signin_enabled: Settings.gitlab['signin_enabled'],
twitter_sharing_enabled: Settings.gitlab['twitter_sharing_enabled'],
gravatar_enabled: Settings.gravatar['enabled'],
sign_in_text: Settings.extra['sign_in_text'],
)
......
......@@ -47,31 +47,9 @@ class Event < ActiveRecord::Base
scope :recent, -> { order("created_at DESC") }
scope :code_push, -> { where(action: PUSHED) }
scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent }
scope :with_associations, -> { includes(project: :namespace) }
class << self
def create_ref_event(project, user, ref, action = 'add', prefix = 'refs/heads')
commit = project.repository.commit(ref.target)
if action.to_s == 'add'
before = '00000000'
after = commit.id
else
before = commit.id
after = '00000000'
end
Event.create(
project: project,
action: Event::PUSHED,
data: {
ref: "#{prefix}/#{ref.name}",
before: before,
after: after
},
author_id: user.id
)
end
def reset_event_cache_for(target)
Event.where(target_id: target.id, target_type: target.class.to_s).
order('id DESC').limit(100).
......@@ -84,6 +62,8 @@ class Event < ActiveRecord::Base
true
elsif membership_changed?
true
elsif created_project?
true
else
(issue? || merge_request? || note? || milestone?) && target
end
......@@ -98,25 +78,51 @@ class Event < ActiveRecord::Base
end
def target_title
if target && target.respond_to?(:title)
target.title
end
target.title if target && target.respond_to?(:title)
end
def created?
action == CREATED
end
def push?
action == self.class::PUSHED && valid_push?
action == PUSHED && valid_push?
end
def merged?
action == self.class::MERGED
action == MERGED
end
def closed?
action == self.class::CLOSED
action == CLOSED
end
def reopened?
action == self.class::REOPENED
action == REOPENED
end
def joined?
action == JOINED
end
def left?
action == LEFT
end
def commented?
action == COMMENTED
end
def membership_changed?
joined? || left?
end
def created_project?
created? && !target
end
def created_target?
created? && target
end
def milestone?
......@@ -135,32 +141,32 @@ class Event < ActiveRecord::Base
target_type == "MergeRequest"
end
def joined?
action == JOINED
end
def left?
action == LEFT
end
def membership_changed?
joined? || left?
def milestone
target if milestone?
end
def issue
target if target_type == "Issue"
target if issue?
end
def merge_request
target if target_type == "MergeRequest"
target if merge_request?
end
def note
target if target_type == "Note"
target if note?
end
def action_name
if closed?
if push?
if new_ref?
"pushed new"
elsif rm_ref?
"deleted"
else
"pushed to"
end
elsif closed?
"closed"
elsif merged?
"accepted"
......@@ -168,6 +174,10 @@ class Event < ActiveRecord::Base
'joined'
elsif left?
'left'
elsif commented?
"commented on"
elsif created_project?
"created"
else
"opened"
end
......@@ -236,16 +246,6 @@ class Event < ActiveRecord::Base
tag? ? "tag" : "branch"
end
def push_action_name
if new_ref?
"pushed new"
elsif rm_ref?
"deleted"
else
"pushed to"
end
end
def push_with_commits?
md_ref? && commits.any? && commit_from && commit_to
end
......
......@@ -114,13 +114,11 @@ class ProjectMember < Member
end
def post_create_hook
Event.create(
project_id: self.project.id,
action: Event::JOINED,
author_id: self.user.id
)
notification_service.new_team_member(self) unless owner?
unless owner?
event_service.join_project(self.project, self.user)
notification_service.new_team_member(self)
end
system_hook_service.execute_hooks_for(self, :create)
end
......@@ -129,15 +127,14 @@ class ProjectMember < Member
end
def post_destroy_hook
Event.create(
project_id: self.project.id,
action: Event::LEFT,
author_id: self.user.id
)
event_service.leave_project(self.project, self.user)
system_hook_service.execute_hooks_for(self, :destroy)
end
def event_service
EventCreateService.new
end
def notification_service
NotificationService.new
end
......
......@@ -55,14 +55,13 @@ class User < ActiveRecord::Base
include Gitlab::ConfigHelper
include TokenAuthenticatable
extend Gitlab::ConfigHelper
extend Gitlab::CurrentSettings
include Gitlab::CurrentSettings
default_value_for :admin, false
default_value_for :can_create_group, gitlab_config.default_can_create_group
default_value_for :can_create_team, false
default_value_for :hide_no_ssh_key, false
default_value_for :hide_no_password, false
default_value_for :projects_limit, current_application_settings.default_projects_limit
default_value_for :theme_id, gitlab_config.default_theme
devise :database_authenticatable, :lockable, :async,
......@@ -141,6 +140,7 @@ class User < ActiveRecord::Base
before_save :ensure_authentication_token
after_save :ensure_namespace_correct
after_initialize :set_projects_limit
after_create :post_create_hook
after_destroy :post_destroy_hook
......@@ -255,7 +255,7 @@ class User < ActiveRecord::Base
counter = 0
base = username
while User.by_login(username).present? || Namespace.by_path(username).present?
counter += 1
counter += 1
username = "#{base}#{counter}"
end
......@@ -459,10 +459,17 @@ class User < ActiveRecord::Base
def set_notification_email
if self.notification_email.blank? || !self.all_emails.include?(self.notification_email)
self.notification_email = self.email
self.notification_email = self.email
end
end
def set_projects_limit
connection_default_value_defined = new_record? && !projects_limit_changed?
return unless self.projects_limit.nil? || connection_default_value_defined
self.projects_limit = current_application_settings.default_projects_limit
end
def requires_ldap_check?
if !Gitlab.config.ldap.enabled
false
......@@ -559,7 +566,7 @@ class User < ActiveRecord::Base
def post_create_hook
log_info("User \"#{self.name}\" (#{self.email}) was created")
notification_service.new_user(self, @reset_token)
notification_service.new_user(self, @reset_token) if self.created_by_id
system_hook_service.execute_hooks_for(self, :create)
end
......@@ -607,4 +614,13 @@ class User < ActiveRecord::Base
def oauth_authorized_tokens
Doorkeeper::AccessToken.where(resource_owner_id: self.id, revoked_at: nil)
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
......@@ -17,7 +17,7 @@ class CreateBranchService < BaseService
new_branch = repository.find_branch(branch_name)
if new_branch
Event.create_ref_event(project, current_user, new_branch, 'add')
EventCreateService.new.push_ref(project, current_user, new_branch, 'add')
return success(new_branch)
else
return error('Invalid reference name')
......
......@@ -26,7 +26,7 @@ class CreateTagService < BaseService
project.gitlab_ci_service.async_execute(push_data)
end
Event.create_ref_event(project, current_user, new_tag, 'add', 'refs/tags')
EventCreateService.new.push_ref(project, current_user, new_tag, 'add', 'refs/tags')
success(new_tag)
else
error('Invalid reference name')
......
......@@ -25,7 +25,7 @@ class DeleteBranchService < BaseService
end
if repository.rm_branch(branch_name)
Event.create_ref_event(project, current_user, branch, 'rm')
EventCreateService.new.push_ref(project, current_user, branch, 'rm')
success('Branch was removed')
else
return error('Failed to remove branch')
......
......@@ -7,58 +7,98 @@
#
class EventCreateService
def open_issue(issue, current_user)
create_event(issue, current_user, Event::CREATED)
create_record_event(issue, current_user, Event::CREATED)
end
def close_issue(issue, current_user)
create_event(issue, current_user, Event::CLOSED)
create_record_event(issue, current_user, Event::CLOSED)
end
def reopen_issue(issue, current_user)
create_event(issue, current_user, Event::REOPENED)
create_record_event(issue, current_user, Event::REOPENED)
end
def open_mr(merge_request, current_user)
create_event(merge_request, current_user, Event::CREATED)
create_record_event(merge_request, current_user, Event::CREATED)
end
def close_mr(merge_request, current_user)
create_event(merge_request, current_user, Event::CLOSED)
create_record_event(merge_request, current_user, Event::CLOSED)
end
def reopen_mr(merge_request, current_user)
create_event(merge_request, current_user, Event::REOPENED)
create_record_event(merge_request, current_user, Event::REOPENED)
end
def merge_mr(merge_request, current_user)
create_event(merge_request, current_user, Event::MERGED)
create_record_event(merge_request, current_user, Event::MERGED)
end
def open_milestone(milestone, current_user)
create_event(milestone, current_user, Event::CREATED)
create_record_event(milestone, current_user, Event::CREATED)
end
def close_milestone(milestone, current_user)
create_event(milestone, current_user, Event::CLOSED)
create_record_event(milestone, current_user, Event::CLOSED)
end
def reopen_milestone(milestone, current_user)
create_event(milestone, current_user, Event::REOPENED)
create_record_event(milestone, current_user, Event::REOPENED)
end
def leave_note(note, current_user)
create_event(note, current_user, Event::COMMENTED)
create_record_event(note, current_user, Event::COMMENTED)
end
def join_project(project, current_user)
create_event(project, current_user, Event::JOINED)
end
def leave_project(project, current_user)
create_event(project, current_user, Event::LEFT)
end
def create_project(project, current_user)
create_event(project, current_user, Event::CREATED)
end
def push_ref(project, current_user, ref, action = 'add', prefix = 'refs/heads')
commit = project.repository.commit(ref.target)
if action.to_s == 'add'
before = '00000000'
after = commit.id
else
before = commit.id
after = '00000000'
end
data = {
ref: "#{prefix}/#{ref.name}",
before: before,
after: after
}
push(project, current_user, data)
end
def push(project, current_user, push_data)
create_event(project, current_user, Event::PUSHED, data: push_data)
end
private
def create_event(record, current_user, status)
Event.create(
project: record.project,
target_id: record.id,
target_type: record.class.name,
def create_record_event(record, current_user, status)
create_event(record.project, current_user, status, target_id: record.id, target_type: record.class.name)
end
def create_event(project, current_user, status, attributes = {})
attributes.reverse_merge!(
project: project,
action: status,
author_id: current_user.id
)
Event.create(attributes)
end
end
......@@ -52,7 +52,7 @@ class GitPushService
end
@push_data = post_receive_data(oldrev, newrev, ref)
create_push_event(@push_data)
EventCreateService.new.push(project, user, @push_data)
project.execute_hooks(@push_data.dup, :push_hooks)
project.execute_services(@push_data.dup)
end
......@@ -60,15 +60,6 @@ class GitPushService
protected
def create_push_event(push_data)
Event.create!(
project: project,
action: Event::PUSHED,
data: push_data,
author_id: push_data[:user_id]
)
end
# Extract any GFM references from the pushed commit messages. If the configured issue-closing regex is matched,
# close the referenced Issue. Create cross-reference Notes corresponding to any other referenced Mentionables.
def process_commit_messages(ref)
......
......@@ -5,7 +5,7 @@ class GitTagPushService
@project, @user = project, user
@push_data = create_push_data(oldrev, newrev, ref)
create_push_event
EventCreateService.new.push(project, user, @push_data)
project.repository.expire_cache
project.execute_hooks(@push_data.dup, :tag_push_hooks)
......@@ -22,13 +22,4 @@ class GitTagPushService
Gitlab::PushDataBuilder.
build(project, user, oldrev, newrev, ref, [])
end
def create_push_event
Event.create!(
project: project,
action: Event::PUSHED,
data: push_data,
author_id: push_data[:user_id]
)
end
end
......@@ -52,13 +52,7 @@ module Projects
end
end
if @project.persisted?
if @project.wiki_enabled?
@project.create_wiki
end
after_create_actions
end
after_create_actions if @project.persisted?
@project
rescue => ex
......@@ -79,6 +73,10 @@ module Projects
def after_create_actions
log_info("#{@project.owner.name} created a new project \"#{@project.name_with_namespace}\"")
@project.create_wiki if @project.wiki_enabled?
event_service.create_project(@project, current_user)
system_hook_service.execute_hooks_for(@project, :create)
unless @project.group
......
......@@ -19,6 +19,11 @@
= f.label :gravatar_enabled, class: 'control-label'
.col-sm-10
= f.check_box :gravatar_enabled, class: 'checkbox'
.form-group
= f.label :twitter_sharing_enabled, "Twitter enabled", class: 'control-label'
.col-sm-10
= f.check_box :twitter_sharing_enabled, class: 'checkbox'
%span.help-block Show users button to share their newly created public or internal projects on twitter
%fieldset
%legend Misc
.form-group
......
......@@ -17,6 +17,6 @@
%tr{:id => "application_#{application.id}"}
%td= link_to application.name, admin_application_path(application)
%td= application.redirect_uri
%td= application.access_tokens.count
%td= application.access_tokens.map(&:resource_owner_id).uniq.count
%td= link_to 'Edit', edit_admin_application_path(application), class: 'btn btn-link'
%td= render 'delete_form', application: application
......@@ -13,15 +13,13 @@
.form-group
%strong Activity
.checkbox
= label_tag :with_push, 'Not empty'
= check_box_tag :with_push, 1, params[:with_push]
&nbsp;
%span.light Projects with push events
= label_tag :with_push do
= check_box_tag :with_push, 1, params[:with_push]
%span Projects with push events
.checkbox
= label_tag :abandoned, 'Abandoned'
= check_box_tag :abandoned, 1, params[:abandoned]
&nbsp;
%span.light No activity over 6 month
= label_tag :abandoned do
= check_box_tag :abandoned, 1, params[:abandoned]
%span No activity over 6 month
%fieldset
%strong Visibility level:
......
= render "events/event_last_push", event: @last_push
= render 'shared/event_filter'
- if @events.any?
.content_list
- else
.nothing-here-block Projects activity will be displayed here
.content_list
= spinner
......@@ -3,7 +3,7 @@
.input-group
= search_field_tag :filter_group, nil, placeholder: 'Filter by name', class: 'dash-filter form-control'
- if current_user.can_create_group?
.input-group-addon
.input-group-addon.dash-new-group
= link_to new_group_path, class: "" do
%strong New group
%ul.well-list.dash-list
......
= link_to namespace_project_path(project.namespace, project), class: dom_class(project) do
.dash-project-avatar
= project_icon("#{project.namespace.to_param}/#{project.to_param}", alt: '', class: 'avatar project-avatar s40')
= project_icon(project, alt: '', class: 'avatar project-avatar s40')
.dash-project-access-icon
= visibility_level_icon(project.visibility_level)
%span.str-truncated
......
......@@ -2,11 +2,11 @@
= f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus"
= f.password_field :password, class: "form-control bottom", placeholder: "Password"
- if devise_mapping.rememberable?
.remember-me
%label.checkbox.remember_me{for: "user_remember_me"}
.remember-me.checkbox
%label{for: "user_remember_me"}
= f.check_box :remember_me
%span Remember me
.pull-right
= link_to "Forgot your password?", new_password_path(resource_name)
.pull-right
= link_to "Forgot your password?", new_password_path(resource_name)
%div
= f.submit "Sign in", class: "btn btn-save"
......@@ -3,12 +3,14 @@
.event-item-timestamp
#{time_ago_with_tooltip(event.created_at)}
= cache event do
= cache [event, current_user] do
= image_tag avatar_icon(event.author_email, 24), class: "avatar s24", alt:''
- if event.push?
= render "events/event/push", event: event
- elsif event.note?
- elsif event.commented?
= render "events/event/note", event: event
- elsif event.created_project?
= render "events/event/created_project", event: event
- else
= render "events/event/common", event: event
\ No newline at end of file
.event-title
%span.author_name= link_to_author event
%span.event_label{class: event.action_name}= event_action_name(event)
%span.event_label{class: event.action_name}
= event_action_name(event)
- if event.target
%strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target]
- else
%strong= gfm event.target_title
at
at
- if event.project
= link_to_project event.project
- else
= event.project_name
- if event.target.respond_to?(:title)
.event-body
.event-note
......
.event-title
%span.author_name= link_to_author event
%span.event_label{class: event.action_name}
= event_action_name(event)
- if event.project
= link_to_project event.project
- else
= event.project_name
- if current_user == event.author && !event.project.private? && twitter_sharing_enabled?
.event-body
.event-note
.md
%p
Congratulations! Why not share your accomplishment with the world?
%a.twitter-share-button{ |
href: "https://twitter.com/share", |
"data-url" => event.project.web_url, |
"data-text" => "I just created a new project in GitLab! GitLab is version control on your server.", |
"data-size" => "medium", |
"data-related" => "gitlab", |
"data-hashtags" => "gitlab", |
"data-count" => "none"}
Tweet
%script{src: "//platform.twitter.com/widgets.js"}
\ No newline at end of file
.event-title
%span.author_name= link_to_author event
%span.event_label commented on #{event_note_title_html(event)} at
%span.event_label
= event.action_name
= event_note_title_html(event)
at
- if event.project
= link_to_project event.project
- else
......
.event-title
%span.author_name= link_to_author event
%span.event_label.pushed #{event.push_action_name} #{event.ref_type}
%span.event_label.pushed #{event.action_name} #{event.ref_type}
- if event.rm_ref?
%strong= event.ref_name
- else
......
......@@ -3,11 +3,9 @@
.project-access-icon
= visibility_level_icon(project.visibility_level)
= link_to project.name_with_namespace, [project.namespace.becomes(Namespace), project]
- if current_page?(starred_explore_projects_path)
%strong.pull-right
%i.fa.fa-star
= pluralize project.star_count, 'star'
%span.pull-right
%i.fa.fa-star
= project.star_count
.project-info
- if project.description.present?
......
......@@ -13,7 +13,7 @@
%li.project-row
= link_to namespace_project_path(project.namespace, project), class: dom_class(project) do
.dash-project-avatar
= project_icon("#{project.namespace.to_param}/#{project.to_param}", alt: '', class: 'avatar s40')
= project_icon(project, alt: '', class: 'avatar s40')
.dash-project-access-icon
= visibility_level_icon(project.visibility_level)
%span.str-truncated
......
......@@ -13,10 +13,7 @@
- if current_user
= render "events/event_last_push", event: @last_push
= render 'shared/event_filter'
- if @events.any?
.content_list
- else
.nothing-here-block Project activity will be displayed here
.content_list
= spinner
%aside.side.col-md-4
= render "projects", projects: @projects
......@@ -42,3 +42,9 @@
%li
Use
= link_to 'shortcuts', '#', onclick: 'Shortcuts.showHelp(event)'
%li
Get a support
= link_to 'subscription', 'https://about.gitlab.com/pricing/'
%li
= link_to 'Compare', 'https://about.gitlab.com/features/#compare'
GitLab editions
......@@ -49,8 +49,14 @@
%span
Graphs
= nav_link(controller: :milestones) do
= link_to project_milestones_path(@project), title: 'Milestones' do
%i.fa.fa-clock-o
%span
Milestones
- if project_nav_tab? :issues
= nav_link(controller: %w(issues milestones labels)) do
= nav_link(controller: :issues) do
= link_to url_for_project_issues, title: 'Issues', class: 'shortcuts-issues' do
%i.fa.fa-exclamation-circle
%span
......@@ -66,6 +72,12 @@
Merge Requests
%span.count.merge_counter= @project.merge_requests.opened.count
= nav_link(controller: :labels) do
= link_to project_labels_path(@project), title: 'Labels' do
%i.fa.fa-tags
%span
Labels
- if project_nav_tab? :wiki
= nav_link(controller: :wikis) do
= link_to namespace_project_wiki_path(@project.namespace, @project, :home), title: 'Wiki', class: 'shortcuts-wiki' do
......
......@@ -36,12 +36,12 @@
%th Scope
%th
%tbody
- @authorized_tokens.each do |token|
- application = token.application
%tr{:id => "application_#{application.id}"}
%td= application.name
- @authorized_apps.each do |app|
- token = app.authorized_tokens.order('created_at desc').first
%tr{:id => "application_#{app.id}"}
%td= app.name
%td= token.created_at
%td= token.scopes
%td= render 'doorkeeper/authorized_applications/delete_form', application: application
%td= render 'doorkeeper/authorized_applications/delete_form', application: app
- else
%p.light You dont have any authorized applications
- empty_repo = @project.empty_repo?
.project-home-panel{:class => ("empty-project" if empty_repo)}
.project-identicon-holder
= project_icon("#{@project.namespace.to_param}/#{@project.to_param}", alt: '', class: 'avatar project-avatar')
= project_icon(@project, alt: '', class: 'avatar project-avatar')
.project-home-row
.project-home-desc
- if @project.description.present?
......
......@@ -15,7 +15,7 @@
= f.label :description, 'Description', class: 'control-label'
.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'
.col-sm-12.hint
......
%ul.nav.nav-tabs
- if project_nav_tab? :issues
= nav_link(controller: :issues) do
= link_to namespace_project_issues_path(@project.namespace, @project), class: "tab" do
%i.fa.fa-exclamation-circle
Issues
- if project_nav_tab? :merge_requests
= nav_link(controller: :merge_requests) do
= link_to namespace_project_merge_requests_path(@project.namespace, @project), class: "tab" do
%i.fa.fa-tasks
Merge Requests
= nav_link(controller: :milestones) do
= link_to namespace_project_milestones_path(@project.namespace, @project), class: "tab" do
%i.fa.fa-clock-o
Milestones
= nav_link(controller: :labels) do
= link_to namespace_project_labels_path(@project.namespace, @project), class: "tab" do
%i.fa.fa-tags
Labels
- if current_controller?(:issues)
- if current_user
%li.hidden-xs
= link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }) do
%i.fa.fa-rss
%li.pull-right
.pull-right
.pull-left
= form_tag namespace_project_issues_path(@project.namespace, @project), method: :get, id: "issue_search_form", class: 'pull-left issue-search-form' do
.append-right-10.hidden-xs.hidden-sm
= search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input input-mn-300' }
= hidden_field_tag :state, params['state']
= hidden_field_tag :scope, params['scope']
= hidden_field_tag :assignee_id, params['assignee_id']
= hidden_field_tag :milestone_id, params['milestone_id']
= hidden_field_tag :label_id, params['label_id']
- if can? current_user, :write_issue, @project
= link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-left", title: "New Issue", id: "new_issue_link" do
%i.fa.fa-plus
New Issue
- if current_controller?(:merge_requests)
%li.pull-right
.pull-right
- if can? current_user, :write_merge_request, @project
= link_to new_namespace_project_merge_request_path(@project.namespace, @project), class: "btn btn-new pull-left", title: "New Merge Request" do
%i.fa.fa-plus
New Merge Request
......@@ -10,4 +10,4 @@
.md-write-holder
= yield
.md-preview-holder.hide
.js-md-preview
.js-md-preview{class: (preview_class if defined?(preview_class))}
......@@ -7,8 +7,8 @@
- Gitlab::VisibilityLevel.values.each do |level|
.radio
- restricted = restricted_visibility_levels.include?(level)
= f.radio_button :visibility_level, level, checked: (visibility_level == level), disabled: restricted
= label :project_visibility_level, level do
= f.radio_button :visibility_level, level, checked: (visibility_level == level), disabled: restricted
= visibility_level_icon(level)
.option-title
= visibility_level_label(level)
......
......@@ -15,5 +15,5 @@
%p
To preserve performance only
%strong #{allowed_diff_size} of #{diffs.size}
files displayed.
files are displayed.
......@@ -14,24 +14,24 @@
.voting_notes#notes= render "projects/notes/notes_with_form"
.col-md-3
%div
.clearfix
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
= 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?
.issuable-affix
.clearfix
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
= cross_project_reference(@project, @issue)
%hr
%h6 Labels
.issue-show-labels
- @issue.labels.each do |label|
= link_to namespace_project_issues_path(@project.namespace, @project, label_name: label.name) do
%p= render_colored_label(label)
.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
%h6 Labels
.issue-show-labels
- @issue.labels.each do |label|
= link_to namespace_project_issues_path(@project.namespace, @project, label_name: label.name) do
= render_colored_label(label)
.append-bottom-10
.check-all-holder
= check_box_tag "check_all_issues", nil, false, class: "check_all_issues left", disabled: !can?(current_user, :modify_issue, @project)
= 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[status]', options_for_select([['Open', 'open'], ['Closed', 'closed']]), prompt: "Status")
= project_users_select_tag('update[assignee_id]', placeholder: 'Assignee')
= select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone")
= hidden_field_tag 'update[issues_ids]', []
= hidden_field_tag :status, params[:status]
= button_tag "Update issues", class: "btn update_selected_issues btn-save"
.panel.panel-default
%ul.well-list.issues-list
= render @issues
......
= render "projects/issues_nav"
.append-bottom-10
.pull-right
.pull-left
- if current_user
.hidden-xs.pull-left
= link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do
%i.fa.fa-rss
= form_tag project_issues_path(@project), method: :get, id: "issue_search_form", class: 'pull-left issue-search-form' do
.append-right-10.hidden-xs.hidden-sm
= search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input input-mn-300' }
= hidden_field_tag :state, params['state']
= hidden_field_tag :scope, params['scope']
= hidden_field_tag :assignee_id, params['assignee_id']
= hidden_field_tag :milestone_id, params['milestone_id']
= hidden_field_tag :label_id, params['label_id']
- if can? current_user, :write_issue, @project
= link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-left", title: "New Issue", id: "new_issue_link" do
%i.fa.fa-plus
New Issue
= render 'shared/issuable_filter'
.clearfix
.issues_bulk_update.hide
= form_tag bulk_update_project_issues_path(@project), method: :post do
= select_tag('update[status]', options_for_select([['Open', 'open'], ['Closed', 'closed']]), prompt: "Status")
= project_users_select_tag('update[assignee_id]', placeholder: 'Assignee')
= select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone")
= hidden_field_tag 'update[issues_ids]', []
= hidden_field_tag :status, params[:status]
= button_tag "Update issues", class: "btn update_selected_issues btn-save"
.issues-holder
= render "issues"
%h4.page-title
.issue-box{ class: issue_box_class(@issue) }
- if @issue.closed?
Closed
- else
Open
Issue ##{@issue.iid}
%small.creator
&middot; created by #{link_to_member(@project, @issue.author)} #{issue_timestamp(@issue)}
.issue
.issue-details
%h4.page-title
.issue-box{ class: issue_box_class(@issue) }
- if @issue.closed?
Closed
- else
Open
Issue ##{@issue.iid}
%small.creator
&middot; created by #{link_to_member(@project, @issue.author)} #{issue_timestamp(@issue)}
.pull-right
- if can?(current_user, :write_issue, @project)
= link_to new_namespace_project_issue_path(@project.namespace, @project), class: "btn btn-grouped new-issue-link", title: "New Issue", id: "new_issue_link" do
%i.fa.fa-plus
New Issue
- if can?(current_user, :modify_issue, @issue)
- if @issue.closed?
= link_to 'Reopen', namespace_project_issue_path(@project.namespace, @project, @issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-grouped btn-reopen"
- else
= link_to 'Close', namespace_project_issue_path(@project.namespace, @project, @issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close", title: "Close Issue"
.pull-right
- if can?(current_user, :write_issue, @project)
= link_to new_namespace_project_issue_path(@project.namespace, @project), class: "btn btn-grouped new-issue-link", title: "New Issue", id: "new_issue_link" do
%i.fa.fa-plus
New Issue
- if can?(current_user, :modify_issue, @issue)
- if @issue.closed?
= link_to 'Reopen', namespace_project_issue_path(@project.namespace, @project, @issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-grouped btn-reopen"
- else
= link_to 'Close', namespace_project_issue_path(@project.namespace, @project, @issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close", title: "Close Issue"
= link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: "btn btn-grouped issuable-edit" do
%i.fa.fa-pencil-square-o
Edit
= link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: "btn btn-grouped issuable-edit" do
%i.fa.fa-pencil-square-o
Edit
%hr
%h3.issue-title
= gfm escape_once(@issue.title)
%div
- if @issue.description.present?
.description
.wiki
= preserve do
= markdown(@issue.description, parse_tasks: true)
%hr
%h3.issue-title
= gfm escape_once(@issue.title)
%div
- if @issue.description.present?
.description
.wiki
= preserve do
= markdown(@issue.description, parse_tasks: true)
%hr
= render "projects/issues/discussion"
%hr
.issue-discussion
= render "projects/issues/discussion"
= render "projects/issues_nav"
- if can? current_user, :admin_label, @project
= link_to new_namespace_project_label_path(@project.namespace, @project), class: "pull-right btn btn-new" do
New label
......
......@@ -10,22 +10,23 @@
= render "projects/merge_requests/show/participants"
= render "projects/notes/notes_with_form"
.col-md-3
.clearfix
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
= cross_project_reference(@project, @merge_request)
%hr
.context
%cite.cgray
= render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request }
%hr
.votes-holder
%h6 Votes
#votes= render 'votes/votes_block', votable: @merge_request
- if @merge_request.labels.any?
.issuable-affix
.clearfix
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
= cross_project_reference(@project, @merge_request)
%hr
.context
%cite.cgray
= render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request }
%hr
%h6 Labels
.merge-request-show-labels
- @merge_request.labels.each do |label|
= link_to namespace_project_merge_requests_path(@project.namespace, @project, label_name: label.name) do
%p= render_colored_label(label)
.votes-holder
%h6 Votes
#votes= render 'votes/votes_block', votable: @merge_request
- if @merge_request.labels.any?
%hr
%h6 Labels
.merge-request-show-labels
- @merge_request.labels.each do |label|
= link_to namespace_project_merge_requests_path(@project.namespace, @project, label_name: label.name) do
= render_colored_label(label)
......@@ -18,7 +18,7 @@
- if merge_request.assignee
assigned to #{link_to_member(merge_request.source_project, merge_request.assignee)}
- else
Work In Progress
Unassigned
- if merge_request.votes_count > 0
= render 'votes/votes_inline', votable: merge_request
- if merge_request.notes.any?
......
......@@ -19,7 +19,7 @@
.form-group.issuable-description
= f.label :description, 'Description', class: 'control-label'
.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'
.col-sm-12-hint
......
.merge-request{'data-url' => namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}
= render "projects/merge_requests/show/mr_title"
%hr
= render "projects/merge_requests/show/mr_box"
%hr
.append-bottom-20
.slead
%span From
- if @merge_request.for_fork?
%strong.label-branch<
- if @merge_request.source_project
= link_to @merge_request.source_project_namespace, namespace_project_path(@merge_request.source_project.namespace, @merge_request.source_project)
- else
\ #{@merge_request.source_project_namespace}
\:#{@merge_request.source_branch}
%span into
%strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch}
- else
%strong.label-branch #{@merge_request.source_branch}
%span into
%strong.label-branch #{@merge_request.target_branch}
- if @merge_request.open?
%span.pull-right
.btn-group
%a.btn.dropdown-toggle{ data: {toggle: :dropdown} }
%i.fa.fa-download
Download as
%span.caret
%ul.dropdown-menu
%li= link_to "Email Patches", namespace_project_merge_request_path(@project.namespace, @project, @merge_request, format: :patch)
%li= link_to "Plain Diff", namespace_project_merge_request_path(@project.namespace, @project, @merge_request, format: :diff)
.merge-request-details
= render "projects/merge_requests/show/mr_title"
%hr
= render "projects/merge_requests/show/mr_box"
%hr
.append-bottom-20
.slead
%span From
- if @merge_request.for_fork?
%strong.label-branch<
- if @merge_request.source_project
= link_to @merge_request.source_project_namespace, namespace_project_path(@merge_request.source_project.namespace, @merge_request.source_project)
- else
\ #{@merge_request.source_project_namespace}
\:#{@merge_request.source_branch}
%span into
%strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch}
- else
%strong.label-branch #{@merge_request.source_branch}
%span into
%strong.label-branch #{@merge_request.target_branch}
- if @merge_request.open?
%span.pull-right
.btn-group
%a.btn.dropdown-toggle{ data: {toggle: :dropdown} }
%i.fa.fa-download
Download as
%span.caret
%ul.dropdown-menu
%li= link_to "Email Patches", namespace_project_merge_request_path(@project.namespace, @project, @merge_request, format: :patch)
%li= link_to "Plain Diff", namespace_project_merge_request_path(@project.namespace, @project, @merge_request, format: :diff)
= render "projects/merge_requests/show/how_to_merge"
= render "projects/merge_requests/show/state_widget"
= render "projects/merge_requests/show/how_to_merge"
= render "projects/merge_requests/show/state_widget"
- if @commits.present?
%ul.nav.nav-tabs.merge-request-tabs
......
= render "projects/issues_nav"
.merge-requests-holder
.append-bottom-10
.pull-right
- if can? current_user, :write_merge_request, @project
= link_to new_project_merge_request_path(@project), class: "btn btn-new pull-left", title: "New Merge Request" do
%i.fa.fa-plus
New Merge Request
= render 'shared/issuable_filter'
.panel.panel-default
%ul.well-list.mr-list
......
......@@ -17,7 +17,7 @@
.accept-action
= f.submit "Accept Merge Request", class: "btn btn-create accept_merge_request"
- if can_remove_branch?(@merge_request.source_project, @merge_request.source_branch) && !@merge_request.for_fork?
.accept-control
.accept-control.checkbox
= label_tag :should_remove_source_branch, class: "remove_source_checkbox" do
= check_box_tag :should_remove_source_branch
Remove source-branch
......
......@@ -21,7 +21,7 @@
.form-group.milestone-description
= f.label :description, "Description", class: "control-label"
.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'
.hint
.pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
......
= render "projects/issues_nav"
.milestones_content
%h3.page-title
Milestones
- if can? current_user, :admin_milestone, @project
= link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "pull-right btn btn-new", title: "New Milestone" do
%i.fa.fa-plus
New Milestone
.pull-right
- if can? current_user, :admin_milestone, @project
= link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "pull-right btn btn-new", title: "New Milestone" do
%i.fa.fa-plus
New Milestone
= render 'shared/milestones_filter'
.milestones
......
= render "projects/issues_nav"
%h4.page-title
.issue-box{ class: issue_box_class(@milestone) }
- if @milestone.closed?
......
......@@ -52,7 +52,7 @@
%i.fa.fa-github
Import projects from GitHub
= render 'github_import_modal'
.project-import.form-group
.col-sm-2
.col-sm-10
......@@ -60,7 +60,7 @@
= link_to status_import_gitlab_path do
%i.fa.fa-heart
Import projects from GitLab.com
- else
- elsif request.host != 'gitlab.com'
= link_to '#', class: 'how_to_import_link light' do
%i.fa.fa-heart
Import projects from GitLab.com
......@@ -99,4 +99,4 @@
e.preventDefault()
import_modal = $(this).parent().find(".modal").show()
$('.modal-header .close').bind 'click', ->
$(".modal").hide()
\ No newline at end of file
$(".modal").hide()
.note-edit-form
= form_for note, url: namespace_project_note_path(@project.namespace, @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,
classes: 'note_text js-note-text'
......
......@@ -5,7 +5,7 @@
= f.hidden_field :noteable_id
= 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,
classes: 'note_text js-note-text'
......
......@@ -22,7 +22,7 @@
.form-group.wiki-content
= f.label :content, class: 'control-label'
.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'
.col-sm-12.hint
.pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}
......
......@@ -7,4 +7,5 @@
= link_to "#L#{i}", id: "L#{i}", rel: "#L#{i}" do
%i.fa.fa-link
= i
= highlight(blob.name, blob.data)
:preserve
#{highlight(blob.name, blob.data)}
.issues-filters
.pull-left.append-right-20
%ul.nav.nav-pills.nav-compact
.issues-state-filters
%ul.nav.nav-tabs
%li{class: ("active" if params[:state] == 'opened')}
= link_to page_filter_path(state: 'opened') do
%i.fa.fa-exclamation-circle
......@@ -14,99 +14,106 @@
%i.fa.fa-compass
All
.dropdown.inline.assignee-filter
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-user
%span.light assignee:
- if @assignee.present?
%strong= @assignee.name
- elsif params[:assignee_id] == "0"
Unassigned
- else
Any
%b.caret
%ul.dropdown-menu
%li
= link_to page_filter_path(assignee_id: nil) do
Any
= link_to page_filter_path(assignee_id: 0) do
Unassigned
- @assignees.sort_by(&:name).each do |user|
%li
= link_to page_filter_path(assignee_id: user.id) do
= image_tag avatar_icon(user.email), class: "avatar s16", alt: ''
= user.name
.dropdown.inline.prepend-left-10.author-filter
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-user
%span.light author:
- if @author.present?
%strong= @author.name
- elsif params[:author_id] == "0"
Unassigned
- else
Any
%b.caret
%ul.dropdown-menu
%li
= link_to page_filter_path(author_id: nil) do
Any
= link_to page_filter_path(author_id: 0) do
Unassigned
- @authors.sort_by(&:name).each do |user|
%li
= link_to page_filter_path(author_id: user.id) do
= image_tag avatar_icon(user.email), class: "avatar s16", alt: ''
= user.name
.dropdown.inline.prepend-left-10.milestone-filter
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-clock-o
%span.light milestone:
- if @milestone.present?
%strong= @milestone.title
- elsif params[:milestone_id] == "0"
None (backlog)
- else
Any
%b.caret
%ul.dropdown-menu
%li
= link_to page_filter_path(milestone_id: nil) do
Any
= link_to page_filter_path(milestone_id: 0) do
None (backlog)
- @milestones.each do |milestone|
%li
= link_to page_filter_path(milestone_id: milestone.id) do
%strong= milestone.title
%small.light= milestone.expires_at
%div
- if controller.controller_name == 'issues'
.check-all-holder
= check_box_tag "check_all_issues", nil, false,
class: "check_all_issues left",
disabled: !can?(current_user, :modify_issue, @project)
.issues-other-filters
.dropdown.inline.assignee-filter
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-user
%span.light assignee:
- if @assignee.present?
%strong= @assignee.name
- elsif params[:assignee_id] == "0"
Unassigned
- else
Any
%b.caret
%ul.dropdown-menu
%li
= link_to page_filter_path(assignee_id: nil) do
Any
= link_to page_filter_path(assignee_id: 0) do
Unassigned
- @assignees.sort_by(&:name).each do |user|
%li
= link_to page_filter_path(assignee_id: user.id) do
= image_tag avatar_icon(user.email), class: "avatar s16", alt: ''
= user.name
- if @project
.dropdown.inline.prepend-left-10.labels-filter
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-tags
%span.light label:
- if params[:label_name].present?
%strong= params[:label_name]
- else
Any
%b.caret
%ul.dropdown-menu
%li
= link_to page_filter_path(label_name: nil) do
.dropdown.inline.prepend-left-10.author-filter
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-user
%span.light author:
- if @author.present?
%strong= @author.name
- elsif params[:author_id] == "0"
Unassigned
- else
Any
- if @project.labels.any?
- @project.labels.each do |label|
%b.caret
%ul.dropdown-menu
%li
= link_to page_filter_path(author_id: nil) do
Any
= link_to page_filter_path(author_id: 0) do
Unassigned
- @authors.sort_by(&:name).each do |user|
%li
= link_to page_filter_path(label_name: label.name) do
= render_colored_label(label)
- else
= link_to page_filter_path(author_id: user.id) do
= image_tag avatar_icon(user.email), class: "avatar s16", alt: ''
= user.name
.dropdown.inline.prepend-left-10.milestone-filter
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-clock-o
%span.light milestone:
- if @milestone.present?
%strong= @milestone.title
- elsif params[:milestone_id] == "0"
None (backlog)
- else
Any
%b.caret
%ul.dropdown-menu
%li
= link_to generate_namespace_project_labels_path(@project.namespace, @project, redirect: request.original_url), method: :post do
%i.fa.fa-plus-circle
Create default labels
= link_to page_filter_path(milestone_id: nil) do
Any
= link_to page_filter_path(milestone_id: 0) do
None (backlog)
- @milestones.each do |milestone|
%li
= link_to page_filter_path(milestone_id: milestone.id) do
%strong= milestone.title
%small.light= milestone.expires_at
- if @project
.dropdown.inline.prepend-left-10.labels-filter
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-tags
%span.light label:
- if params[:label_name].present?
%strong= params[:label_name]
- else
Any
%b.caret
%ul.dropdown-menu
%li
= link_to page_filter_path(label_name: nil) do
Any
- if @project.labels.any?
- @project.labels.each do |label|
%li
= link_to page_filter_path(label_name: label.name) do
= render_colored_label(label)
- else
%li
= link_to generate_namespace_project_labels_path(@project.namespace, @project, redirect: request.original_url), method: :post do
%i.fa.fa-plus-circle
Create default labels
.pull-right
= render 'shared/sort_dropdown'
.pull-right
= render 'shared/sort_dropdown'
.milestones-filters.append-bottom-10
%ul.nav.nav-pills.nav-compact
%ul.nav.nav-tabs
%li{class: ("active" if params[:state].blank? || params[:state] == 'opened')}
= link_to milestones_filter_path(state: 'opened') do
%i.fa.fa-exclamation-circle
......
.panel.panel-default
.panel-heading Personal projects
%ul.well-list
- projects.each do |project|
%li
= link_to_project project
- if @contributed_projects.present?
.panel.panel-default
.panel-heading Projects contributed to
%ul.well-list
- @contributed_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
- 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
:javascript
new calendar(
......
......@@ -35,9 +35,7 @@
= render @events
.col-md-4
= render 'profile', user: @user
- if @projects.present?
= render 'projects', projects: @projects
= render 'projects'
:coffeescript
$ ->
......
......@@ -112,6 +112,7 @@ end
Settings.gitlab['time_zone'] ||= nil
Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil?
Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil?
Settings.gitlab['twitter_sharing_enabled'] ||= true if Settings.gitlab['twitter_sharing_enabled'].nil?
Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)' if Settings.gitlab['issue_closing_pattern'].nil?
......
......@@ -3,6 +3,7 @@ Gitlab::Seeder.quiet do
s.id = 1
s.name = 'Administrator'
s.email = 'admin@example.com'
s.notification_email = 'admin@example.com'
s.username = 'root'
s.password = '5iveL!fe'
s.admin = true
......
class AddTwitterSharingEnabledToApplicationSettings < ActiveRecord::Migration
def change
add_column :application_settings, :twitter_sharing_enabled, :boolean, default: true
end
end
......@@ -10,10 +10,11 @@
- [SSH](ssh/README.md) Setup your ssh keys and deploy keys for secure access to your projects.
- [Web hooks](web_hooks/web_hooks.md) Let GitLab notify you when new code has been pushed to your project.
- [Workflow](workflow/README.md) Using GitLab functionality and importing projects from GitHub and SVN.
- [GitLab as OAuth2 authentication service provider](integration/oauth_provider.md). It allows you to login to other applications from GitLab.
## Administrator documentation
- [Install](install/README.md) Requirements, directory structures and manual installation.
- [Install](install/README.md) Requirements, directory structures and installation from source.
- [Integration](integration/README.md) How to integrate with systems such as JIRA, Redmine, LDAP and Twitter.
- [Raketasks](raketasks/README.md) Backups, maintenance, automatic web hook setup and the importing of projects.
- [Custom git hooks](hooks/custom_hooks.md) Custom git hooks (on the filesystem) for when web hooks aren't enough.
......
......@@ -22,6 +22,7 @@
## Clients
Find API Clients for GitLab [on our website](https://about.gitlab.com/applications/#api-clients).
You can use [GitLab as an OAuth2 client](oauth2.md) to make API calls.
## Introduction
......@@ -67,7 +68,7 @@ curl https://localhost:3000/api/v3/user?access_token=OAUTH-TOKEN
curl -H "Authorization: Bearer OAUTH-TOKEN" https://localhost:3000/api/v3/user
```
Read more about [OAuth2 in GitLab](oauth2.md).
Read more about [GitLab as an OAuth2 client](oauth2.md).
## Status codes
......
......@@ -15,27 +15,20 @@ Parameters:
```json
[
{
"name": "master",
"commit": {
"author_email": "john@example.com",
"author_name": "John Smith",
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00",
"committer_email": "john@example.com",
"committer_name": "John Smith",
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
"parents": [
{
"id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
}
],
"tree": "46e82de44b1061621357f24c05515327f2795a95",
"message": "add projects API",
"author": {
"name": "John Smith",
"email": "john@example.com"
},
"committer": {
"name": "John Smith",
"email": "john@example.com"
},
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00"
"parent_ids": [
"4ad91d3c1144c406e50c7b33bae684bd6837faf8"
]
},
"name": "master",
"protected": true
}
]
......@@ -56,27 +49,20 @@ Parameters:
```json
{
"name": "master",
"commit": {
"author_email": "john@example.com",
"author_name": "John Smith",
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00",
"committer_email": "john@example.com",
"committer_name": "John Smith",
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
"parents": [
{
"id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
}
],
"tree": "46e82de44b1061621357f24c05515327f2795a95",
"message": "add projects API",
"author": {
"name": "John Smith",
"email": "john@example.com"
},
"committer": {
"name": "John Smith",
"email": "john@example.com"
},
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00"
"parent_ids": [
"4ad91d3c1144c406e50c7b33bae684bd6837faf8"
]
},
"name": "master",
"protected": true
}
```
......@@ -97,27 +83,20 @@ Parameters:
```json
{
"name": "master",
"commit": {
"author_email": "john@example.com",
"author_name": "John Smith",
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00",
"committer_email": "john@example.com",
"committer_name": "John Smith",
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
"parents": [
{
"id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
}
],
"tree": "46e82de44b1061621357f24c05515327f2795a95",
"message": "add projects API",
"author": {
"name": "John Smith",
"email": "john@example.com"
},
"committer": {
"name": "John Smith",
"email": "john@example.com"
},
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00"
"parent_ids": [
"4ad91d3c1144c406e50c7b33bae684bd6837faf8"
]
},
"name": "master",
"protected": true
}
```
......@@ -138,27 +117,20 @@ Parameters:
```json
{
"name": "master",
"commit": {
"author_email": "john@example.com",
"author_name": "John Smith",
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00",
"committer_email": "john@example.com",
"committer_name": "John Smith",
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
"parents": [
{
"id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
}
],
"tree": "46e82de44b1061621357f24c05515327f2795a95",
"message": "add projects API",
"author": {
"name": "John Smith",
"email": "john@example.com"
},
"committer": {
"name": "John Smith",
"email": "john@example.com"
},
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00"
"parent_ids": [
"4ad91d3c1144c406e50c7b33bae684bd6837faf8"
]
},
"name": "master",
"protected": false
}
```
......@@ -177,21 +149,20 @@ Parameters:
```json
{
"name": "my-new-branch",
"commit": {
"id": "8848c0e90327a0b70f1865b843fb2fbfb9345e57",
"message": "Merge pull request #54 from brightbox/use_fog_brightbox_module\n\nUpdate to use fog-brightbox module",
"parent_ids": [
"fff449e0bf453576f16c91d6544f00a2664009d8",
"f93a93626fec20fd659f4ed3ab2e64019b6169ae"
],
"authored_date": "2014-02-20T19:54:55+02:00",
"author_name": "john smith",
"author_email": "john@example.com",
"committed_date": "2014-02-20T19:54:55+02:00",
"committer_name": "john smith",
"committer_email": "john@example.com"
"author_name": "John Smith",
"authored_date": "2012-06-27T05:51:39-07:00",
"committed_date": "2012-06-28T03:44:20-07:00",
"committer_email": "john@example.com",
"committer_name": "John Smith",
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
"message": "add projects API",
"parent_ids": [
"4ad91d3c1144c406e50c7b33bae684bd6837faf8"
]
},
"name": "master",
"protected": false
}
```
......
......@@ -14,7 +14,6 @@ GET /groups
"id": 1,
"name": "Foobar Group",
"path": "foo-bar",
"owner_id": 18,
"description": "An interesting group"
}
]
......@@ -87,7 +86,6 @@ GET /groups?search=foobar
"id": 1,
"name": "Foobar Group",
"path": "foo-bar",
"owner_id": 18,
"description": "An interesting group"
}
]
......
# OAuth2 authentication
# GitLab as an OAuth2 client
OAuth2 is a protocol that enables us to get access to private details of user's account without getting its password.
This document is about using other OAuth authentication service providers to sign into GitLab.
If you want GitLab to be an OAuth authentication service provider to sign into other services please see the [Oauth2 provider documentation](../integration/oauth_provider.md).
Before using the OAuth2 you should create an application in user's account. Each application getting unique App ID and App Secret parameters. You should not share them.
OAuth2 is a protocol that enables us to authenticate a user without requiring them to give their password.
Before using the OAuth2 you should create an application in user's account. Each application gets a unique App ID and App Secret parameters. You should not share these.
This functionality is based on [doorkeeper gem](https://github.com/doorkeeper-gem/doorkeeper)
## Web Application Flow
This flow is using for authentication from third-party web sites and probably is most used.
This flow is using for authentication from third-party web sites and is probably used the most.
It basically consists of an exchange of an authorization token for an access token. For more detailed info, check out the [RFC spec here](http://tools.ietf.org/html/rfc6749#section-4.1)
This flow consists from 3 steps.
......
# What you should know about omnibus packages
Most users install GitLab using our omnibus packages. As a developer it can be
good to know how the omnibus packages differ from what you have on your laptop
when you are coding.
## Files are owned by root by default
All the files in the Rails tree (`app/`, `config/` etc.) are owned by 'root' in
omnibus installations. This makes the installation simpler and it provides
extra security. The omnibus reconfigure script contains commands that give
write access to the 'git' user only where needed.
For example, the 'git' user is allowed to write in the `log/` directory, in
`public/uploads`, and they are allowed to rewrite the `db/schema.rb` file.
In other cases, the reconfigure script tricks GitLab into not trying to write a
file. For instance, GitLab will generate a `.secret` file if it cannot find one
and write it to the Rails root. In the omnibus packages, reconfigure writes the
`.secret` file first, so that GitLab never tries to write it.
## Code, data and logs are in separate directories
The omnibus design separates code (read-only, under `/opt/gitlab`) from data
(read/write, under `/var/opt/gitlab`) and logs (read/write, under
`/var/log/gitlab`). To make this happen the reconfigure script sets custom
paths where it can in GitLab config files, and where there are no path
settings, it uses symlinks.
For example, `config/gitlab.yml` is treated as data so that file is a symlink.
The same goes for `public/uploads`. The `log/` directory is replaced by omnibus
with a symlink to `/var/log/gitlab/gitlab-rails`.
......@@ -24,7 +24,7 @@ set up a custom hook.
1. Pick a project that needs a custom git hook.
1. On the GitLab server, navigate to the project's repository directory.
For a manual install the path is usually
For an installation from source the path is usually
`/home/git/repositories/<group>/<project>.git`. For Omnibus installs the path is
usually `/var/opt/gitlab/git-data/repositories/<group>/<project>.git`.
1. Create a new directory in this location called `custom_hooks`.
......
......@@ -2,7 +2,7 @@
## Consider the Omnibus package installation
Since a manual installation is a lot of work and error prone we strongly recommend the fast and reliable [Omnibus package installation](https://about.gitlab.com/downloads/) (deb/rpm).
Since an installation from source is a lot of work and error prone we strongly recommend the fast and reliable [Omnibus package installation](https://about.gitlab.com/downloads/) (deb/rpm).
## Select Version to Install
......@@ -183,9 +183,9 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
### Clone the Source
# Clone GitLab repository
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-6-stable gitlab
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-8-stable gitlab
**Note:** You can change `7-6-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
**Note:** You can change `7-8-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
......@@ -280,7 +280,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
GitLab Shell is an SSH access and repository management software developed specially for GitLab.
# Run the installation task for gitlab-shell (replace `REDIS_URL` if needed):
sudo -u git -H bundle exec rake gitlab:shell:install[v2.4.2] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production
sudo -u git -H bundle exec rake gitlab:shell:install[v2.4.3] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production
# By default, the gitlab-shell config is generated from your main GitLab config.
# You can review (and modify) the gitlab-shell config as follows:
......
......@@ -22,7 +22,7 @@ For the installations options please see [the installation page on the GitLab we
- FreeBSD
On the above unsupported distributions is still possible to install GitLab yourself.
Please see the [manual installation guide](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) and the [unofficial installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) on the public wiki for more information.
Please see the [installation from source guide](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) and the [unofficial installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) on the public wiki for more information.
### Non-Unix operating systems such as Windows
......
......@@ -8,9 +8,8 @@ See the documentation below for details on how to configure these services.
- [LDAP](ldap.md) Set up sign in via LDAP
- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab, and Google via OAuth.
- [Slack](slack.md) Integrate with the Slack chat service
- [OAuth2 provider](oauth_provider.md) OAuth2 application creation
Jenkins support is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jenkins.html).
GitLab Enterprise Edition contains [advanced JIRA support](http://doc.gitlab.com/ee/integration/jira.html) and [advanced Jenkins support](http://doc.gitlab.com/ee/integration/jenkins.html).
## Project services
......
......@@ -8,6 +8,8 @@ GitLab has a great issue tracker but you can also use an external issue tracker
![Jira screenshot](jira-integration-points.png)
GitLab Enterprise Edition contains [advanced JIRA support](http://doc.gitlab.com/ee/integration/jira.html).
## Configuration
### Project Service
......@@ -23,7 +25,6 @@ Fill in the required details on the page:
* `issues_url` The URL to the issue in Redmine project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the url. This id is used by GitLab as a placeholder to replace the issue number.
* `new_issue_url` This is the URL to create a new issue in Redmine for the project linked to this GitLab project.
### Service Template
It is necessary to configure the external issue tracker per project, because project specific details are needed for the integration with GitLab.
......
......@@ -35,7 +35,7 @@ To enable the GitHub OmniAuth provider you must register your application with G
sudo -u git -H editor config/gitlab.yml
```
1. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for inital settings.
1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for inital settings.
1. Add the provider configuration:
......
# GitLab OAuth2 OmniAuth Provider
# Integrate your server with GitLab.com
To enable the GitLab OmniAuth provider you must register your application with GitLab. GitLab will generate a client ID and secret key for you to use.
Import projects from GitLab.com and login to your GitLab instance with your GitLab.com account.
1. Sign in to GitLab.
To enable the GitLab.com OmniAuth provider you must register your application with GitLab.com.
GitLab.com will generate a application ID and secret key for you to use.
1. Navigate to your settings.
1. Sign in to GitLab.com
1. Navigate to your profile settings.
1. Select "Applications" in the left menu.
......@@ -15,17 +18,17 @@ To enable the GitLab OmniAuth provider you must register your application with G
- Redirect URI:
```
http://gitlab.example.com/import/gitlab/callback
http://gitlab.example.com/users/auth/gitlab/callback
http://your-gitlab.example.com/import/gitlab/callback
http://your-gitlab.example.com/users/auth/gitlab/callback
```
The first link is required for the importer and second for the authorization.
1. Select "Submit".
1. You should now see a Application ID and Secret. Keep this page open as you continue configuration.
1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot). Keep this page open as you continue configuration. ![GitHub app](github_app.png)
1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot).
Keep this page open as you continue configuration.
![GitLab app](gitlab_app.png)
1. On your GitLab server, open the configuration file.
......@@ -43,7 +46,7 @@ To enable the GitLab OmniAuth provider you must register your application with G
sudo -u git -H editor config/gitlab.yml
```
1. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for inital settings.
1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for inital settings.
1. Add the provider configuration:
......@@ -76,4 +79,6 @@ To enable the GitLab OmniAuth provider you must register your application with G
1. Restart GitLab for the changes to take effect.
On the sign in page there should now be a GitLab icon below the regular sign in form. Click the icon to begin the authentication process. GitLab will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to your GitLab instance and will be signed in.
On the sign in page there should now be a GitLab.com icon below the regular sign in form.
Click the icon to begin the authentication process. GitLab.com will ask the user to sign in and authorize the GitLab application.
If everything goes well the user will be returned to your GitLab instance and will be signed in.
......@@ -68,9 +68,9 @@ To enable the Google OAuth2 OmniAuth provider you must register your application
args: { access_type: 'offline', approval_prompt: '' } }
```
1. Change 'YOUR APP ID' to the client ID from the GitHub application page from step 7.
1. Change 'YOUR APP ID' to the client ID from the Google Developer page from step 10.
1. Change 'YOUR APP SECRET' to the client secret from the GitHub application page from step 7.
1. Change 'YOUR APP SECRET' to the client secret from the Google Developer page from step 10.
1. Save the configuration file.
......
## GitLab as OAuth2 provider
## GitLab as OAuth2 authentication service provider
This document is about using GitLab as an OAuth authentication service provider to sign into other services.
If you want to use other OAuth authentication service providers to sign into GitLab please see the [OAuth2 client documentation](../api/oauth2.md)
OAuth2 provides client applications a 'secure delegated access' to server resources on behalf of a resource owner. Or you can allow users to sign in to your application with their GitLab.com account.
In fact OAuth allows to issue access token to third-party clients by an authorization server,
with the approval of the resource owner, or end-user.
......
......@@ -70,7 +70,7 @@ Now we can choose one or more of the Supported Providers below to continue confi
## Supported Providers
- [GitHub](github.md)
- [GitLab](gitlab.md)
- [GitLab.com](gitlab.md)
- [Google](google.md)
- [Shibboleth](shibboleth.md)
- [Twitter](twitter.md)
......
......@@ -137,7 +137,7 @@ with the name of your bucket:
Please be informed that a backup does not store your configuration files.
If you use an Omnibus package please see the [instructions in the readme to backup your configuration](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#backup-and-restore-omnibus-gitlab-configuration).
If you have a cookbook installation there should be a copy of your configuration in Chef.
If you have a manual installation please consider backing up your `gitlab.yml` file, any SSL keys and certificates, and your [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
If you have an installation from source, please consider backing up your `gitlab.yml` file, any SSL keys and certificates, and your [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
## Restore a previously created backup
......
......@@ -13,7 +13,7 @@
- For omnibus-gitlab, it is located at: `/var/opt/gitlab/git-data/repositories` by default, unless you changed
it in the `/etc/gitlab/gitlab.rb` file.
- For manual installations, it is usually located at: `/home/git/repositories` or you can see where
- For installations from source, it is usually located at: `/home/git/repositories` or you can see where
your repositories are located by looking at `config/gitlab.yml` under the `gitlab_shell => repos_path` entry.
New folder needs to have git user ownership and read/write/execute access for git user and its group:
......@@ -47,7 +47,7 @@ with `/home/git`.
$ sudo gitlab-rake gitlab:import:repos
```
#### Manual Installation
#### Installation from source
Before running this command you need to change the directory to where your GitLab installation is located:
......
......@@ -5,6 +5,9 @@
GitLab 6.0 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489.
**You need to follow this guide first, before updating past 6.0, as it contains critical migration steps that are only present
in the `6-0-stable` branch**
## Deprecations
### Global projects
......
# From 6.x or 7.x to 7.7
*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.x-or-7.x-to-7.4.md) for the most up to date instructions.*
# From 6.x or 7.x to 7.8
*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.x-or-7.x-to-7.8.md) for the most up to date instructions.*
This allows you to upgrade any version of GitLab from 6.0 and up (including 7.0 and up) to 7.7.
This allows you to upgrade any version of GitLab from 6.0 and up (including 7.0 and up) to 7.8.
## Global issue numbers
......@@ -71,7 +71,7 @@ sudo -u git -H git checkout -- db/schema.rb # local changes will be restored aut
For GitLab Community Edition:
```bash
sudo -u git -H git checkout 7-7-stable
sudo -u git -H git checkout 7-8-stable
```
OR
......@@ -79,7 +79,7 @@ OR
For GitLab Enterprise Edition:
```bash
sudo -u git -H git checkout 7-7-stable-ee
sudo -u git -H git checkout 7-8-stable-ee
```
## 4. Install additional packages
......@@ -123,7 +123,7 @@ sudo apt-get install libkrb5-dev
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch
sudo -u git -H git checkout v2.4.1
sudo -u git -H git checkout v2.4.3
```
## 7. Install libs, migrations, etc.
......@@ -158,14 +158,14 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
TIP: to see what changed in `gitlab.yml.example` in this release use next command:
```
git diff 6-0-stable:config/gitlab.yml.example 7-7-stable:config/gitlab.yml.example
git diff 6-0-stable:config/gitlab.yml.example 7-8-stable:config/gitlab.yml.example
```
* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/config/gitlab.yml.example but with your settings.
* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/config/unicorn.rb.example but with your settings.
* Make `/home/git/gitlab-shell/config.yml` the same as https://gitlab.com/gitlab-org/gitlab-shell/blob/v2.4.0/config.yml.example but with your settings.
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/lib/support/nginx/gitlab but with your settings.
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/lib/support/nginx/gitlab-ssl but with your settings.
* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/config/gitlab.yml.example but with your settings.
* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/config/unicorn.rb.example but with your settings.
* Make `/home/git/gitlab-shell/config.yml` the same as https://gitlab.com/gitlab-org/gitlab-shell/blob/v2.4.3/config.yml.example but with your settings.
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/lib/support/nginx/gitlab but with your settings.
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stablef/lib/support/nginx/gitlab-ssl but with your settings.
* Copy rack attack middleware config
```bash
......@@ -235,7 +235,7 @@ SET foreign_key_checks = 1;
# Find MySQL users
mysql> SELECT user FROM mysql.user WHERE user LIKE '%git%';
# If git user exists and gitlab user does not exist
# If git user exists and gitlab user does not exist
# you are done with the database cleanup tasks
mysql> \q
......@@ -273,11 +273,11 @@ mysql> \q
sudo -u git -H editor /home/git/gitlab/config/database.yml
```
## Things went south? Revert to previous version (6.0)
## Things went south? Revert to previous version (7.0)
### 1. Revert the code to the previous version
Follow the [upgrade guide from 5.4 to 6.0](5.4-to-6.0.md), except for the database migration (the backup is already migrated to the previous version).
Follow the [upgrade guide from 6.9 to 7.0](6.9-to-7.0.md), except for the database migration (the backup is already migrated to the previous version).
### 2. Restore from the backup:
......
# From 7.7 to 7.8
### 0. Stop server
sudo service gitlab stop
### 1. Backup
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 2. Get latest code
```bash
sudo -u git -H git fetch --all
sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
```
For GitLab Community Edition:
```bash
sudo -u git -H git checkout 7-8-stable
```
OR
For GitLab Enterprise Edition:
```bash
sudo -u git -H git checkout 7-8-stable-ee
```
### 3. Update gitlab-shell
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch
sudo -u git -H git checkout v2.4.3
```
### 4. Install libs, migrations, etc.
```bash
sudo apt-get install libkrb5-dev
cd /home/git/gitlab
# MySQL installations (note: the line below states '--without ... postgres')
sudo -u git -H bundle install --without development test postgres --deployment
# PostgreSQL installations (note: the line below states '--without ... mysql')
sudo -u git -H bundle install --without development test mysql --deployment
# Run database migrations
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
# Clean up assets and cache
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
# Update init.d script
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
```
### 5. Update config files
#### New configuration options for `gitlab.yml`
There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
```
git diff origin/7-6-stable:config/gitlab.yml.example origin/7-8-stable:config/gitlab.yml.example
```
#### Change Nginx settings
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your setting
#### Setup time zone (optional)
Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`](config/application.rb) (unlikely), unset it.
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade is complete!
### 8. GitHub settings (if applicable)
If you are using GitHub as an OAuth provider for authentication, you should change the callback URL so that it
only contains a root URL (ex. `https://gitlab.example.com/`)
## Things went south? Revert to previous version (7.6)
### 1. Revert the code to the previous version
Follow the [upgrade guide from 7.5 to 7.6](7.5-to-7.6.md), except for the database migration
(The backup is already migrated to the previous version)
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
......@@ -4,11 +4,11 @@ Depending on the installation method and your GitLab version, there are multiple
- [Omnibus update guide](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md) contains the steps needed to update a GitLab [package](https://about.gitlab.com/downloads/).
## Manual Installation
## Installation from source
- [The individual upgrade guides](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update) are for those who have installed GitLab manually.
- [The individual upgrade guides](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update) are for those who have installed GitLab from source.
- [The CE to EE update guides](https://gitlab.com/subscribers/gitlab-ee/tree/master/doc/update) are for subscribers of the Enterprise Edition only. The steps are very similar to a version upgrade: stop the server, get the code, update config files for the new functionality, install libs and do migrations, update the init script, start the application and check the application status.
- [Upgrader](upgrader.md) is an automatic ruby script that performs the update for manual installations.
- [Upgrader](upgrader.md) is an automatic ruby script that performs the update for installations from source.
- [Patch versions](patch_versions.md) guide includes the steps needed for a patch version, eg. 6.2.0 to 6.2.1.
## Miscellaneous
......
......@@ -27,11 +27,11 @@ Feature: Dashboard
Scenario: I should see User joined Project event
Given user with name "John Doe" joined project "Shop"
When I visit dashboard page
Then I should see "John Doe joined project at Shop" event
Then I should see "John Doe joined project Shop" event
@javascript
Scenario: I should see User left Project event
Given user with name "John Doe" joined project "Shop"
And user with name "John Doe" left project "Shop"
When I visit dashboard page
Then I should see "John Doe left project at Shop" event
Then I should see "John Doe left project Shop" event
......@@ -106,24 +106,19 @@ Feature: Project Active Tab
And no other sub tabs should be active
And the active main tab should be Commits
# Sub Tabs: Issues
Scenario: On Project Issues/Browse
Given I visit my project's issues page
Then the active sub tab should be Issues
And no other sub tabs should be active
And the active main tab should be Issues
Then the active main tab should be Issues
And no other main tabs should be active
Scenario: On Project Issues/Milestones
Given I visit my project's issues page
And I click the "Milestones" tab
Then the active sub tab should be Milestones
And no other sub tabs should be active
And the active main tab should be Issues
Then the active main tab should be Milestones
And no other main tabs should be active
Scenario: On Project Issues/Labels
Given I visit my project's issues page
And I click the "Labels" tab
Then the active sub tab should be Labels
And no other sub tabs should be active
And the active main tab should be Issues
Then the active main tab should be Labels
And no other main tabs should be active
......@@ -37,8 +37,8 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps
)
end
step 'I should see "John Doe joined project at Shop" event' do
page.should have_content "John Doe joined project at #{project.name_with_namespace}"
step 'I should see "John Doe joined project Shop" event' do
page.should have_content "John Doe joined project #{project.name_with_namespace}"
end
step 'user with name "John Doe" left project "Shop"' do
......@@ -50,8 +50,8 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps
)
end
step 'I should see "John Doe left project at Shop" event' do
page.should have_content "John Doe left project at #{project.name_with_namespace}"
step 'I should see "John Doe left project Shop" event' do
page.should have_content "John Doe left project #{project.name_with_namespace}"
end
step 'I have group with projects' do
......
......@@ -93,11 +93,11 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
ensure_active_sub_tab('Issues')
end
step 'the active sub tab should be Milestones' do
ensure_active_sub_tab('Milestones')
step 'the active main tab should be Milestones' do
ensure_active_main_tab('Milestones')
end
step 'the active sub tab should be Labels' do
ensure_active_sub_tab('Labels')
step 'the active main tab should be Labels' do
ensure_active_main_tab('Labels')
end
end
......@@ -253,7 +253,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end
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"
end
end
......@@ -271,7 +271,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end
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"
end
end
......
......@@ -116,7 +116,7 @@ module SharedNote
end
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_not have_css("#comment-with-a-header")
end
......
......@@ -65,7 +65,7 @@ module API
end
class Group < Grape::Entity
expose :id, :name, :path, :owner_id, :description
expose :id, :name, :path, :description
end
class GroupDetail < Group
......
......@@ -33,9 +33,9 @@ module API
attrs = attributes_for_keys [:name, :path, :description]
@group = Group.new(attrs)
@group.owner = current_user
if @group.save
@group.add_owner(current_user)
present @group, with: Entities::Group
else
render_api_error!("Failed to save group #{@group.errors.messages}", 400)
......
......@@ -83,7 +83,7 @@ module API
end
def authenticate_by_gitlab_shell_token!
unauthorized! unless secret_token == params['secret_token']
unauthorized! unless secret_token == params['secret_token'].try(:chomp)
end
def authenticated_as_admin!
......@@ -236,7 +236,7 @@ module API
end
def secret_token
File.read(Rails.root.join('.gitlab_shell_secret'))
File.read(Rails.root.join('.gitlab_shell_secret')).chomp
end
def handle_member_errors(errors)
......
......@@ -74,7 +74,7 @@ module API
if message = BroadcastMessage.current
present message, with: Entities::BroadcastMessage
else
not_found!
{}
end
end
end
......
module Gitlab
module CurrentSettings
def current_application_settings
if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('application_settings')
ApplicationSetting.current ||
ApplicationSetting.create_from_defaults
else
fake_application_settings
key = :current_application_settings
RequestStore.store[key] ||= begin
if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('application_settings')
RequestStore.store[:current_application_settings] =
(ApplicationSetting.current || ApplicationSetting.create_from_defaults)
else
fake_application_settings
end
end
end
......
......@@ -6,6 +6,8 @@ module Gitlab
attr_reader :params, :project, :git_cmd, :user
def self.can_push_to_branch?(user, project, ref)
return false unless user
if project.protected_branch?(ref) &&
!(project.developers_can_push_to_protected_branch?(ref) && project.team.developer?(user))
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
within("#note_#{note.id}") do
expect(find('.current-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
......
......@@ -584,7 +584,7 @@ describe GitlabMarkdownHelper do
it "should leave code blocks untouched" do
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")).
to eq(target_html)
......@@ -638,6 +638,18 @@ describe GitlabMarkdownHelper do
expect(markdown(actual)).to match(expected)
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
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"
......
......@@ -32,7 +32,8 @@ describe API::API, api: true do
it do
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
......
......@@ -347,7 +347,7 @@ describe API::API, api: true do
end
describe 'GET /projects/:id/events' do
before { project_member }
before { project_member2 }
it 'should return a project events' do
get api("/projects/#{project.id}/events", user)
......@@ -356,7 +356,7 @@ describe API::API, api: true do
expect(json_event['action_name']).to eq('joined')
expect(json_event['project_id'].to_i).to eq(project.id)
expect(json_event['author_username']).to eq(user.username)
expect(json_event['author_username']).to eq(user3.username)
end
it 'should return a 404 error if not found' do
......
......@@ -22,16 +22,7 @@ module TestEnv
# Disable mailer for spinach tests
disable_mailer if opts[:mailer] == false
# Clean /tmp/tests
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
clean_test_path
FileUtils.mkdir_p(repos_path)
......@@ -50,15 +41,30 @@ module TestEnv
allow_any_instance_of(NotificationService).to receive(:mailer).and_call_original
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
`rake gitlab:shell:install`
unless File.directory?(Rails.root.join(*%w(tmp tests gitlab-shell)))
`rake gitlab:shell:install`
end
end
def setup_factory_repo
clone_url = "https://gitlab.com/gitlab-org/#{factory_repo_name}.git"
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
Dir.chdir(factory_repo_path) do
......@@ -79,7 +85,7 @@ module TestEnv
end
# 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
def copy_repo(project)
......@@ -101,7 +107,7 @@ module TestEnv
end
def factory_repo_path_bare
factory_repo_path.to_s + '_bare'
"#{factory_repo_path}_bare"
end
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