Commit c70dcd29 authored by Marin Jankovski's avatar Marin Jankovski

Merge branch 'master' into move_external_issue_tracker_away_from_yml_config

parents a720dde6 25a5c848
......@@ -11,16 +11,17 @@ v 7.8.0
-
-
-
- Allow more variations for commit messages closing issues (Julien Bianchi and Hannes Rosenögger)
-
-
- Show tags in commit view (Hannes Rosenögger)
- Only count a user's vote once on a merge request or issue (Michael Clarke)
-
-
-
-
-
-
-
-
- Upgrade Sidekiq gem to version 3.3.0
- Stop git zombie creation during force push check
-
-
- Fix commits pagination
......@@ -47,16 +48,22 @@ v 7.8.0
-
-
-
- Add a new API function that retrieves all issues assigned to a single milestone (Justin Whear and Hannes Rosenögger)
-
-
-
-
-
-
- API: Add support for editing an existing project (Mika Mäenpää and Hannes Rosenögger)
-
-
-
-
v 7.7.1
- Improve mention autocomplete performance
- Show setup instructions for GitHub import if disabled
- Allow use http for OAuth applications
v 7.7.0
- Import from GitHub.com feature
......
......@@ -118,7 +118,7 @@ gem "acts-as-taggable-on"
# Background jobs
gem 'slim'
gem 'sinatra', require: nil
gem 'sidekiq', '2.17.8'
gem 'sidekiq', '~> 3.3'
# HTTP requests
gem "httparty"
......
......@@ -62,8 +62,8 @@ GEM
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
json (>= 1.7)
celluloid (0.15.2)
timers (~> 1.1.0)
celluloid (0.16.0)
timers (~> 4.0.0)
charlock_holmes (0.6.9.4)
cliver (0.3.2)
code_analyzer (0.4.3)
......@@ -244,6 +244,7 @@ GEM
hike (1.2.3)
hipchat (1.4.0)
httparty
hitimes (1.2.2)
html-pipeline (1.11.0)
activesupport (>= 2)
nokogiri (~> 1.4)
......@@ -495,12 +496,12 @@ GEM
sexp_processor (4.4.0)
shoulda-matchers (2.1.0)
activesupport (>= 3.0.0)
sidekiq (2.17.8)
celluloid (= 0.15.2)
connection_pool (~> 2.0)
sidekiq (3.3.0)
celluloid (>= 0.16.0)
connection_pool (>= 2.0.0)
json
redis (~> 3.1)
redis-namespace (~> 1.3)
redis (>= 3.0.6)
redis-namespace (>= 1.3.1)
simple_oauth (0.1.9)
simplecov (0.9.0)
docile (~> 1.1.0)
......@@ -555,7 +556,8 @@ GEM
thor (0.19.1)
thread_safe (0.3.4)
tilt (1.4.1)
timers (1.1.0)
timers (4.0.1)
hitimes
timfel-krb5-auth (0.8)
tinder (1.9.3)
eventmachine (~> 1.0)
......@@ -716,7 +718,7 @@ DEPENDENCIES
semantic-ui-sass (~> 0.16.1.0)
settingslogic
shoulda-matchers (~> 2.1.0)
sidekiq (= 2.17.8)
sidekiq (~> 3.3)
simplecov
sinatra
six
......
app/assets/images/bg-header.png

210 Bytes | W: | H:

app/assets/images/bg-header.png

90 Bytes | W: | H:

app/assets/images/bg-header.png
app/assets/images/bg-header.png
app/assets/images/bg-header.png
app/assets/images/bg-header.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/bg_fallback.png

2.91 KB | W: | H:

app/assets/images/bg_fallback.png

167 Bytes | W: | H:

app/assets/images/bg_fallback.png
app/assets/images/bg_fallback.png
app/assets/images/bg_fallback.png
app/assets/images/bg_fallback.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/brand_logo.png

31.4 KB | W: | H:

app/assets/images/brand_logo.png

26.4 KB | W: | H:

app/assets/images/brand_logo.png
app/assets/images/brand_logo.png
app/assets/images/brand_logo.png
app/assets/images/brand_logo.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/chosen-sprite.png

396 Bytes | W: | H:

app/assets/images/chosen-sprite.png

367 Bytes | W: | H:

app/assets/images/chosen-sprite.png
app/assets/images/chosen-sprite.png
app/assets/images/chosen-sprite.png
app/assets/images/chosen-sprite.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/diff_note_add.png

691 Bytes | W: | H:

app/assets/images/diff_note_add.png

418 Bytes | W: | H:

app/assets/images/diff_note_add.png
app/assets/images/diff_note_add.png
app/assets/images/diff_note_add.png
app/assets/images/diff_note_add.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/icon-link.png

1019 Bytes | W: | H:

app/assets/images/icon-link.png

726 Bytes | W: | H:

app/assets/images/icon-link.png
app/assets/images/icon-link.png
app/assets/images/icon-link.png
app/assets/images/icon-link.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/icon-search.png

331 Bytes | W: | H:

app/assets/images/icon-search.png

222 Bytes | W: | H:

app/assets/images/icon-search.png
app/assets/images/icon-search.png
app/assets/images/icon-search.png
app/assets/images/icon-search.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/icon_sprite.png

2.72 KB | W: | H:

app/assets/images/icon_sprite.png

2.57 KB | W: | H:

app/assets/images/icon_sprite.png
app/assets/images/icon_sprite.png
app/assets/images/icon_sprite.png
app/assets/images/icon_sprite.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/images.png

