Commit eab086bd authored by Douwe Maan's avatar Douwe Maan

Merge branch 'master' into merge-if-green

# Conflicts:
#	app/controllers/projects/merge_requests_controller.rb
#	config/routes.rb
parents 1464a69c ee0ab46d
...@@ -25,6 +25,7 @@ v 8.3.0 (unreleased) ...@@ -25,6 +25,7 @@ v 8.3.0 (unreleased)
- Fix bug when simultaneously accepting multiple MRs results in MRs that are of "merged" status, but not merged to the target branch - Fix bug when simultaneously accepting multiple MRs results in MRs that are of "merged" status, but not merged to the target branch
- Add languages page to graphs - Add languages page to graphs
- Block LDAP user when they are no longer found in the LDAP server - Block LDAP user when they are no longer found in the LDAP server
- Improve wording on project visibility levels (Zeger-Jan van de Weg)
v 8.2.3 v 8.2.3
- Fix application settings cache not expiring after changes (Stan Hu) - Fix application settings cache not expiring after changes (Stan Hu)
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
# #
class @MergeRequestTabs class @MergeRequestTabs
diffsLoaded: false diffsLoaded: false
buildsLoaded: false
commitsLoaded: false commitsLoaded: false
constructor: (@opts = {}) -> constructor: (@opts = {}) ->
...@@ -54,6 +55,12 @@ class @MergeRequestTabs ...@@ -54,6 +55,12 @@ class @MergeRequestTabs
bindEvents: -> bindEvents: ->
$(document).on 'shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', @tabShown $(document).on 'shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', @tabShown
$(document).on 'click', '.js-show-tab', @showTab
showTab: (event) =>
event.preventDefault()
@activateTab $(event.target).data('action')
tabShown: (event) => tabShown: (event) =>
$target = $(event.target) $target = $(event.target)
...@@ -63,6 +70,8 @@ class @MergeRequestTabs ...@@ -63,6 +70,8 @@ class @MergeRequestTabs
@loadCommits($target.attr('href')) @loadCommits($target.attr('href'))
else if action == 'diffs' else if action == 'diffs'
@loadDiff($target.attr('href')) @loadDiff($target.attr('href'))
else if action == 'builds'
@loadBuilds($target.attr('href'))
@setCurrentAction(action) @setCurrentAction(action)
...@@ -101,7 +110,7 @@ class @MergeRequestTabs ...@@ -101,7 +110,7 @@ class @MergeRequestTabs
action = 'notes' if action == 'show' action = 'notes' if action == 'show'
# Remove a trailing '/commits' or '/diffs' # Remove a trailing '/commits' or '/diffs'
new_state = @_location.pathname.replace(/\/(commits|diffs)(\.html)?\/?$/, '') new_state = @_location.pathname.replace(/\/(commits|diffs|builds)(\.html)?\/?$/, '')
# Append the new action if we're on a tab other than 'notes' # Append the new action if we're on a tab other than 'notes'
unless action == 'notes' unless action == 'notes'
...@@ -139,6 +148,17 @@ class @MergeRequestTabs ...@@ -139,6 +148,17 @@ class @MergeRequestTabs
@diffsLoaded = true @diffsLoaded = true
@scrollToElement("#diffs") @scrollToElement("#diffs")
loadBuilds: (source) ->
return if @buildsLoaded
@_get
url: "#{source}.json"
success: (data) =>
document.getElementById('builds').innerHTML = data.html
$('.js-timeago').timeago()
@buildsLoaded = true
@scrollToElement("#builds")
# Show or hide the loading spinner # Show or hide the loading spinner
# #
# status - Boolean, true to show, false to hide # status - Boolean, true to show, false to hide
......
...@@ -83,6 +83,10 @@ ...@@ -83,6 +83,10 @@
&.ci-error { &.ci-error {
color: $gl-danger; color: $gl-danger;
} }
a.monospace {
color: inherit;
}
} }
.mr-widget-body, .mr-widget-body,
......
...@@ -21,7 +21,7 @@ class Projects::ApplicationController < ApplicationController ...@@ -21,7 +21,7 @@ class Projects::ApplicationController < ApplicationController
unless @repository.branch_names.include?(@ref) unless @repository.branch_names.include?(@ref)
redirect_to( redirect_to(
namespace_project_tree_path(@project.namespace, @project, @ref), namespace_project_tree_path(@project.namespace, @project, @ref),
notice: "This action is not allowed unless you are on top of a branch" notice: "This action is not allowed unless you are on a branch"
) )
end end
end end
......
...@@ -162,12 +162,20 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -162,12 +162,20 @@ class Projects::BlobController < Projects::ApplicationController
end end
def sanitized_new_branch_name def sanitized_new_branch_name
@new_branch ||= sanitize(strip_tags(params[:new_branch])) sanitize(strip_tags(params[:new_branch]))
end end
def editor_variables def editor_variables
@current_branch = @ref @current_branch = @ref
@new_branch = params[:new_branch].present? ? sanitized_new_branch_name : @ref
@new_branch =
if params[:new_branch].present?
sanitized_new_branch_name
elsif ::Gitlab::GitAccess.new(current_user, @project).can_push_to_branch?(@ref)
@ref
else
@repository.next_patch_branch
end
@file_path = @file_path =
if action_name.to_s == 'create' if action_name.to_s == 'create'
......
...@@ -37,7 +37,7 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -37,7 +37,7 @@ class Projects::CommitController < Projects::ApplicationController
def cancel_builds def cancel_builds
ci_commit.builds.running_or_pending.each(&:cancel) ci_commit.builds.running_or_pending.each(&:cancel)
redirect_to builds_namespace_project_commit_path(project.namespace, project, commit.sha) redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha)
end end
def retry_builds def retry_builds
...@@ -47,7 +47,7 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -47,7 +47,7 @@ class Projects::CommitController < Projects::ApplicationController
end end
end end
redirect_to builds_namespace_project_commit_path(project.namespace, project, commit.sha) redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha)
end end
def branches def branches
...@@ -75,7 +75,7 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -75,7 +75,7 @@ class Projects::CommitController < Projects::ApplicationController
@notes_count = commit.notes.count @notes_count = commit.notes.count
@builds = ci_commit.builds if ci_commit @statuses = ci_commit.statuses if ci_commit
end end
def authorize_manage_builds! def authorize_manage_builds!
......
class Projects::MergeRequestsController < Projects::ApplicationController class Projects::MergeRequestsController < Projects::ApplicationController
before_action :module_enabled before_action :module_enabled
before_action :merge_request, only: [ before_action :merge_request, only: [
:edit, :update, :show, :diffs, :commits, :merge, :merge_check, :edit, :update, :show, :diffs, :commits, :builds, :merge, :merge_check,
:ci_status, :toggle_subscription, :cancel_merge_when_build_succeeds :ci_status, :toggle_subscription, :cancel_merge_when_build_succeeds
] ]
before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits] before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits, :builds]
before_action :validates_merge_request, only: [:show, :diffs, :commits] before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds]
before_action :define_show_vars, only: [:show, :diffs, :commits] before_action :define_show_vars, only: [:show, :diffs, :commits, :builds]
before_action :ensure_ref_fetched, only: [:show, :commits, :diffs] before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds]
# Allow read any merge_request # Allow read any merge_request
before_action :authorize_read_merge_request! before_action :authorize_read_merge_request!
...@@ -79,6 +79,15 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -79,6 +79,15 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
end end
def builds
@ci_project = @merge_request.source_project.gitlab_ci_project
respond_to do |format|
format.html { render 'show' }
format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_builds') } }
end
end
def new def new
params[:merge_request] ||= ActionController::Parameters.new(source_project: @project) params[:merge_request] ||= ActionController::Parameters.new(source_project: @project)
@merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute @merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute
...@@ -91,20 +100,19 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -91,20 +100,19 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@target_project = merge_request.target_project @target_project = merge_request.target_project
@source_project = merge_request.source_project @source_project = merge_request.source_project
@commits = @merge_request.compare_commits @commits = @merge_request.compare_commits.reverse
@commit = @merge_request.last_commit @commit = @merge_request.last_commit
@first_commit = @merge_request.first_commit @first_commit = @merge_request.first_commit
@diffs = @merge_request.compare_diffs @diffs = @merge_request.compare_diffs
@ci_project = @source_project.gitlab_ci_project
@ci_commit = @merge_request.ci_commit
@statuses = @ci_commit.statuses if @ci_commit
@note_counts = Note.where(commit_id: @commits.map(&:id)). @note_counts = Note.where(commit_id: @commits.map(&:id)).
group(:commit_id).count group(:commit_id).count
end end
def edit
@source_project = @merge_request.source_project
@target_project = @merge_request.target_project
@target_branches = @merge_request.target_project.repository.branch_names
end
def create def create
@target_branches ||= [] @target_branches ||= []
@merge_request = MergeRequests::CreateService.new(project, current_user, merge_request_params).execute @merge_request = MergeRequests::CreateService.new(project, current_user, merge_request_params).execute
...@@ -118,6 +126,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -118,6 +126,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
end end
def edit
@source_project = @merge_request.source_project
@target_project = @merge_request.target_project
@target_branches = @merge_request.target_project.repository.branch_names
end
def update def update
@merge_request = MergeRequests::UpdateService.new(project, current_user, merge_request_params).execute(@merge_request) @merge_request = MergeRequests::UpdateService.new(project, current_user, merge_request_params).execute(@merge_request)
...@@ -279,6 +293,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -279,6 +293,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request_diff = @merge_request.merge_request_diff @merge_request_diff = @merge_request.merge_request_diff
@ci_commit = @merge_request.ci_commit @ci_commit = @merge_request.ci_commit
@statuses = @ci_commit.statuses if @ci_commit
if @merge_request.locked_long_ago? if @merge_request.locked_long_ago?
@merge_request.unlock_mr @merge_request.unlock_mr
......
...@@ -23,7 +23,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -23,7 +23,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
@group_members = @group_members.where(user_id: users) @group_members = @group_members.where(user_id: users)
end end
@group_members = @group_members.order('access_level DESC').limit(20) @group_members = @group_members.order('access_level DESC')
end end
@project_member = @project.project_members.new @project_member = @project.project_members.new
......
...@@ -30,26 +30,24 @@ module BlobHelper ...@@ -30,26 +30,24 @@ module BlobHelper
nil nil
end end
if blob_viewable?(blob) return unless blob && blob.text? && blob_editable?(blob)
text = 'Edit' text = 'Edit'
after = options[:after] || '' after = options[:after] || ''
from_mr = options[:from_merge_request_id] from_mr = options[:from_merge_request_id]
link_opts = {} link_opts = {}
link_opts[:from_merge_request_id] = from_mr if from_mr link_opts[:from_merge_request_id] = from_mr if from_mr
cls = 'btn btn-small' cls = 'btn btn-small'
if allowed_tree_edit?(project, ref)
link_to(text, link_to(text,
namespace_project_edit_blob_path(project.namespace, project, namespace_project_edit_blob_path(project.namespace, project,
tree_join(ref, path), tree_join(ref, path),
link_opts), link_opts),
class: cls class: cls
) ) + after.html_safe
else
content_tag :span, text, class: cls + ' disabled'
end + after.html_safe
else
''
end end
def blob_editable?(blob, project = @project, ref = @ref)
!blob.lfs_pointer? && allowed_tree_edit?(project, ref)
end end
def leave_edit_message def leave_edit_message
......
...@@ -46,16 +46,26 @@ module TreeHelper ...@@ -46,16 +46,26 @@ module TreeHelper
File.join(*args) File.join(*args)
end end
def on_top_of_branch?(project = @project, ref = @ref)
project.repository.branch_names.include?(ref)
end
def allowed_tree_edit?(project = nil, ref = nil) def allowed_tree_edit?(project = nil, ref = nil)
project ||= @project project ||= @project
ref ||= @ref ref ||= @ref
return false unless project.repository.branch_names.include?(ref) return false unless on_top_of_branch?(project, ref)
::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(ref) can?(current_user, :push_code, project)
end end
def can_delete_or_replace?(blob) def tree_edit_branch(project = @project, ref = @ref)
allowed_tree_edit? && !blob.lfs_pointer? if allowed_tree_edit?(project, ref)
if can_push_branch?(project, ref)
ref
else
project.repository.next_patch_branch
end
end
end end
def tree_breadcrumbs(tree, max_links = 2) def tree_breadcrumbs(tree, max_links = 2)
......
...@@ -16,18 +16,18 @@ module VisibilityLevelHelper ...@@ -16,18 +16,18 @@ module VisibilityLevelHelper
# +form_model+ Either a model object (Project, Snippet, etc.) or the name of # +form_model+ Either a model object (Project, Snippet, etc.) or the name of
# a Project or Snippet class. # a Project or Snippet class.
def visibility_level_description(level, form_model) def visibility_level_description(level, form_model)
case form_model.is_a?(String) ? form_model : form_model.class.name case form_model
when 'PersonalSnippet', 'ProjectSnippet', 'Snippet' when Project
snippet_visibility_level_description(level)
when 'Project'
project_visibility_level_description(level) project_visibility_level_description(level)
when Snippet
snippet_visibility_level_description(level, form_model)
end end
end end
def project_visibility_level_description(level) def project_visibility_level_description(level)
case level case level
when Gitlab::VisibilityLevel::PRIVATE when Gitlab::VisibilityLevel::PRIVATE
"Project access must be granted explicitly for each user." "Project access must be granted explicitly to each user."
when Gitlab::VisibilityLevel::INTERNAL when Gitlab::VisibilityLevel::INTERNAL
"The project can be cloned by any logged in user." "The project can be cloned by any logged in user."
when Gitlab::VisibilityLevel::PUBLIC when Gitlab::VisibilityLevel::PUBLIC
...@@ -35,12 +35,16 @@ module VisibilityLevelHelper ...@@ -35,12 +35,16 @@ module VisibilityLevelHelper
end end
end end
def snippet_visibility_level_description(level) def snippet_visibility_level_description(level, snippet = nil)
case level case level
when Gitlab::VisibilityLevel::PRIVATE when Gitlab::VisibilityLevel::PRIVATE
"The snippet is visible only for me." if snippet.is_a? ProjectSnippet
"The snippet is visible only to project members."
else
"The snippet is visible only to me."
end
when Gitlab::VisibilityLevel::INTERNAL when Gitlab::VisibilityLevel::INTERNAL
"The snippet is visible for any logged in user." "The snippet is visible to any logged in user."
when Gitlab::VisibilityLevel::PUBLIC when Gitlab::VisibilityLevel::PUBLIC
"The snippet can be accessed without any authentication." "The snippet can be accessed without any authentication."
end end
......
# == Schema Information
#
# Table name: lfs_objects
#
# id :integer not null, primary key
# oid :string(255) not null
# size :integer not null
# created_at :datetime
# updated_at :datetime
# file :string(255)
#
class LfsObject < ActiveRecord::Base class LfsObject < ActiveRecord::Base
has_many :lfs_objects_projects, dependent: :destroy has_many :lfs_objects_projects, dependent: :destroy
has_many :projects, through: :lfs_objects_projects has_many :projects, through: :lfs_objects_projects
......
# == Schema Information
#
# Table name: lfs_objects_projects
#
# id :integer not null, primary key
# lfs_object_id :integer not null
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
#
class LfsObjectsProject < ActiveRecord::Base class LfsObjectsProject < ActiveRecord::Base
belongs_to :project belongs_to :project
belongs_to :lfs_object belongs_to :lfs_object
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
# system :boolean default(FALSE), not null # system :boolean default(FALSE), not null
# st_diff :text # st_diff :text
# updated_by_id :integer # updated_by_id :integer
# is_award :boolean default(FALSE), not null
# #
require 'carrierwave/orm/activerecord' require 'carrierwave/orm/activerecord'
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
# import_type :string(255) # import_type :string(255)
# import_source :string(255) # import_source :string(255)
# commit_count :integer default(0) # commit_count :integer default(0)
# import_error :text
# #
require 'carrierwave/orm/activerecord' require 'carrierwave/orm/activerecord'
......
...@@ -329,6 +329,17 @@ class Repository ...@@ -329,6 +329,17 @@ class Repository
commit(sha) commit(sha)
end end
def next_patch_branch
patch_branch_ids = self.branch_names.map do |n|
result = n.match(/\Apatch-([0-9]+)\z/)
result[1].to_i if result
end.compact
highest_patch_branch_id = patch_branch_ids.max || 0
"patch-#{highest_patch_branch_id + 1}"
end
# Remove archives older than 2 hours # Remove archives older than 2 hours
def branches_sorted_by(value) def branches_sorted_by(value)
case value case value
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
# project_view :integer default(0) # project_view :integer default(0)
# consumed_timestep :integer # consumed_timestep :integer
# layout :integer default(0) # layout :integer default(0)
# hide_project_limit :boolean default(FALSE)
# #
require 'carrierwave/orm/activerecord' require 'carrierwave/orm/activerecord'
......
...@@ -53,7 +53,7 @@ module Files ...@@ -53,7 +53,7 @@ module Files
unless project.empty_repo? unless project.empty_repo?
unless repository.branch_names.include?(@current_branch) unless repository.branch_names.include?(@current_branch)
raise_error("You can only create files if you are on top of a branch") raise_error("You can only create or edit files when you are on a branch")
end end
if @current_branch != @target_branch if @current_branch != @target_branch
......
...@@ -14,11 +14,11 @@ ...@@ -14,11 +14,11 @@
.form-group.project-visibility-level-holder .form-group.project-visibility-level-holder
= f.label :default_project_visibility, class: 'control-label col-sm-2' = f.label :default_project_visibility, class: 'control-label col-sm-2'
.col-sm-10 .col-sm-10
= render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: 'Project') = render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project)
.form-group.project-visibility-level-holder .form-group.project-visibility-level-holder
= f.label :default_snippet_visibility, class: 'control-label col-sm-2' = f.label :default_snippet_visibility, class: 'control-label col-sm-2'
.col-sm-10 .col-sm-10
= render('shared/visibility_radios', model_method: :default_snippet_visibility, form: f, selected_level: @application_setting.default_snippet_visibility, form_model: 'Snippet') = render('shared/visibility_radios', model_method: :default_snippet_visibility, form: f, selected_level: @application_setting.default_snippet_visibility, form_model: PersonalSnippet)
.form-group .form-group
= f.label :restricted_visibility_levels, class: 'control-label col-sm-2' = f.label :restricted_visibility_levels, class: 'control-label col-sm-2'
.col-sm-10 .col-sm-10
......
.btn-group.tree-btn-group .btn-group.tree-btn-group
= edit_blob_link(@project, @ref, @path)
= link_to 'Raw', namespace_project_raw_path(@project.namespace, @project, @id), = link_to 'Raw', namespace_project_raw_path(@project.namespace, @project, @id),
class: 'btn btn-sm', target: '_blank' class: 'btn btn-sm', target: '_blank'
-# only show normal/blame view links for text files -# only show normal/blame view links for text files
...@@ -12,11 +11,16 @@ ...@@ -12,11 +11,16 @@
class: 'btn btn-sm' unless @blob.empty? class: 'btn btn-sm' unless @blob.empty?
= link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id), = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id),
class: 'btn btn-sm' class: 'btn btn-sm'
- if @ref != @commit.sha
= link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project, = link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project,
tree_join(@commit.sha, @path)), class: 'btn btn-sm' tree_join(@commit.sha, @path)), class: 'btn btn-sm'
- if can_delete_or_replace?(@blob) - if blob_editable?(@blob)
.btn-group{ role: "group" } .btn-group{ role: "group" }
= edit_blob_link(@project, @ref, @path)
%button.btn.btn-default{ 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal' } Replace %button.btn.btn-default{ 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal' } Replace
%button.btn.btn-remove{ 'data-target' => '#modal-remove-blob', 'data-toggle' => 'modal' } Delete %button.btn.btn-remove{ 'data-target' => '#modal-remove-blob', 'data-toggle' => 'modal' } Delete
- elsif !on_top_of_branch?
.btn-group{ role: "group" }
%button.btn.btn-default.disabled.has_tooltip{title: "You can only edit files when you are on a branch.", data: {container: 'body'}} Edit
%button.btn.btn-default.disabled.has_tooltip{title: "You can only replace files when you are on a branch.", data: {container: 'body'}} Replace
%button.btn.btn-remove.disabled.has_tooltip{title: "You can only delete files when you are on a branch.", data: {container: 'body'}} Delete
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
%div#tree-holder.tree-holder %div#tree-holder.tree-holder
= render 'blob', blob: @blob = render 'blob', blob: @blob
- if can_delete_or_replace?(@blob) - if blob_editable?(@blob)
= render 'projects/blob/remove' = render 'projects/blob/remove'
- title = "Replace #{@blob.name}" - title = "Replace #{@blob.name}"
......
.gray-content-block.middle-block
.pull-right
- if @ci_project && can?(current_user, :manage_builds, @ci_commit.gl_project)
- if @ci_commit.builds.latest.failed.any?(&:retryable?)
= link_to "Retry failed", retry_builds_namespace_project_commit_path(@ci_commit.gl_project.namespace, @ci_commit.gl_project, @ci_commit.sha), class: 'btn btn-grouped btn-primary', method: :post
- if @ci_commit.builds.running_or_pending.any?
= link_to "Cancel running", cancel_builds_namespace_project_commit_path(@ci_commit.gl_project.namespace, @ci_commit.gl_project, @ci_commit.sha), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
.oneline
= pluralize @statuses.count(:id), "build"
- if defined?(link_to_commit) && link_to_commit
for commit
= link_to @ci_commit.short_sha, namespace_project_commit_path(@ci_commit.gl_project.namespace, @ci_commit.gl_project, @ci_commit.sha), class: "monospace"
- if @ci_commit.duration > 0
in
= time_interval_in_words @ci_commit.duration
- if @ci_commit.yaml_errors.present?
.bs-callout.bs-callout-danger
%h4 Found errors in your .gitlab-ci.yml:
%ul
- @ci_commit.yaml_errors.split(",").each do |error|
%li= error
- if @ci_commit.gl_project.builds_enabled? && !@ci_commit.ci_yaml_file
.bs-callout.bs-callout-warning
\.gitlab-ci.yml not found in this commit
.table-holder
%table.table.builds
%thead
%tr
%th Status
%th Build ID
%th Ref
%th Stage
%th Name
%th Duration
%th Finished at
- if @ci_project && @ci_project.coverage_enabled?
%th Coverage
%th
- @ci_commit.refs.each do |ref|
= render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.for_ref(ref).latest.ordered,
locals: { coverage: @ci_project.try(:coverage_enabled?), stage: true, allow_retry: true }
- if @ci_commit.retried.any?
.gray-content-block.second-block
Retried builds
.table-holder
%table.table.builds
%thead
%tr
%th Status
%th Build ID
%th Ref
%th Stage
%th Name
%th Duration
%th Finished at
- if @ci_project && @ci_project.coverage_enabled?
%th Coverage
%th
= render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.retried,
locals: { coverage: @ci_project.try(:coverage_enabled?), stage: true }
...@@ -6,4 +6,4 @@ ...@@ -6,4 +6,4 @@
= nav_link(path: 'commit#builds') do = nav_link(path: 'commit#builds') do
= link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id) do = link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id) do
Builds Builds
%span.badge= @builds.count(:id) %span.badge= @statuses.count
...@@ -3,70 +3,4 @@ ...@@ -3,70 +3,4 @@
= render "commit_box" = render "commit_box"
= render "ci_menu" = render "ci_menu"
= render "builds"
- if @ci_commit.yaml_errors.present?
.bs-callout.bs-callout-danger
%h4 Found errors in your .gitlab-ci.yml:
%ul
- @ci_commit.yaml_errors.split(",").each do |error|
%li= error
- unless @ci_commit.ci_yaml_file
.bs-callout.bs-callout-warning
\.gitlab-ci.yml not found in this commit
.gray-content-block.second-block
Latest builds
.pull-right
- if @ci_commit.duration > 0
%i.fa.fa-time
#{time_interval_in_words @ci_commit.duration}
&nbsp;
- if @ci_project && current_user && can?(current_user, :manage_builds, @project)
- if @ci_commit.builds.latest.failed.any?(&:retryable?)
= link_to "Retry failed", retry_builds_namespace_project_commit_path(@project.namespace, @project, @commit.sha), class: 'btn btn-xs btn-primary', method: :post
- if @ci_commit.builds.running_or_pending.any?
= link_to "Cancel running", cancel_builds_namespace_project_commit_path(@project.namespace, @project, @commit.sha), class: 'btn btn-xs btn-danger', method: :post
.table-holder
%table.table.builds
%thead
%tr
%th Status
%th Build ID
%th Ref
%th Stage
%th Name
%th Duration
%th Finished at
- if @ci_project && @ci_project.coverage_enabled?
%th Coverage
%th
- @ci_commit.refs.each do |ref|
= render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.for_ref(ref).latest.ordered,
locals: { coverage: @ci_project.try(:coverage_enabled?), stage: true, allow_retry: true }
- if @ci_commit.retried.any?
.gray-content-block.second-block
Retried builds
.table-holder
%table.table.builds
%thead
%tr
%th Status
%th Build ID
%th Ref
%th Stage
%th Name
%th Duration
%th Finished at
- if @ci_project && @ci_project.coverage_enabled?
%th Coverage
%th
= render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.retried,
locals: { coverage: @ci_project.try(:coverage_enabled?), stage: true }
...@@ -27,6 +27,11 @@ ...@@ -27,6 +27,11 @@
= link_to url_for(params), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do = link_to url_for(params), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
Changes Changes
%span.badge= @diffs.size %span.badge= @diffs.size
- if @ci_commit
%li.builds-tab.active
= link_to url_for(params), data: {target: 'div#builds', action: 'builds', toggle: 'tab'} do
Builds
%span.badge= @statuses.size
.tab-content .tab-content
#commits.commits.tab-pane #commits.commits.tab-pane
...@@ -42,6 +47,9 @@ ...@@ -42,6 +47,9 @@
.alert.alert-danger .alert.alert-danger
%h4 This comparison includes a huge diff. %h4 This comparison includes a huge diff.
%p To preserve performance the line changes are not shown. %p To preserve performance the line changes are not shown.
- if @ci_commit
#builds.builds.tab-pane
= render "projects/merge_requests/show/builds"
:javascript :javascript
$('.assign-to-me-link').on('click', function(e){ $('.assign-to-me-link').on('click', function(e){
......
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
%li= link_to "Plain Diff", merge_request_path(@merge_request, format: :diff) %li= link_to "Plain Diff", merge_request_path(@merge_request, format: :diff)
.normal .normal
%span Request to merge %span Request to merge
%span.label-branch %span.label-branch= source_branch_with_namespace(@merge_request)
= source_branch_with_namespace(@merge_request)
%span into %span into
= link_to namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch" do = link_to namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch" do
= @merge_request.target_branch = @merge_request.target_branch
...@@ -55,6 +54,11 @@ ...@@ -55,6 +54,11 @@
= link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
Changes Changes
%span.badge= @merge_request.diffs.size %span.badge= @merge_request.diffs.size
- if @ci_commit
%li.builds-tab
= link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#builds', action: 'builds', toggle: 'tab'} do
Builds
%span.badge= @statuses.size
.tab-content .tab-content
#notes.notes.tab-pane.voting_notes #notes.notes.tab-pane.voting_notes
...@@ -63,6 +67,8 @@ ...@@ -63,6 +67,8 @@
- # This tab is always loaded via AJAX - # This tab is always loaded via AJAX
#diffs.diffs.tab-pane #diffs.diffs.tab-pane
- # This tab is always loaded via AJAX - # This tab is always loaded via AJAX
#builds.builds.tab-pane
- # This tab is always loaded via AJAX
.mr-loading-status .mr-loading-status
= spinner = spinner
......
= render "projects/commit/builds", link_to_commit: true
- if @ci_commit - if @ci_commit
- status = @ci_commit.status
.mr-widget-heading .mr-widget-heading
.ci_widget{class: "ci-#{status}"} .ci_widget{class: "ci-#{@ci_commit.status}"}
= ci_status_icon(@ci_commit) = ci_status_icon(@ci_commit)
%span CI build #{status} %span
for #{@merge_request.last_commit_short_sha}. Build
= ci_status_label(@ci_commit)
for
= succeed "." do
= link_to @ci_commit.short_sha, namespace_project_commit_path(@merge_request.source_project.namespace, @merge_request.source_project, @ci_commit.sha), class: "monospace"
%span.ci-coverage %span.ci-coverage
= link_to "View build details", ci_status_path(@ci_commit) = link_to "View details", builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: "js-show-tab", data: {action: 'builds'}
- elsif @merge_request.has_ci? - elsif @merge_request.has_ci?
- # Compatibility with old CI integrations (ex jenkins) when you request status from CI server via AJAX - # Compatibility with old CI integrations (ex jenkins) when you request status from CI server via AJAX
- # Remove in later versions when services like Jenkins will set CI status via Commit status API - # Remove in later versions when services like Jenkins will set CI status via Commit status API
.mr-widget-heading .mr-widget-heading
- [:success, :skipped, :canceled, :failed, :running, :pending].each do |status| - %w[success skipped canceled failed running pending].each do |status|
.ci_widget{class: "ci-#{status}", style: "display:none"} .ci_widget{class: "ci-#{status}", style: "display:none"}
- if status == :success = ci_icon_for_status(status)
- status = "passed" %span
= icon("check-circle") CI build
- else = ci_label_for_status(status)
= icon("circle") for
%span CI build #{status} - commit = @merge_request.last_commit
for #{@merge_request.last_commit_short_sha}. = succeed "." do
= link_to commit.short_id, namespace_project_commit_path(@merge_request.source_project.namespace, @merge_request.source_project, commit), class: "monospace"
%span.ci-coverage %span.ci-coverage
- if ci_build_details_path(@merge_request) - if details_path = ci_build_details_path(@merge_request)
= link_to "View build details", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink" = link_to "View details", details_path, :"data-no-turbolink" => "data-no-turbolink"
.ci_widget .ci_widget
= icon("spinner spin") = icon("spinner spin")
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
= icon('pencil-square-o') = icon('pencil-square-o')
Manage group members Manage group members
%ul.content-list %ul.content-list
- members.each do |member| - members.limit(20).each do |member|
= render 'groups/group_members/group_member', member: member, show_controls: false = render 'groups/group_members/group_member', member: member, show_controls: false
- if members.count > 20 - if members.count > 20
%li %li
......
...@@ -30,3 +30,7 @@ ...@@ -30,3 +30,7 @@
= link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do
= icon('folder fw') = icon('folder fw')
New directory New directory
- elsif !on_top_of_branch?
%li
%span.btn.add-to-tree.disabled.has_tooltip{title: "You can only add files when you are on a branch.", data: {container: 'body'}}
= icon('plus')
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
.form-group.branch .form-group.branch
= label_tag 'new_branch', 'Target branch', class: 'control-label' = label_tag 'new_branch', 'Target branch', class: 'control-label'
.col-sm-10 .col-sm-10
= text_field_tag 'new_branch', @new_branch || @ref, required: true, class: "form-control js-new-branch" = text_field_tag 'new_branch', @new_branch || tree_edit_branch, required: true, class: "form-control js-new-branch"
.js-create-merge-request-container .js-create-merge-request-container
.checkbox .checkbox
......
.issuable-details .issuable-details
.page-title .page-title
.snippet-box.has_tooltip{class: visibility_level_color(@snippet.visibility_level), title: snippet_visibility_level_description(@snippet.visibility_level), data: { container: 'body' }} .snippet-box.has_tooltip{class: visibility_level_color(@snippet.visibility_level), title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: 'body' }}
= visibility_level_icon(@snippet.visibility_level, fw: false) = visibility_level_icon(@snippet.visibility_level, fw: false)
= visibility_level_label(@snippet.visibility_level) = visibility_level_label(@snippet.visibility_level)
Snippet ##{@snippet.id} Snippet ##{@snippet.id}
......
...@@ -76,7 +76,7 @@ production: &base ...@@ -76,7 +76,7 @@ production: &base
# This happens when the commit is pushed or merged into the default branch of a project. # This happens when the commit is pushed or merged into the default branch of a project.
# When not specified the default issue_closing_pattern as specified below will be used. # When not specified the default issue_closing_pattern as specified below will be used.
# Tip: you can test your closing pattern at http://rubular.com. # Tip: you can test your closing pattern at http://rubular.com.
# issue_closing_pattern: '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)' # issue_closing_pattern: '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?))+)'
## Default project features settings ## Default project features settings
default_projects_features: default_projects_features:
......
...@@ -570,8 +570,9 @@ Rails.application.routes.draw do ...@@ -570,8 +570,9 @@ Rails.application.routes.draw do
resources :merge_requests, constraints: { id: /\d+/ }, except: [:destroy] do resources :merge_requests, constraints: { id: /\d+/ }, except: [:destroy] do
member do member do
get :diffs
get :commits get :commits
get :diffs
get :builds
get :merge_check get :merge_check
post :merge post :merge
post :cancel_merge_when_build_succeeds post :cancel_merge_when_build_succeeds
......
# Issue closing pattern # Issue closing pattern
Here's how to close multiple issues in one commit message: When a commit or merge request resolves one or more issues, it is possible to automatically have these issues closed when the commit or merge request lands in the project's default branch.
If a commit message matches the regular expression below, all issues referenced from If a commit message or merge request description contains a sentence matching the regular expression below, all issues referenced from
the matched text will be closed. This happens when the commit is pushed or merged the matched text will be closed. This happens when the commit is pushed to a project's default branch, or when a commit or merge request is merged into there.
into the default branch of a project.
When not specified, the default issue_closing_pattern as shown below will be used: When not specified, the default `issue_closing_pattern` as shown below will be used:
```bash ```bash
((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+) ((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?))+)
``` ```
Here, `%{issue_ref}` is a complex regular expression defined inside GitLab, that matches a reference to a local issue (`#123`), cross-project issue (`group/project#123`) or a link to an issue (`https://gitlab.example.com/group/project/issues/123`).
For example: For example:
``` ```
git commit -m "Awesome commit message (Fix #20, Fixes #21 and Closes #22). This commit is also related to #17 and fixes #18, #19 and #23." git commit -m "Awesome commit message (Fix #20, Fixes #21 and Closes group/otherproject#2). This commit is also related to #17 and fixes #18, #19 and https://gitlab.example.com/group/otherproject/issues/23."
``` ```
will close `#20`, `#21`, `#22`, `#18`, `#19` and `#23`, but `#17` won't be closed will close `#18`, `#19`, `#20`, and `#21` in the project this commit is pushed to, as well as `#22` and `#23` in group/otherproject. `#17` won't be closed as it does not match the pattern. It also works with multiline commit messages.
as it does not match the pattern. It also works with multiline commit messages.
Tip: you can test this closing pattern at [http://rubular.com][1]. Use this site Tip: you can test this closing pattern at [http://rubular.com][1]. Use this site
to test your own patterns. to test your own patterns.
Because Rubular doesn't understand `%{issue_ref}`, you can replace this by `#\d+` in testing, which matches only local issue references like `#123`.
## Change the pattern ## Change the pattern
For Omnibus installs you can change the default pattern in `/etc/gitlab/gitlab.rb`: For Omnibus installs you can change the default pattern in `/etc/gitlab/gitlab.rb`:
``` ```
issue_closing_pattern: '((?:[Cc]los(?:e[sd]|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)' issue_closing_pattern: '((?:[Cc]los(?:e[sd]|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?))+)'
``` ```
For manual installs you can customize the pattern in [gitlab.yml][0]. For manual installs you can customize the pattern in [gitlab.yml][0] using the `issue_closing_pattern` key.
[0]: https://gitlab.com/gitlab-org/gitlab-ce/blob/40c3675372320febf5264061c9bcd63db2dfd13c/config/gitlab.yml.example#L65 [0]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example
[1]: http://rubular.com/r/Xmbexed1OJ [1]: http://rubular.com/r/Xmbexed1OJ
...@@ -110,12 +110,6 @@ Feature: Project Source Browse Files ...@@ -110,12 +110,6 @@ Feature: Project Source Browse Files
Given I visit a binary file in the repo Given I visit a binary file in the repo
Then I cannot see the edit button Then I cannot see the edit button
Scenario: If I don't have edit permission the edit link is disabled
Given public project "Community"
And I visit project "Community" source page
And I click on ".gitignore" file in repo
Then The edit button is disabled
@javascript @javascript
Scenario: I can edit and commit file Scenario: I can edit and commit file
Given I click on ".gitignore" file in repo Given I click on ".gitignore" file in repo
......
...@@ -118,6 +118,6 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps ...@@ -118,6 +118,6 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
step 'I see builds list' do step 'I see builds list' do
expect(page).to have_content "build: pending" expect(page).to have_content "build: pending"
expect(page).to have_content "Latest builds" expect(page).to have_content "1 build"
end end
end end
...@@ -53,10 +53,6 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps ...@@ -53,10 +53,6 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
expect(page).not_to have_link 'edit' expect(page).not_to have_link 'edit'
end end
step 'The edit button is disabled' do
expect(page).to have_css '.disabled', text: 'Edit'
end
step 'I can edit code' do step 'I can edit code' do
set_new_content set_new_content
expect(evaluate_script('blob.editor.getValue()')).to eq new_gitignore_content expect(evaluate_script('blob.editor.getValue()')).to eq new_gitignore_content
......
...@@ -47,6 +47,17 @@ module Gitlab ...@@ -47,6 +47,17 @@ module Gitlab
def object_link_title(commit) def object_link_title(commit)
commit.link_title commit.link_title
end end
def object_link_text_extras(object, matches)
extras = super
path = matches[:path] if matches.names.include?("path")
if path == '/builds'
extras.unshift "builds"
end
extras
end
end end
end end
end end
...@@ -24,8 +24,14 @@ module Gitlab ...@@ -24,8 +24,14 @@ module Gitlab
def object_link_text_extras(object, matches) def object_link_text_extras(object, matches)
extras = super extras = super
if matches.names.include?("path") && matches[:path] && matches[:path] == '/diffs' path = matches[:path] if matches.names.include?("path")
case path
when '/diffs'
extras.unshift "diffs" extras.unshift "diffs"
when '/commits'
extras.unshift "commits"
when '/builds'
extras.unshift "builds"
end end
extras extras
......
# == Schema Information
#
# Table name: lfs_objects
#
# id :integer not null, primary key
# oid :string(255) not null
# size :integer not null
# created_at :datetime
# updated_at :datetime
# file :string(255)
#
# Read about factories at https://github.com/thoughtbot/factory_girl # Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do FactoryGirl.define do
......
# == Schema Information
#
# Table name: lfs_objects_projects
#
# id :integer not null, primary key
# lfs_object_id :integer not null
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
#
# Read about factories at https://github.com/thoughtbot/factory_girl # Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do FactoryGirl.define do
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
# system :boolean default(FALSE), not null # system :boolean default(FALSE), not null
# st_diff :text # st_diff :text
# updated_by_id :integer # updated_by_id :integer
# is_award :boolean default(FALSE), not null
# #
require_relative '../support/repo_helpers' require_relative '../support/repo_helpers'
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
# import_type :string(255) # import_type :string(255)
# import_source :string(255) # import_source :string(255)
# commit_count :integer default(0) # commit_count :integer default(0)
# import_error :text
# #
FactoryGirl.define do FactoryGirl.define do
......
...@@ -7,69 +7,52 @@ describe VisibilityLevelHelper do ...@@ -7,69 +7,52 @@ describe VisibilityLevelHelper do
init_haml_helpers init_haml_helpers
end end
let(:project) { create(:project) } let(:project) { build(:project) }
let(:personal_snippet) { build(:personal_snippet) }
let(:project_snippet) { build(:project_snippet) }
describe 'visibility_level_description' do describe 'visibility_level_description' do
shared_examples 'a visibility level description' do context 'used with a Project' do
let(:desc) do it 'delegates projects to #project_visibility_level_description' do
visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, expect(visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, project))
form_model) .to match /project/i
end end
let(:expected_class) do
class_name = case form_model.class.name
when 'String'
form_model
else
form_model.class.name
end end
class_name.match(/(project|snippet)$/i)[0] context 'called with a Snippet' do
it 'delegates snippets to #snippet_visibility_level_description' do
expect(visibility_level_description(Gitlab::VisibilityLevel::INTERNAL, project_snippet))
.to match /snippet/i
end end
it 'should refer to the correct class' do
expect(desc).to match(/#{expected_class}/i)
end end
end end
context 'form_model argument is a String' do describe "#project_visibility_level_description" do
context 'model object is a personal snippet' do it "describes private projects" do
it_behaves_like 'a visibility level description' do expect(project_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE))
let(:form_model) { 'PersonalSnippet' } .to eq "Project access must be granted explicitly to each user."
end
end end
context 'model object is a project snippet' do it "describes public projects" do
it_behaves_like 'a visibility level description' do expect(project_visibility_level_description(Gitlab::VisibilityLevel::PUBLIC))
let(:form_model) { 'ProjectSnippet' } .to eq "The project can be cloned without any authentication."
end end
end end
context 'model object is a project' do describe "#snippet_visibility_level_description" do
it_behaves_like 'a visibility level description' do it 'describes visibility only for me' do
let(:form_model) { 'Project' } expect(snippet_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, personal_snippet))
end .to eq "The snippet is visible only to me."
end
end end
context 'form_model argument is a model object' do it 'describes visibility for project members' do
context 'model object is a personal snippet' do expect(snippet_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, project_snippet))
it_behaves_like 'a visibility level description' do .to eq "The snippet is visible only to project members."
let(:form_model) { create(:personal_snippet) }
end
end end
context 'model object is a project snippet' do it 'defaults to personal snippet' do
it_behaves_like 'a visibility level description' do expect(snippet_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE))
let(:form_model) { create(:project_snippet, project: project) } .to eq "The snippet is visible only to me."
end
end
context 'model object is a project' do
it_behaves_like 'a visibility level description' do
let(:form_model) { project }
end
end
end end
end end
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
# system :boolean default(FALSE), not null # system :boolean default(FALSE), not null
# st_diff :text # st_diff :text
# updated_by_id :integer # updated_by_id :integer
# is_award :boolean default(FALSE), not null
# #
require 'spec_helper' require 'spec_helper'
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
# import_type :string(255) # import_type :string(255)
# import_source :string(255) # import_source :string(255)
# commit_count :integer default(0) # commit_count :integer default(0)
# import_error :text
# #
require 'spec_helper' require 'spec_helper'
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
# project_view :integer default(0) # project_view :integer default(0)
# consumed_timestep :integer # consumed_timestep :integer
# layout :integer default(0) # layout :integer default(0)
# hide_project_limit :boolean default(FALSE)
# #
require 'spec_helper' require 'spec_helper'
......
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