Commit 492b5adb authored by Valery Sizov's avatar Valery Sizov

Merge remote-tracking branch 'origin/master' into ce_master

parents 90c312e7 0e51ca7c
# This file is generated by GitLab CI
image: "ruby:2.1"
services:
- mysql:latest
- postgres:latest
- redis:latest
variables:
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
before_script:
- ./scripts/prepare_build.sh
- ruby -v
......
......@@ -7,6 +7,7 @@ v 8.5.0 (unreleased)
v 8.4.0 (unreleased)
- Hide issues settings when issues are disabled (Hannes Rosenögger)
v 8.4.0
- Allow LDAP users to change their email if it was not set by the LDAP server
- Ensure Gravatar host looks like an actual host
- Consider re-assign as a mention from a notification point of view
......
File mode changed from 100644 to 100755
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
class @BuildArtifacts
constructor: () ->
@disablePropagation()
@setupEntryClick()
disablePropagation: ->
$('.top-block').on 'click', '.download', (e) ->
e.stopPropagation()
$('.tree-holder').on 'click', 'tr[data-link] a', (e) ->
e.stopImmediatePropagation()
setupEntryClick: ->
$('.tree-holder').on 'click', 'tr[data-link]', (e) ->
window.location = @dataset.link
......@@ -100,6 +100,8 @@ class Dispatcher
shortcut_handler = true
when 'projects:forks:new'
new ProjectFork()
when 'projects:artifacts:browse'
new BuildArtifacts()
when 'users:show'
new User()
new Activities()
......
......@@ -120,14 +120,6 @@ span.update-author {
display: inline;
}
.line_holder {
&:hover {
td {
background: #FFFFCF !important;
}
}
}
p.time {
color: #999;
font-size: 90%;
......
......@@ -92,15 +92,6 @@
&:last-child {
border-right: none;
}
background: #fff;
}
.lines {
pre {
padding: 0;
margin: 0;
background: none;
border: none;
}
}
img.avatar {
border: 0 none;
......@@ -116,18 +107,18 @@
color: #888;
}
}
td.blame-numbers {
pre {
color: #AAA;
white-space: pre;
}
background: #f1f1f1;
td.line-numbers {
float: none;
border-left: 1px solid #DDD;
}
td.lines {
padding: 0;
code {
font-family: $monospace_font;
}
pre {
margin: 0;
}
}
}
......
......@@ -53,3 +53,14 @@
color: #333;
}
}
.ui-sortable-handle {
cursor: move;
cursor: -webkit-grab;
cursor: -moz-grab;
&:active {
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
}
}
/* https://github.com/MozMorris/tomorrow-pygments */
.code.dark {
// Line numbers
.line-numbers, .diff-line-num {
background-color: #1d1f21;
}
background-color: #1d1f21 !important;
color: #c5c8c6 !important;
pre.highlight,
.line-numbers,
.line-numbers a {
background-color: #1d1f21 !important;
color: #c5c8c6 !important;
.diff-line-num, .diff-line-num a {
color: rgba(255, 255, 255, 0.3);
}
// Code itself
pre.code {
border-left: 1px solid #666;
}
&, pre.code, .line_holder .line_content {
background-color: #1d1f21;
color: #c5c8c6;
}
// Diff line
.line_holder {
.diff-line-num.new, .line_content.new {
@include diff_background(rgba(51, 255, 51, 0.1), rgba(51, 255, 51, 0.3), #808080);
}
.diff-line-num.old, .line_content.old {
@include diff_background(rgba(255, 51, 51, 0.2), rgba(255, 51, 51, 0.3), #808080);
}
.line_content.match {
color: rgba(255, 255, 255, 0.3);
background: rgba(255, 255, 255, 0.1);
}
}
// highlight line via anchor
pre .hll {
background-color: #557 !important;
......@@ -90,22 +110,4 @@
.vg { color: #cc6666 } /* Name.Variable.Global */
.vi { color: #cc6666 } /* Name.Variable.Instance */
.il { color: #de935f } /* Literal.Number.Integer.Long */
.line_holder {
&.parallel .new.new_line,
&.parallel .new.line_content,
&.new .old_line,
&.new .new_line,
&.new .line_content {
@include diff_background(255, 255, 255, #808080);
}
&.parallel .old.old_line,
&.parallel .old.line_content,
&.old .old_line,
&.old .new_line,
&.old .line_content {
@include diff_background(255, 51, 51, #808080);
}
}
}
/* https://github.com/richleland/pygments-css/blob/master/monokai.css */
.code.monokai {
// Line numbers
.line-numbers, .diff-line-num {
background-color: #272822;
}
background-color: #272822 !important;
color: #f8f8f2 !important;
pre.highlight,
.line-numbers,
.line-numbers a {
background-color :#272822 !important;
color: #f8f8f2 !important;
.diff-line-num, .diff-line-num a {
color: rgba(255, 255, 255, 0.3);
}
// Code itself
pre.code {
border-left: 1px solid #555;
}
&, pre.code, .line_holder .line_content {
background-color: #272822;
color: #f8f8f2;
}
// Diff line
.line_holder {
.diff-line-num.new, .line_content.new {
@include diff_background(rgba(166, 226, 46, 0.2), rgba(166, 226, 46, 0.3), #808080);
}
.diff-line-num.old, .line_content.old {
@include diff_background(rgba(254, 147, 140, 0.2), rgba(254, 147, 140, 0.3), #808080);
}
.line_content.match {
color: rgba(255, 255, 255, 0.3);
background: rgba(255, 255, 255, 0.1);
}
}
// highlight line via anchor
pre .hll {
background-color: #49483e !important;
......@@ -90,22 +110,4 @@
.gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */
.gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */
.gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */
.line_holder {
&.parallel .new.new_line,
&.parallel .new.line_content,
&.new .old_line,
&.new .new_line,
&.new .line_content {
@include diff_background(156, 175, 183, #808080);
}
&.parallel .old.old_line,
&.parallel .old.line_content,
&.old .old_line,
&.old .new_line,
&.old .line_content {
@include diff_background(254, 147, 140, #808080);
}
}
}
/* https://gist.github.com/qguv/7936275 */
.code.solarized-dark {
// Line numbers
.line-numbers, .diff-line-num {
background-color: #002b36;
}
background-color: #002b36 !important;
color: #93a1a1 !important;
pre.highlight,
.line-numbers,
.line-numbers a {
background-color: #002b36 !important;
color: #93a1a1 !important;
.diff-line-num, .diff-line-num a {
color: rgba(255, 255, 255, 0.3);
}
// Code itself
pre.code {
border-left: 1px solid #113b46;
}
&, pre.code, .line_holder .line_content {
background-color: #002b36;
color: #93a1a1;
}
// Diff line
.line_holder {
.diff-line-num.new, .line_content.new {
@include diff_background(rgba(133, 153, 0, 0.2), rgba(133, 153, 0, 0.3), #808080);
}
.diff-line-num.old, .line_content.old {
@include diff_background(rgba(220, 50, 47, 0.2), rgba(220, 50, 47, 0.3), #808080);
}
.line_content.match {
color: rgba(255, 255, 255, 0.3);
background: rgba(255, 255, 255, 0.1);
}
}
// highlight line via anchor
pre .hll {
background-color: #174652 !important;
......@@ -111,22 +131,4 @@
.vg { color: #268bd2 } /* Name.Variable.Global */
.vi { color: #268bd2 } /* Name.Variable.Instance */
.il { color: #2aa198 } /* Literal.Number.Integer.Long */
.line_holder {
&.parallel .new.new_line,
&.parallel .new.line_content,
&.new .old_line,
&.new .new_line,
&.new .line_content {
@include diff_background(255, 255, 255, #808080);
}
&.parallel .old.old_line,
&.parallel .old.line_content,
&.old .old_line,
&.old .new_line,
&.old .line_content {
@include diff_background(255, 51, 51, #808080);
}
}
}
/* https://gist.github.com/qguv/7936275 */
.code.solarized-light {
// Line numbers
.line-numbers, .diff-line-num {
background-color: #fdf6e3;
}
background-color: #fdf6e3 !important;
color: #586e75 !important;
pre.highlight,
.line-numbers,
.line-numbers a {
background-color: #fdf6e3 !important;
color: #586e75 !important;
.diff-line-num, .diff-line-num a {
color: rgba(0, 0, 0, 0.3);
}
// Code itself
pre.code {
border-left: 1px solid #c5d0d4;
}
&, pre.code, .line_holder .line_content {
background-color: #fdf6e3;
color: #586e75;
}
// Diff line
.line_holder {
.diff-line-num.new, .line_content.new {
@include diff_background(rgba(133, 153, 0, 0.2), rgba(133, 153, 0, 0.3), #FAF3DD);
}
.diff-line-num.old, .line_content.old {
@include diff_background(rgba(220, 50, 47, 0.2), rgba(220, 50, 47, 0.3), #FAF3DD);
}
.line_content.match {
color: rgba(0, 0, 0, 0.3);
background: rgba(255, 255, 255, 0.4);
}
}
// highlight line via anchor
pre .hll {
background-color: #ddd8c5 !important;
......@@ -111,23 +131,4 @@
.vg { color: #268bd2 } /* Name.Variable.Global */
.vi { color: #268bd2 } /* Name.Variable.Instance */
.il { color: #2aa198 } /* Literal.Number.Integer.Long */
.line_holder {
&.parallel .new.new_line,
&.parallel .new.line_content,
&.new .old_line,
&.new .new_line,
&.new .line_content {
@include diff_background(92, 164, 169, #FAF3DD);
}
&.parallel .old.old_line,
&.parallel .old.line_content,
&.old .old_line,
&.old .new_line,
&.old .line_content {
@include diff_background(237, 106, 90, #FAF3DD);
}
}
}
/* https://github.com/aahan/pygments-github-style */
.code.white {
// Line numbers
.line-numbers, .diff-line-num {
background-color: $background-color;
}
background-color: #f8fafc !important;
color: #5b6169 !important;
pre.highlight,
.line-numbers,
.line-numbers a {
background-color: $background-color !important;
color: $gl-gray !important;
.diff-line-num, .diff-line-num a {
color: rgba(0, 0, 0, 0.3);
}
// Code itself
pre.code {
border-left: 1px solid $border-color;
background-color: #fff !important;
color: #333 !important;
}
&, pre.code, .line_holder .line_content {
background-color: #fff;
color: #333;
}
// Diff line
.line_holder {
.diff-line-num {
&.old {
background: #ffdddd;
border-color: #f1c0c0;
}
&.new {
background: #dbffdb;
border-color: #c1e9c1;
}
}
.line_content {
&.old {
background: #ffecec;
span.idiff {
background-color: #f8cbcb;
}
}
&.new {
background: #eaffea;
span.idiff {
background-color: #a6f3a6;
}
}
&.match {
color: rgba(0, 0, 0, 0.3);
background: #fafafa;
}
}
}
// highlight line via anchor
......
......@@ -32,16 +32,6 @@
background: #FFF;
color: #333;
.old {
span.idiff {
background-color: #f8cbcb;
}
}
.new {
span.idiff {
background-color: #a6f3a6;
}
}
.unfold {
cursor: pointer;
}
......@@ -76,7 +66,7 @@
}
tr.line_holder.parallel {
.old_line, .new_line, .diff_line {
.old_line, .new_line {
min-width: 50px;
}
......@@ -85,7 +75,7 @@
}
}
.old_line, .new_line, .diff_line {
.old_line, .new_line {
margin: 0px;
padding: 0px;
border: none;
......@@ -107,43 +97,12 @@
text-decoration: underline;
}
}
&.new {
background: #CFD;
}
&.old {
background: #FDD;
}
}
.diff_line {
padding: 0;
}
.line_holder {
&.old .old_line,
&.old .new_line {
background: #ffdddd;
border-color: #f1c0c0;
}
&.new .old_line,
&.new .new_line {
background: #dbffdb;
border-color: #c1e9c1;
}
}
.line_content {
display: block;
margin: 0px;
padding: 0px 0.5em;
border: none;
&.new {
background: #eaffea;
}
&.old {
background: #ffecec;
}
&.matched {
color: $border-color;
background: #fafafa;
}
&.parallel {
display: table-cell;
}
......@@ -394,17 +353,14 @@
}
}
@mixin diff_background($r, $g, $b, $custom-border) {
/* Fallback for web browsers that doesn't support RGBa */
background: rgb($r, $g, $b);
/* RGBa with 0.3 opacity */
background: rgba($r, $g, $b, 0.3);
@mixin diff_background($background, $idiff, $border) {
background: $background;
&.new_line, &.old_line {
border-right-color: $custom-border !important;
&.line_content span.idiff {
background: $idiff;
}
&.line_content span.idiff {
background: rgb($r, $g, $b);
&.diff-line-num {
border-color: $border;
}
}
......@@ -10,18 +10,6 @@
margin: 10px $gl-padding;
}
.diff-file .diff-content {
tr.line_holder:hover {
&> td.line_content {
background: $hover !important;
border-color: darken($hover, 10%) !important;
}
&> td.new_line,
&> td.old_line {
background: darken($hover, 4%) !important;
border-color: darken($hover, 10%) !important;
}
}
tr.line_holder:hover > td .line_note_link {
opacity: 1.0;
filter: alpha(opacity=100);
......
......@@ -242,11 +242,8 @@ ul.notes {
// "show" the icon also if we just hover somewhere over the line
&:hover > td {
background: $hover !important;
.add-diff-note {
@include show-add-diff-note;
}
}
}
......@@ -97,7 +97,7 @@ module CreatesCommit
# Merge request from fork to this project
@mr_source_project = @tree_edit_project
@mr_target_project = @project
@mr_target_branch = @mr_target_project.repository.root_ref
@mr_target_branch = @ref
end
end
end
......@@ -52,7 +52,9 @@ class Projects::BlobController < Projects::ApplicationController
def preview
@content = params[:content]
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
@diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/))
diff_lines = diffy.diff.scan(/.*\n/)[2..-1]
diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines)
@diff_lines = Gitlab::Diff::Highlight.new(diff_lines).highlight
render layout: false
end
......
......@@ -26,10 +26,10 @@ module BlobHelper
tree_join(ref, path),
link_opts)
if !on_top_of_branch?
if !on_top_of_branch?(project, ref)
button_tag "Edit", class: "btn btn-default disabled has_tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' }
elsif can_edit_blob?(blob)
link_to "Edit", edit_path, class: 'btn btn-small'
elsif can_edit_blob?(blob, project, ref)
link_to "Edit", edit_path, class: 'btn'
elsif can?(current_user, :fork_project, project)
continue_params = {
to: edit_path,
......@@ -39,7 +39,7 @@ module BlobHelper
fork_path = namespace_project_fork_path(project.namespace, project, namespace_key: current_user.namespace.id,
continue: continue_params)
link_to "Edit", fork_path, class: 'btn btn-small', method: :post
link_to "Edit", fork_path, class: 'btn', method: :post
end
end
......@@ -50,11 +50,11 @@ module BlobHelper
return unless blob
if !on_top_of_branch?
if !on_top_of_branch?(project, ref)
button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "You can only #{action} files when you are on a branch", data: { container: 'body' }
elsif blob.lfs_pointer?
button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "It is not possible to #{action} files that are stored in LFS using the web interface", data: { container: 'body' }
elsif can_edit_blob?(blob)
elsif can_edit_blob?(blob, project, ref)
button_tag label, class: "btn btn-#{btn_class}", 'data-target' => "#modal-#{modal_type}-blob", 'data-toggle' => 'modal'
elsif can?(current_user, :fork_project, project)
continue_params = {
......
......@@ -166,7 +166,7 @@ module CommitsHelper
link_to(
namespace_project_blob_path(project.namespace, project,
tree_join(commit_sha, diff.new_path)),
class: 'btn btn-small view-file js-view-file'
class: 'btn view-file js-view-file'
) do
raw('View file @') + content_tag(:span, commit_sha[0..6],
class: 'commit-short-id')
......
......@@ -347,17 +347,17 @@ module Ci
end
def artifacts_browse_url
if artifacts_browser_supported?
if artifacts_metadata?
browse_namespace_project_build_artifacts_path(project.namespace, project, self)
end
end
def artifacts_browser_supported?
def artifacts_metadata?
artifacts? && artifacts_metadata.exists?
end
def artifacts_metadata_entry(path)
Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path).to_entry
def artifacts_metadata_entry(path, **options)
Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path, **options).to_entry
end
private
......
......@@ -84,7 +84,7 @@ class ProjectMember < Member
def truncate_teams(project_ids)
ProjectMember.transaction do
members = ProjectMember.where(source_id: project_ids)
members.each do |member|
member.destroy
end
......@@ -133,7 +133,7 @@ class ProjectMember < Member
event_service.join_project(self.project, self.user)
notification_service.new_project_member(self) unless @skip_notification
end
super
end
......
......@@ -246,7 +246,7 @@ class Note < ActiveRecord::Base
prev_match_line = nil
prev_lines = []
diff_lines.each do |line|
highlighted_diff_lines.each do |line|
if line.type == "match"
prev_lines.clear
prev_match_line = line
......@@ -263,7 +263,11 @@ class Note < ActiveRecord::Base
end
def diff_lines
@diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.lines.to_a)
@diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.lines)
end
def highlighted_diff_lines
Gitlab::Diff::Highlight.new(diff_lines).highlight
end
def discussion_id
......
......@@ -4,7 +4,7 @@
.top-block.gray-content-block.clearfix
.pull-right
= link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build),
class: 'btn btn-default' do
class: 'btn btn-default download' do
= icon('download')
Download artifacts archive
......@@ -20,12 +20,3 @@
- if @entry.empty?
.center Empty
:javascript
$('.tree-holder').on('click', 'tr[data-link] a', function(e) {
e.stopImmediatePropagation();
});
$('.tree-holder').on('click', 'tr[data-link]', function(e) {
window.location = this.dataset.link;
});
......@@ -12,7 +12,7 @@
%small= number_to_human_size @blob.size
.file-actions
= render "projects/blob/actions"
.file-content.blame.highlight
.file-content.blame.code.js-syntax-highlight
%table
- current_line = 1
- blame_highlighter = highlighter(@blob.name, @blob.data, nowrap: true)
......@@ -31,15 +31,14 @@
= commit_author_link(commit, avatar: false)
authored
#{time_ago_with_tooltip(commit.committed_date, skip_js: true)}
%td.lines.blame-numbers
%pre
- line_count = blame_group[:lines].count
- (current_line...(current_line + line_count)).each do |i|
= i
\
- current_line += line_count
%td.line-numbers
- line_count = blame_group[:lines].count
- (current_line...(current_line + line_count)).each do |i|
%a.diff-line-num= i
\
- current_line += line_count
%td.lines
%pre{class: 'code highlight white'}
%pre{class: 'code highlight'}
%code
- blame_group[:lines].each do |line|
:preserve
......
......@@ -10,7 +10,8 @@
%tr.line_holder
%td.old_line.diff-line-num{data: {linenumber: line_old}}
= link_to raw(line_old), "#"
%td.new_line= link_to raw(line_new) , "#"
%td.new_line.diff-line-num
= link_to raw(line_new) , "#"
%td.line_content.noteable_line==#{' ' * @form.indent}#{line}
- if @form.unfold? && @form.bottom? && @form.to < @blob.loc
......
......@@ -14,12 +14,12 @@
- @diff_lines.each do |line|
%tr.line_holder{ class: "#{line.type}" }
- if line.type == "match"
%td.old_line= "..."
%td.new_line= "..."
%td.line_content.matched= line.text
%td.old_line.diff-line-num= "..."
%td.new_line.diff-line-num= "..."
%td.line_content.match= line.text
- else
%td.old_line
%td.new_line
%td.old_line.diff-line-num
%td.new_line.diff-line-num
%td.line_content{class: "#{line.type}"}= diff_line_content(line.text)
- else
.nothing-here-block No changes.
......@@ -96,7 +96,7 @@
.center
.btn-group{ role: :group }
= link_to "Download", @build.artifacts_download_url, class: 'btn btn-sm btn-primary'
- if @build.artifacts_browser_supported?
- if @build.artifacts_metadata?
= link_to "Browse", @build.artifacts_browse_url, class: 'btn btn-sm btn-primary'
.build-widget
......
.diff-file{id: "diff-#{i}", data: diff_file_html_data(project, diff_commit, diff_file)}
.diff-header{id: "file-path-#{hexdigest(diff_file.file_path)}"}
.diff-file.file-holder{id: "diff-#{i}", data: diff_file_html_data(project, diff_commit, diff_file)}
.file-title{id: "file-path-#{hexdigest(diff_file.file_path)}"}
- if diff_file.diff.submodule?
%span
= icon('archive fw')
%strong
= submodule_link(blob, @commit.id, project.repository)
- else
%span
= blob_icon blob.mode, blob.name
= link_to "#diff-#{i}" do
%strong
= diff_file.new_path
= blob_icon blob.mode, blob.name
= link_to "#diff-#{i}" do
%strong
= diff_file.new_path
- if diff_file.deleted_file
deleted
- elsif diff_file.renamed_file
renamed from
%strong
= diff_file.old_path
- if diff_file.deleted_file
deleted
- elsif diff_file.renamed_file
renamed from
%strong
= diff_file.old_path
- if diff_file.mode_changed?
%small
= "#{diff_file.diff.a_mode}#{diff_file.diff.b_mode}"
- if diff_file.mode_changed?
%small
= "#{diff_file.diff.a_mode}#{diff_file.diff.b_mode}"
.diff-controls
.file-actions.hidden-xs
- if blob_text_viewable?(blob)
= link_to '#', class: 'js-toggle-diff-comments btn btn-sm active has_tooltip', title: "Toggle comments for this file" do
%i.fa.fa-comments
&nbsp;
= link_to '#', class: 'js-toggle-diff-comments btn active has_tooltip', title: "Toggle comments for this file" do
= icon('comments')
\
- if editable_diff?(diff_file)
= edit_blob_link(@merge_request.source_project,
@merge_request.source_branch, diff_file.new_path,
from_merge_request_id: @merge_request.id)
&nbsp;
= view_file_btn(diff_commit.id, diff_file, project)
......
......@@ -4,4 +4,4 @@
%td.new_line.diff-line-num{data: {linenumber: line_new},
class: [unfold_bottom_class(bottom), unfold_class(!new_file)]}
\...
%td.line_content.matched= line
%td.line_content.match= line
%td.old_line
%td.line_content.parallel.matched= line
%td.new_line
%td.line_content.parallel.matched= line
%td.old_line.diff-line-num
%td.line_content.parallel.match= line
%td.new_line.diff-line-num
%td.line_content.parallel.match= line
......@@ -9,16 +9,16 @@
= render "projects/diffs/match_line_parallel", { line: left[:text],
line_old: left[:number], line_new: right[:number] }
- elsif left[:type] == 'nonewline'
%td.old_line
%td.line_content.parallel.matched= left[:text]
%td.new_line
%td.line_content.parallel.matched= left[:text]
%td.old_line.diff-line-num
%td.line_content.parallel.match= left[:text]
%td.new_line.diff-line-num
%td.line_content.parallel.match= left[:text]
- else
%td.old_line{id: left[:line_code], class: "#{left[:type]}"}
%td.old_line.diff-line-num{id: left[:line_code], class: "#{left[:type]}"}
= link_to raw(left[:number]), "##{left[:line_code]}", id: left[:line_code]
- if @comments_allowed && can?(current_user, :create_note, @project)
= link_to_new_diff_note(left[:line_code], 'old')
%td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]}", data: { line_code: left[:line_code] }}= diff_line_content(left[:text])
%td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]}", data: { line_code: left[:line_code] }}= diff_line_content(left[:text])
- if right[:type] == 'new'
- new_line_class = 'new'
......@@ -27,11 +27,11 @@
- new_line_class = nil
- new_line_code = left[:line_code]
%td.new_line{id: new_line_code, class: "#{new_line_class}", data: { linenumber: right[:number] }}
%td.new_line.diff-line-num{id: new_line_code, class: "#{new_line_class}", data: { linenumber: right[:number] }}
= link_to raw(right[:number]), "##{new_line_code}", id: new_line_code
- if @comments_allowed && can?(current_user, :create_note, @project)
= link_to_new_diff_note(right[:line_code], 'new')
%td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", data: { line_code: new_line_code }}= diff_line_content(right[:text])
%td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", data: { line_code: new_line_code }}= diff_line_content(right[:text])
- if @reply_allowed
- comments_left, comments_right = organize_comments(left[:type], right[:type], left[:line_code], right[:line_code])
......
......@@ -6,6 +6,7 @@
%table.text-file.code.js-syntax-highlight{ class: too_big ? 'hide' : '' }
- last_line = 0
- raw_diff_lines = diff_file.diff_lines
- diff_file.highlighted_diff_lines.each_with_index do |line, index|
- type = line.type
- last_line = line.new_pos
......@@ -18,20 +19,20 @@
- elsif type == 'nonewline'
%td.old_line.diff-line-num
%td.new_line.diff-line-num
%td.line_content.matched= line.text
%td.line_content.match= line.text
- else
%td.old_line
%td.old_line.diff-line-num{class: type}
= link_to raw(type == "new" ? "&nbsp;" : line_old), "##{line_code}", id: line_code
- if @comments_allowed && can?(current_user, :create_note, @project)
= link_to_new_diff_note(line_code)
%td.new_line{data: {linenumber: line.new_pos}}
%td.new_line.diff-line-num{class: type, data: {linenumber: line.new_pos}}
= link_to raw(type == "old" ? "&nbsp;" : line.new_pos), "##{line_code}", id: line_code
%td.line_content{class: "noteable_line #{type} #{line_code}", data: { line_code: line_code }}= diff_line_content(line.text)
- if @reply_allowed
- comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at)
- unless comments.empty?
= render "projects/notes/diff_notes_with_reply", notes: comments, line: line.text
= render "projects/notes/diff_notes_with_reply", notes: comments, line: raw_diff_lines[index].text
- if last_line > 0
= render "projects/diffs/match_line", {line: "",
......
......@@ -16,13 +16,13 @@
- line_code = generate_line_code(note.file_path, line)
%tr.line_holder{ id: line_code, class: "#{type}" }
- if type == "match"
%td.old_line= "..."
%td.new_line= "..."
%td.line_content.matched= line.text
%td.old_line.diff-line-num= "..."
%td.new_line.diff-line-num= "..."
%td.line_content.match= line.text
- else
%td.old_line
%td.old_line.diff-line-num
= raw(type == "new" ? "&nbsp;" : line.old_pos)
%td.new_line
%td.new_line.diff-line-num
= raw(type == "old" ? "&nbsp;" : line.new_pos)
%td.line_content{class: "noteable_line #{type} #{line_code}", line_code: line_code}= diff_line_content(line.text)
......
......@@ -22,29 +22,27 @@
.file-content.code
.nothing-here-block Empty file
- else
.file-content.code
%div.highlighted-data{ class: user_color_scheme }
.line-numbers
.file-content.code.js-syntax-highlight
.line-numbers
- snippet_blob[:snippet_chunks].each do |snippet|
- unless snippet[:data].empty?
- snippet[:data].lines.to_a.size.times do |index|
- offset = defined?(snippet[:start_line]) ? snippet[:start_line] : 1
- i = index + offset
= link_to snippet_path+"#L#{i}", id: "L#{i}", rel: "#L#{i}", class: "diff-line-num" do
%i.fa.fa-link
= i
- unless snippet == snippet_blob[:snippet_chunks].last
%a.diff-line-num
= "."
%pre.code
%code
- snippet_blob[:snippet_chunks].each do |snippet|
- unless snippet[:data].empty?
- snippet[:data].lines.to_a.size.times do |index|
- offset = defined?(snippet[:start_line]) ? snippet[:start_line] : 1
- i = index + offset
= link_to snippet_path+"#L#{i}", id: "L#{i}", rel: "#L#{i}" do
%i.fa.fa-link
= i
= snippet[:data]
- unless snippet == snippet_blob[:snippet_chunks].last
%a
= "."
.highlight.term
%pre
%code
- snippet_blob[:snippet_chunks].each do |snippet|
- unless snippet[:data].empty?
= snippet[:data]
- unless snippet == snippet_blob[:snippet_chunks].last
%a
= "..."
- else
.file-content.code
.nothing-here-block Empty file
= "..."
- else
.file-content.code
.nothing-here-block Empty file
.file-content.code.js-syntax-highlight{ class: user_color_scheme }
.file-content.code.js-syntax-highlight
.line-numbers
- if blob.data.present?
- blob.data.lines.each_index do |index|
- offset = defined?(first_line_number) ? first_line_number : 1
- i = index + offset
-# We're not using `link_to` because it is too slow once we get to thousands of lines.
%a{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i}
%a.diff-line-num{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i}
%i.fa.fa-link
= i
.blob-content{data: {blob_id: blob.id}}
......
......@@ -32,6 +32,7 @@
- [User permissions](ci/permissions/README.md)
- [API](ci/api/README.md)
- [Triggering builds through the API](ci/triggers/README.md)
- [Build artifacts](ci/build_artifacts/README.md)
### CI Languages
......@@ -60,6 +61,7 @@
- [Git Hooks](git_hooks/git_hooks.md) Advanced push rules for your project.
- [Help message](customization/help_message.md) Set information about administrators of your GitLab instance.
- [Install](install/README.md) Requirements, directory structures and installation from source.
- [Restart GitLab](administration/restart_gitlab.md) Learn how to restart GitLab and its components
- [Installing your license](license/README.md)
- [Integration](integration/README.md) How to integrate with systems such as JIRA, Redmine, LDAP and Twitter.
- [Issue closing](customization/issue_closing.md) Customize how to close an issue from commit messages.
......@@ -76,6 +78,7 @@
- [Migrate GitLab CI to CE/EE](migrate_ci_to_ce/README.md) Follow this guide to migrate your existing GitLab CI data to GitLab CE/EE.
- [Downgrade back to CE](downgrade_ee_to_ce/README.md) Follow this guide if you need to downgrade from EE to CE.
- [Git LFS configuration](workflow/lfs/lfs_administration.md)
- [Housekeeping](administration/housekeeping.md) Keep your Git repository tidy and fast.
- [GitLab Pages configuration](pages/administration.md)
- [Elasticsearch (EE-only)](integration/elasticsearch.md) Enable Elasticsearch
- [GitLab Performance Monitoring](monitoring/performance/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics
......
# Housekeeping
_**Note:** This feature was [introduced][ce-2371] in GitLab 8.4_
---
The housekeeping function runs [`git gc`][man] on the current project Git
repository.
`git gc` runs a number of housekeeping tasks, such as compressing file
revisions (to reduce disk space and increase performance) and removing
unreachable objects which may have been created from prior invocations of
`git add`.
You can find this option under your **[Project] > Settings**.
---
![Housekeeping settings](img/housekeeping_settings.png)
[ce-2371]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2371 "Housekeeping merge request"
[man]: https://www.kernel.org/pub/software/scm/git/docs/git-gc.html "git gc man page"
# How to restart GitLab
Depending on how you installed GitLab, there are different methods to restart
its service(s).
If you want the TL;DR versions, jump to:
- [Omnibus GitLab restart](#omnibus-gitlab-restart)
- [Omnibus GitLab reconfigure](#omnibus-gitlab-reconfigure)
- [Source installation restart](#installations-from-source)
## Omnibus installations
If you have used the [Omnibus packages][omnibus-dl] to install GitLab, then
you should already have `gitlab-ctl` in your `PATH`.
`gitlab-ctl` interacts with the Omnibus packages and can be used to restart the
GitLab Rails application (Unicorn) as well as the other components, like:
- GitLab Workhorse
- Sidekiq
- PostgreSQL (if you are using the bundled one)
- NGINX (if you are using the bundled one)
- Redis (if you are using the bundled one)
- [Mailroom][]
- Logrotate
### Omnibus GitLab restart
There may be times in the documentation where you will be asked to _restart_
GitLab. In that case, you need to run the following command:
```bash
sudo gitlab-ctl restart
```
The output should be similar to this:
```
ok: run: gitlab-workhorse: (pid 11291) 1s
ok: run: logrotate: (pid 11299) 0s
ok: run: mailroom: (pid 11306) 0s
ok: run: nginx: (pid 11309) 0s
ok: run: postgresql: (pid 11316) 1s
ok: run: redis: (pid 11325) 0s
ok: run: sidekiq: (pid 11331) 1s
ok: run: unicorn: (pid 11338) 0s
```
To restart a component separately, you can append its service name to the
`restart` command. For example, to restart **only** NGINX you would run:
```bash
sudo gitlab-ctl restart nginx
```
To check the status of GitLab services, run:
```bash
sudo gitlab-ctl status
```
Notice that all services say `ok: run`.
Sometimes, components time out during the restart and sometimes they get stuck.
In that case, you can use `gitlab-ctl kill <service>` to send the `SIGKILL`
signal to the service, for example `sidekiq`. After that, a restart should
perform fine.
As a last resort, you can try to
[reconfigure GitLab](#omnibus-gitlab-reconfigure) instead.
### Omnibus GitLab reconfigure
There may be times in the documentation where you will be asked to _reconfigure_
GitLab. Remember that this method applies only for the Omnibus packages.
Reconfigure Omnibus GitLab with:
```bash
sudo gitlab-ctl reconfigure
```
Reconfiguring GitLab should occur in the event that something in its
configuration (`/etc/gitlab/gitlab.rb`) has changed.
When you run this command, [Chef], the underlying configuration management
application that powers Omnibus GitLab, will make sure that all directories,
permissions, services, etc., are in place and in the same shape that they were
initially shipped.
It will also restart GitLab components where needed, if any of their
configuration files have changed.
If you manually edit any files in `/var/opt/gitlab` that are managed by Chef,
running reconfigure will revert the changes AND restart the services that
depend on those files.
## Installations from source
If you have followed the official installation guide to [install GitLab from
source][install], run the following command to restart GitLab:
```
sudo service gitlab restart
```
The output should be similar to this:
```
Shutting down GitLab Unicorn
Shutting down GitLab Sidekiq
Shutting down GitLab Workhorse
Shutting down GitLab MailRoom
...
GitLab is not running.
Starting GitLab Unicorn
Starting GitLab Sidekiq
Starting GitLab Workhorse
Starting GitLab MailRoom
...
The GitLab Unicorn web server with pid 28059 is running.
The GitLab Sidekiq job dispatcher with pid 28176 is running.
The GitLab Workhorse with pid 28122 is running.
The GitLab MailRoom email processor with pid 28114 is running.
GitLab and all its components are up and running.
```
This should restart Unicorn, Sidekiq, GitLab Workhorse and [Mailroom][]
(if enabled). The init service file that does all the magic can be found on
your server in `/etc/init.d/gitlab`.
---
If you are using other init systems, like systemd, you can check the
[GitLab Recipes][gl-recipes] repository for some unofficial services. These are
**not** officially supported so use them at your own risk.
[omnibus-dl]: https://about.gitlab.com/downloads/ "Download the Omnibus packages"
[install]: ../install/installation.md "Documentation to install GitLab from source"
[mailroom]: ../incoming_email/README.md "Used for replying by email in GitLab issues and merge requests"
[chef]: https://www.chef.io/chef/ "Chef official website"
[src-service]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/init.d/gitlab "GitLab init service file"
[gl-recipes]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/init "GitLab Recipes repository"
......@@ -8,10 +8,16 @@ Get a list of repository commits in a project.
GET /projects/:id/repository/commits
```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID of a project |
| `ref_name` | string | no | The name of a repository branch or tag or if not given the default branch |
```bash
curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/commits"
```
- `id` (required) - The ID of a project
- `ref_name` (optional) - The name of a repository branch or tag or if not given the default branch
Example response:
```json
[
......@@ -48,8 +54,16 @@ GET /projects/:id/repository/commits/:sha
Parameters:
- `id` (required) - The ID of a project
- `sha` (required) - The commit hash or name of a repository branch or tag
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID of a project |
| `sha` | string | yes | The commit hash or name of a repository branch or tag |
```bash
curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/commits/master
```
Example response:
```json
{
......@@ -79,8 +93,16 @@ GET /projects/:id/repository/commits/:sha/diff
Parameters:
- `id` (required) - The ID of a project
- `sha` (required) - The name of a repository branch or tag or if not given the default branch
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID of a project |
| `sha` | string | yes | The commit hash or name of a repository branch or tag |
```bash
curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/commits/master/diff"
```
Example response:
```json
[
......@@ -107,8 +129,16 @@ GET /projects/:id/repository/commits/:sha/comments
Parameters:
- `id` (required) - The ID of a project
- `sha` (required) - The name of a repository branch or tag or if not given the default branch
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID of a project |
| `sha` | string | yes | The commit hash or name of a repository branch or tag |
```bash
curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/commits/master/comments"
```
Example response:
```json
[
......@@ -128,39 +158,65 @@ Parameters:
## Post comment to commit
Adds a comment to a commit. Optionally you can post comments on a specific line of a commit. Therefor both `path`, `line_new` and `line_old` are required.
Adds a comment to a commit.
In order to post a comment in a particular line of a particular file, you must
specify the full commit SHA, the `path`, the `line` and `line_type` should be
`new`.
The comment will be added at the end of the last commit if at least one of the
cases below is valid:
- the `sha` is instead a branch or a tag and the `line` or `path` are invalid
- the `line` number is invalid (does not exist)
- the `path` is invalid (does not exist)
In any of the above cases, the response of `line`, `line_type` and `path` is
set to `null`.
```
POST /projects/:id/repository/commits/:sha/comments
```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID of a project |
| `sha` | string | yes | The commit SHA or name of a repository branch or tag |
| `note` | string | yes | The text of the comment |
| `path` | string | no | The file path relative to the repository |
| `line` | integer | no | The line number where the comment should be placed |
| `line_type` | string | no | The line type. Takes `new` or `old` as arguments |
```bash
curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" -F "note=Nice picture man\!" -F "path=dudeism.md" -F "line=11" -F "line_type=new" https://gitlab.example.com/api/v3/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/comments
```
- `id` (required) - The ID of a project
- `sha` (required) - The name of a repository branch or tag or if not given the default branch
- `note` (required) - Text of comment
- `path` (optional) - The file path
- `line` (optional) - The line number
- `line_type` (optional) - The line type (new or old)
Example response:
```json
{
"author": {
"id": 1,
"username": "admin",
"email": "admin@local.host",
"name": "Administrator",
"blocked": false,
"created_at": "2012-04-29T08:46:00Z"
},
"note": "text1",
"path": "example.rb",
"line": 5,
"line_type": "new"
"author" : {
"web_url" : "https://gitlab.example.com/u/thedude",
"avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png",
"username" : "thedude",
"state" : "active",
"name" : "Jeff Lebowski",
"id" : 28
},
"created_at" : "2016-01-19T09:44:55.600Z",
"line_type" : "new",
"path" : "dudeism.md",
"line" : 11,
"note" : "Nice picture man!"
}
```
## Get the status of a commit
## Commit status
Since GitLab 8.1, this is the new commit status API. The documentation in
[ci/api/commits](../ci/api/commits.md) is deprecated.
### Get the status of a commit
Get the statuses of a commit in a project.
......@@ -168,75 +224,116 @@ Get the statuses of a commit in a project.
GET /projects/:id/repository/commits/:sha/statuses
```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID of a project
| `sha` | string | yes | The commit SHA
| `ref_name`| string | no | The name of a repository branch or tag or, if not given, the default branch
| `stage` | string | no | Filter by [build stage](../ci/yaml/README.md#stages), e.g., `test`
| `name` | string | no | Filter by [job name](../ci/yaml/README.md#jobs), e.g., `bundler:audit`
| `all` | boolean | no | Return all statuses, not only the latest ones
```bash
curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/statuses
```
- `id` (required) - The ID of a project
- `sha` (required) - The commit SHA
- `ref` (optional) - Filter by ref name, it can be branch or tag
- `stage` (optional) - Filter by stage
- `name` (optional) - Filer by status name, eg. jenkins
- `all` (optional) - The flag to return all statuses, not only latest ones
Example response:
```json
[
{
"id": 13,
"sha": "b0b3a907f41409829b307a28b82fdbd552ee5a27",
"ref": "test",
"status": "success",
"name": "ci/jenkins",
"target_url": "http://jenkins/project/url",
"description": "Jenkins success",
"created_at": "2015-10-12T09:47:16.250Z",
"started_at": "2015-10-12T09:47:16.250Z",
"finished_at": "2015-10-12T09:47:16.262Z",
"author": {
"id": 1,
"username": "admin",
"email": "admin@local.host",
"name": "Administrator",
"blocked": false,
"created_at": "2012-04-29T08:46:00Z"
}
}
...
{
"status" : "pending",
"created_at" : "2016-01-19T08:40:25.934Z",
"started_at" : null,
"name" : "bundler:audit",
"allow_failure" : true,
"author" : {
"username" : "thedude",
"state" : "active",
"web_url" : "https://gitlab.example.com/u/thedude",
"avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png",
"id" : 28,
"name" : "Jeff Lebowski"
},
"description" : null,
"sha" : "18f3e63d05582537db6d183d9d557be09e1f90c8",
"target_url" : "https://gitlab.example.com/thedude/gitlab-ce/builds/91",
"finished_at" : null,
"id" : 91,
"ref" : "master"
},
{
"started_at" : null,
"name" : "flay",
"allow_failure" : false,
"status" : "pending",
"created_at" : "2016-01-19T08:40:25.832Z",
"target_url" : "https://gitlab.example.com/thedude/gitlab-ce/builds/90",
"id" : 90,
"finished_at" : null,
"ref" : "master",
"sha" : "18f3e63d05582537db6d183d9d557be09e1f90c8",
"author" : {
"id" : 28,
"name" : "Jeff Lebowski",
"username" : "thedude",
"web_url" : "https://gitlab.example.com/u/thedude",
"state" : "active",
"avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png"
},
"description" : null
},
...
]
```
## Post the status to commit
### Post the build status to a commit
Adds or updates a status of a commit.
Adds or updates a build status of a commit.
```
POST /projects/:id/statuses/:sha
```
- `id` (required) - The ID of a project
- `sha` (required) - The commit SHA
- `state` (required) - The state of the status. Can be: pending, running, success, failed, canceled
- `ref` (optional) - The ref (branch or tag) to which the status refers
- `name` or `context` (optional) - The label to differentiate this status from the status of other systems. Default: "default"
- `target_url` (optional) - The target URL to associate with this status
- `description` (optional) - The short description of the status
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID of a project
| `sha` | string | yes | The commit SHA
| `state` | string | yes | The state of the status. Can be one of the following: `pending`, `running`, `success`, `failed`, `canceled`
| `ref` | string | no | The `ref` (branch or tag) to which the status refers
| `name` or `context` | string | no | The label to differentiate this status from the status of other systems. Default value is `default`
| `target_url` | string | no | The target URL to associate with this status
| `description` | string | no | The short description of the status
```bash
curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/17/statuses/18f3e63d05582537db6d183d9d557be09e1f90c8?state=success"
```
Example response:
```json
{
"id": 13,
"sha": "b0b3a907f41409829b307a28b82fdbd552ee5a27",
"ref": "test",
"status": "success",
"name": "ci/jenkins",
"target_url": "http://jenkins/project/url",
"description": "Jenkins success",
"created_at": "2015-10-12T09:47:16.250Z",
"started_at": "2015-10-12T09:47:16.250Z",
"finished_at": "2015-10-12T09:47:16.262Z",
"author": {
"id": 1,
"username": "admin",
"email": "admin@local.host",
"name": "Administrator",
"blocked": false,
"created_at": "2012-04-29T08:46:00Z"
}
"author" : {
"web_url" : "https://gitlab.example.com/u/thedude",
"name" : "Jeff Lebowski",
"avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png",
"username" : "thedude",
"state" : "active",
"id" : 28
},
"name" : "default",
"sha" : "18f3e63d05582537db6d183d9d557be09e1f90c8",
"status" : "success",
"description" : null,
"id" : 93,
"target_url" : null,
"ref" : null,
"started_at" : null,
"created_at" : "2016-01-19T09:05:50.355Z",
"allow_failure" : false,
"finished_at" : "2016-01-19T09:05:50.365Z"
}
```
......@@ -12,6 +12,7 @@
* [Using Variables](variables/README.md)
* [Using SSH keys](ssh_keys/README.md)
* [Triggering builds through the API](triggers/README.md)
* [Build artifacts](build_artifacts/README.md)
### Languages
......
# Commits API
**DEPRECATED**
Since GitLab 8.1, there is a new commit status API. Please see the [revised
documentation](../../api/commits.md#commit-status).
---
__Authentication is done by GitLab CI project token__
## Commits
......
# Introduction to build artifacts
Artifacts is a list of files and directories which are attached to a build
after it completes successfully.
Since GitLab 8.2 and [GitLab Runner] 0.7.0, build artifacts that are created by
GitLab Runner are uploaded to GitLab and are downloadable as a single archive
(`tar.gz`) using the GitLab UI.
Starting from GitLab 8.4 and GitLab Runner 1.0, the artifacts archive format
changed to `ZIP`, and it is now possible to browse its contents, with the added
ability of downloading the files separately.
## Enabling build artifacts
_If you are searching for ways to use artifacts, jump to
[Defining artifacts in `.gitlab-ci.yml`](#defining-artifacts-in-gitlab-ciyml)._
The artifacts feature is enabled by default in all GitLab installations.
To disable it site-wide, follow the steps below.
---
**In Omnibus installations:**
1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
```ruby
gitlab_rails['artifacts_enabled'] = false
```
1. Save the file and [reconfigure GitLab][] for the changes to take effect.
---
**In installations from source:**
1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
```yaml
artifacts:
enabled: false
```
1. Save the file and [restart GitLab][] for the changes to take effect.
## Defining artifacts in `.gitlab-ci.yml`
A simple example of using the artifacts definition in `.gitlab-ci.yml` would be
the following:
```yaml
pdf:
script: xelatex mycv.tex
artifacts:
paths:
- mycv.pdf
```
A job named `pdf` calls the `xelatex` command in order to build a pdf file from
the latex source file `mycv.tex`. We then define the `artifacts` paths which in
turn are defined with the `paths` keyword. All paths to files and directories
are relative to the repository that was cloned during the build.
For more examples on artifacts, follow the
[separate artifacts yaml documentation](../yaml/README.md#artifacts).
## Storing build artifacts
After a successful build, GitLab Runner uploads an archive containing the build
artifacts to GitLab.
To change the location where the artifacts are stored, follow the steps below.
---
**In Omnibus installations:**
_The artifacts are stored by default in
`/var/opt/gitlab/gitlab-rails/shared/artifacts`._
1. To change the storage path for example to `/mnt/storage/artifacts`, edit
`/etc/gitlab/gitlab.rb` and add the following line:
```ruby
gitlab_rails['artifacts_path'] = "/mnt/storage/artifacts"
```
1. Save the file and [reconfigure GitLab][] for the changes to take effect.
---
**In installations from source:**
_The artifacts are stored by default in
`/home/git/gitlab/shared/artifacts`._
1. To change the storage path for example to `/mnt/storage/artifacts`, edit
`/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
```yaml
artifacts:
enabled: true
path: /mnt/storage/artifacts
```
1. Save the file and [restart GitLab][] for the changes to take effect.
## Browsing build artifacts
When GitLab receives an artifacts archive, an archive metadata file is also
generated. This metadata file describes all the entries that are located in the
artifacts archive itself. The metadata file is in a binary format, with
additional GZIP compression.
GitLab does not extract the artifacts archive in order to save space, memory
and disk I/O. It instead inspects the metadata file which contains all the
relevant information. This is especially important when there is a lot of
artifacts, or an archive is a very large file.
---
After a successful build, if you visit the build's specific page, you can see
that there are two buttons.
One is for downloading the artifacts archive and the other for browsing its
contents.
![Build artifacts browser button](img/build_artifacts_browser_button.png)
---
The archive browser shows the name and the actual file size of each file in the
archive. If your artifacts contained directories, then you are also able to
browse inside them.
Below you can see an image of three different file formats, as well as two
directories.
![Build artifacts browser](img/build_artifacts_browser.png)
---
## Downloading build artifacts
If you need to download the whole archive, there are buttons in various places
inside GitLab that make that possible.
1. While on the builds page, you can see the download icon for each build's
artifacts archive in the right corner
1. While inside a specific build, you are presented with a download button
along with the one that browses the archive
1. And finally, when browsing and archive you can see the download button at
the top right corner
---
Note that GitLab does not extract the entire artifacts archive to send just a
single file to the user.
When clicking on a specific file, [GitLab Workhorse] extracts it from the
archive and the download begins.
This implementation saves space, memory and disk I/O.
[gitlab runner]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner "GitLab Runner repository"
[reconfigure gitlab]: ../../administration/restart_gitlab.md "How to restart GitLab documentation"
[restart gitlab]: ../../administration/restart_gitlab.md "How to restart GitLab documentation"
[gitlab workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse "GitLab Workhorse repository"
......@@ -12,7 +12,7 @@ configuration from the developer. To overcome this we will be using the
official [PHP docker image][php-hub] that can be found in Docker Hub.
This will allow us to test PHP projects against different versions of PHP.
However, not everything is plug 'n' play, you still need to onfigure some
However, not everything is plug 'n' play, you still need to configure some
things manually.
As with every build, you need to create a valid `.gitlab-ci.yml` describing the
......
......@@ -159,50 +159,55 @@ The `key` directive allows you to define the affinity of caching
between jobs, allowing to have a single cache for all jobs,
cache per-job, cache per-branch or any other way you deem proper.
This allows you to fine tune caching, allowing you to cache data between different jobs or even different branches.
The `cache:key` variable can use any of the [predefined variables](../variables/README.md):
This allows you to fine tune caching, allowing you to cache data between
different jobs or even different branches.
Example configurations:
The `cache:key` variable can use any of the [predefined variables](../variables/README.md).
---
**Example configurations**
To enable per-job caching:
```yaml
cache:
key: "$CI_BUILD_NAME"
untracked: true
```
```yaml
cache:
key: "$CI_BUILD_NAME"
untracked: true
```
To enable per-branch caching:
```yaml
cache:
key: "$CI_BUILD_REF_NAME"
untracked: true
```
```yaml
cache:
key: "$CI_BUILD_REF_NAME"
untracked: true
```
To enable per-job and per-branch caching:
```yaml
cache:
key: "$CI_BUILD_NAME/$CI_BUILD_REF_NAME"
untracked: true
```
```yaml
cache:
key: "$CI_BUILD_NAME/$CI_BUILD_REF_NAME"
untracked: true
```
To enable per-branch and per-stage caching:
```yaml
cache:
key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
untracked: true
```
```yaml
cache:
key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
untracked: true
```
If you use **Windows Batch** to run your shell scripts you need to replace the `$` with `%`:
If you use **Windows Batch** to run your shell scripts you need to replace
`$` with `%`:
```yaml
cache:
key: "%CI_BUILD_STAGE%/%CI_BUILD_REF_NAME%"
untracked: true
```
```yaml
cache:
key: "%CI_BUILD_STAGE%/%CI_BUILD_REF_NAME%"
untracked: true
```
## Jobs
......
......@@ -103,6 +103,23 @@ Inside the document:
`_**Note:** This feature was introduced in GitLab EE 8.3_`. Otherwise, leave
this mention out
## References
- **GitLab Restart:**
There are many cases that a restart/reconfigure of GitLab is required. To
avoid duplication, link to the special document that can be found in
[`doc/administration/restart_gitlab.md`][doc-restart]. Usually the text will
read like:
```
Save the file and [reconfigure GitLab](../administration/restart_gitlab.md)
for the changes to take effect.
```
If the document you are editing resides in a place other than the GitLab CE/EE
`doc/` directory, instead of the relative link, use the full path:
`http://doc.gitlab.com/ce/administration/restart_gitlab.html`.
Replace `reconfigure` with `restart` where appropriate.
## API
Here is a list of must-have items. Use them in the exact order that appears
......@@ -229,3 +246,4 @@ curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" -d "restricted_signup_domai
[cURL]: http://curl.haxx.se/ "cURL website"
[single spaces]: http://www.slate.com/articles/technology/technology/2011/01/space_invaders.html
[gfm]: http://doc.gitlab.com/ce/markdown/markdown.html#newlines "GitLab flavored markdown documentation"
[doc-restart]: ../administration/restart_gitlab.md "GitLab restart documentation"
......@@ -20,7 +20,13 @@ In the Admin area under **Settings** (`/admin/application_settings`), look for
the "Sign-in Restrictions" area, where you can configure both.
If you want 2FA enforcement to take effect on next login, change the grace
period to `0`
period to `0`.
---
![Two factor authentication admin settings](img/two_factor_authentication_settings.png)
---
## Disabling 2FA for everyone
......@@ -28,11 +34,12 @@ There may be some special situations where you want to disable 2FA for everyone
even when forced 2FA is disabled. There is a rake task for that:
```
# use this command if you've installed GitLab with the Omnibus package
# Omnibus installations
sudo gitlab-rake gitlab:two_factor:disable_for_all_users
# if you've installed GitLab from source
# Installations from source
sudo -u git -H bundle exec rake gitlab:two_factor:disable_for_all_users RAILS_ENV=production
```
**IMPORTANT: this is a permanent and irreversible action. Users will have to reactivate 2FA from scratch if they want to use it again.**
**IMPORTANT: this is a permanent and irreversible action. Users will have to
reactivate 2FA from scratch if they want to use it again.**
......@@ -37,7 +37,7 @@ sudo -u git -H git checkout 8-4-stable-ee
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch --all
sudo -u git -H git checkout v2.6.9
sudo -u git -H git checkout v2.6.10
```
### 5. Update gitlab-workhorse
......@@ -48,7 +48,7 @@ which should already be on your system from GitLab 8.1.
```bash
cd /home/git/gitlab-workhorse
sudo -u git -H git fetch --all
sudo -u git -H git checkout 0.6.0
sudo -u git -H git checkout 0.6.1
sudo -u git -H make
```
......@@ -104,10 +104,7 @@ via [/etc/default/gitlab].
#### Init script
We updated the init script for GitLab in order to pass new
configuration options to gitlab-workhorse. We let gitlab-workhorse
connect to the Rails application via a Unix domain socket and we tell
it where the 'public' directory of GitLab is.
We updated the init script for GitLab in order to set a specific PATH for gitlab-workhorse.
```
cd /home/git/gitlab
......
......@@ -7,6 +7,7 @@
- [Groups](groups.md)
- [Importing to GitLab](doc/importing/README.md)
- [Keyboard shortcuts](shortcuts.md)
- [File finder](file_finder.md)
- [Labels](labels.md)
- [Issue weight](issue_weight.md)
- [Manage large binaries with git annex](git_annex.md)
......
# File finder
_**Note:** This feature was [introduced][gh-9889] in GitLab 8.4._
---
The file finder feature allows you to quickly shortcut your way when you are
searching for a file in a repository using the GitLab UI.
You can find the **Find File** button when in the **Files** section of a
project.
![Find file button](img/file_finder_find_button.png)
---
For those who prefer to keep their fingers on the keyboard, there is a
[shortcut button](shortcuts.md) as well, which you can invoke from _anywhere_
in a project.
Press `t` to launch the File search function when in **Issues**,
**Merge requests**, **Milestones**, even the project's settings.
Start typing what you are searching for and watch the magic happen. With the
up/down arrows, you go up and down the results, with `Esc` you close the search
and go back to **Files**.
## How it works
The File finder feature is powered by the [Fuzzy filter] library.
It implements a fuzzy search with highlight, and tries to provide intuitive
results by recognizing patterns that people use while searching.
For example, consider the [GitLab CE repository][ce] and that we want to open
the `app/controllers/admin/deploy_keys_controller.rb` file.
Using fuzzy search, we start by typing letters that get us closer to the file.
**Protip:** To narrow down your search, include `/` in your search terms.
![Find file button](img/file_finder_find_file.png)
[gh-9889]: https://github.com/gitlabhq/gitlabhq/pull/9889 "File finder pull request"
[fuzzy filter]: https://github.com/jeancroy/fuzzaldrin-plus "fuzzaldrin-plus on GitHub"
[ce]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master "GitLab CE repository"
......@@ -13,8 +13,8 @@ module Gitlab
attr_reader :file, :path, :full_version
def initialize(file, path)
@file, @path = file, path
def initialize(file, path, **opts)
@file, @path, @opts = file, path, opts
@full_version = read_version
end
......@@ -52,7 +52,9 @@ module Gitlab
def match_entries(gz)
entries = {}
match_pattern = %r{^#{Regexp.escape(@path)}[^/]*/?$}
child_pattern = '[^/]*/?$' unless @opts[:recursive]
match_pattern = /^#{Regexp.escape(@path)}#{child_pattern}/
until gz.eof? do
begin
......
......@@ -95,6 +95,13 @@ module Gitlab
children.empty?
end
def total_size
descendant_pattern = %r{^#{Regexp.escape(@path)}}
entries.sum do |path, entry|
(entry[:size] if path =~ descendant_pattern).to_i
end
end
def to_s
@path
end
......
module Gitlab
module Diff
class Highlight
attr_reader :diff_file
attr_reader :diff_file, :diff_lines, :raw_lines
delegate :old_path, :new_path, :old_ref, :new_ref, to: :diff_file, prefix: :diff
def initialize(diff_file)
@diff_file = diff_file
@diff_lines = diff_file.diff_lines
def initialize(diff_lines)
if diff_lines.is_a?(Gitlab::Diff::File)
@diff_file = diff_lines
@diff_lines = @diff_file.diff_lines
else
@diff_lines = diff_lines
end
@raw_lines = @diff_lines.map(&:text)
end
def highlight
@diff_lines.each_with_index do |diff_line, i|
@diff_lines.map.with_index do |diff_line, i|
diff_line = diff_line.dup
# ignore highlighting for "match" lines
next if diff_line.type == 'match' || diff_line.type == 'nonewline'
next diff_line if diff_line.type == 'match' || diff_line.type == 'nonewline'
rich_line = highlight_line(diff_line, i)
......@@ -23,15 +28,15 @@ module Gitlab
end
diff_line.text = rich_line.html_safe
end
@diff_lines
diff_line
end
end
private
def highlight_line(diff_line, index)
return html_escape(diff_line.text) unless diff_file.diff_refs
return html_escape(diff_line.text) unless diff_file && diff_file.diff_refs
line_prefix = diff_line.text.match(/\A(.)/) ? $1 : ' '
......@@ -52,10 +57,12 @@ module Gitlab
end
def old_lines
return unless diff_file
@old_lines ||= Gitlab::Highlight.highlight_lines(*processing_args(:old))
end
def new_lines
return unless diff_file
@new_lines ||= Gitlab::Highlight.highlight_lines(*processing_args(:new))
end
......
......@@ -11,7 +11,8 @@ module Gitlab
lines = []
skip_next = false
diff_file.highlighted_diff_lines.each do |line|
highlighted_diff_lines = diff_file.highlighted_diff_lines
highlighted_diff_lines.each do |line|
full_line = line.text
type = line.type
line_code = generate_line_code(diff_file.file_path, line)
......@@ -21,6 +22,7 @@ module Gitlab
next_line = diff_file.next_line(line.index)
if next_line
next_line = highlighted_diff_lines[next_line.index]
next_line_code = generate_line_code(diff_file.file_path, next_line)
next_type = next_line.type
next_line = next_line.text
......
......@@ -82,8 +82,12 @@ module Gitlab
end
true
rescue Gitlab::Shell::Error
false
rescue Gitlab::Shell::Error => e
if e.message =~ /repository not exported/
true
else
false
end
end
end
end
......
......@@ -38,6 +38,7 @@ web_server_pid_path="$pid_path/unicorn.pid"
sidekiq_pid_path="$pid_path/sidekiq.pid"
mail_room_enabled=false
mail_room_pid_path="$pid_path/mail_room.pid"
gitlab_workhorse_dir=$(cd $app_root/../gitlab-workhorse && pwd)
gitlab_workhorse_pid_path="$pid_path/gitlab-workhorse.pid"
gitlab_workhorse_options="-listenUmask 0 -listenNetwork unix -listenAddr $socket_path/gitlab-workhorse.socket -authBackend http://127.0.0.1:8080 -authSocket $rails_socket -documentRoot $app_root/public"
gitlab_workhorse_log="$app_root/log/gitlab-workhorse.log"
......@@ -233,10 +234,12 @@ start_gitlab() {
if [ "$gitlab_workhorse_status" = "0" ]; then
echo "The gitlab-workhorse is already running with pid $spid, not restarting"
else
# No need to remove a socket, gitlab-workhorse does this itself
# No need to remove a socket, gitlab-workhorse does this itself.
# Because gitlab-workhorse has multiple executables we need to fix
# the PATH.
$app_root/bin/daemon_with_pidfile $gitlab_workhorse_pid_path \
$app_root/../gitlab-workhorse/gitlab-workhorse \
$gitlab_workhorse_options \
/usr/bin/env PATH=$gitlab_workhorse_dir:$PATH \
gitlab-workhorse $gitlab_workhorse_options \
>> $gitlab_workhorse_log 2>&1 &
fi
......
......@@ -30,6 +30,9 @@ web_server_pid_path="$pid_path/unicorn.pid"
# The default is "$pid_path/sidekiq.pid"
sidekiq_pid_path="$pid_path/sidekiq.pid"
# The directory where the gitlab-workhorse binaries are. Usually
# /home/git/gitlab-workhorse .
gitlab_workhorse_dir=$(cd $app_root/../gitlab-workhorse && pwd)
gitlab_workhorse_pid_path="$pid_path/gitlab-workhorse.pid"
# The -listenXxx settings determine where gitlab-workhorse
# listens for connections from NGINX. To listen on localhost:8181, write
......
......@@ -4,13 +4,13 @@ describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do
let(:entries) do
{ 'path/' => {},
'path/dir_1/' => {},
'path/dir_1/file_1' => {},
'path/dir_1/file_b' => {},
'path/dir_1/file_1' => { size: 10 },
'path/dir_1/file_b' => { size: 10 },
'path/dir_1/subdir/' => {},
'path/dir_1/subdir/subfile' => {},
'path/dir_1/subdir/subfile' => { size: 10 },
'path/second_dir' => {},
'path/second_dir/dir_3/file_2' => {},
'path/second_dir/dir_3/file_3'=> {},
'path/second_dir/dir_3/file_2' => { size: 10 },
'path/second_dir/dir_3/file_3'=> { size: 10 },
'another_directory/'=> {},
'another_file' => {},
'/file/with/absolute_path' => {} }
......@@ -112,6 +112,11 @@ describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do
subject { |example| path(example).empty? }
it { is_expected.to be false }
end
describe '#total_size' do
subject { |example| path(example).total_size }
it { is_expected.to eq(30) }
end
end
end
......
require 'spec_helper'
describe Gitlab::Ci::Build::Artifacts::Metadata do
def metadata(path = '')
described_class.new(metadata_file_path, path)
def metadata(path = '', **opts)
described_class.new(metadata_file_path, path, **opts)
end
let(:metadata_file_path) do
......@@ -51,6 +51,19 @@ describe Gitlab::Ci::Build::Artifacts::Metadata do
end
end
describe '#find_entries! recursively for other_artifacts_0.1.2/' do
subject { metadata('other_artifacts_0.1.2/', recursive: true).find_entries! }
it 'matches correct paths' do
expect(subject.keys).
to contain_exactly 'other_artifacts_0.1.2/',
'other_artifacts_0.1.2/doc_sample.txt',
'other_artifacts_0.1.2/another-subdirectory/',
'other_artifacts_0.1.2/another-subdirectory/empty_directory/',
'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif'
end
end
describe '#to_entry' do
subject { metadata('').to_entry }
it { is_expected.to be_an_instance_of(Gitlab::Ci::Build::Artifacts::Metadata::Entry) }
......
......@@ -362,12 +362,12 @@ describe Ci::Build, models: true do
subject { build.artifacts_browse_url }
it "should be nil if artifacts browser is unsupported" do
allow(build).to receive(:artifacts_browser_supported?).and_return(false)
allow(build).to receive(:artifacts_metadata?).and_return(false)
is_expected.to be_nil
end
it 'should not be nil if artifacts browser is supported' do
allow(build).to receive(:artifacts_browser_supported?).and_return(true)
allow(build).to receive(:artifacts_metadata?).and_return(true)
is_expected.to_not be_nil
end
end
......@@ -391,8 +391,8 @@ describe Ci::Build, models: true do
end
describe :artifacts_browser_supported? do
subject { build.artifacts_browser_supported? }
describe :artifacts_metadata? do
subject { build.artifacts_metadata? }
context 'artifacts metadata does not exist' do
it { is_expected.to be_falsy }
end
......
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