6.49 KB | W: | H:

app/assets/images/images.png

5.71 KB | W: | H:

app/assets/images/images.png
app/assets/images/images.png
app/assets/images/images.png
app/assets/images/images.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/logo-black.png

2.73 KB | W: | H:

app/assets/images/logo-black.png

2.55 KB | W: | H:

app/assets/images/logo-black.png
app/assets/images/logo-black.png
app/assets/images/logo-black.png
app/assets/images/logo-black.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/logo-white.png

7.33 KB | W: | H:

app/assets/images/logo-white.png

7.16 KB | W: | H:

app/assets/images/logo-white.png
app/assets/images/logo-white.png
app/assets/images/logo-white.png
app/assets/images/logo-white.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/move.png

260 Bytes | W: | H:

app/assets/images/move.png

197 Bytes | W: | H:

app/assets/images/move.png
app/assets/images/move.png
app/assets/images/move.png
app/assets/images/move.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/no_avatar.png

704 Bytes | W: | H:

app/assets/images/no_avatar.png

621 Bytes | W: | H:

app/assets/images/no_avatar.png
app/assets/images/no_avatar.png
app/assets/images/no_avatar.png
app/assets/images/no_avatar.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/no_group_avatar.png

4.77 KB | W: | H:

app/assets/images/no_group_avatar.png

942 Bytes | W: | H:

app/assets/images/no_group_avatar.png
app/assets/images/no_group_avatar.png
app/assets/images/no_group_avatar.png
app/assets/images/no_group_avatar.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/slider_handles.png

4.03 KB | W: | H:

app/assets/images/slider_handles.png

1.34 KB | W: | H:

app/assets/images/slider_handles.png
app/assets/images/slider_handles.png
app/assets/images/slider_handles.png
app/assets/images/slider_handles.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/switch_icon.png

1.17 KB | W: | H:

app/assets/images/switch_icon.png

231 Bytes | W: | H:

app/assets/images/switch_icon.png
app/assets/images/switch_icon.png
app/assets/images/switch_icon.png
app/assets/images/switch_icon.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/trans_bg.gif

50 Bytes | W: | H:

app/assets/images/trans_bg.gif

49 Bytes | W: | H:

app/assets/images/trans_bg.gif
app/assets/images/trans_bg.gif
app/assets/images/trans_bg.gif
app/assets/images/trans_bg.gif
  • 2-up
  • Swipe
  • Onion skin
......@@ -74,24 +74,18 @@ window.disableButtonIfEmptyField = (field_selector, button_selector) ->
# Disable button if any input field with given selector is empty
window.disableButtonIfAnyEmptyField = (form, form_selector, button_selector) ->
closest_submit = form.find(button_selector)
empty = false
updateButtons = ->
filled = true
form.find('input').filter(form_selector).each ->
empty = true if rstrip($(this).val()) is ""
filled = rstrip($(this).val()) != "" || !$(this).attr('required')
if empty
closest_submit.disable()
else
if filled
closest_submit.enable()
form.keyup ->
empty = false
form.find('input').filter(form_selector).each ->
empty = true if rstrip($(this).val()) is ""
if empty
closest_submit.disable()
else
closest_submit.enable()
closest_submit.disable()
updateButtons()
form.keyup(updateButtons)
window.sanitize = (str) ->
return str.replace(/<(?:.|\n)*?>/gm, '')
......
......@@ -2,8 +2,9 @@
float: left;
margin-right: 12px;
width: 40px;
padding: 1px;
@include border-radius(4px);
height: 40px;
padding: 0;
@include border-radius($avatar_radius);
&.avatar-inline {
float: none;
......
......@@ -42,7 +42,7 @@
background: #fff;
color: #737881;
float: left;
@include border-radius(40px);
@include border-radius($avatar_radius);
@include box-shadow(0 0 0 3px #EEE);
overflow: hidden;
......@@ -58,6 +58,10 @@
padding: 10px 15px;
margin-left: 60px;
img {
max-width: 100%;
}
&:after {
content: '';
display: block;
......
......@@ -128,3 +128,7 @@ a:focus {
textarea.js-gfm-input {
font-family: $monospace_font;
}
.strikethrough {
text-decoration: line-through;
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
* General Colors
*/
$style_color: #474D57;
$hover: #FFECDB;
$hover: #FFF3EB;
$box_bg: #F9F9F9;
/*
......@@ -56,4 +56,6 @@ $list-font-size: 15px;
/**
* Sidebar navigation width
*/
$sidebar_width: 240px;
$sidebar_width: 230px;
$avatar_radius: 50%;
......@@ -101,7 +101,6 @@
.commit-title {
margin: 0;
font-size: 20px;
}
.commit-description {
......
......@@ -140,7 +140,7 @@ header {
img {
width: 26px;
height: 26px;
@include border-radius(4px);
@include border-radius($avatar_radius);
}
}
......
......@@ -52,6 +52,10 @@
}
}
img {
max-width: 100%;
}
.note_text {
width: 100%;
}
......
......@@ -102,12 +102,3 @@
}
}
}
.profile-groups-avatars {
margin: 0 5px 10px 0;
img {
width: 50px;
height: 50px;
}
}
......@@ -49,7 +49,7 @@ class ApplicationController < ActionController::Base
end
def authenticate_user!(*args)
# If user is not signe-in and tries to access root_path - redirect him to landing page
# If user is not signed-in and tries to access root_path - redirect him to landing page
if current_application_settings.home_page_url.present?
if current_user.nil? && controller_name == 'dashboard' && action_name == 'show'
redirect_to current_application_settings.home_page_url and return
......
......@@ -63,11 +63,11 @@ class GithubImportsController < ApplicationController
def github_auth
if current_user.github_access_token.blank?
go_to_gihub_for_permissions
go_to_github_for_permissions
end
end
def go_to_gihub_for_permissions
def go_to_github_for_permissions
redirect_to client.auth_code.authorize_url({
redirect_uri: callback_github_import_url,
scope: "repo, user, user:email"
......@@ -75,6 +75,6 @@ class GithubImportsController < ApplicationController
end
def github_unauthorized
go_to_gihub_for_permissions
go_to_github_for_permissions
end
end
......@@ -12,6 +12,7 @@ class Projects::CommitController < Projects::ApplicationController
@line_notes = @project.notes.for_commit_id(commit.id).inline
@branches = @project.repository.branch_names_contains(commit.id)
@tags = @project.repository.tag_names_contains(commit.id)
@diffs = @commit.diffs
@note = @project.build_commit_note(commit)
@notes_count = @project.notes.for_commit_id(commit.id).count
......
......@@ -233,13 +233,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def allowed_to_push_code?(project, branch)
action = if project.protected_branch?(branch)
:push_code_to_protected_branches
else
:push_code
end
can?(current_user, action, project)
::Gitlab::GitAccess.can_push_to_branch?(current_user, project, branch)
end
def merge_request_params
......
......@@ -41,9 +41,9 @@ class Projects::RefsController < Projects::ApplicationController
@path = params[:path]
contents = []
contents += tree.trees
contents += tree.blobs
contents += tree.submodules
contents.push(*tree.trees)
contents.push(*tree.blobs)
contents.push(*tree.submodules)
@logs = contents[@offset, @limit].to_a.map do |content|
file = @path ? File.join(@path, content.name) : content.name
......
......@@ -101,11 +101,20 @@ class ProjectsController < ApplicationController
def autocomplete_sources
note_type = params['type']
note_id = params['type_id']
autocomplete = ::Projects::AutocompleteService.new(@project)
participants = ::Projects::ParticipantsService.new(@project).execute(note_type, note_id)
emojis = Emoji.names.map do |e|
{
name: e,
path: view_context.image_url("emoji/#{e}.png")
}
end
@suggestions = {
emojis: Emoji.names.map { |e| { name: e, path: view_context.image_url("emoji/#{e}.png") } },
issues: @project.issues.select([:iid, :title, :description]),
mergerequests: @project.merge_requests.select([:iid, :title, :description]),
emojis: emojis,
issues: autocomplete.issues,
mergerequests: autocomplete.merge_requests,
members: participants
}
......
......@@ -11,12 +11,7 @@ module BranchesHelper
def can_push_branch?(project, branch_name)
return false unless project.repository.branch_names.include?(branch_name)
action = if project.protected_branch?(branch_name)
:push_code_to_protected_branches
else
:push_code
end
current_user.can?(action, project)
::Gitlab::GitAccess.can_push_to_branch?(current_user, project, branch_name)
end
end
......@@ -44,7 +44,7 @@ module CommitsHelper
parts = @path.split('/')
parts.each_with_index do |part, i|
crumbs += content_tag(:li) do
crumbs << content_tag(:li) do
# The text is just the individual part, but the link needs all the parts before it
link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/')))
end
......@@ -62,7 +62,27 @@ module CommitsHelper
# Returns the sorted alphabetically links to branches, separated by a comma
def commit_branches_links(project, branches)
branches.sort.map { |branch| link_to(branch, project_tree_path(project, branch)) }.join(", ").html_safe
branches.sort.map do |branch|
link_to(project_tree_path(project, branch)) do
content_tag :span, class: 'label label-gray' do
content_tag(:i, nil, class: 'fa fa-code-fork') + ' ' +
branch
end
end
end.join(" ").html_safe
end
# Returns the sorted links to tags, separated by a comma
def commit_tags_links(project, tags)
sorted = VersionSorter.rsort(tags)
sorted.map do |tag|
link_to(project_commits_path(project, project.repository.find_tag(tag).name)) do
content_tag :span, class: 'label label-gray' do
content_tag(:i, nil, class: 'fa fa-tag') + ' ' +
tag
end
end
end.join(" ").html_safe
end
def link_to_browse_code(project, commit)
......
......@@ -135,4 +135,19 @@ module DiffHelper
'Side-by-side'
end
end
def submodule_link(blob, ref)
tree, commit = submodule_links(blob, ref)
commit_id = if commit.nil?
blob.id[0..10]
else
link_to "#{blob.id[0..10]}", commit
end
[
content_tag(:span, link_to(truncate(blob.name, length: 40), tree)),
'@',
content_tag(:span, commit_id, class: 'monospace'),
].join(' ').html_safe
end
end
module GraphHelper
def get_refs(repo, commit)
refs = ""
refs += commit.ref_names(repo).join(" ")
refs << commit.ref_names(repo).join(' ')
# append note count
refs += "[#{@graph.notes[commit.id]}]" if @graph.notes[commit.id] > 0
refs << "[#{@graph.notes[commit.id]}]" if @graph.notes[commit.id] > 0
refs
end
......
......@@ -74,7 +74,7 @@ module ProjectsHelper
def link_to_toggle_star(title, starred, signed_in)
cls = 'star-btn'
cls += ' disabled' unless signed_in
cls << ' disabled' unless signed_in
toggle_html = content_tag('span', class: 'toggle') do
toggle_text = if starred
......
......@@ -2,8 +2,8 @@ module SubmoduleHelper
include Gitlab::ShellAdapter
# links to files listing for submodule if submodule is a project on this server
def submodule_links(submodule_item)
url = @repository.submodule_url_for(@ref, submodule_item.path)
def submodule_links(submodule_item, ref = nil)
url = @repository.submodule_url_for(ref, submodule_item.path)
return url, nil unless url =~ /([^\/:]+\/[^\/]+\.git)\Z/
......
......@@ -6,7 +6,7 @@ module TagsHelper
def tag_list(project)
html = ''
project.tag_list.each do |tag|
html += link_to tag, tag_path(tag)
html << link_to(tag, tag_path(tag))
end
html.html_safe
......
......@@ -10,13 +10,16 @@ module TreeHelper
tree = ""
# Render folders if we have any
tree += render partial: 'projects/tree/tree_item', collection: folders, locals: {type: 'folder'} if folders.present?
tree << render(partial: 'projects/tree/tree_item', collection: folders,
locals: { type: 'folder' }) if folders.present?
# Render files if we have any
tree += render partial: 'projects/tree/blob_item', collection: files, locals: {type: 'file'} if files.present?
tree << render(partial: 'projects/tree/blob_item', collection: files,
locals: { type: 'file' }) if files.present?
# Render submodules if we have any
tree += render partial: 'projects/tree/submodule_item', collection: submodules if submodules.present?
tree << render(partial: 'projects/tree/submodule_item',
collection: submodules) if submodules.present?
tree.html_safe
end
......@@ -58,11 +61,7 @@ module TreeHelper
ref ||= @ref
return false unless project.repository.branch_names.include?(ref)
if project.protected_branch? ref
can?(current_user, :push_code_to_protected_branches, project)
else
can?(current_user, :push_code, project)
end
::Gitlab::GitAccess.can_push_to_branch?(current_user, project, ref)
end
def edit_blob_link(project, ref, path, options = {})
......@@ -113,7 +112,7 @@ module TreeHelper
tree_join(@ref, file)
end
# returns the relative path of the first subdir that doesn't have only one directory descendand
# returns the relative path of the first subdir that doesn't have only one directory descendant
def flatten_tree(tree)
subtree = Gitlab::Git::Tree.where(@repository, @commit.id, tree.path)
if subtree.count == 1 && subtree.first.dir?
......
......@@ -56,7 +56,7 @@ module Emails
end
end
# Over rides default behavour to show source/target
# Over rides default behaviour to show source/target
# Formats arguments into a String suitable for use as an email subject
#
# extra - Extra Strings to be inserted into the subject
......
......@@ -26,8 +26,8 @@ class Notify < ActionMailer::Base
delay_for(2.seconds)
end
def test_email(recepient_email, subject, body)
mail(to: recepient_email,
def test_email(recipient_email, subject, body)
mail(to: recipient_email,
subject: subject,
body: body.html_safe,
content_type: 'text/html'
......
......@@ -73,28 +73,28 @@ class Ability
# Rules based on role in project
if team.master?(user)
rules += project_master_rules
rules.push(*project_master_rules)
elsif team.developer?(user)
rules += project_dev_rules
rules.push(*project_dev_rules)
elsif team.reporter?(user)
rules += project_report_rules
rules.push(*project_report_rules)
elsif team.guest?(user)
rules += project_guest_rules
rules.push(*project_guest_rules)
end
if project.public? || project.internal?
rules += public_project_rules
rules.push(*public_project_rules)
end
if project.owner == user || user.admin?
rules += project_admin_rules
rules.push(*project_admin_rules)
end
if project.group && project.group.has_owner?(user)
rules += project_admin_rules
rules.push(*project_admin_rules)
end
if project.archived?
......@@ -193,17 +193,17 @@ class Ability
# Only group masters and group owners can create new projects in group
if group.has_master?(user) || group.has_owner?(user) || user.admin?
rules += [
rules.push(*[
:create_projects,
]
])
end
# Only group owner and administrators can manage group
if group.has_owner?(user) || user.admin?
rules += [
rules.push(*[
:manage_group,
:manage_namespace
]
])
end
rules.flatten
......@@ -214,10 +214,10 @@ class Ability
# Only namespace owner and administrators can manage it
if namespace.owner == user || user.admin?
rules += [
rules.push(*[
:create_projects,
:manage_namespace
]
])
end
rules.flatten
......
# == Schema Information
#
# Table name: application_settings
#
# id :integer not null, primary key
# default_projects_limit :integer
# signup_enabled :boolean
# signin_enabled :boolean
# gravatar_enabled :boolean
# sign_in_text :text
# created_at :datetime
# updated_at :datetime
# home_page_url :string(255)
#
class ApplicationSetting < ActiveRecord::Base
validates :home_page_url, allow_blank: true,
format: { with: URI::regexp(%w(http https)), message: "should be a valid url" },
......
......@@ -88,7 +88,7 @@ module Issuable
# Return the number of -1 comments (downvotes)
def downvotes
notes.select(&:downvote?).size
filter_superceded_votes(notes.select(&:downvote?), notes).size
end
def downvotes_in_percent
......@@ -101,7 +101,7 @@ module Issuable
# Return the number of +1 comments (upvotes)
def upvotes
notes.select(&:upvote?).size
filter_superceded_votes(notes.select(&:upvote?), notes).size
end
def upvotes_in_percent
......@@ -124,10 +124,12 @@ module Issuable
users << assignee if is_assigned?
mentions = []
mentions << self.mentioned_users
notes.each do |note|
users << note.author
mentions << note.mentioned_users
end
users.concat(mentions.reduce([], :|)).uniq
end
......@@ -149,9 +151,23 @@ module Issuable
def add_labels_by_names(label_names)
label_names.each do |label_name|
label = project.labels.create_with(
color: Label::DEFAULT_COLOR).find_or_create_by(title: label_name.strip)
label = project.labels.create_with(color: Label::DEFAULT_COLOR).
find_or_create_by(title: label_name.strip)
self.labels << label
end
end
private
def filter_superceded_votes(votes, notes)
filteredvotes = [] + votes
votes.each do |vote|
if vote.superceded?(notes)
filteredvotes.delete(vote)
end
end
filteredvotes
end
end
......@@ -50,7 +50,7 @@ module Mentionable
matches.each do |match|
identifier = match.delete "@"
if identifier == "all"
users += project.team.members.flatten
users.push(*project.team.members.flatten)
else
id = User.find_by(username: identifier).try(:id)
users << User.find(id) unless id.blank?
......
# == Schema Information
#
# Table name: identities
#
# id :integer not null, primary key
# extern_uid :string(255)
# provider :string(255)
# user_id :integer
#
class Identity < ActiveRecord::Base
belongs_to :user
......
......@@ -19,7 +19,7 @@ class Key < ActiveRecord::Base
belongs_to :user
before_validation :strip_white_space, :generate_fingerpint
before_validation :strip_white_space, :generate_fingerprint
validates :title, presence: true, length: { within: 0..255 }
validates :key, presence: true, length: { within: 0..5000 }, format: { with: /\A(ssh|ecdsa)-.*\Z/ }, uniqueness: true
......@@ -76,7 +76,7 @@ class Key < ActiveRecord::Base
private
def generate_fingerpint
def generate_fingerprint
self.fingerprint = nil
return unless key.present?
......
......@@ -18,6 +18,7 @@
# iid :integer
# description :text
# position :integer default(0)
# locked_at :datetime
#
require Rails.root.join("app/models/commit")
......@@ -250,7 +251,8 @@ class MergeRequest < ActiveRecord::Base
def closes_issues
if target_branch == project.default_branch
issues = commits.flat_map { |c| c.closes_issues(project) }
issues += Gitlab::ClosingIssueExtractor.closed_by_message_in_project(description, project)
issues.push(*Gitlab::ClosingIssueExtractor.
closed_by_message_in_project(description, project))
issues.uniq.sort_by(&:id)
else
[]
......@@ -330,7 +332,7 @@ class MergeRequest < ActiveRecord::Base
end
# Return array of possible target branches
# dependes on target project of MR
# depends on target project of MR
def target_branches
if target_project.nil?
[]
......@@ -340,7 +342,7 @@ class MergeRequest < ActiveRecord::Base
end
# Return array of possible source branches
# dependes on source project of MR
# depends on source project of MR
def source_branches
if source_project.nil?
[]
......
......@@ -84,7 +84,7 @@ module Network
skip += self.class.max_count
end
else
# Cant't find the target commit in the repo.
# Can't find the target commit in the repo.
offset = 0
end
end
......@@ -226,7 +226,7 @@ module Network
reserved = []
for day in time_range
reserved += @reserved[day]
reserved.push(*@reserved[day])
end
reserved.uniq!
......
......@@ -459,6 +459,26 @@ class Note < ActiveRecord::Base
)
end
def superceded?(notes)
return false unless vote?
notes.each do |note|
next if note == self
if note.vote? &&
self[:author_id] == note[:author_id] &&
self[:created_at] <= note[:created_at]
return true
end
end
false
end
def vote?
upvote? || downvote?
end
def votable?
for_issue? || (for_merge_request? && !for_diff_line?)
end
......@@ -480,7 +500,7 @@ class Note < ActiveRecord::Base
end
# FIXME: Hack for polymorphic associations with STI
# For more information wisit http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Polymorphic+Associations
# For more information visit http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Polymorphic+Associations
def noteable_type=(sType)
super(sType.to_s.classify.constantize.base_class.to_s)
end
......
......@@ -24,6 +24,8 @@
# import_status :string(255)
# repository_size :float default(0.0)
# star_count :integer default(0), not null
# import_type :string(255)
# import_source :string(255)
#
class Project < ActiveRecord::Base
......@@ -174,7 +176,7 @@ class Project < ActiveRecord::Base
def publicish(user)
visibility_levels = [Project::PUBLIC]
visibility_levels += [Project::INTERNAL] if user
visibility_levels << Project::INTERNAL if user
where(visibility_level: visibility_levels)
end
......
# == Schema Information
#
# Table name: services
#
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# properties :text
#
class BambooService < CiService
include HTTParty
......
# == Schema Information
#
# Table name: services
#
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# properties :text
#
class TeamcityService < CiService
include HTTParty
......
......@@ -160,7 +160,7 @@ class ProjectTeam
end
user_ids = project_members.pluck(:user_id)
user_ids += group_members.pluck(:user_id) if group
user_ids.push(*group_members.pluck(:user_id)) if group
User.where(id: user_ids)
end
......
......@@ -7,6 +7,7 @@
# name :string(255) not null
# created_at :datetime
# updated_at :datetime
# developers_can_push :boolean default(FALSE), not null
#
class ProtectedBranch < ActiveRecord::Base
......
......@@ -312,4 +312,21 @@ class Repository
[]
end
end
def tag_names_contains(sha)
args = %W(git tag --contains #{sha})
names = Gitlab::Popen.popen(args, path_to_repo).first
if names.respond_to?(:split)
names = names.split("\n").map(&:strip)
names.each do |name|
name.slice! '* '
end
names
else
[]
end
end
end
......@@ -26,8 +26,6 @@
# bio :string(255)
# failed_attempts :integer default(0)
# locked_at :datetime
# extern_uid :string(255)
# provider :string(255)
# username :string(255)
# can_create_group :boolean default(TRUE), not null
# can_create_team :boolean default(TRUE), not null
......@@ -36,7 +34,6 @@
# notification_level :integer default(1), not null
# password_expires_at :datetime
# created_by_id :integer
# last_credential_check_at :datetime
# avatar :string(255)
# confirmation_token :string(255)
# confirmed_at :datetime
......@@ -44,6 +41,8 @@
# unconfirmed_email :string(255)
# hide_no_ssh_key :boolean default(FALSE)
# website_url :string(255) default(""), not null
# last_credential_check_at :datetime
# github_access_token :string(255)
#
require 'carrierwave/orm/activerecord'
......@@ -298,8 +297,8 @@ class User < ActiveRecord::Base
def authorized_projects
@authorized_projects ||= begin
project_ids = personal_projects.pluck(:id)
project_ids += groups_projects.pluck(:id)
project_ids += projects.pluck(:id).uniq
project_ids.push(*groups_projects.pluck(:id))
project_ids.push(*projects.pluck(:id).uniq)
Project.where(id: project_ids).joins(:namespace).order('namespaces.name ASC')
end
end
......@@ -497,7 +496,7 @@ class User < ActiveRecord::Base
def avatar_url(size = nil)
if avatar.present?
[gitlab_config.url, avatar.url].join("/")
[gitlab_config.url, avatar.url].join
else
GravatarService.new.execute(email, size)
end
......
......@@ -3,11 +3,7 @@ require_relative "base_service"
module Files
class CreateService < BaseService
def execute
allowed = if project.protected_branch?(ref)
can?(current_user, :push_code_to_protected_branches, project)
else
can?(current_user, :push_code, project)
end
allowed = Gitlab::GitAccess.can_push_to_branch?(current_user, project, ref)
unless allowed
return error("You are not allowed to create file in this branch")
......
......@@ -3,11 +3,7 @@ require_relative "base_service"
module Files
class DeleteService < BaseService
def execute
allowed = if project.protected_branch?(ref)
can?(current_user, :push_code_to_protected_branches, project)
else
can?(current_user, :push_code, project)
end
allowed = ::Gitlab::GitAccess.can_push_to_branch?(current_user, project, ref)
unless allowed
return error("You are not allowed to push into this branch")
......
......@@ -3,11 +3,7 @@ require_relative "base_service"
module Files
class UpdateService < BaseService
def execute
allowed = if project.protected_branch?(ref)
can?(current_user, :push_code_to_protected_branches, project)
else
can?(current_user, :push_code, project)
end
allowed = ::Gitlab::GitAccess.can_push_to_branch?(current_user, project, ref)
unless allowed
return error("You are not allowed to push into this branch")
......
......@@ -242,7 +242,7 @@ class NotificationService
users
end
# Build a list of users based on group notifcation settings
# Build a list of users based on group notification settings
def select_users_group_setting(project, project_members, global_setting, users_global_level_watch)
uids = users_group_notification(project, Notification::N_WATCH)
......
......@@ -13,7 +13,7 @@ module Oauth2::AccessTokenValidationService
elsif token.revoked?
return REVOKED
elsif !self.sufficent_scope?(token, scopes)
elsif !self.sufficient_scope?(token, scopes)
return INSUFFICIENT_SCOPE
else
......@@ -24,7 +24,7 @@ module Oauth2::AccessTokenValidationService
protected
# True if the token's scope is a superset of required scopes,
# or the required scopes is empty.
def sufficent_scope?(token, scopes)
def sufficient_scope?(token, scopes)
if scopes.blank?
# if no any scopes required, the scopes of token is sufficient.
return true
......
module Projects
class AutocompleteService < BaseService
def initialize(project)
@project = project
end
def issues
@project.issues.opened.select([:iid, :title, :description])
end
def merge_requests
@project.merge_requests.opened.select([:iid, :title, :description])
end
end
end
......@@ -7,7 +7,7 @@ module Projects
def execute
@project = Project.new(params)
# Reset visibility levet if is not allowed to set it
# Reset visibility level if is not allowed to set it
unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
@project.visibility_level = default_features.visibility_level
end
......
......@@ -20,7 +20,7 @@
= radio_button_tag :notification_level, Notification::N_MENTION, @notification.mention?, class: 'trigger-submit'
.level-title
Mention
%p You will receive notifications only for comments where you was @mentioned
%p You will receive notifications only for comments in which you were @mentioned
.radio
= label_tag nil, class: '' do
......
%div#github_import_modal.modal.hide
.modal-dialog
.modal-content
.modal-header
%a.close{href: "#", "data-dismiss" => "modal"} ×
%h3 GitHub OAuth import
.modal-body
You need to setup integration with GitHub first.
= link_to 'How to setup integration with GitHub', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/github.md'
:javascript
$(function(){
var import_modal = $('#github_import_modal').modal({modal: true, show:false});
$('.how_to_import_link').bind("click", function(e){
e.preventDefault();
import_modal.show();
});
$('.modal-header .close').bind("click", function(){
import_modal.hide();
})
})
......@@ -5,7 +5,7 @@
%h3.page-title
%i.fa.fa-code-fork
New branch
= form_tag project_branches_path, method: :post, class: "form-horizontal" do
= form_tag project_branches_path, method: :post, id: "new-branch-form", class: "form-horizontal" do
.form-group
= label_tag :branch_name, 'Name for new branch', class: 'control-label'
.col-sm-10
......@@ -19,6 +19,7 @@
= link_to 'Cancel', project_branches_path(@project), class: 'btn btn-cancel'
:javascript
disableButtonIfAnyEmptyField($("#new-branch-form"), ".form-control", ".btn-create");
var availableTags = #{@project.repository.ref_names.to_json};
$("#ref").autocomplete({
......
......@@ -37,18 +37,23 @@
- @commit.parents.each do |parent|
= link_to parent.short_id, project_commit_path(@project, parent)
- if @branches.any?
.commit-info-row
%span.cgray
Exists in
.commit-info-row
- if @branches.any?
%span
- branch = commit_default_branch(@project, @branches)
= link_to(branch, project_tree_path(@project, branch))
- if @branches.any?
and in
= link_to("#{pluralize(@branches.count, "other branch")}", "#", class: "js-details-expand")
= link_to(project_tree_path(@project, branch)) do
%span.label.label-gray
%i.fa.fa-code-fork
= branch
- if @branches.any? || @tags.any?
= link_to("#", class: "js-details-expand") do
%span.label.label-gray
\...
%span.js-details-content.hide
- if @branches.any?
= commit_branches_links(@project, @branches)
- if @tags.any?
= commit_tags_links(@project, @tags)
.commit-box
%h3.commit-title
......
......@@ -9,6 +9,9 @@
.diff-btn-group
- if @commit.parent_ids.present?
= view_file_btn(@commit.parent_id, diff_file, project)
- elsif diff_file.diff.submodule?
- submodule_item = project.repository.blob_at(@commit.id, diff_file.file_path)
= submodule_link(submodule_item, @commit.id)
- else
- if diff_file.renamed_file
%span= "#{diff_file.old_path} renamed to #{diff_file.new_path}"
......
.append-bottom-10
.check-all-holder
= check_box_tag "check_all_issues", nil, false, class: "check_all_issues left"
= check_box_tag "check_all_issues", nil, false, class: "check_all_issues left", disabled: !can?(current_user, :modify_issue, @project)
= render 'shared/issuable_filter'
.clearfix
......
......@@ -3,21 +3,21 @@
%i.fa.fa-check
%span CI build passed
for #{@merge_request.last_commit_short_sha}.
= link_to "Build page", ci_build_details_path(@merge_request)
= link_to "Build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
.ci_widget.ci-failed{style: "display:none"}
%i.fa.fa-times
%span CI build failed
for #{@merge_request.last_commit_short_sha}.
= link_to "Build page", ci_build_details_path(@merge_request)
= link_to "Build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
- [:running, :pending].each do |status|
.ci_widget{class: "ci-#{status}", style: "display:none"}
%i.fa.fa-clock-o
%span CI build #{status}
for #{@merge_request.last_commit_short_sha}.
= link_to "Build page", ci_build_details_path(@merge_request)
= link_to "Build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
.ci_widget
%i.fa.fa-spinner
......
......@@ -12,6 +12,6 @@
Failed to remove source branch '#{@merge_request.source_branch}'
.remove_source_branch_in_progress.hide
%i.fa.fa-refresh.fa-spin
%i.fa.fa-spinner.fa-spin
&nbsp;
Removing source branch '#{@merge_request.source_branch}'. Please wait. Page will be automatically reloaded. &nbsp;
......@@ -40,13 +40,18 @@
The import will time out after 4 minutes. For big repositories, use a clone/push combination.
For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}
- if github_import_enabled?
.project-import.form-group
.col-sm-2
.col-sm-10
- if github_import_enabled?
= link_to status_github_import_path do
%i.fa.fa-github
Import projects from GitHub
- else
= link_to '#', class: 'how_to_import_link light' do
%i.fa.fa-github
Import projects from GitHub
= render 'github_import_modal'
%hr.prepend-botton-10
......
......@@ -28,6 +28,16 @@
%span.note-last-update
= note_timestamp(note)
- if note.superceded?(@notes)
- if note.upvote?
%span.vote.upvote.label.label-gray.strikethrough
%i.fa.fa-thumbs-up
\+1
- if note.downvote?
%span.vote.downvote.label.label-gray.strikethrough
%i.fa.fa-thumbs-down
\-1
- else
- if note.upvote?
%span.vote.upvote.label.label-success
%i.fa.fa-thumbs-up
......
......@@ -68,11 +68,11 @@
- @project.ci_services.each do |ci_service|
- if ci_service.active? && ci_service.respond_to?(:builds_path)
- if ci_service.respond_to?(:status_img_path)
= link_to ci_service.builds_path do
= link_to ci_service.builds_path, :'data-no-turbolink' => 'data-no-turbolink' do
= image_tag ci_service.status_img_path, alt: "build status"
- else
%span.light CI provided by
= link_to ci_service.title, ci_service.builds_path
= link_to ci_service.title, ci_service.builds_path, :'data-no-turbolink' => 'data-no-turbolink'
- if readme
.tab-pane#tab-readme
......
......@@ -5,7 +5,7 @@
%h3.page-title
%i.fa.fa-code-fork
New tag
= form_tag project_tags_path, method: :post, class: "form-horizontal" do
= form_tag project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal" do
.form-group
= label_tag :tag_name, 'Name for new tag', class: 'control-label'
.col-sm-10
......@@ -25,6 +25,7 @@
= link_to 'Cancel', project_tags_path(@project), class: 'btn btn-cancel'
:javascript
disableButtonIfAnyEmptyField($("#new-tag-form"), ".form-control", ".btn-create");
var availableTags = #{@project.repository.ref_names.to_json};
$("#ref").autocomplete({
......
- tree, commit = submodule_links(submodule_item)
%tr{ class: "tree-item" }
%td.tree-item-file-name
%i.fa.fa-archive
%span
= link_to truncate(submodule_item.name, length: 40), tree
@
%span.monospace
- if commit.nil?
#{truncate_sha(submodule_item.id)}
- else
= link_to "#{truncate_sha(submodule_item.id)}", commit
= submodule_link(submodule_item, @ref)
%td
%td.hidden-xs
- groups.each do |group|
= link_to group, class: 'profile-groups-avatars', :title => group.name do
- image_tag group_icon(group.path)
.clearfix
- groups.each do |group|
= link_to group, class: 'profile-groups-avatars', title: group.name do
= image_tag group_icon(group.path), class: 'avatar s40'
......@@ -12,11 +12,11 @@ module Gitlab
# -- all .rb files in that directory are automatically loaded.
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/lib
config.autoload_paths.push(*%W(#{config.root}/lib
#{config.root}/app/models/hooks
#{config.root}/app/models/concerns
#{config.root}/app/models/project_services
#{config.root}/app/models/members)
#{config.root}/app/models/members))
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
......@@ -31,7 +31,7 @@ module Gitlab
config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
config.filter_parameters.push(*[:password])
# Enable escaping HTML in JSON.
config.active_support.escape_html_entities_in_json = true
......
......@@ -60,7 +60,7 @@ production: &base
## Users can create accounts
# This also allows normal users to sign up for accounts themselves
# default: false - By default GitLab administrators must create all new accounts
# default: true - By default users can sign up themselves
# signup_enabled: true
## Standard login settings
......@@ -77,7 +77,7 @@ production: &base
# 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.
# Tip: you can test your closing pattern at http://rubular.com
# issue_closing_pattern: '([Cc]lose[sd]|[Ff]ixe[sd]) #(\d+)'
# issue_closing_pattern: '((?:[Cc]los(?:e[sd]|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)'
## Default project features settings
default_projects_features:
......
......@@ -109,7 +109,7 @@ Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].
Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil?
Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
Settings.gitlab['issue_closing_pattern'] = '([Cc]lose[sd]|[Ff]ixe[sd]) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)' if Settings.gitlab['issue_closing_pattern'].nil?
Settings.gitlab['default_projects_features'] ||= {}
Settings.gitlab['webhook_timeout'] ||= 10
Settings.gitlab.default_projects_features['issues'] = true if Settings.gitlab.default_projects_features['issues'].nil?
......
......@@ -36,6 +36,12 @@ Doorkeeper.configure do
# Issue access tokens with refresh token (disabled by default)
use_refresh_token
# Forces the usage of the HTTPS protocol in non-native redirect uris (enabled
# by default in non-development environments). OAuth2 delegates security in
# communication to the HTTPS protocol so it is wise to keep this enabled.
#
force_ssl_in_redirect_uri false
# Provide support for an owner to be assigned to each registered application (disabled by default)
# Optional parameter :confirmation => true (default false) if you want to enforce ownership of
# a registered application
......
......@@ -72,3 +72,16 @@ Parameters:
- `description` (optional) - The description of a milestone
- `due_date` (optional) - The due date of the milestone
- `state_event` (optional) - The state event of the milestone (close|activate)
## Get all issues assigned to a single milestone
Gets all issues assigned to a single project milestone.
```
GET /projects/:id/milestones/:milestone_id/issues
```
Parameters:
- `id` (required) - The ID of a project
- `milestone_id` (required) - The ID of a project milestone
......@@ -287,6 +287,31 @@ Parameters:
- `visibility_level` (optional)
- `import_url` (optional)
### Edit project
Updates an existing project
```
PUT /projects/:id
```
Parameters:
- `id` (required) - The ID of a project
- `name` (optional) - project name
- `path` (optional) - repository name for project
- `description` (optional) - short project description
- `default_branch` (optional)
- `issues_enabled` (optional)
- `merge_requests_enabled` (optional)
- `wiki_enabled` (optional)
- `snippets_enabled` (optional)
- `public` (optional) - if `true` same as setting visibility_level = 20
- `visibility_level` (optional)
On success, method returns 200 with the updated project. If parameters are
invalid, 400 is returned.
### Fork project
Forks a project into the user namespace of the authenticated user.
......
......@@ -108,7 +108,7 @@ In other repositories, such as gitlab-shell you can also use `IO.popen`.
```ruby
# Safe IO.popen example
logs = IO.popen(%W(git log), chdir: repo_dir).read
logs = IO.popen(%W(git log), chdir: repo_dir) { |p| p.read }
```
Note that unlike `Gitlab::Popen.popen`, `IO.popen` does not capture standard error.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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